From 1daa371dff851f9a14489acae8e4dd6adc3e47c9 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Thu, 23 Jan 2020 19:06:41 +0200 Subject: [PATCH 01/42] initial commit --- .../bottom_sheet_item_additional_data.xml | 31 + .../layout/profile_data_list_item_child.xml | 49 ++ .../layout/profile_data_list_item_group.xml | 72 +++ OsmAnd/res/values/strings.xml | 5 + .../src/net/osmand/plus/SettingsHelper.java | 110 ++++ .../plus/profiles/AdditionalDataWrapper.java | 35 ++ .../ExportImportProfileBottomSheet.java | 567 ++++++++++++++++++ .../settings/ConfigureProfileFragment.java | 40 +- 8 files changed, 877 insertions(+), 32 deletions(-) create mode 100644 OsmAnd/res/layout/bottom_sheet_item_additional_data.xml create mode 100644 OsmAnd/res/layout/profile_data_list_item_child.xml create mode 100644 OsmAnd/res/layout/profile_data_list_item_group.xml create mode 100644 OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java create mode 100644 OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java diff --git a/OsmAnd/res/layout/bottom_sheet_item_additional_data.xml b/OsmAnd/res/layout/bottom_sheet_item_additional_data.xml new file mode 100644 index 0000000000..286b32260f --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_additional_data.xml @@ -0,0 +1,31 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/profile_data_list_item_child.xml b/OsmAnd/res/layout/profile_data_list_item_child.xml new file mode 100644 index 0000000000..4b8ad4c01b --- /dev/null +++ b/OsmAnd/res/layout/profile_data_list_item_child.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/profile_data_list_item_group.xml b/OsmAnd/res/layout/profile_data_list_item_group.xml new file mode 100644 index 0000000000..8b889bb860 --- /dev/null +++ b/OsmAnd/res/layout/profile_data_list_item_group.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 93ca5c4889..afd34bbbe5 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,11 @@ Thx - Hardy --> + Routing + Custom rendering style + Include additional data + The imported profile contains additional data. Click Import to import only profile data or select additional data to import. + You can select additional data to export along with the profile. \'%1$s\' file doesn\'t contain routing rules, please choose another file. Not supported file type. You need to select a file with %1$s extension. Import from file diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 61509da462..5855d98941 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -7,11 +7,21 @@ import android.content.DialogInterface; import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; import net.osmand.PlatformUtil; import net.osmand.plus.ApplicationMode.ApplicationModeBuilder; import net.osmand.plus.OsmandSettings.OsmandPreference; +import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.profiles.AdditionalDataWrapper; +import net.osmand.plus.profiles.ExportImportProfileBottomSheet; +import net.osmand.plus.quickaction.QuickAction; +import net.osmand.plus.quickaction.QuickActionFactory; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -125,6 +135,7 @@ public class SettingsHelper { PLUGIN, DATA, FILE, + QUICK_ACTION } public abstract static class SettingsItem { @@ -457,6 +468,10 @@ public class SettingsHelper { } } + public ApplicationMode getAppMode() { + return appMode; + } + @Override void writeToJson(@NonNull JSONObject json) throws JSONException { super.writeToJson(json); @@ -693,6 +708,98 @@ public class SettingsHelper { } } + public static class QuickActionSettingsItem extends OsmandSettingsItem { + + private List quickActions; + + public QuickActionSettingsItem(@NonNull OsmandSettings settings, + @NonNull List quickActions) { + super(SettingsItemType.QUICK_ACTION, settings); + this.quickActions = quickActions; + } + + public QuickActionSettingsItem(@NonNull OsmandSettings settings, + @NonNull JSONObject jsonObject) throws JSONException { + super(SettingsItemType.QUICK_ACTION, settings, jsonObject); + readFromJson(jsonObject); + } + + public List getQuickActions() { + return quickActions; + } + + @NonNull + @Override + public String getName() { + return "quick_actions"; + } + + @NonNull + @Override + public String getPublicName(@NonNull Context ctx) { + return null; + } + + @NonNull + @Override + public String getFileName() { + return getName() + ".json"; + } + + @NonNull + @Override + SettingsItemReader getReader() { + return new OsmandSettingsItemReader(this, getSettings()) { + + @Override + protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + + } + + @Override + public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + StringBuilder buf = new StringBuilder(); + try { + BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String str; + while ((str = in.readLine()) != null) { + buf.append(str); + } + } catch (IOException e) { + throw new IOException("Cannot read json body", e); + } + String jsonStr = buf.toString(); + if (Algorithms.isEmpty(jsonStr)) { + throw new IllegalArgumentException("Cannot find json body"); + } + final JSONObject json; + String itemsString; + try { + json = new JSONObject(jsonStr); + itemsString = json.getString("items"); + getSettings().QUICK_ACTION_LIST.set(itemsString); + QuickActionFactory factory = new QuickActionFactory(); + quickActions = factory.parseActiveActionsList(itemsString); + } catch (JSONException e) { + throw new IllegalArgumentException("Json parse error", e); + } + } + }; + } + + @NonNull + @Override + SettingsItemWriter getWriter() { + return new OsmandSettingsItemWriter(this, getSettings()) { + @Override + protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + QuickActionFactory factory = new QuickActionFactory(); + json.put("items", new JSONArray(factory.quickActionListToString(quickActions))); + } + }; + } + } + private static class SettingsItemsFactory { private OsmandApplication app; @@ -749,6 +856,9 @@ public class SettingsHelper { case FILE: item = new FileSettingsItem(app, json); break; + case QUICK_ACTION: + item = new QuickActionSettingsItem(settings, json); + break; } return item; } diff --git a/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java new file mode 100644 index 0000000000..a4358828ac --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java @@ -0,0 +1,35 @@ +package net.osmand.plus.profiles; + +import java.util.List; + +public class AdditionalDataWrapper { + + private Type type; + + private List items; + + public AdditionalDataWrapper(Type type, List items) { + this.type = type; + this.items = items; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public List getItems() { + return items; + } + + public enum Type { + QUICK_ACTIONS, + POI_TYPES, + MAP_SOURCES, + CUSTOM_RENDER_STYLE, + ROUTING + } +} diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java new file mode 100644 index 0000000000..0d5d3ab0a9 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -0,0 +1,567 @@ +package net.osmand.plus.profiles; + +import android.content.Context; +import android.content.Intent; +import android.content.res.ColorStateList; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.content.ContextCompat; +import android.support.v4.widget.CompoundButtonCompat; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.ExpandableListView; +import android.widget.ImageView; +import android.widget.Switch; +import android.widget.TextView; +import android.widget.Toast; + +import net.osmand.AndroidUtils; +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.SettingsHelper; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.quickaction.QuickAction; +import net.osmand.plus.quickaction.QuickActionFactory; +import net.osmand.plus.render.RenderingIcons; +import net.osmand.plus.settings.BaseSettingsFragment; +import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet; + +import org.apache.commons.logging.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { + + private static final Log LOG = PlatformUtil.getLog(ExportImportProfileBottomSheet.class); + + public static final String TAG = ExportImportProfileBottomSheet.class.getSimpleName(); + + private static final String STATE_KEY = "EXPORT_IMPORT_DIALOG_STATE_KEY"; + + private OsmandApplication app; + + private Context context; + + private OsmandSettings settings; + + private ApplicationMode profile; + + private boolean includeAdditionalData = false; + + private State state; + + private List dataList; + + private ExpandableListView listView; + + private ProfileAdditionalDataAdapter adapter; + + private List dataToOperate = new ArrayList<>(); + + private List settingsItems; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + app = requiredMyApplication(); + context = requireContext(); + settings = app.getSettings(); + Bundle bundle = getArguments(); + if (bundle != null) { + this.state = (State) getArguments().getSerializable(STATE_KEY); + } + + dataList = state == State.IMPORT ? getDataFromSettingsItems() : getAdditionalData(); + for (AdditionalDataWrapper dataWrapper : dataList) { + dataToOperate.addAll(dataWrapper.getItems()); + } + } + + + private ApplicationMode getAppModeFromItems() { + for (SettingsHelper.SettingsItem item : settingsItems) { + if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { + return ((SettingsHelper.ProfileSettingsItem) item).getAppMode(); + } + } + return getAppMode(); + } + + @Override + public void createMenuItems(Bundle savedInstanceState) { + final Context context = getContext(); + if (context == null) { + return; + } + + profile = state == State.IMPORT ? getAppModeFromItems() : getAppMode(); + + int profileColor = profile.getIconColorInfo().getColor(nightMode); + int colorNoAlpha = ContextCompat.getColor(context, profileColor); + + Drawable backgroundIcon = UiUtilities.getColoredSelectableDrawable(context, colorNoAlpha, 0.3f); + Drawable[] layers = {new ColorDrawable(UiUtilities.getColorWithAlpha(colorNoAlpha, 0.10f)), backgroundIcon}; + + items.add(new TitleItem(state == State.EXPORT ? + getString(R.string.export_profile) + : getString(R.string.import_profile))); + + BaseBottomSheetItem profileItem = new BottomSheetItemWithCompoundButton.Builder() + .setChecked(true) + .setCompoundButtonColorId(profileColor) + .setButtonTintList(ColorStateList.valueOf(getResolvedColor(profileColor))) + .setDescription(BaseSettingsFragment.getAppModeDescription(context, profile)) + .setIcon(getIcon(profile.getIconRes(), profileColor)) + .setTitle(profile.toHumanString(context)) + .setBackground(new LayerDrawable(layers)) + .setLayoutId(R.layout.preference_profile_item_with_radio_btn) + .create(); + items.add(profileItem); + + BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder() + .setDescription(state == State.EXPORT ? + getString(R.string.export_profile_dialog_description) + : getString(R.string.import_profile_dialog_description)) + .setLayoutId(R.layout.bottom_sheet_item_pref_info) + .create(); + items.add(descriptionItem); + + final View additionalDataView = View.inflate(new ContextThemeWrapper(context, themeRes), + R.layout.bottom_sheet_item_additional_data, null); + listView = additionalDataView.findViewById(R.id.list); + Switch switchItem = additionalDataView.findViewById(R.id.switchItem); + switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); + + switchItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + includeAdditionalData = !includeAdditionalData; + listView.setVisibility(includeAdditionalData ? + View.VISIBLE : View.GONE); + } + }); + adapter = new ProfileAdditionalDataAdapter(requiredMyApplication(), dataList, profileColor); + listView.setAdapter(adapter); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(additionalDataView) + .create(); + items.add(titleItem); + } + + private List getDataFromSettingsItems() { + List dataList = new ArrayList<>(); + + List quickActions = new ArrayList<>(); + for (SettingsHelper.SettingsItem item : settingsItems) { + if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) { + quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); + } + } + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, + quickActions)); + + return dataList; + } + + private List getAdditionalData() { + List dataList = new ArrayList<>(); + + QuickActionFactory factory = new QuickActionFactory(); + List quickActions = factory.parseActiveActionsList(settings.QUICK_ACTION_LIST.get()); + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, quickActions)); + + List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.POI_TYPES, + poiList + )); + + final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries()); + List mapSourceWrapperList = new ArrayList<>(); + for (Map.Entry entry : entriesMap.entrySet()) { + mapSourceWrapperList.add(new MapSourceWrapper(entry.getKey(), entry.getValue())); + } + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.MAP_SOURCES, + mapSourceWrapperList + )); + + return dataList; + } + + public void setSettingsItems(List settingsItems) { + this.settingsItems = settingsItems; + } + + @Override + protected int getRightBottomButtonTextId() { + return state == State.EXPORT ? R.string.shared_string_export : R.string.shared_string_import; + } + + @Override + protected void onRightBottomButtonClick() { + super.onRightBottomButtonClick(); + prepareFile(); +// if (state == State.EXPORT) { +// if (includeAdditionalData) { +// prepareFileWithAdditional(); +// } else { +// prepareFile(); +// } +// } else { +// +// } + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_cancel; + } + + @Override + protected boolean useScrollableItemsContainer() { + return false; + } + + private List prepareSettingsItems() { + List settingsItems = new ArrayList<>(); + settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile)); + + if (includeAdditionalData) { + List quickActions = new ArrayList<>(); + List poiUIFilters = new ArrayList<>(); + List mapSourceWrappers = new ArrayList<>(); + for (Object object : dataToOperate) { + if (object instanceof QuickAction) { + quickActions.add((QuickAction) object); + } else if (object instanceof PoiUIFilter) { + poiUIFilters.add((PoiUIFilter) object); + } else if (object instanceof MapSourceWrapper) { + mapSourceWrappers.add((MapSourceWrapper) object); + } + } + if (!quickActions.isEmpty()) { + settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app.getSettings(), quickActions)); + } +// if (!poiUIFilters.isEmpty()) { +// settingsItems.add(); +// } +// if (!mapSourceWrappers.isEmpty()) { +// settingsItems.add(); +// } + } + return settingsItems; + } + + private void prepareFile() { + if (app != null) { + File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); + if (!tempDir.exists()) { + tempDir.mkdirs(); + } + String fileName = profile.toHumanString(context); + app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() { + @Override + public void onSettingsExportFinished(@NonNull File file, boolean succeed) { + if (succeed) { + shareProfile(file, profile); + } else { + app.showToastMessage(R.string.export_profile_failed); + } + } + }, prepareSettingsItems()); + } + } + + private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) { + try { + Context ctx = requireContext(); + final Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString(ctx))); + sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file)); + sendIntent.setType("*/*"); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivity(sendIntent); + dismiss(); + } catch (Exception e) { + Toast.makeText(context, R.string.export_profile_failed, Toast.LENGTH_SHORT).show(); + LOG.error("Share profile error", e); + } + } + + public static boolean showInstance(@NonNull FragmentManager fragmentManager, + State state, + Fragment target, + @NonNull ApplicationMode appMode) { + try { + Bundle bundle = new Bundle(); + bundle.putSerializable(STATE_KEY, state); + ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); + fragment.setArguments(bundle); + fragment.setAppMode(appMode); + fragment.setTargetFragment(target, 0); + fragment.show(fragmentManager, TAG); + return true; + } catch (RuntimeException e) { + return false; + } + } + + public static boolean showInstance(@NonNull FragmentManager fragmentManager, + State state, + List items) { + try { + Bundle bundle = new Bundle(); + bundle.putSerializable(STATE_KEY, state); + ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); + fragment.setArguments(bundle); + fragment.setSettingsItems(items); + fragment.show(fragmentManager, TAG); + return true; + } catch (RuntimeException e) { + return false; + } + } + + public enum State { + EXPORT, + IMPORT + } + + boolean isContainsInDataToOperate(AdditionalDataWrapper.Type type, Object object) { + return dataToOperate.contains(object); + +// for (AdditionalDataWrapper data : dataList) { +// if (data.getType() == type) { +// return data.getItems().contains(object); +// } +// } +// return false; + } + + class ProfileAdditionalDataAdapter extends OsmandBaseExpandableListAdapter { + + private OsmandApplication app; + + private List list; + + private int profileColor; + + + ProfileAdditionalDataAdapter(OsmandApplication app, List list, int profileColor) { + this.app = app; + this.list = list; + this.profileColor = profileColor; + } + + @Override + public int getGroupCount() { + return list.size(); + } + + @Override + public int getChildrenCount(int i) { + return list.get(i).getItems().size(); + } + + @Override + public Object getGroup(int i) { + return list.get(i); + } + + @Override + public Object getChild(int groupPosition, int childPosition) { + return list.get(groupPosition).getItems().get(childPosition); + } + + @Override + public long getGroupId(int i) { + return i; + } + + @Override + public long getChildId(int groupPosition, int childPosition) { + return groupPosition * 10000 + childPosition; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { + View group = convertView; + if (group == null) { + LayoutInflater inflater = (LayoutInflater) app.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false); + } + + + boolean isLastGroup = groupPosition == getGroupCount() - 1; + final AdditionalDataWrapper.Type type = list.get(groupPosition).getType(); + + TextView titleTv = group.findViewById(R.id.title_tv); + TextView subTextTv = group.findViewById(R.id.sub_text_tv); + final CheckBox checkBox = group.findViewById(R.id.check_box); + ImageView expandIv = group.findViewById(R.id.explist_indicator); + View divider = group.findViewById(R.id.divider); + + titleTv.setText(getGroupTitle(type)); + divider.setVisibility(isExpanded || isLastGroup ? View.GONE : View.VISIBLE); + CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor))); + + final List listItems = list.get(groupPosition).getItems(); + subTextTv.setText(String.valueOf(listItems.size())); + + checkBox.setChecked(dataToOperate.containsAll(listItems)); + checkBox.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + if (checkBox.isChecked()) { + for (Object object : listItems) { + if (!isContainsInDataToOperate(type, object)) { + dataToOperate.add(object); + } + } + } else { + dataToOperate.removeAll(listItems); + } + notifyDataSetInvalidated(); + } + }); + + adjustIndicator(app, groupPosition, isExpanded, group, true); + + return group; + } + + @Override + public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { + View child = convertView; + if (child == null) { + LayoutInflater inflater = (LayoutInflater) app.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + child = inflater.inflate(R.layout.profile_data_list_item_child, parent, false); + } + final Object currentItem = list.get(groupPosition).getItems().get(childPosition); + + + boolean isLastGroup = groupPosition == getGroupCount() - 1; + final AdditionalDataWrapper.Type type = list.get(groupPosition).getType(); + + TextView title = child.findViewById(R.id.title_tv); + final CheckBox checkBox = child.findViewById(R.id.check_box); + ImageView icon = child.findViewById(R.id.icon); + View divider = child.findViewById(R.id.divider); + + divider.setVisibility(isLastChild && !isLastGroup ? View.VISIBLE : View.GONE); + CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor))); + + checkBox.setChecked(isContainsInDataToOperate(type, currentItem)); + checkBox.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (checkBox.isChecked()) { + dataToOperate.add(currentItem); + } else { + dataToOperate.remove(currentItem); + } + } + }); + + switch (type) { + case QUICK_ACTIONS: + title.setText(((QuickAction) currentItem).getName(app.getApplicationContext())); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; + case POI_TYPES: + title.setText(((PoiUIFilter) currentItem).getName()); + icon.setVisibility(View.VISIBLE); + int iconRes = RenderingIcons.getBigIconResourceId(((PoiUIFilter) currentItem).getIconId()); + icon.setImageDrawable(app.getUIUtilities().getIcon(iconRes != 0 ? iconRes : R.drawable.ic_person, profileColor)); + break; + case MAP_SOURCES: + title.setText(((MapSourceWrapper) currentItem).getName()); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; + default: + return child; + } + return child; + } + + @Override + public boolean isChildSelectable(int i, int i1) { + return false; + } + + private int getGroupTitle(AdditionalDataWrapper.Type type) { + switch (type) { + case QUICK_ACTIONS: + return R.string.configure_screen_quick_action; + case POI_TYPES: + return R.string.poi_dialog_poi_type; + case MAP_SOURCES: + return R.string.quick_action_map_source_title; + case CUSTOM_RENDER_STYLE: + return R.string.shared_string_custom_rendering_style; + case ROUTING: + return R.string.shared_string_routing; + default: + return R.string.access_empty_list; + } + } + } + + class MapSourceWrapper { + private String name; + private String url; + + MapSourceWrapper(String name, String url) { + this.name = name; + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java b/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java index ea40709d09..fad8ef9748 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java @@ -40,6 +40,7 @@ import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.FontCache; import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin; +import net.osmand.plus.profiles.ExportImportProfileBottomSheet; import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet; import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet; import net.osmand.plus.skimapsplugin.SkiMapsPlugin; @@ -288,22 +289,6 @@ public class ConfigureProfileFragment extends BaseSettingsFragment { isNightMode() ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); } - private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) { - try { - Context ctx = requireContext(); - final Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString(ctx))); - sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file)); - sendIntent.setType("*/*"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(sendIntent); - } catch (Exception e) { - app.showToastMessage(R.string.export_profile_failed); - LOG.error("Share profile error", e); - } - } - private void setupOsmandPluginsPref(PreferenceCategory preferenceCategory) { Context ctx = getContext(); if (ctx == null) { @@ -362,23 +347,14 @@ public class ConfigureProfileFragment extends BaseSettingsFragment { ResetProfilePrefsBottomSheet.showInstance(fragmentManager, prefId, this, false, getSelectedAppMode()); } } else if (EXPORT_PROFILE.equals(prefId)) { - Context ctx = requireContext(); - final ApplicationMode profile = getSelectedAppMode(); - File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); - if (!tempDir.exists()) { - tempDir.mkdirs(); + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager != null) { + ExportImportProfileBottomSheet.showInstance( + fragmentManager, + ExportImportProfileBottomSheet.State.EXPORT, + this, + getSelectedAppMode()); } - String fileName = profile.toHumanString(ctx); - app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() { - @Override - public void onSettingsExportFinished(@NonNull File file, boolean succeed) { - if (succeed) { - shareProfile(file, profile); - } else { - app.showToastMessage(R.string.export_profile_failed); - } - } - }, new ProfileSettingsItem(app.getSettings(), profile)); } else if (DELETE_PROFILE.equals(prefId)) { onDeleteProfileClick(); } From 224cc71ce7aef787c432ad1989a0d2711c715626 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Mon, 27 Jan 2020 19:05:49 +0200 Subject: [PATCH 02/42] wip --- OsmAnd/res/values/strings.xml | 5 + .../src/net/osmand/plus/SettingsHelper.java | 329 +++++++++++++++++- .../net/osmand/plus/helpers/ImportHelper.java | 48 ++- .../ExportImportProfileBottomSheet.java | 190 ++++++---- .../osmand/plus/quickaction/QuickAction.java | 2 +- 5 files changed, 475 insertions(+), 99 deletions(-) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 8635f82a6e..98583c2738 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,11 @@ Thx - Hardy --> + Routing + Custom rendering style + Include additional data + The imported profile contains additional data. Click Import to import only profile data or select additional data to import. + You can select additional data to export along with the profile. Permission is required to use this option. Check and share detailed logs of the application No routing rules in \'%1$s\'. Please choose another file. diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 5855d98941..9500f1d757 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -7,19 +7,12 @@ import android.content.DialogInterface; import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import net.osmand.PlatformUtil; import net.osmand.plus.ApplicationMode.ApplicationModeBuilder; import net.osmand.plus.OsmandSettings.OsmandPreference; import net.osmand.plus.poi.PoiUIFilter; -import net.osmand.plus.profiles.AdditionalDataWrapper; -import net.osmand.plus.profiles.ExportImportProfileBottomSheet; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.quickaction.QuickActionFactory; import net.osmand.util.Algorithms; @@ -100,6 +93,10 @@ public class SettingsHelper { void onSettingsExportFinished(@NonNull File file, boolean succeed); } + public interface SettingsImportPrepareListener { + void onSettingsPrepared(boolean succeed, boolean empty, @NonNull List items); + } + public SettingsHelper(OsmandApplication app) { this.app = app; } @@ -135,7 +132,9 @@ public class SettingsHelper { PLUGIN, DATA, FILE, - QUICK_ACTION + QUICK_ACTION_LIST, + POI_UI_FILTERS_LIST, + MAP_SOURCES_LIST, } public abstract static class SettingsItem { @@ -712,15 +711,18 @@ public class SettingsHelper { private List quickActions; - public QuickActionSettingsItem(@NonNull OsmandSettings settings, + private OsmandApplication app; + + public QuickActionSettingsItem(@NonNull OsmandApplication app, @NonNull List quickActions) { - super(SettingsItemType.QUICK_ACTION, settings); + super(SettingsItemType.QUICK_ACTION_LIST, app.getSettings()); + this.app = app; this.quickActions = quickActions; } public QuickActionSettingsItem(@NonNull OsmandSettings settings, @NonNull JSONObject jsonObject) throws JSONException { - super(SettingsItemType.QUICK_ACTION, settings, jsonObject); + super(SettingsItemType.QUICK_ACTION_LIST, settings, jsonObject); readFromJson(jsonObject); } @@ -728,6 +730,25 @@ public class SettingsHelper { return quickActions; } +// void readFromJson(JSONObject jsonObject) { +// try { +// JSONArray jsonArray = jsonObject.getJSONArray(""); +// +// } catch (JSONException e) { +// +// } +// } + + @Override + public void apply() { + if (quickActions.isEmpty()) { + QuickActionFactory factory = new QuickActionFactory(); + List quickActionsList = factory.parseActiveActionsList(getSettings().QUICK_ACTION_LIST.get()); + quickActionsList.addAll(quickActions); + getSettings().QUICK_ACTION_LIST.set(factory.quickActionListToString(quickActionsList)); + } + } + @NonNull @Override public String getName() { @@ -746,6 +767,16 @@ public class SettingsHelper { return getName() + ".json"; } + @Override + void writeToJson(@NonNull JSONObject json) throws JSONException { + super.writeToJson(json); +// JSONArray jsonArray = new JSONArray(); +// for (QuickAction quickAction : quickActions) { +// jsonArray.put(quickAction.getName(app)); +// } +// json.put("name_list", jsonArray); + } + @NonNull @Override SettingsItemReader getReader() { @@ -773,13 +804,22 @@ public class SettingsHelper { throw new IllegalArgumentException("Cannot find json body"); } final JSONObject json; - String itemsString; try { + quickActions = new ArrayList<>(); json = new JSONObject(jsonStr); - itemsString = json.getString("items"); - getSettings().QUICK_ACTION_LIST.set(itemsString); - QuickActionFactory factory = new QuickActionFactory(); - quickActions = factory.parseActiveActionsList(itemsString); + JSONArray items = json.getJSONArray("items"); + for (int i = 0; i < items.length(); i++) { + JSONObject object = items.getJSONObject(i); + String name = object.getString("name"); + int type = object.getInt("type"); + QuickAction quickAction = new QuickAction(type); + quickAction.setName(name); + quickActions.add(quickAction); + } +// QuickActionFactory factory = new QuickActionFactory(); +// List quickActionsList = factory.parseActiveActionsList(getSettings().QUICK_ACTION_LIST.get()); +// quickActionsList.addAll(quickActions); +// getSettings().QUICK_ACTION_LIST.set(factory.quickActionListToString(quickActionsList)); } catch (JSONException e) { throw new IllegalArgumentException("Json parse error", e); } @@ -793,8 +833,82 @@ public class SettingsHelper { return new OsmandSettingsItemWriter(this, getSettings()) { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { - QuickActionFactory factory = new QuickActionFactory(); - json.put("items", new JSONArray(factory.quickActionListToString(quickActions))); + JSONArray items = new JSONArray(); + if (!quickActions.isEmpty()) { + for (QuickAction action : quickActions) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("name", action.getName(app)); + jsonObject.put("params", action.getParams()); + jsonObject.put("type", action.getType()); + items.put(jsonObject); + } + json.put("items", items); + } + } + }; + } + } + + public static class PoiUiFilterSettingsItem extends OsmandSettingsItem { + + private List poiUIFilters; + + public PoiUiFilterSettingsItem(OsmandSettings settings, List poiUIFilters) { + super(SettingsItemType.POI_UI_FILTERS_LIST, settings); + this.poiUIFilters = poiUIFilters; + } + + public PoiUiFilterSettingsItem(OsmandSettings settings, JSONObject jsonObject) throws JSONException { + super(SettingsItemType.POI_UI_FILTERS_LIST, settings, jsonObject); + readFromJson(jsonObject); + } + + @NonNull + @Override + public String getName() { + return "poi_ui_filters"; + } + + @NonNull + @Override + public String getPublicName(@NonNull Context ctx) { + return null; + } + + @NonNull + @Override + public String getFileName() { + return getName() + ".json"; + } + + @NonNull + @Override + SettingsItemReader getReader() { + return new OsmandSettingsItemReader(this, getSettings()) { + @Override + protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + + } + }; + } + + @NonNull + @Override + SettingsItemWriter getWriter() { + return new OsmandSettingsItemWriter(this, getSettings()) { + @Override + protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + JSONArray items = new JSONArray(); + if (!poiUIFilters.isEmpty()) { + for (PoiUIFilter filter : poiUIFilters) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("name", filter.getName()); + jsonObject.put("filterId", filter.getFilterId()); + jsonObject.put("acceptedTypes", filter.getAcceptedTypes()); + items.put(jsonObject); + } + json.put("items", items); + } } }; } @@ -856,9 +970,15 @@ public class SettingsHelper { case FILE: item = new FileSettingsItem(app, json); break; - case QUICK_ACTION: + case QUICK_ACTION_LIST: item = new QuickActionSettingsItem(settings, json); break; + case POI_UI_FILTERS_LIST: + item = new PoiUiFilterSettingsItem(settings, json); + break; +// case MAP_SOURCES_LIST: +// item = new +// break; } return item; } @@ -998,6 +1118,164 @@ public class SettingsHelper { } } + @SuppressLint("StaticFieldLeak") + public class PrepareImportFileAsyncTask extends AsyncTask> { + + private File file; + private SettingsImportPrepareListener listener; + private SettingsImporter importer; + + PrepareImportFileAsyncTask(@NonNull File settingsFile, @Nullable SettingsImportPrepareListener listener) { + this.file = settingsFile; + this.listener = listener; + importer = new SettingsImporter(app); + } + + @Override + protected List doInBackground(Void... voids) { + try { + return importer.collectItems(file); + } catch (IllegalArgumentException e) { + LOG.error("Failed to collect items from: " + file.getName(), e); + } catch (IOException e) { + LOG.error("Failed to collect items from: " + file.getName(), e); + } + return null; + } + + @Override + protected void onPostExecute(List settingsItems) { + super.onPostExecute(settingsItems); + if (settingsItems != null && settingsItems.size() > 0) { + listener.onSettingsPrepared(true, false, settingsItems); + } + } + } + + @SuppressLint("StaticFieldLeak") + private class ImportSettingsTask extends AsyncTask { + + private File file; + private String latestChanges; + private int version; + + private SettingsImportListener listener; + private SettingsImporter importer; + private List items; + private List processedItems = new ArrayList<>(); + private SettingsItem currentItem; + private AlertDialog dialog; + + ImportSettingsTask(List items, File file, SettingsImportListener listener) { + this.items = items; + this.file = file; + importer = new SettingsImporter(app); + this.listener = listener; + } + + @Override + protected Void doInBackground(Void... voids) { + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + processNextItem(); + } + + private void processNextItem() { + if (activity == null) { + return; + } + if (items.size() == 0 && !importSuspended) { + if (processedItems.size() > 0) { + new ImportItemsAsyncTask(file, listener, processedItems).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + finishImport(listener, false, true, items); + } + return; + } + final SettingsItem item; + if (importSuspended && currentItem != null) { + item = currentItem; + } else if (items.size() > 0) { + item = items.remove(0); + currentItem = item; + } else { + item = null; + } + importSuspended = false; + if (item != null) { + if (item.exists()) { + switch (item.getType()) { + case PROFILE: { + String title = activity.getString(R.string.overwrite_profile_q, item.getPublicName(app)); + dialog = showConfirmDialog(item, title, latestChanges); + break; + } + case FILE: + // overwrite now + acceptItem(item); + break; + default: + acceptItem(item); + break; + } + } else { + if (item.getType() == SettingsItemType.PROFILE) { + String title = activity.getString(R.string.add_new_profile_q, item.getPublicName(app)); + dialog = showConfirmDialog(item, title, latestChanges); + } else { + acceptItem(item); + } + } + } else { + processNextItem(); + } + } + + private AlertDialog showConfirmDialog(final SettingsItem item, String title, String message) { + AlertDialog.Builder b = new AlertDialog.Builder(activity); + b.setTitle(title); + b.setMessage(message); + b.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + acceptItem(item); + } + }); + b.setNegativeButton(R.string.shared_string_no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + processNextItem(); + } + }); + b.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + ImportSettingsTask.this.dialog = null; + } + }); + b.setCancelable(false); + return b.show(); + } + + private void suspendImport() { + if (dialog != null) { + dialog.dismiss(); + dialog = null; + } + } + + private void acceptItem(SettingsItem item) { +// item.apply(); + processedItems.add(item); + processNextItem(); + } + + + } + @SuppressLint("StaticFieldLeak") private class ImportAsyncTask extends AsyncTask> { @@ -1184,6 +1462,11 @@ public class SettingsHelper { if (listener != null) { listener.onSettingsImportFinished(success, empty, items); } + if (success) { + app.showShortToastMessage(app.getString(R.string.file_imported_successfully, "")); + } else if (!empty) { + app.showShortToastMessage(app.getString(R.string.file_import_error, "", app.getString(R.string.shared_string_unexpected_error))); + } } @SuppressLint("StaticFieldLeak") @@ -1240,4 +1523,12 @@ public class SettingsHelper { @NonNull SettingsItem... items) { exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items))); } + + public void prepareSettings(@NonNull File settingsFile, @Nullable SettingsImportPrepareListener listener) { + new PrepareImportFileAsyncTask(settingsFile, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + public void importSettings(List items, File file, SettingsImportListener listener) { + new ImportSettingsTask(items, file, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } } diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index 44adb57ca9..ba7038ebfd 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -15,6 +15,7 @@ import android.provider.OpenableColumns; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.text.style.ForegroundColorSpan; @@ -33,6 +34,7 @@ import net.osmand.data.FavouritePoint; import net.osmand.plus.AppInitializer; import net.osmand.plus.AppInitializer.AppInitializeListener; import net.osmand.plus.AppInitializer.InitEvents; +import net.osmand.plus.ApplicationMode; import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.GPXDatabase; import net.osmand.plus.OsmandApplication; @@ -49,6 +51,9 @@ import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.ShortDescriptionItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.profiles.AdditionalDataWrapper; +import net.osmand.plus.profiles.ExportImportProfileBottomSheet; +import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.router.RoutingConfiguration; @@ -769,24 +774,43 @@ public class ImportHelper { @Override protected void onPostExecute(String error) { File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); - File file = new File(tempDir, name); + final File file = new File(tempDir, name); if (error == null && file.exists()) { - app.getSettingsHelper().importSettings(file, latestChanges, version, new SettingsImportListener() { + app.getSettingsHelper().prepareSettings(file, new SettingsHelper.SettingsImportPrepareListener() { @Override - public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { - if (isActivityNotDestroyed(activity)) { - progress.dismiss(); - } - if (succeed) { - app.showShortToastMessage(app.getString(R.string.file_imported_successfully, name)); - if (callback != null) { - callback.processResult(items); + public void onSettingsPrepared(boolean succeed, boolean empty, @NonNull List items) { + progress.dismiss(); + if (succeed && !empty) { + FragmentManager fragmentManager = activity.getSupportFragmentManager(); + if (fragmentManager != null) { + ExportImportProfileBottomSheet.showInstance( + fragmentManager, + ExportImportProfileBottomSheet.State.IMPORT, + file, + items); } - } else if (!empty) { - app.showShortToastMessage(app.getString(R.string.file_import_error, name, app.getString(R.string.shared_string_unexpected_error))); + } else { + app.showShortToastMessage(app.getString(R.string.file_import_error, name, "")); } } }); + +// app.getSettingsHelper().importSettings(file, latestChanges, version, new SettingsImportListener() { +// @Override +// public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { +// if (isActivityNotDestroyed(activity)) { +// progress.dismiss(); +// } +// if (succeed) { +// app.showShortToastMessage(app.getString(R.string.file_imported_successfully, name)); +// if (callback != null) { +// callback.processResult(items); +// } +// } else if (!empty) { +// app.showShortToastMessage(app.getString(R.string.file_import_error, name, app.getString(R.string.shared_string_unexpected_error))); +// } +// } +// }); } else { if (isActivityNotDestroyed(activity)) { progress.dismiss(); diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index 0d5d3ab0a9..f476044d2c 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -70,10 +70,11 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private ApplicationMode profile; private boolean includeAdditionalData = false; + private boolean containsAdditionalData = false; private State state; - private List dataList; + private List dataList = new ArrayList<>(); private ExpandableListView listView; @@ -83,6 +84,8 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private List settingsItems; + private File file; + @Override public void onCreate(Bundle savedInstanceState) { @@ -94,14 +97,17 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { if (bundle != null) { this.state = (State) getArguments().getSerializable(STATE_KEY); } - - dataList = state == State.IMPORT ? getDataFromSettingsItems() : getAdditionalData(); - for (AdditionalDataWrapper dataWrapper : dataList) { - dataToOperate.addAll(dataWrapper.getItems()); + if (state == State.IMPORT) { + containsAdditionalData = checkAdditionalDataContains(); + } else { + dataList = getAdditionalData(); + for (AdditionalDataWrapper dataWrapper : dataList) { + dataToOperate.addAll(dataWrapper.getItems()); + } } +// dataList = state == State.IMPORT ? getDataFromSettingsItems() : getAdditionalData(); } - private ApplicationMode getAppModeFromItems() { for (SettingsHelper.SettingsItem item : settingsItems) { if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { @@ -142,50 +148,79 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { .create(); items.add(profileItem); - BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder() - .setDescription(state == State.EXPORT ? - getString(R.string.export_profile_dialog_description) - : getString(R.string.import_profile_dialog_description)) - .setLayoutId(R.layout.bottom_sheet_item_pref_info) - .create(); - items.add(descriptionItem); + if (state == State.IMPORT && containsAdditionalData || state == State.EXPORT && !dataList.isEmpty()) { + BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder() + .setDescription(state == State.EXPORT ? + getString(R.string.export_profile_dialog_description) + : getString(R.string.import_profile_dialog_description)) + .setLayoutId(R.layout.bottom_sheet_item_pref_info) + .create(); + items.add(descriptionItem); - final View additionalDataView = View.inflate(new ContextThemeWrapper(context, themeRes), - R.layout.bottom_sheet_item_additional_data, null); - listView = additionalDataView.findViewById(R.id.list); - Switch switchItem = additionalDataView.findViewById(R.id.switchItem); - switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); + final View additionalDataView = View.inflate(new ContextThemeWrapper(context, themeRes), + R.layout.bottom_sheet_item_additional_data, null); + listView = additionalDataView.findViewById(R.id.list); + Switch switchItem = additionalDataView.findViewById(R.id.switchItem); + switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); - switchItem.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - includeAdditionalData = !includeAdditionalData; - listView.setVisibility(includeAdditionalData ? - View.VISIBLE : View.GONE); - } - }); - adapter = new ProfileAdditionalDataAdapter(requiredMyApplication(), dataList, profileColor); - listView.setAdapter(adapter); - final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() - .setCustomView(additionalDataView) - .create(); - items.add(titleItem); + switchItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + includeAdditionalData = !includeAdditionalData; + listView.setVisibility(includeAdditionalData ? + View.VISIBLE : View.GONE); + if (includeAdditionalData && state == State.IMPORT) { + updateDataFromSettingsItems(); + } + } + }); + adapter = new ProfileAdditionalDataAdapter(requiredMyApplication(), dataList, profileColor); + listView.setAdapter(adapter); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(additionalDataView) + .create(); + items.add(titleItem); + } } - private List getDataFromSettingsItems() { - List dataList = new ArrayList<>(); - - List quickActions = new ArrayList<>(); - for (SettingsHelper.SettingsItem item : settingsItems) { - if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) { - quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); + private void updateDataFromSettingsItems() { + app.getSettingsHelper().importSettings(settingsItems, file, new SettingsHelper.SettingsImportListener() { + @Override + public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { + List dataList = new ArrayList<>(); + List quickActions = new ArrayList<>(); + List poiUIFilters = new ArrayList<>(); + for (SettingsHelper.SettingsItem item : items) { + if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST)) { + quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); + } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST)) { +// poiUIFilters.addAll() + } + } + if (!quickActions.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, + quickActions)); + } + if (!poiUIFilters.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.POI_TYPES, + poiUIFilters)); + } + adapter.updateList(dataList); } - } - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.QUICK_ACTIONS, - quickActions)); + }); - return dataList; + + } + + private Boolean checkAdditionalDataContains() { + boolean containsData = false; + for (SettingsHelper.SettingsItem item : settingsItems) { + containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST) + || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST); + } + return containsData; } private List getAdditionalData() { @@ -202,15 +237,15 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { poiList )); - final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries()); - List mapSourceWrapperList = new ArrayList<>(); - for (Map.Entry entry : entriesMap.entrySet()) { - mapSourceWrapperList.add(new MapSourceWrapper(entry.getKey(), entry.getValue())); - } - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.MAP_SOURCES, - mapSourceWrapperList - )); +// final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries()); +// List mapSourceWrapperList = new ArrayList<>(); +// for (Map.Entry entry : entriesMap.entrySet()) { +// mapSourceWrapperList.add(new MapSourceWrapper(entry.getKey(), entry.getValue())); +// } +// dataList.add(new AdditionalDataWrapper( +// AdditionalDataWrapper.Type.MAP_SOURCES, +// mapSourceWrapperList +// )); return dataList; } @@ -227,16 +262,22 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { @Override protected void onRightBottomButtonClick() { super.onRightBottomButtonClick(); - prepareFile(); -// if (state == State.EXPORT) { -// if (includeAdditionalData) { -// prepareFileWithAdditional(); -// } else { -// prepareFile(); -// } -// } else { -// -// } + if (state == State.EXPORT) { + prepareFile(); + } else { + importSettings(); + } + } + + private void importSettings() { + app.getSettingsHelper().importSettings(settingsItems, file, new SettingsHelper.SettingsImportListener() { + + @Override + public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { + + } + }); + dismiss(); } @Override @@ -267,11 +308,11 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } if (!quickActions.isEmpty()) { - settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app.getSettings(), quickActions)); + settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); + } + if (!poiUIFilters.isEmpty()) { + settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app.getSettings(), poiUIFilters)); } -// if (!poiUIFilters.isEmpty()) { -// settingsItems.add(); -// } // if (!mapSourceWrappers.isEmpty()) { // settingsItems.add(); // } @@ -336,6 +377,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { public static boolean showInstance(@NonNull FragmentManager fragmentManager, State state, + File file, List items) { try { Bundle bundle = new Bundle(); @@ -343,6 +385,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); fragment.setArguments(bundle); fragment.setSettingsItems(items); + fragment.setFile(file); fragment.show(fragmentManager, TAG); return true; } catch (RuntimeException e) { @@ -350,6 +393,14 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + public enum State { EXPORT, IMPORT @@ -381,6 +432,11 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { this.profileColor = profileColor; } + public void updateList(List list) { + this.list = list; + notifyDataSetChanged(); + } + @Override public int getGroupCount() { return list.size(); diff --git a/OsmAnd/src/net/osmand/plus/quickaction/QuickAction.java b/OsmAnd/src/net/osmand/plus/quickaction/QuickAction.java index 220cde20cf..ccde8f0dee 100644 --- a/OsmAnd/src/net/osmand/plus/quickaction/QuickAction.java +++ b/OsmAnd/src/net/osmand/plus/quickaction/QuickAction.java @@ -41,7 +41,7 @@ public class QuickAction { this.type = type; } - protected QuickAction(int type) { + public QuickAction(int type) { this.id = System.currentTimeMillis(); this.type = type; this.nameRes = QuickActionFactory.getActionName(type); From 8294a0f08b550e56ca041c34a52d3f7442c21b2b Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Tue, 28 Jan 2020 16:05:30 +0200 Subject: [PATCH 03/42] wip --- .../layout/profile_data_list_item_child.xml | 5 +- .../layout/profile_data_list_item_group.xml | 8 +- .../src/net/osmand/plus/SettingsHelper.java | 134 +++++++++++++++--- .../ExportImportProfileBottomSheet.java | 125 +++++++++------- 4 files changed, 194 insertions(+), 78 deletions(-) diff --git a/OsmAnd/res/layout/profile_data_list_item_child.xml b/OsmAnd/res/layout/profile_data_list_item_child.xml index 4b8ad4c01b..eb9b1705d0 100644 --- a/OsmAnd/res/layout/profile_data_list_item_child.xml +++ b/OsmAnd/res/layout/profile_data_list_item_child.xml @@ -22,8 +22,7 @@ @@ -42,7 +41,7 @@ android:id="@+id/divider" android:layout_width="match_parent" android:layout_height="1dp" - android:background="?attr/divider_color" + android:background="?attr/divider_color_basic" android:visibility="gone" tools:visibility="visible" /> diff --git a/OsmAnd/res/layout/profile_data_list_item_group.xml b/OsmAnd/res/layout/profile_data_list_item_group.xml index 8b889bb860..e0c7ff7203 100644 --- a/OsmAnd/res/layout/profile_data_list_item_group.xml +++ b/OsmAnd/res/layout/profile_data_list_item_group.xml @@ -30,14 +30,14 @@ android:id="@+id/title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="?android:textColorPrimary" - android:textSize="@dimen/default_list_text_size" + android:textAppearance="@style/TextAppearance.ListItemCategoryTitle" tools:text="Quick actions" /> @@ -50,7 +50,7 @@ android:layout_height="match_parent" android:layout_marginTop="@dimen/content_padding" android:layout_marginBottom="@dimen/content_padding" - android:background="?attr/divider_color" /> + android:background="?attr/divider_color_basic" /> diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 9500f1d757..2272a03917 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -13,6 +13,7 @@ import net.osmand.PlatformUtil; import net.osmand.plus.ApplicationMode.ApplicationModeBuilder; import net.osmand.plus.OsmandSettings.OsmandPreference; import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.profiles.ExportImportProfileBottomSheet; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.quickaction.QuickActionFactory; import net.osmand.util.Algorithms; @@ -721,27 +722,52 @@ public class SettingsHelper { } public QuickActionSettingsItem(@NonNull OsmandSettings settings, - @NonNull JSONObject jsonObject) throws JSONException { + @NonNull JSONObject jsonObject, File file) throws JSONException { super(SettingsItemType.QUICK_ACTION_LIST, settings, jsonObject); - readFromJson(jsonObject); + try { + readFromJson(jsonObject, file); + } catch (IOException e) { + e.printStackTrace(); + } } public List getQuickActions() { return quickActions; } -// void readFromJson(JSONObject jsonObject) { -// try { -// JSONArray jsonArray = jsonObject.getJSONArray(""); -// -// } catch (JSONException e) { -// -// } -// } + void readFromJson(JSONObject jsonObject, File file) throws IllegalArgumentException, IOException, JSONException { + ZipInputStream zis = new ZipInputStream(new FileInputStream(file)); + InputStream ois = new BufferedInputStream(zis); + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null){ + if (entry.getName().equals(getFileName())) { + String itemsJson = null; + try { + itemsJson = Algorithms.readFromInputStream(ois).toString(); + } catch (IOException e) { + LOG.error("Error reading items.json: " + itemsJson, e); + throw new IllegalArgumentException("No items"); + } finally { + zis.closeEntry(); + } + quickActions = new ArrayList<>(); + JSONObject json = new JSONObject(itemsJson); + JSONArray items = json.getJSONArray("items"); + for (int i = 0; i < items.length(); i++) { + JSONObject object = items.getJSONObject(i); + String name = object.getString("name"); + int type = object.getInt("type"); + QuickAction quickAction = new QuickAction(type); + quickAction.setName(name); + quickActions.add(quickAction); + } + } + } + } @Override public void apply() { - if (quickActions.isEmpty()) { + if (!quickActions.isEmpty()) { QuickActionFactory factory = new QuickActionFactory(); List quickActionsList = factory.parseActiveActionsList(getSettings().QUICK_ACTION_LIST.get()); quickActionsList.addAll(quickActions); @@ -914,13 +940,78 @@ public class SettingsHelper { } } + public static class MapSourcesSettingsItem extends OsmandSettingsItem { + + private List mapSources; + + public MapSourcesSettingsItem(OsmandSettings settings, List mapSources) { + super(SettingsItemType.MAP_SOURCES_LIST, settings); + this.mapSources = mapSources; + } + + public MapSourcesSettingsItem(OsmandSettings settings, JSONObject jsonObject) throws JSONException { + super(SettingsItemType.MAP_SOURCES_LIST, settings, jsonObject); + } + + @NonNull + @Override + public String getName() { + return "map_sources"; + } + + @NonNull + @Override + public String getPublicName(@NonNull Context ctx) { + return null; + } + + @NonNull + @Override + public String getFileName() { + return getName() + ".json"; + } + + @NonNull + @Override + SettingsItemReader getReader() { + return new OsmandSettingsItemReader(this, getSettings()) { + @Override + protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + + } + }; + } + + @NonNull + @Override + SettingsItemWriter getWriter() { + return new OsmandSettingsItemWriter(this, getSettings()) { + @Override + protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + JSONArray items = new JSONArray(); + if (!mapSources.isEmpty()) { + for (ExportImportProfileBottomSheet.MapSourceWrapper mapSourceWrapper : mapSources) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("name", mapSourceWrapper.getName()); + jsonObject.put("url", mapSourceWrapper.getUrl()); + items.put(jsonObject); + } + json.put("items", items); + } + } + }; + } + } + private static class SettingsItemsFactory { private OsmandApplication app; private List items = new ArrayList<>(); + private File file; - SettingsItemsFactory(OsmandApplication app, String jsonStr) throws IllegalArgumentException, JSONException { + SettingsItemsFactory(OsmandApplication app, String jsonStr, File file) throws IllegalArgumentException, JSONException { this.app = app; + this.file = file; JSONObject json = new JSONObject(jsonStr); JSONArray itemsJson = json.getJSONArray("items"); for (int i = 0; i < itemsJson.length(); i++) { @@ -971,14 +1062,14 @@ public class SettingsHelper { item = new FileSettingsItem(app, json); break; case QUICK_ACTION_LIST: - item = new QuickActionSettingsItem(settings, json); + item = new QuickActionSettingsItem(settings, json, file); break; case POI_UI_FILTERS_LIST: item = new PoiUiFilterSettingsItem(settings, json); break; -// case MAP_SOURCES_LIST: -// item = new -// break; + case MAP_SOURCES_LIST: + item = new MapSourcesSettingsItem(settings, json); + break; } return item; } @@ -1079,7 +1170,7 @@ public class SettingsHelper { } SettingsItemsFactory itemsFactory; try { - itemsFactory = new SettingsItemsFactory(app, itemsJson); + itemsFactory = new SettingsItemsFactory(app, itemsJson, file); if (collecting) { items.addAll(itemsFactory.getItems()); } @@ -1462,11 +1553,6 @@ public class SettingsHelper { if (listener != null) { listener.onSettingsImportFinished(success, empty, items); } - if (success) { - app.showShortToastMessage(app.getString(R.string.file_imported_successfully, "")); - } else if (!empty) { - app.showShortToastMessage(app.getString(R.string.file_import_error, "", app.getString(R.string.shared_string_unexpected_error))); - } } @SuppressLint("StaticFieldLeak") @@ -1531,4 +1617,8 @@ public class SettingsHelper { public void importSettings(List items, File file, SettingsImportListener listener) { new ImportSettingsTask(items, file, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + +// public void preImportSettings(List items, File file, SettingsImportListener listener) { +// new ImportSettingsTask(items, file, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); +// } } diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index f476044d2c..66c252557e 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -70,6 +70,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private ApplicationMode profile; private boolean includeAdditionalData = false; + private boolean containsAdditionalData = false; private State state; @@ -86,6 +87,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private File file; + private SettingsHelper.ProfileSettingsItem profileSettingsItem; @Override public void onCreate(Bundle savedInstanceState) { @@ -111,6 +113,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private ApplicationMode getAppModeFromItems() { for (SettingsHelper.SettingsItem item : settingsItems) { if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { + profileSettingsItem = ((SettingsHelper.ProfileSettingsItem) item); return ((SettingsHelper.ProfileSettingsItem) item).getAppMode(); } } @@ -184,41 +187,49 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } private void updateDataFromSettingsItems() { - app.getSettingsHelper().importSettings(settingsItems, file, new SettingsHelper.SettingsImportListener() { - @Override - public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { - List dataList = new ArrayList<>(); - List quickActions = new ArrayList<>(); - List poiUIFilters = new ArrayList<>(); - for (SettingsHelper.SettingsItem item : items) { - if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST)) { + + List dataList = new ArrayList<>(); + List quickActions = new ArrayList<>(); + List poiUIFilters = new ArrayList<>(); + for (SettingsHelper.SettingsItem item : settingsItems) { + if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST)) { quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); - } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST)) { + } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST)) { // poiUIFilters.addAll() - } - } - if (!quickActions.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.QUICK_ACTIONS, - quickActions)); - } - if (!poiUIFilters.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.POI_TYPES, - poiUIFilters)); - } - adapter.updateList(dataList); } - }); - + } + if (!quickActions.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, + quickActions)); + } + if (!poiUIFilters.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.POI_TYPES, + poiUIFilters)); + } + for (AdditionalDataWrapper dataWrapper : dataList) { + dataToOperate.addAll(dataWrapper.getItems()); + } + adapter.updateList(dataList); +// app.getSettingsHelper().importSettings(settingsItems, file, new SettingsHelper.SettingsImportListener() { +// @Override +// public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { +// +// } +// }); } private Boolean checkAdditionalDataContains() { boolean containsData = false; for (SettingsHelper.SettingsItem item : settingsItems) { containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST) - || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST); + || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST) + || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES_LIST); + if (containsData) { + break; + } } return containsData; } @@ -228,24 +239,30 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { QuickActionFactory factory = new QuickActionFactory(); List quickActions = factory.parseActiveActionsList(settings.QUICK_ACTION_LIST.get()); - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.QUICK_ACTIONS, quickActions)); + if (!quickActions.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, quickActions)); + } List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.POI_TYPES, - poiList - )); + if (!poiList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.POI_TYPES, + poiList + )); + } -// final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries()); -// List mapSourceWrapperList = new ArrayList<>(); -// for (Map.Entry entry : entriesMap.entrySet()) { -// mapSourceWrapperList.add(new MapSourceWrapper(entry.getKey(), entry.getValue())); -// } -// dataList.add(new AdditionalDataWrapper( -// AdditionalDataWrapper.Type.MAP_SOURCES, -// mapSourceWrapperList -// )); + final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries()); + List mapSourceWrapperList = new ArrayList<>(); + for (Map.Entry entry : entriesMap.entrySet()) { + mapSourceWrapperList.add(new MapSourceWrapper(entry.getKey(), entry.getValue())); + } + if (!mapSourceWrapperList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.MAP_SOURCES, + mapSourceWrapperList + )); + } return dataList; } @@ -270,13 +287,23 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } private void importSettings() { - app.getSettingsHelper().importSettings(settingsItems, file, new SettingsHelper.SettingsImportListener() { + if (includeAdditionalData) { - @Override - public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { + } else { + List list = new ArrayList<>(); + list.add(profileSettingsItem); + app.getSettingsHelper().importSettings(list, file, new SettingsHelper.SettingsImportListener() { - } - }); + @Override + public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { + if (succeed) { + app.showShortToastMessage(app.getString(R.string.file_imported_successfully, "")); + } else if (!empty) { + app.showShortToastMessage(app.getString(R.string.file_import_error, "", app.getString(R.string.shared_string_unexpected_error))); + } + } + }); + } dismiss(); } @@ -313,9 +340,9 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { if (!poiUIFilters.isEmpty()) { settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app.getSettings(), poiUIFilters)); } -// if (!mapSourceWrappers.isEmpty()) { -// settingsItems.add(); -// } + if (!mapSourceWrappers.isEmpty()) { + settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), mapSourceWrappers)); + } } return settingsItems; } @@ -599,7 +626,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } - class MapSourceWrapper { + public class MapSourceWrapper { private String name; private String url; From 13a48e61c7f0ac0e4d0b4b2581253bae994ad502 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Mon, 3 Feb 2020 19:04:37 +0200 Subject: [PATCH 04/42] wip --- .../src/net/osmand/plus/SettingsHelper.java | 502 ++++++++---------- .../net/osmand/plus/helpers/ImportHelper.java | 29 +- .../ExportImportProfileBottomSheet.java | 77 ++- .../settings/ConfigureProfileFragment.java | 11 - 4 files changed, 270 insertions(+), 349 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index afb8601890..d6a8450f91 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -9,7 +9,11 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + import net.osmand.PlatformUtil; +import net.osmand.osm.PoiCategory; import net.osmand.plus.ApplicationMode.ApplicationModeBean; import net.osmand.plus.ApplicationMode.ApplicationModeBuilder; import net.osmand.plus.OsmandSettings.OsmandPreference; @@ -37,11 +41,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -53,10 +60,8 @@ import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT; /* Usage: - SettingsHelper helper = app.getSettingsHelper(); File file = new File(app.getAppPath(null), "settings.zip"); - List items = new ArrayList<>(); items.add(new GlobalSettingsItem(app.getSettings())); items.add(new ProfileSettingsItem(app.getSettings(), ApplicationMode.DEFAULT)); @@ -68,9 +73,7 @@ import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT; items.add(new FileSettingsItem(app, new File(app.getAppPath(RENDERERS_DIR), "default.render.xml"))); items.add(new DataSettingsItem(new byte[] {'t', 'e', 's', 't', '1'}, "data1")); items.add(new DataSettingsItem(new byte[] {'t', 'e', 's', 't', '2'}, "data2")); - helper.exportSettings(file, items); - helper.importSettings(file); */ @@ -97,8 +100,8 @@ public class SettingsHelper { void onSettingsExportFinished(@NonNull File file, boolean succeed); } - public interface SettingsImportPrepareListener { - void onSettingsPrepared(boolean succeed, boolean empty, @NonNull List items); + public interface SettingsPreImportListener { + void onSettingsPreImported(boolean isSuccessful, List items); } public SettingsHelper(OsmandApplication app) { @@ -268,6 +271,8 @@ public class SettingsHelper { private OsmandSettings settings; + JSONObject json; + public OsmandSettingsItemReader(@NonNull OsmandSettingsItem item, @NonNull OsmandSettings settings) { super(item); this.settings = settings; @@ -292,32 +297,32 @@ public class SettingsHelper { if (Algorithms.isEmpty(jsonStr)) { throw new IllegalArgumentException("Cannot find json body"); } - final JSONObject json; +// final JSONObject json; try { json = new JSONObject(jsonStr); } catch (JSONException e) { throw new IllegalArgumentException("Json parse error", e); } - settings.getContext().runInUIThread(new Runnable() { - @Override - public void run() { - Map> prefs = settings.getRegisteredPreferences(); - Iterator iter = json.keys(); - while (iter.hasNext()) { - String key = iter.next(); - OsmandPreference p = prefs.get(key); - if (p != null) { - try { - readPreferenceFromJson(p, json); - } catch (Exception e) { - LOG.error("Failed to read preference: " + key, e); - } - } else { - LOG.warn("No preference while importing settings: " + key); - } - } - } - }); +// settings.getContext().runInUIThread(new Runnable() { +// @Override +// public void run() { +// Map> prefs = settings.getRegisteredPreferences(); +// Iterator iter = json.keys(); +// while (iter.hasNext()) { +// String key = iter.next(); +// OsmandPreference p = prefs.get(key); +// if (p != null) { +// try { +// readPreferenceFromJson(p, json); +// } catch (Exception e) { +// LOG.error("Failed to read preference: " + key, e); +// } +// } else { +// LOG.warn("No preference while importing settings: " + key); +// } +// } +// } +// }); } } @@ -430,6 +435,10 @@ public class SettingsHelper { appModeBeanPrefsIds = new HashSet<>(Arrays.asList(settings.appModeBeanPrefsIds)); } + public ApplicationMode getAppMode() { + return appMode; + } + @NonNull @Override public String getName() { @@ -475,10 +484,27 @@ public class SettingsHelper { if (appMode.isCustomProfile()) { appMode = ApplicationMode.saveProfile(builder, getSettings().getContext()); } - } - public ApplicationMode getAppMode() { - return appMode; + getSettings().getContext().runInUIThread(new Runnable() { + @Override + public void run() { + Map> prefs = getSettings().getRegisteredPreferences(); + Iterator iter = reader.json.keys(); + while (iter.hasNext()) { + String key = iter.next(); + OsmandPreference p = prefs.get(key); + if (p != null) { + try { + reader.readPreferenceFromJson(p, reader.json); + } catch (Exception e) { + LOG.error("Failed to read preference: " + key, e); + } + } else { + LOG.warn("No preference while importing settings: " + key); + } + } + } + }); } @Override @@ -488,17 +514,19 @@ public class SettingsHelper { } + OsmandSettingsItemReader reader = new OsmandSettingsItemReader(this, getSettings()) { + @Override + protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + if (!appModeBeanPrefsIds.contains(preference.getId())) { + preference.readFromJson(json, appMode); + } + } + }; + @NonNull @Override SettingsItemReader getReader() { - return new OsmandSettingsItemReader(this, getSettings()) { - @Override - protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { - if (!appModeBeanPrefsIds.contains(preference.getId())) { - preference.readFromJson(json, appMode); - } - } - }; + return reader; } @NonNull @@ -735,49 +763,14 @@ public class SettingsHelper { } public QuickActionSettingsItem(@NonNull OsmandSettings settings, - @NonNull JSONObject jsonObject, File file) throws JSONException { + @NonNull JSONObject jsonObject) throws JSONException { super(SettingsItemType.QUICK_ACTION_LIST, settings, jsonObject); - try { - readFromJson(jsonObject, file); - } catch (IOException e) { - e.printStackTrace(); - } } public List getQuickActions() { return quickActions; } - void readFromJson(JSONObject jsonObject, File file) throws IllegalArgumentException, IOException, JSONException { - ZipInputStream zis = new ZipInputStream(new FileInputStream(file)); - InputStream ois = new BufferedInputStream(zis); - ZipEntry entry; - while ((entry = zis.getNextEntry()) != null){ - if (entry.getName().equals(getFileName())) { - String itemsJson = null; - try { - itemsJson = Algorithms.readFromInputStream(ois).toString(); - } catch (IOException e) { - LOG.error("Error reading items.json: " + itemsJson, e); - throw new IllegalArgumentException("No items"); - } finally { - zis.closeEntry(); - } - quickActions = new ArrayList<>(); - JSONObject json = new JSONObject(itemsJson); - JSONArray items = json.getJSONArray("items"); - for (int i = 0; i < items.length(); i++) { - JSONObject object = items.getJSONObject(i); - String name = object.getString("name"); - int type = object.getInt("type"); - QuickAction quickAction = new QuickAction(type); - quickAction.setName(name); - quickActions.add(quickAction); - } - } - } - } - @Override public void apply() { if (!quickActions.isEmpty()) { @@ -797,7 +790,7 @@ public class SettingsHelper { @NonNull @Override public String getPublicName(@NonNull Context ctx) { - return null; + return "quick_actions"; } @NonNull @@ -806,16 +799,6 @@ public class SettingsHelper { return getName() + ".json"; } - @Override - void writeToJson(@NonNull JSONObject json) throws JSONException { - super.writeToJson(json); -// JSONArray jsonArray = new JSONArray(); -// for (QuickAction quickAction : quickActions) { -// jsonArray.put(quickAction.getName(app)); -// } -// json.put("name_list", jsonArray); - } - @NonNull @Override SettingsItemReader getReader() { @@ -855,10 +838,6 @@ public class SettingsHelper { quickAction.setName(name); quickActions.add(quickAction); } -// QuickActionFactory factory = new QuickActionFactory(); -// List quickActionsList = factory.parseActiveActionsList(getSettings().QUICK_ACTION_LIST.get()); -// quickActionsList.addAll(quickActions); -// getSettings().QUICK_ACTION_LIST.set(factory.quickActionListToString(quickActionsList)); } catch (JSONException e) { throw new IllegalArgumentException("Json parse error", e); } @@ -892,13 +871,17 @@ public class SettingsHelper { private List poiUIFilters; - public PoiUiFilterSettingsItem(OsmandSettings settings, List poiUIFilters) { - super(SettingsItemType.POI_UI_FILTERS_LIST, settings); + private OsmandApplication app; + + public PoiUiFilterSettingsItem(OsmandApplication app, List poiUIFilters) { + super(SettingsItemType.POI_UI_FILTERS_LIST, app.getSettings()); + this.app = app; this.poiUIFilters = poiUIFilters; } - public PoiUiFilterSettingsItem(OsmandSettings settings, JSONObject jsonObject) throws JSONException { - super(SettingsItemType.POI_UI_FILTERS_LIST, settings, jsonObject); + public PoiUiFilterSettingsItem(OsmandApplication app, JSONObject jsonObject) throws JSONException { + super(SettingsItemType.POI_UI_FILTERS_LIST, app.getSettings(), jsonObject); + this.app = app; readFromJson(jsonObject); } @@ -928,6 +911,44 @@ public class SettingsHelper { protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { } + + @Override + public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + StringBuilder buf = new StringBuilder(); + try { + BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String str; + while ((str = in.readLine()) != null) { + buf.append(str); + } + } catch (IOException e) { + throw new IOException("Cannot read json body", e); + } + String jsonStr = buf.toString(); + if (Algorithms.isEmpty(jsonStr)) { + throw new IllegalArgumentException("Cannot find json body"); + } + final JSONObject json; + try { + poiUIFilters = new ArrayList<>(); + json = new JSONObject(jsonStr); + JSONArray items = json.getJSONArray("items"); + Gson gson = new Gson(); + Type type = new TypeToken>>() { + }.getType(); + for (int i = 0; i < items.length(); i++) { + JSONObject object = items.getJSONObject(i); + String name = object.getString("name"); + String filterId = object.getString("filterId"); + String acceptedTypesString = object.getString("acceptedTypes"); +// Map> acceptedTypes = gson.fromJson(acceptedTypesString, type); +// PoiUIFilter filter = new PoiUIFilter(name, filterId, acceptedTypes, app); +// poiUIFilters.add(filter); + } + } catch (JSONException e) { + throw new IllegalArgumentException("Json parse error", e); + } + } }; } @@ -938,12 +959,15 @@ public class SettingsHelper { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { JSONArray items = new JSONArray(); + Gson gson = new Gson(); + Type type = new TypeToken>>() { + }.getType(); if (!poiUIFilters.isEmpty()) { for (PoiUIFilter filter : poiUIFilters) { JSONObject jsonObject = new JSONObject(); jsonObject.put("name", filter.getName()); jsonObject.put("filterId", filter.getFilterId()); - jsonObject.put("acceptedTypes", filter.getAcceptedTypes()); + jsonObject.put("acceptedTypes", gson.toJson(filter.getAcceptedTypes(), type)); items.put(jsonObject); } json.put("items", items); @@ -1020,11 +1044,9 @@ public class SettingsHelper { private OsmandApplication app; private List items = new ArrayList<>(); - private File file; - SettingsItemsFactory(OsmandApplication app, String jsonStr, File file) throws IllegalArgumentException, JSONException { + SettingsItemsFactory(OsmandApplication app, String jsonStr) throws IllegalArgumentException, JSONException { this.app = app; - this.file = file; JSONObject json = new JSONObject(jsonStr); JSONArray itemsJson = json.getJSONArray("items"); for (int i = 0; i < itemsJson.length(); i++) { @@ -1075,10 +1097,10 @@ public class SettingsHelper { item = new FileSettingsItem(app, json); break; case QUICK_ACTION_LIST: - item = new QuickActionSettingsItem(settings, json, file); + item = new QuickActionSettingsItem(settings, json); break; case POI_UI_FILTERS_LIST: - item = new PoiUiFilterSettingsItem(settings, json); + item = new PoiUiFilterSettingsItem(app, json); break; case MAP_SOURCES_LIST: item = new MapSourcesSettingsItem(settings, json); @@ -1159,14 +1181,15 @@ public class SettingsHelper { } private List processItems(@NonNull File file, @Nullable List items) throws IllegalArgumentException, IOException { - boolean collecting = items == null; - if (collecting) { - items = new ArrayList<>(); - } else { - if (items.size() == 0) { - throw new IllegalArgumentException("No items"); - } - } +// boolean collecting = items == null; +// if (collecting) { +// items = new ArrayList<>(); +// } else { +// if (items.size() == 0) { +// throw new IllegalArgumentException("No items"); +// } +// } + items = new ArrayList<>(); ZipInputStream zis = new ZipInputStream(new FileInputStream(file)); InputStream ois = new BufferedInputStream(zis); try { @@ -1183,10 +1206,10 @@ public class SettingsHelper { } SettingsItemsFactory itemsFactory; try { - itemsFactory = new SettingsItemsFactory(app, itemsJson, file); - if (collecting) { + itemsFactory = new SettingsItemsFactory(app, itemsJson); +// if (collecting) { items.addAll(itemsFactory.getItems()); - } +// } } catch (IllegalArgumentException e) { LOG.error("Error parsing items: " + itemsJson, e); throw new IllegalArgumentException("No items"); @@ -1194,7 +1217,7 @@ public class SettingsHelper { LOG.error("Error parsing items: " + itemsJson, e); throw new IllegalArgumentException("No items"); } - while (!collecting && (entry = zis.getNextEntry()) != null) { + while ((entry = zis.getNextEntry()) != null) { String fileName = entry.getName(); SettingsItem item = itemsFactory.getItemByFileName(fileName); if (item != null) { @@ -1222,164 +1245,6 @@ public class SettingsHelper { } } - @SuppressLint("StaticFieldLeak") - public class PrepareImportFileAsyncTask extends AsyncTask> { - - private File file; - private SettingsImportPrepareListener listener; - private SettingsImporter importer; - - PrepareImportFileAsyncTask(@NonNull File settingsFile, @Nullable SettingsImportPrepareListener listener) { - this.file = settingsFile; - this.listener = listener; - importer = new SettingsImporter(app); - } - - @Override - protected List doInBackground(Void... voids) { - try { - return importer.collectItems(file); - } catch (IllegalArgumentException e) { - LOG.error("Failed to collect items from: " + file.getName(), e); - } catch (IOException e) { - LOG.error("Failed to collect items from: " + file.getName(), e); - } - return null; - } - - @Override - protected void onPostExecute(List settingsItems) { - super.onPostExecute(settingsItems); - if (settingsItems != null && settingsItems.size() > 0) { - listener.onSettingsPrepared(true, false, settingsItems); - } - } - } - - @SuppressLint("StaticFieldLeak") - private class ImportSettingsTask extends AsyncTask { - - private File file; - private String latestChanges; - private int version; - - private SettingsImportListener listener; - private SettingsImporter importer; - private List items; - private List processedItems = new ArrayList<>(); - private SettingsItem currentItem; - private AlertDialog dialog; - - ImportSettingsTask(List items, File file, SettingsImportListener listener) { - this.items = items; - this.file = file; - importer = new SettingsImporter(app); - this.listener = listener; - } - - @Override - protected Void doInBackground(Void... voids) { - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - processNextItem(); - } - - private void processNextItem() { - if (activity == null) { - return; - } - if (items.size() == 0 && !importSuspended) { - if (processedItems.size() > 0) { - new ImportItemsAsyncTask(file, listener, processedItems).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } else { - finishImport(listener, false, true, items); - } - return; - } - final SettingsItem item; - if (importSuspended && currentItem != null) { - item = currentItem; - } else if (items.size() > 0) { - item = items.remove(0); - currentItem = item; - } else { - item = null; - } - importSuspended = false; - if (item != null) { - if (item.exists()) { - switch (item.getType()) { - case PROFILE: { - String title = activity.getString(R.string.overwrite_profile_q, item.getPublicName(app)); - dialog = showConfirmDialog(item, title, latestChanges); - break; - } - case FILE: - // overwrite now - acceptItem(item); - break; - default: - acceptItem(item); - break; - } - } else { - if (item.getType() == SettingsItemType.PROFILE) { - String title = activity.getString(R.string.add_new_profile_q, item.getPublicName(app)); - dialog = showConfirmDialog(item, title, latestChanges); - } else { - acceptItem(item); - } - } - } else { - processNextItem(); - } - } - - private AlertDialog showConfirmDialog(final SettingsItem item, String title, String message) { - AlertDialog.Builder b = new AlertDialog.Builder(activity); - b.setTitle(title); - b.setMessage(message); - b.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - acceptItem(item); - } - }); - b.setNegativeButton(R.string.shared_string_no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - processNextItem(); - } - }); - b.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - ImportSettingsTask.this.dialog = null; - } - }); - b.setCancelable(false); - return b.show(); - } - - private void suspendImport() { - if (dialog != null) { - dialog.dismiss(); - dialog = null; - } - } - - private void acceptItem(SettingsItem item) { -// item.apply(); - processedItems.add(item); - processNextItem(); - } - - - } - @SuppressLint("StaticFieldLeak") private class ImportAsyncTask extends AsyncTask> { @@ -1568,6 +1433,46 @@ public class SettingsHelper { } } + @SuppressLint("StaticFieldLeak") + public class PreImportAsyncTask extends AsyncTask> { + + private String latestChanges; + private int version; + private File file; + private SettingsPreImportListener listener; + private SettingsImporter importer; + + PreImportAsyncTask(@NonNull File file, String latestChanges, int version, SettingsPreImportListener listener) { + this.file = file; + this.listener = listener; + this.latestChanges = latestChanges; + this.version = version; + importer = new SettingsImporter(app); + } + + @Override + protected List doInBackground(Void... voids) { + try { + return importer.collectItems(file); + } catch (IllegalArgumentException e) { + LOG.error("Failed to collect items from: " + file.getName(), e); + } catch (IOException e) { + LOG.error("Failed to collect items from: " + file.getName(), e); + } + return null; + } + + @Override + protected void onPostExecute(List settingsItems) { + super.onPostExecute(settingsItems); + if (settingsItems != null && settingsItems.size() > 0) { + listener.onSettingsPreImported(true, settingsItems); + } else { + listener.onSettingsPreImported(false, settingsItems); + } + } + } + @SuppressLint("StaticFieldLeak") private class ExportAsyncTask extends AsyncTask { @@ -1623,15 +1528,58 @@ public class SettingsHelper { exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items))); } - public void prepareSettings(@NonNull File settingsFile, @Nullable SettingsImportPrepareListener listener) { - new PrepareImportFileAsyncTask(settingsFile, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + public void preImportSettings(File file, String latestChanges, int version, SettingsPreImportListener listener) { + new PreImportAsyncTask(file, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - public void importSettings(List items, File file, SettingsImportListener listener) { - new ImportSettingsTask(items, file, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + public void importSettingsItems(List list) { + for (SettingsItem item : list) { + if (item.exists()) { + switch (item.getType()) { + case PROFILE: { + String title = activity.getString(R.string.overwrite_profile_q, item.getPublicName(app)); + showConfirmDialog(item, title, ""); + break; + } + default: + item.apply(); + break; + } + } else { + if (item.getType() == SettingsItemType.PROFILE) { + String title = activity.getString(R.string.add_new_profile_q, item.getPublicName(app)); + showConfirmDialog(item, title, ""); + } else { + item.apply(); +// acceptItem(item); + } + } + } } -// public void preImportSettings(List items, File file, SettingsImportListener listener) { -// new ImportSettingsTask(items, file, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); -// } -} + private AlertDialog showConfirmDialog(final SettingsItem item, String title, String message) { + AlertDialog.Builder b = new AlertDialog.Builder(activity); + b.setTitle(title); + b.setMessage(message); + b.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + item.apply(); + } + }); + b.setNegativeButton(R.string.shared_string_no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + b.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + + } + }); + b.setCancelable(false); + return b.show(); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index ba7038ebfd..acb174ad42 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -776,11 +776,13 @@ public class ImportHelper { File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); final File file = new File(tempDir, name); if (error == null && file.exists()) { - app.getSettingsHelper().prepareSettings(file, new SettingsHelper.SettingsImportPrepareListener() { + app.getSettingsHelper().preImportSettings(file, latestChanges, version, new SettingsHelper.SettingsPreImportListener() { @Override - public void onSettingsPrepared(boolean succeed, boolean empty, @NonNull List items) { - progress.dismiss(); - if (succeed && !empty) { + public void onSettingsPreImported(boolean isSuccessful, List items) { + if (isActivityNotDestroyed(activity)) { + progress.dismiss(); + } + if (isSuccessful) { FragmentManager fragmentManager = activity.getSupportFragmentManager(); if (fragmentManager != null) { ExportImportProfileBottomSheet.showInstance( @@ -790,27 +792,10 @@ public class ImportHelper { items); } } else { - app.showShortToastMessage(app.getString(R.string.file_import_error, name, "")); + app.showShortToastMessage(app.getString(R.string.file_import_error, name, app.getString(R.string.shared_string_unexpected_error))); } } }); - -// app.getSettingsHelper().importSettings(file, latestChanges, version, new SettingsImportListener() { -// @Override -// public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { -// if (isActivityNotDestroyed(activity)) { -// progress.dismiss(); -// } -// if (succeed) { -// app.showShortToastMessage(app.getString(R.string.file_imported_successfully, name)); -// if (callback != null) { -// callback.processResult(items); -// } -// } else if (!empty) { -// app.showShortToastMessage(app.getString(R.string.file_import_error, name, app.getString(R.string.shared_string_unexpected_error))); -// } -// } -// }); } else { if (isActivityNotDestroyed(activity)) { progress.dismiss(); diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index 66c252557e..456b8b94e5 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -145,7 +145,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { .setButtonTintList(ColorStateList.valueOf(getResolvedColor(profileColor))) .setDescription(BaseSettingsFragment.getAppModeDescription(context, profile)) .setIcon(getIcon(profile.getIconRes(), profileColor)) - .setTitle(profile.toHumanString(context)) + .setTitle(profile.toHumanString()) .setBackground(new LayerDrawable(layers)) .setLayoutId(R.layout.preference_profile_item_with_radio_btn) .create(); @@ -287,23 +287,12 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } private void importSettings() { + List list = new ArrayList<>(); + list.add(profileSettingsItem); if (includeAdditionalData) { - - } else { - List list = new ArrayList<>(); - list.add(profileSettingsItem); - app.getSettingsHelper().importSettings(list, file, new SettingsHelper.SettingsImportListener() { - - @Override - public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { - if (succeed) { - app.showShortToastMessage(app.getString(R.string.file_imported_successfully, "")); - } else if (!empty) { - app.showShortToastMessage(app.getString(R.string.file_import_error, "", app.getString(R.string.shared_string_unexpected_error))); - } - } - }); + list.addAll(prepareAdditionalSettingsItems()); } + app.getSettingsHelper().importSettingsItems(list); dismiss(); } @@ -322,38 +311,48 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile)); if (includeAdditionalData) { - List quickActions = new ArrayList<>(); - List poiUIFilters = new ArrayList<>(); - List mapSourceWrappers = new ArrayList<>(); - for (Object object : dataToOperate) { - if (object instanceof QuickAction) { - quickActions.add((QuickAction) object); - } else if (object instanceof PoiUIFilter) { - poiUIFilters.add((PoiUIFilter) object); - } else if (object instanceof MapSourceWrapper) { - mapSourceWrappers.add((MapSourceWrapper) object); - } - } - if (!quickActions.isEmpty()) { - settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); - } - if (!poiUIFilters.isEmpty()) { - settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app.getSettings(), poiUIFilters)); - } - if (!mapSourceWrappers.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), mapSourceWrappers)); - } + settingsItems.addAll(prepareAdditionalSettingsItems()); } return settingsItems; } + private List prepareAdditionalSettingsItems() { + List settingsItems = new ArrayList<>(); + + List quickActions = new ArrayList<>(); + List poiUIFilters = new ArrayList<>(); + List mapSourceWrappers = new ArrayList<>(); + for (Object object : dataToOperate) { + if (object instanceof QuickAction) { + quickActions.add((QuickAction) object); + } else if (object instanceof PoiUIFilter) { + poiUIFilters.add((PoiUIFilter) object); + } else if (object instanceof MapSourceWrapper) { + mapSourceWrappers.add((MapSourceWrapper) object); + } + } + if (!quickActions.isEmpty()) { + settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); + } + if (!poiUIFilters.isEmpty()) { + settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); + } + if (!mapSourceWrappers.isEmpty()) { + settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), mapSourceWrappers)); + } + return settingsItems; + } + + + + private void prepareFile() { if (app != null) { File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); if (!tempDir.exists()) { tempDir.mkdirs(); } - String fileName = profile.toHumanString(context); + String fileName = profile.toHumanString(); app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() { @Override public void onSettingsExportFinished(@NonNull File file, boolean succeed) { @@ -372,7 +371,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { Context ctx = requireContext(); final Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString(ctx))); + sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString())); sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file)); sendIntent.setType("*/*"); sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); diff --git a/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java b/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java index 22320bc4d0..967b8a2915 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java @@ -404,17 +404,6 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co this, getSelectedAppMode()); } - String fileName = profile.toHumanString(); - app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() { - @Override - public void onSettingsExportFinished(@NonNull File file, boolean succeed) { - if (succeed) { - shareProfile(file, profile); - } else { - app.showToastMessage(R.string.export_profile_failed); - } - } - }, new ProfileSettingsItem(app.getSettings(), profile)); } else if (DELETE_PROFILE.equals(prefId)) { onDeleteProfileClick(); } From feca38ac4b36851b58bd1ce8cdf381612e6ef8ef Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Tue, 4 Feb 2020 13:30:19 +0200 Subject: [PATCH 05/42] wip --- .../net/osmand/plus/helpers/ImportHelper.java | 1 - .../ExportImportProfileBottomSheet.java | 25 ++++++++----------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index acb174ad42..c82053bcae 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -788,7 +788,6 @@ public class ImportHelper { ExportImportProfileBottomSheet.showInstance( fragmentManager, ExportImportProfileBottomSheet.State.IMPORT, - file, items); } } else { diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index 456b8b94e5..0527197799 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -85,8 +85,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private List settingsItems; - private File file; - private SettingsHelper.ProfileSettingsItem profileSettingsItem; @Override @@ -191,11 +189,14 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { List dataList = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); + List mapSourceWrappers = new ArrayList<>(); for (SettingsHelper.SettingsItem item : settingsItems) { if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST)) { quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST)) { -// poiUIFilters.addAll() +// poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).) + } else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES_LIST)) { +// mapSourceWrappers.addAll(((SettingsHelper.MapSourcesSettingsItem) item).) } } if (!quickActions.isEmpty()) { @@ -208,6 +209,12 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { AdditionalDataWrapper.Type.POI_TYPES, poiUIFilters)); } + if (!mapSourceWrappers.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.MAP_SOURCES, + mapSourceWrappers + )); + } for (AdditionalDataWrapper dataWrapper : dataList) { dataToOperate.addAll(dataWrapper.getItems()); } @@ -252,7 +259,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { )); } - final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries()); + final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries(false)); List mapSourceWrapperList = new ArrayList<>(); for (Map.Entry entry : entriesMap.entrySet()) { mapSourceWrapperList.add(new MapSourceWrapper(entry.getKey(), entry.getValue())); @@ -403,7 +410,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { public static boolean showInstance(@NonNull FragmentManager fragmentManager, State state, - File file, List items) { try { Bundle bundle = new Bundle(); @@ -411,7 +417,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); fragment.setArguments(bundle); fragment.setSettingsItems(items); - fragment.setFile(file); fragment.show(fragmentManager, TAG); return true; } catch (RuntimeException e) { @@ -419,14 +424,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - public enum State { EXPORT, IMPORT From ccd638f2edee32e782b6287db0cc881cab1e3966 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Tue, 4 Feb 2020 19:04:25 +0200 Subject: [PATCH 06/42] refactor/wip --- .../src/net/osmand/plus/SettingsHelper.java | 289 +++++++----------- .../net/osmand/plus/helpers/ImportHelper.java | 7 +- .../ExportImportProfileBottomSheet.java | 38 ++- 3 files changed, 133 insertions(+), 201 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index d6a8450f91..ed525566e2 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -139,9 +139,9 @@ public class SettingsHelper { PLUGIN, DATA, FILE, - QUICK_ACTION_LIST, - POI_UI_FILTERS_LIST, - MAP_SOURCES_LIST, + QUICK_ACTION, + POI_UI_FILTERS, + MAP_SOURCES, } public abstract static class SettingsItem { @@ -171,6 +171,10 @@ public class SettingsHelper { @NonNull public abstract String getFileName(); + public Boolean shouldReadInCollecting() { + return false; + } + static SettingsItemType parseItemType(@NonNull JSONObject json) throws IllegalArgumentException, JSONException { return SettingsItemType.valueOf(json.getString("type")); } @@ -271,8 +275,6 @@ public class SettingsHelper { private OsmandSettings settings; - JSONObject json; - public OsmandSettingsItemReader(@NonNull OsmandSettingsItem item, @NonNull OsmandSettings settings) { super(item); this.settings = settings; @@ -297,33 +299,32 @@ public class SettingsHelper { if (Algorithms.isEmpty(jsonStr)) { throw new IllegalArgumentException("Cannot find json body"); } -// final JSONObject json; + final JSONObject json; try { json = new JSONObject(jsonStr); } catch (JSONException e) { throw new IllegalArgumentException("Json parse error", e); } -// settings.getContext().runInUIThread(new Runnable() { -// @Override -// public void run() { -// Map> prefs = settings.getRegisteredPreferences(); -// Iterator iter = json.keys(); -// while (iter.hasNext()) { -// String key = iter.next(); -// OsmandPreference p = prefs.get(key); -// if (p != null) { -// try { -// readPreferenceFromJson(p, json); -// } catch (Exception e) { -// LOG.error("Failed to read preference: " + key, e); -// } -// } else { -// LOG.warn("No preference while importing settings: " + key); -// } -// } -// } -// }); - + settings.getContext().runInUIThread(new Runnable() { + @Override + public void run() { + Map> prefs = settings.getRegisteredPreferences(); + Iterator iter = json.keys(); + while (iter.hasNext()) { + String key = iter.next(); + OsmandPreference p = prefs.get(key); + if (p != null) { + try { + readPreferenceFromJson(p, json); + } catch (Exception e) { + LOG.error("Failed to read preference: " + key, e); + } + } else { + LOG.warn("No preference while importing settings: " + key); + } + } + } + }); } } @@ -484,27 +485,6 @@ public class SettingsHelper { if (appMode.isCustomProfile()) { appMode = ApplicationMode.saveProfile(builder, getSettings().getContext()); } - - getSettings().getContext().runInUIThread(new Runnable() { - @Override - public void run() { - Map> prefs = getSettings().getRegisteredPreferences(); - Iterator iter = reader.json.keys(); - while (iter.hasNext()) { - String key = iter.next(); - OsmandPreference p = prefs.get(key); - if (p != null) { - try { - reader.readPreferenceFromJson(p, reader.json); - } catch (Exception e) { - LOG.error("Failed to read preference: " + key, e); - } - } else { - LOG.warn("No preference while importing settings: " + key); - } - } - } - }); } @Override @@ -513,20 +493,17 @@ public class SettingsHelper { json.put("appMode", new JSONObject(appMode.toJson())); } - - OsmandSettingsItemReader reader = new OsmandSettingsItemReader(this, getSettings()) { - @Override - protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { - if (!appModeBeanPrefsIds.contains(preference.getId())) { - preference.readFromJson(json, appMode); - } - } - }; - @NonNull @Override SettingsItemReader getReader() { - return reader; + return new OsmandSettingsItemReader(this, getSettings()) { + @Override + protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { + if (!appModeBeanPrefsIds.contains(preference.getId())) { + preference.readFromJson(json, appMode); + } + } + }; } @NonNull @@ -757,14 +734,14 @@ public class SettingsHelper { public QuickActionSettingsItem(@NonNull OsmandApplication app, @NonNull List quickActions) { - super(SettingsItemType.QUICK_ACTION_LIST, app.getSettings()); + super(SettingsItemType.QUICK_ACTION, app.getSettings()); this.app = app; this.quickActions = quickActions; } public QuickActionSettingsItem(@NonNull OsmandSettings settings, @NonNull JSONObject jsonObject) throws JSONException { - super(SettingsItemType.QUICK_ACTION_LIST, settings, jsonObject); + super(SettingsItemType.QUICK_ACTION, settings, jsonObject); } public List getQuickActions() { @@ -781,6 +758,11 @@ public class SettingsHelper { } } + @Override + public Boolean shouldReadInCollecting() { + return true; + } + @NonNull @Override public String getName() { @@ -874,13 +856,13 @@ public class SettingsHelper { private OsmandApplication app; public PoiUiFilterSettingsItem(OsmandApplication app, List poiUIFilters) { - super(SettingsItemType.POI_UI_FILTERS_LIST, app.getSettings()); + super(SettingsItemType.POI_UI_FILTERS, app.getSettings()); this.app = app; this.poiUIFilters = poiUIFilters; } public PoiUiFilterSettingsItem(OsmandApplication app, JSONObject jsonObject) throws JSONException { - super(SettingsItemType.POI_UI_FILTERS_LIST, app.getSettings(), jsonObject); + super(SettingsItemType.POI_UI_FILTERS, app.getSettings(), jsonObject); this.app = app; readFromJson(jsonObject); } @@ -897,6 +879,11 @@ public class SettingsHelper { return null; } + @Override + public Boolean shouldReadInCollecting() { + return true; + } + @NonNull @Override public String getFileName() { @@ -982,12 +969,12 @@ public class SettingsHelper { private List mapSources; public MapSourcesSettingsItem(OsmandSettings settings, List mapSources) { - super(SettingsItemType.MAP_SOURCES_LIST, settings); + super(SettingsItemType.MAP_SOURCES, settings); this.mapSources = mapSources; } public MapSourcesSettingsItem(OsmandSettings settings, JSONObject jsonObject) throws JSONException { - super(SettingsItemType.MAP_SOURCES_LIST, settings, jsonObject); + super(SettingsItemType.MAP_SOURCES, settings, jsonObject); } @NonNull @@ -1002,6 +989,11 @@ public class SettingsHelper { return null; } + @Override + public Boolean shouldReadInCollecting() { + return true; + } + @NonNull @Override public String getFileName() { @@ -1096,13 +1088,13 @@ public class SettingsHelper { case FILE: item = new FileSettingsItem(app, json); break; - case QUICK_ACTION_LIST: + case QUICK_ACTION: item = new QuickActionSettingsItem(settings, json); break; - case POI_UI_FILTERS_LIST: + case POI_UI_FILTERS: item = new PoiUiFilterSettingsItem(app, json); break; - case MAP_SOURCES_LIST: + case MAP_SOURCES: item = new MapSourcesSettingsItem(settings, json); break; } @@ -1181,15 +1173,14 @@ public class SettingsHelper { } private List processItems(@NonNull File file, @Nullable List items) throws IllegalArgumentException, IOException { -// boolean collecting = items == null; -// if (collecting) { -// items = new ArrayList<>(); -// } else { -// if (items.size() == 0) { -// throw new IllegalArgumentException("No items"); -// } -// } - items = new ArrayList<>(); + boolean collecting = items == null; + if (collecting) { + items = new ArrayList<>(); + } else { + if (items.size() == 0) { + throw new IllegalArgumentException("No items"); + } + } ZipInputStream zis = new ZipInputStream(new FileInputStream(file)); InputStream ois = new BufferedInputStream(zis); try { @@ -1207,9 +1198,9 @@ public class SettingsHelper { SettingsItemsFactory itemsFactory; try { itemsFactory = new SettingsItemsFactory(app, itemsJson); -// if (collecting) { + if (collecting) { items.addAll(itemsFactory.getItems()); -// } + } } catch (IllegalArgumentException e) { LOG.error("Error parsing items: " + itemsJson, e); throw new IllegalArgumentException("No items"); @@ -1220,7 +1211,8 @@ public class SettingsHelper { while ((entry = zis.getNextEntry()) != null) { String fileName = entry.getName(); SettingsItem item = itemsFactory.getItemByFileName(fileName); - if (item != null) { + if (item != null && collecting && item.shouldReadInCollecting() + || item != null && !collecting && !item.shouldReadInCollecting()) { try { item.getReader().readFromStream(ois); } catch (IllegalArgumentException e) { @@ -1251,6 +1243,7 @@ public class SettingsHelper { private File file; private String latestChanges; private int version; + private Boolean isCollecting; private SettingsImportListener listener; private SettingsImporter importer; @@ -1265,6 +1258,17 @@ public class SettingsHelper { this.latestChanges = latestChanges; this.version = version; importer = new SettingsImporter(app); + isCollecting = true; + } + + ImportAsyncTask(@NonNull File settingsFile, @NonNull List items, String latestChanges, int version, @Nullable SettingsImportListener listener) { + this.file = settingsFile; + this.listener = listener; + this.items = items; + this.latestChanges = latestChanges; + this.version = version; + importer = new SettingsImporter(app); + isCollecting = false; } @Override @@ -1279,21 +1283,29 @@ public class SettingsHelper { @Override protected List doInBackground(Void... voids) { - try { - return importer.collectItems(file); - } catch (IllegalArgumentException e) { - LOG.error("Failed to collect items from: " + file.getName(), e); - } catch (IOException e) { - LOG.error("Failed to collect items from: " + file.getName(), e); + if (isCollecting) { + try { + return importer.collectItems(file); + } catch (IllegalArgumentException e) { + LOG.error("Failed to collect items from: " + file.getName(), e); + } catch (IOException e) { + LOG.error("Failed to collect items from: " + file.getName(), e); + } + } else { + return this.items; } return null; } @Override protected void onPostExecute(List items) { - this.items = items; - if (items != null && items.size() > 0) { - processNextItem(); + if (isCollecting) { + listener.onSettingsImportFinished(true, false, items); + } else { + this.items = items; + if (items != null && items.size() > 0) { + processNextItem(); + } } } @@ -1433,46 +1445,6 @@ public class SettingsHelper { } } - @SuppressLint("StaticFieldLeak") - public class PreImportAsyncTask extends AsyncTask> { - - private String latestChanges; - private int version; - private File file; - private SettingsPreImportListener listener; - private SettingsImporter importer; - - PreImportAsyncTask(@NonNull File file, String latestChanges, int version, SettingsPreImportListener listener) { - this.file = file; - this.listener = listener; - this.latestChanges = latestChanges; - this.version = version; - importer = new SettingsImporter(app); - } - - @Override - protected List doInBackground(Void... voids) { - try { - return importer.collectItems(file); - } catch (IllegalArgumentException e) { - LOG.error("Failed to collect items from: " + file.getName(), e); - } catch (IOException e) { - LOG.error("Failed to collect items from: " + file.getName(), e); - } - return null; - } - - @Override - protected void onPostExecute(List settingsItems) { - super.onPostExecute(settingsItems); - if (settingsItems != null && settingsItems.size() > 0) { - listener.onSettingsPreImported(true, settingsItems); - } else { - listener.onSettingsPreImported(false, settingsItems); - } - } - } - @SuppressLint("StaticFieldLeak") private class ExportAsyncTask extends AsyncTask { @@ -1516,6 +1488,10 @@ public class SettingsHelper { new ImportAsyncTask(settingsFile, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + public void importSettings(@NonNull File settingsFile, @NonNull List items, String latestChanges, int version, @Nullable SettingsImportListener listener) { + new ImportAsyncTask(settingsFile, items, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener, @NonNull List items) { @@ -1527,59 +1503,4 @@ public class SettingsHelper { @NonNull SettingsItem... items) { exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items))); } - - public void preImportSettings(File file, String latestChanges, int version, SettingsPreImportListener listener) { - new PreImportAsyncTask(file, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - - public void importSettingsItems(List list) { - for (SettingsItem item : list) { - if (item.exists()) { - switch (item.getType()) { - case PROFILE: { - String title = activity.getString(R.string.overwrite_profile_q, item.getPublicName(app)); - showConfirmDialog(item, title, ""); - break; - } - default: - item.apply(); - break; - } - } else { - if (item.getType() == SettingsItemType.PROFILE) { - String title = activity.getString(R.string.add_new_profile_q, item.getPublicName(app)); - showConfirmDialog(item, title, ""); - } else { - item.apply(); -// acceptItem(item); - } - } - } - } - - private AlertDialog showConfirmDialog(final SettingsItem item, String title, String message) { - AlertDialog.Builder b = new AlertDialog.Builder(activity); - b.setTitle(title); - b.setMessage(message); - b.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - item.apply(); - } - }); - b.setNegativeButton(R.string.shared_string_no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }); - b.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - - } - }); - b.setCancelable(false); - return b.show(); - } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index c82053bcae..5158597ca0 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -776,18 +776,19 @@ public class ImportHelper { File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); final File file = new File(tempDir, name); if (error == null && file.exists()) { - app.getSettingsHelper().preImportSettings(file, latestChanges, version, new SettingsHelper.SettingsPreImportListener() { + app.getSettingsHelper().importSettings(file, latestChanges, version, new SettingsImportListener() { @Override - public void onSettingsPreImported(boolean isSuccessful, List items) { + public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { if (isActivityNotDestroyed(activity)) { progress.dismiss(); } - if (isSuccessful) { + if (succeed) { FragmentManager fragmentManager = activity.getSupportFragmentManager(); if (fragmentManager != null) { ExportImportProfileBottomSheet.showInstance( fragmentManager, ExportImportProfileBottomSheet.State.IMPORT, + file, items); } } else { diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index 0527197799..3225160a66 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -87,6 +87,8 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private SettingsHelper.ProfileSettingsItem profileSettingsItem; + private File file; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -191,11 +193,11 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { List poiUIFilters = new ArrayList<>(); List mapSourceWrappers = new ArrayList<>(); for (SettingsHelper.SettingsItem item : settingsItems) { - if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST)) { + if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) { quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); - } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST)) { + } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS)) { // poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).) - } else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES_LIST)) { + } else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES)) { // mapSourceWrappers.addAll(((SettingsHelper.MapSourcesSettingsItem) item).) } } @@ -219,21 +221,14 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { dataToOperate.addAll(dataWrapper.getItems()); } adapter.updateList(dataList); - -// app.getSettingsHelper().importSettings(settingsItems, file, new SettingsHelper.SettingsImportListener() { -// @Override -// public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { -// -// } -// }); } private Boolean checkAdditionalDataContains() { boolean containsData = false; for (SettingsHelper.SettingsItem item : settingsItems) { - containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION_LIST) - || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS_LIST) - || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES_LIST); + containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION) + || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS) + || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES); if (containsData) { break; } @@ -299,7 +294,12 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { if (includeAdditionalData) { list.addAll(prepareAdditionalSettingsItems()); } - app.getSettingsHelper().importSettingsItems(list); + app.getSettingsHelper().importSettings(file, list, "", 1, new SettingsHelper.SettingsImportListener() { + @Override + public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { + + } + }); dismiss(); } @@ -410,6 +410,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { public static boolean showInstance(@NonNull FragmentManager fragmentManager, State state, + File file, List items) { try { Bundle bundle = new Bundle(); @@ -417,6 +418,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); fragment.setArguments(bundle); fragment.setSettingsItems(items); + fragment.setFile(file); fragment.show(fragmentManager, TAG); return true; } catch (RuntimeException e) { @@ -424,6 +426,14 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + public enum State { EXPORT, IMPORT From ee4c34ac096786b6c95c3e281c27e194ceb2289d Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Wed, 5 Feb 2020 19:07:07 +0200 Subject: [PATCH 07/42] wip / import export mapSources poiFilter --- .../net/osmand/map/TileSourceManager.java | 15 + .../bottom_sheet_item_additional_data.xml | 2 +- .../src/net/osmand/plus/SettingsHelper.java | 117 +++++-- .../ExportImportProfileBottomSheet.java | 310 +++++++++--------- 4 files changed, 260 insertions(+), 184 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java index 6e52928a68..5fd510db61 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java @@ -1,5 +1,8 @@ package net.osmand.map; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + import net.osmand.PlatformUtil; import net.osmand.osm.io.NetworkUtils; import net.osmand.util.Algorithms; @@ -17,6 +20,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.lang.reflect.Type; import java.net.URLConnection; import java.text.MessageFormat; import java.util.ArrayList; @@ -688,4 +692,15 @@ public class TileSourceManager { templ.setRandoms(randoms); return templ; } + + public String templatesListToString(List templates) { + return new Gson().toJson(templates); + } + + public List parseTemplatesList(String json) { + Type type = new TypeToken>() { + }.getType(); + ArrayList templates = new Gson().fromJson(json, type); + return templates != null ? templates : new ArrayList(); + } } diff --git a/OsmAnd/res/layout/bottom_sheet_item_additional_data.xml b/OsmAnd/res/layout/bottom_sheet_item_additional_data.xml index 286b32260f..8a677926b4 100644 --- a/OsmAnd/res/layout/bottom_sheet_item_additional_data.xml +++ b/OsmAnd/res/layout/bottom_sheet_item_additional_data.xml @@ -6,7 +6,7 @@ android:orientation="vertical" android:paddingBottom="20dp"> - quickActionsList = factory.parseActiveActionsList(getSettings().QUICK_ACTION_LIST.get()); - quickActionsList.addAll(quickActions); - getSettings().QUICK_ACTION_LIST.set(factory.quickActionListToString(quickActionsList)); + List savedActions = factory.parseActiveActionsList(getSettings().QUICK_ACTION_LIST.get()); + List newActions = new ArrayList<>(savedActions); + for (QuickAction action : quickActions) { + for (QuickAction savedAction : savedActions) { + if (action.getName(app).equals(savedAction.getName(app))) { + newActions.remove(savedAction); + } + } + } + newActions.addAll(quickActions); + getSettings().QUICK_ACTION_LIST.set(factory.quickActionListToString(newActions)); } } @@ -810,14 +819,20 @@ public class SettingsHelper { final JSONObject json; try { quickActions = new ArrayList<>(); + Gson gson = new Gson(); + Type type = new TypeToken>() { + }.getType(); json = new JSONObject(jsonStr); JSONArray items = json.getJSONArray("items"); for (int i = 0; i < items.length(); i++) { JSONObject object = items.getJSONObject(i); String name = object.getString("name"); - int type = object.getInt("type"); - QuickAction quickAction = new QuickAction(type); + int actionType = object.getInt("type"); + String paramsString = object.getString("params"); + HashMap params = gson.fromJson(paramsString, type); + QuickAction quickAction = new QuickAction(actionType); quickAction.setName(name); + quickAction.setParams(params); quickActions.add(quickAction); } } catch (JSONException e) { @@ -834,12 +849,15 @@ public class SettingsHelper { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { JSONArray items = new JSONArray(); + Gson gson = new Gson(); + Type type = new TypeToken>() { + }.getType(); if (!quickActions.isEmpty()) { for (QuickAction action : quickActions) { JSONObject jsonObject = new JSONObject(); jsonObject.put("name", action.getName(app)); - jsonObject.put("params", action.getParams()); jsonObject.put("type", action.getType()); + jsonObject.put("params", gson.toJson(action.getParams(), type)); items.put(jsonObject); } json.put("items", items); @@ -867,6 +885,20 @@ public class SettingsHelper { readFromJson(jsonObject); } + public List getPoiUIFilters() { + return this.poiUIFilters != null ? this.poiUIFilters : new ArrayList(); + } + + @Override + public void apply() { + if (!poiUIFilters.isEmpty()) { + for (PoiUIFilter filter : poiUIFilters) { + app.getPoiFilters().createPoiFilter(filter, false); + } + app.getSearchUICore().refreshCustomPoiFilters(); + } + } + @NonNull @Override public String getName() { @@ -921,16 +953,22 @@ public class SettingsHelper { json = new JSONObject(jsonStr); JSONArray items = json.getJSONArray("items"); Gson gson = new Gson(); - Type type = new TypeToken>>() { + Type type = new TypeToken>>() { }.getType(); + MapPoiTypes poiTypes = app.getPoiTypes(); for (int i = 0; i < items.length(); i++) { JSONObject object = items.getJSONObject(i); String name = object.getString("name"); String filterId = object.getString("filterId"); String acceptedTypesString = object.getString("acceptedTypes"); -// Map> acceptedTypes = gson.fromJson(acceptedTypesString, type); -// PoiUIFilter filter = new PoiUIFilter(name, filterId, acceptedTypes, app); -// poiUIFilters.add(filter); + HashMap> acceptedTypes = gson.fromJson(acceptedTypesString, type); + Map> acceptedTypesDone = new HashMap<>(); + for (Map.Entry> mapItem : acceptedTypes.entrySet()) { + final PoiCategory a = poiTypes.getPoiCategoryByName(mapItem.getKey()); + acceptedTypesDone.put(a, mapItem.getValue()); + } + PoiUIFilter filter = new PoiUIFilter(name, filterId, acceptedTypesDone, app); + poiUIFilters.add(filter); } } catch (JSONException e) { throw new IllegalArgumentException("Json parse error", e); @@ -966,9 +1004,9 @@ public class SettingsHelper { public static class MapSourcesSettingsItem extends OsmandSettingsItem { - private List mapSources; + private List mapSources; - public MapSourcesSettingsItem(OsmandSettings settings, List mapSources) { + public MapSourcesSettingsItem(OsmandSettings settings, List mapSources) { super(SettingsItemType.MAP_SOURCES, settings); this.mapSources = mapSources; } @@ -977,6 +1015,20 @@ public class SettingsHelper { super(SettingsItemType.MAP_SOURCES, settings, jsonObject); } + public List getMapSources() { + return this.mapSources; + } + + @Override + public void apply() { + if (!mapSources.isEmpty()) { + for (TileSourceManager.TileSourceTemplate template : mapSources) { + boolean writed = getSettings().installTileSource(template); + LOG.info("Temaplate _" + writed); + } + } + } + @NonNull @Override public String getName() { @@ -1008,6 +1060,35 @@ public class SettingsHelper { protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { } + + @Override + public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + StringBuilder buf = new StringBuilder(); + try { + BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String str; + while ((str = in.readLine()) != null) { + buf.append(str); + } + } catch (IOException e) { + throw new IOException("Cannot read json body", e); + } + String jsonStr = buf.toString(); + if (Algorithms.isEmpty(jsonStr)) { + throw new IllegalArgumentException("Cannot find json body"); + } + final JSONObject json; + try { + mapSources = new ArrayList<>(); + json = new JSONObject(jsonStr); + String items = json.getString("items"); + TileSourceManager manager = new TileSourceManager(); + List templates = manager.parseTemplatesList(items); + mapSources.addAll(templates); + } catch (JSONException e) { + throw new IllegalArgumentException("Json parse error", e); + } + } }; } @@ -1017,15 +1098,9 @@ public class SettingsHelper { return new OsmandSettingsItemWriter(this, getSettings()) { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { - JSONArray items = new JSONArray(); + TileSourceManager manager = new TileSourceManager(); if (!mapSources.isEmpty()) { - for (ExportImportProfileBottomSheet.MapSourceWrapper mapSourceWrapper : mapSources) { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("name", mapSourceWrapper.getName()); - jsonObject.put("url", mapSourceWrapper.getUrl()); - items.put(jsonObject); - } - json.put("items", items); + json.put("items", manager.templatesListToString(mapSources)); } } }; diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index 3225160a66..dfee2499ba 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -12,6 +12,8 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; import android.support.v4.widget.CompoundButtonCompat; +import android.support.v4.widget.NestedScrollView; +import android.support.v7.widget.SwitchCompat; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; @@ -26,6 +28,7 @@ import android.widget.Toast; import net.osmand.AndroidUtils; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; +import net.osmand.map.TileSourceManager; import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; @@ -107,17 +110,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { dataToOperate.addAll(dataWrapper.getItems()); } } -// dataList = state == State.IMPORT ? getDataFromSettingsItems() : getAdditionalData(); - } - - private ApplicationMode getAppModeFromItems() { - for (SettingsHelper.SettingsItem item : settingsItems) { - if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { - profileSettingsItem = ((SettingsHelper.ProfileSettingsItem) item); - return ((SettingsHelper.ProfileSettingsItem) item).getAppMode(); - } - } - return getAppMode(); } @Override @@ -160,10 +152,11 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { .create(); items.add(descriptionItem); + final View additionalDataView = View.inflate(new ContextThemeWrapper(context, themeRes), R.layout.bottom_sheet_item_additional_data, null); listView = additionalDataView.findViewById(R.id.list); - Switch switchItem = additionalDataView.findViewById(R.id.switchItem); + SwitchCompat switchItem = additionalDataView.findViewById(R.id.switchItem); switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); switchItem.setOnClickListener(new View.OnClickListener() { @@ -175,9 +168,17 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { if (includeAdditionalData && state == State.IMPORT) { updateDataFromSettingsItems(); } + setupHeightAndBackground(getView()); } }); + adapter = new ProfileAdditionalDataAdapter(requiredMyApplication(), dataList, profileColor); + listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { + @Override + public void onGroupExpand(int i) { + setupHeightAndBackground(getView()); + } + }); listView.setAdapter(adapter); final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() .setCustomView(additionalDataView) @@ -186,19 +187,139 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } - private void updateDataFromSettingsItems() { + @Override + protected int getRightBottomButtonTextId() { + return state == State.EXPORT ? R.string.shared_string_export : R.string.shared_string_import; + } + @Override + protected void onRightBottomButtonClick() { + super.onRightBottomButtonClick(); + if (state == State.EXPORT) { + prepareFile(); + } else { + importSettings(); + } + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_cancel; + } + + @Override + protected boolean useScrollableItemsContainer() { + return false; + } + + private ApplicationMode getAppModeFromItems() { + for (SettingsHelper.SettingsItem item : settingsItems) { + if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { + profileSettingsItem = ((SettingsHelper.ProfileSettingsItem) item); + return ((SettingsHelper.ProfileSettingsItem) item).getAppMode(); + } + } + return getAppMode(); + } + + private List getAdditionalData() { + List dataList = new ArrayList<>(); + + QuickActionFactory factory = new QuickActionFactory(); + List quickActions = factory.parseActiveActionsList(settings.QUICK_ACTION_LIST.get()); + if (!quickActions.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, quickActions)); + } + + List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); + if (!poiList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.POI_TYPES, + poiList + )); + } + + List mapSourceWrapperList = new ArrayList<>(); + final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries(false)); + for (Map.Entry entry : entriesMap.entrySet()) { + File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + entry.getKey()); + TileSourceManager.TileSourceTemplate template = TileSourceManager.createTileSourceTemplate(f); + if (template != null) { + mapSourceWrapperList.add(template); + } + } + if (!mapSourceWrapperList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.MAP_SOURCES, + mapSourceWrapperList + )); + } + + return dataList; + } + + private List prepareSettingsItems() { + List settingsItems = new ArrayList<>(); + settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile)); + + if (includeAdditionalData) { + settingsItems.addAll(prepareAdditionalSettingsItems()); + } + return settingsItems; + } + + private List prepareAdditionalSettingsItems() { + List settingsItems = new ArrayList<>(); + List quickActions = new ArrayList<>(); + List poiUIFilters = new ArrayList<>(); + List mapSourceWrappers = new ArrayList<>(); + for (Object object : dataToOperate) { + if (object instanceof QuickAction) { + quickActions.add((QuickAction) object); + } else if (object instanceof PoiUIFilter) { + poiUIFilters.add((PoiUIFilter) object); + } else if (object instanceof TileSourceManager.TileSourceTemplate) { + mapSourceWrappers.add((TileSourceManager.TileSourceTemplate) object); + } + } + if (!quickActions.isEmpty()) { + settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); + } + if (!poiUIFilters.isEmpty()) { + settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); + } + if (!mapSourceWrappers.isEmpty()) { + settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), mapSourceWrappers)); + } + return settingsItems; + } + + private Boolean checkAdditionalDataContains() { + boolean containsData = false; + for (SettingsHelper.SettingsItem item : settingsItems) { + containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION) + || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS) + || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES); + if (containsData) { + break; + } + } + return containsData; + } + + private void updateDataFromSettingsItems() { List dataList = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); - List mapSourceWrappers = new ArrayList<>(); + List mapSourceWrappers = new ArrayList<>(); for (SettingsHelper.SettingsItem item : settingsItems) { if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) { - quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); + quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS)) { -// poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).) + poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).getPoiUIFilters()); } else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES)) { -// mapSourceWrappers.addAll(((SettingsHelper.MapSourcesSettingsItem) item).) + mapSourceWrappers.addAll(((SettingsHelper.MapSourcesSettingsItem) item).getMapSources()); } } if (!quickActions.isEmpty()) { @@ -223,71 +344,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { adapter.updateList(dataList); } - private Boolean checkAdditionalDataContains() { - boolean containsData = false; - for (SettingsHelper.SettingsItem item : settingsItems) { - containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION) - || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS) - || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES); - if (containsData) { - break; - } - } - return containsData; - } - - private List getAdditionalData() { - List dataList = new ArrayList<>(); - - QuickActionFactory factory = new QuickActionFactory(); - List quickActions = factory.parseActiveActionsList(settings.QUICK_ACTION_LIST.get()); - if (!quickActions.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.QUICK_ACTIONS, quickActions)); - } - - List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); - if (!poiList.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.POI_TYPES, - poiList - )); - } - - final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries(false)); - List mapSourceWrapperList = new ArrayList<>(); - for (Map.Entry entry : entriesMap.entrySet()) { - mapSourceWrapperList.add(new MapSourceWrapper(entry.getKey(), entry.getValue())); - } - if (!mapSourceWrapperList.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.MAP_SOURCES, - mapSourceWrapperList - )); - } - - return dataList; - } - - public void setSettingsItems(List settingsItems) { - this.settingsItems = settingsItems; - } - - @Override - protected int getRightBottomButtonTextId() { - return state == State.EXPORT ? R.string.shared_string_export : R.string.shared_string_import; - } - - @Override - protected void onRightBottomButtonClick() { - super.onRightBottomButtonClick(); - if (state == State.EXPORT) { - prepareFile(); - } else { - importSettings(); - } - } - private void importSettings() { List list = new ArrayList<>(); list.add(profileSettingsItem); @@ -303,56 +359,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { dismiss(); } - @Override - protected int getDismissButtonTextId() { - return R.string.shared_string_cancel; - } - - @Override - protected boolean useScrollableItemsContainer() { - return false; - } - - private List prepareSettingsItems() { - List settingsItems = new ArrayList<>(); - settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile)); - - if (includeAdditionalData) { - settingsItems.addAll(prepareAdditionalSettingsItems()); - } - return settingsItems; - } - - private List prepareAdditionalSettingsItems() { - List settingsItems = new ArrayList<>(); - - List quickActions = new ArrayList<>(); - List poiUIFilters = new ArrayList<>(); - List mapSourceWrappers = new ArrayList<>(); - for (Object object : dataToOperate) { - if (object instanceof QuickAction) { - quickActions.add((QuickAction) object); - } else if (object instanceof PoiUIFilter) { - poiUIFilters.add((PoiUIFilter) object); - } else if (object instanceof MapSourceWrapper) { - mapSourceWrappers.add((MapSourceWrapper) object); - } - } - if (!quickActions.isEmpty()) { - settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); - } - if (!poiUIFilters.isEmpty()) { - settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); - } - if (!mapSourceWrappers.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), mapSourceWrappers)); - } - return settingsItems; - } - - - - private void prepareFile() { if (app != null) { File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); @@ -426,6 +432,10 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } + public void setSettingsItems(List settingsItems) { + this.settingsItems = settingsItems; + } + public File getFile() { return file; } @@ -434,11 +444,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { this.file = file; } - public enum State { - EXPORT, - IMPORT - } - boolean isContainsInDataToOperate(AdditionalDataWrapper.Type type, Object object) { return dataToOperate.contains(object); @@ -450,6 +455,11 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { // return false; } + public enum State { + EXPORT, + IMPORT + } + class ProfileAdditionalDataAdapter extends OsmandBaseExpandableListAdapter { private OsmandApplication app; @@ -458,7 +468,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private int profileColor; - ProfileAdditionalDataAdapter(OsmandApplication app, List list, int profileColor) { this.app = app; this.list = list; @@ -513,7 +522,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false); } - boolean isLastGroup = groupPosition == getGroupCount() - 1; final AdditionalDataWrapper.Type type = list.get(groupPosition).getType(); @@ -599,7 +607,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { icon.setImageDrawable(app.getUIUtilities().getIcon(iconRes != 0 ? iconRes : R.drawable.ic_person, profileColor)); break; case MAP_SOURCES: - title.setText(((MapSourceWrapper) currentItem).getName()); + title.setText(((TileSourceManager.TileSourceTemplate) currentItem).getName()); icon.setVisibility(View.INVISIBLE); icon.setImageResource(R.drawable.ic_action_info_dark); break; @@ -631,26 +639,4 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } } - - public class MapSourceWrapper { - private String name; - private String url; - - MapSourceWrapper(String name, String url) { - this.name = name; - this.url = url; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getUrl() { - return url; - } - } } From ab77ea143c8fb89923500a5a2d09e472be371f18 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Thu, 6 Feb 2020 16:33:56 +0200 Subject: [PATCH 08/42] wip --- .../layout/profile_data_list_item_child.xml | 5 +- .../layout/profile_data_list_item_group.xml | 10 +- .../plus/profiles/AdditionalDataWrapper.java | 2 +- .../ExportImportProfileBottomSheet.java | 175 +++++++++++------- .../osmand/plus/render/RendererRegistry.java | 4 + 5 files changed, 121 insertions(+), 75 deletions(-) diff --git a/OsmAnd/res/layout/profile_data_list_item_child.xml b/OsmAnd/res/layout/profile_data_list_item_child.xml index eb9b1705d0..be6477bb17 100644 --- a/OsmAnd/res/layout/profile_data_list_item_child.xml +++ b/OsmAnd/res/layout/profile_data_list_item_child.xml @@ -22,9 +22,10 @@ diff --git a/OsmAnd/res/layout/profile_data_list_item_group.xml b/OsmAnd/res/layout/profile_data_list_item_group.xml index e0c7ff7203..2f99266f6a 100644 --- a/OsmAnd/res/layout/profile_data_list_item_group.xml +++ b/OsmAnd/res/layout/profile_data_list_item_group.xml @@ -3,12 +3,12 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="center_vertical" android:orientation="vertical"> @@ -30,14 +30,14 @@ android:id="@+id/title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.ListItemCategoryTitle" + android:textColor="?android:textColorPrimary" + android:textSize="@dimen/default_list_text_size" tools:text="Quick actions" /> @@ -50,7 +50,7 @@ android:layout_height="match_parent" android:layout_marginTop="@dimen/content_padding" android:layout_marginBottom="@dimen/content_padding" - android:background="?attr/divider_color_basic" /> + android:background="?attr/list_divider" /> diff --git a/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java index a4358828ac..ac16e83fd4 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java +++ b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java @@ -30,6 +30,6 @@ public class AdditionalDataWrapper { POI_TYPES, MAP_SOURCES, CUSTOM_RENDER_STYLE, - ROUTING + CUSTOM_ROUTING } } diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index dfee2499ba..e239ac2a3e 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -12,7 +12,6 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; import android.support.v4.widget.CompoundButtonCompat; -import android.support.v4.widget.NestedScrollView; import android.support.v7.widget.SwitchCompat; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -21,7 +20,6 @@ import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ExpandableListView; import android.widget.ImageView; -import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; @@ -31,7 +29,6 @@ import net.osmand.PlatformUtil; import net.osmand.map.TileSourceManager; import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.SettingsHelper; import net.osmand.plus.UiUtilities; @@ -52,6 +49,7 @@ import org.apache.commons.logging.Log; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -64,30 +62,26 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private static final String STATE_KEY = "EXPORT_IMPORT_DIALOG_STATE_KEY"; - private OsmandApplication app; - - private Context context; - - private OsmandSettings settings; - - private ApplicationMode profile; - private boolean includeAdditionalData = false; private boolean containsAdditionalData = false; + private OsmandApplication app; + + private ApplicationMode profile; + private State state; private List dataList = new ArrayList<>(); - private ExpandableListView listView; - - private ProfileAdditionalDataAdapter adapter; - private List dataToOperate = new ArrayList<>(); private List settingsItems; + private ExpandableListView listView; + + private ProfileAdditionalDataAdapter adapter; + private SettingsHelper.ProfileSettingsItem profileSettingsItem; private File file; @@ -96,8 +90,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = requiredMyApplication(); - context = requireContext(); - settings = app.getSettings(); Bundle bundle = getArguments(); if (bundle != null) { this.state = (State) getArguments().getSerializable(STATE_KEY); @@ -118,8 +110,9 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { if (context == null) { return; } + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); - profile = state == State.IMPORT ? getAppModeFromItems() : getAppMode(); + profile = state == State.IMPORT ? getAppModeFromSettingsItems() : getAppMode(); int profileColor = profile.getIconColorInfo().getColor(nightMode); int colorNoAlpha = ContextCompat.getColor(context, profileColor); @@ -152,9 +145,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { .create(); items.add(descriptionItem); - - final View additionalDataView = View.inflate(new ContextThemeWrapper(context, themeRes), - R.layout.bottom_sheet_item_additional_data, null); + final View additionalDataView = inflater.inflate(R.layout.bottom_sheet_item_additional_data, null); listView = additionalDataView.findViewById(R.id.list); SwitchCompat switchItem = additionalDataView.findViewById(R.id.switchItem); switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); @@ -166,7 +157,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { listView.setVisibility(includeAdditionalData ? View.VISIBLE : View.GONE); if (includeAdditionalData && state == State.IMPORT) { - updateDataFromSettingsItems(); + updateDataToOperateFromSettingsItems(); } setupHeightAndBackground(getView()); } @@ -212,7 +203,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { return false; } - private ApplicationMode getAppModeFromItems() { + private ApplicationMode getAppModeFromSettingsItems() { for (SettingsHelper.SettingsItem item : settingsItems) { if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { profileSettingsItem = ((SettingsHelper.ProfileSettingsItem) item); @@ -226,10 +217,10 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { List dataList = new ArrayList<>(); QuickActionFactory factory = new QuickActionFactory(); - List quickActions = factory.parseActiveActionsList(settings.QUICK_ACTION_LIST.get()); - if (!quickActions.isEmpty()) { + List actionsList = factory.parseActiveActionsList(app.getSettings().QUICK_ACTION_LIST.get()); + if (!actionsList.isEmpty()) { dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.QUICK_ACTIONS, quickActions)); + AdditionalDataWrapper.Type.QUICK_ACTIONS, actionsList)); } List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); @@ -240,29 +231,49 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { )); } - List mapSourceWrapperList = new ArrayList<>(); - final LinkedHashMap entriesMap = new LinkedHashMap<>(settings.getTileSourceEntries(false)); - for (Map.Entry entry : entriesMap.entrySet()) { + List tileSourceTemplates = new ArrayList<>(); + final LinkedHashMap tileSourceEntries = new LinkedHashMap<>(app.getSettings().getTileSourceEntries(false)); + for (Map.Entry entry : tileSourceEntries.entrySet()) { File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + entry.getKey()); - TileSourceManager.TileSourceTemplate template = TileSourceManager.createTileSourceTemplate(f); - if (template != null) { - mapSourceWrapperList.add(template); + if (f != null) { + TileSourceManager.TileSourceTemplate template = TileSourceManager.createTileSourceTemplate(f); + if (template != null) { + tileSourceTemplates.add(template); + } } } - if (!mapSourceWrapperList.isEmpty()) { + if (!tileSourceTemplates.isEmpty()) { dataList.add(new AdditionalDataWrapper( AdditionalDataWrapper.Type.MAP_SOURCES, - mapSourceWrapperList + tileSourceTemplates )); } + Map externalRenderers = app.getRendererRegistry().getExternalRenderers(); + if (!externalRenderers.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE, + new ArrayList<>(externalRenderers.values()) + )); + } + + File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR); + if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) { + File[] fl = routingProfilesFolder.listFiles(); + if (fl != null && fl.length > 0) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_ROUTING, + Arrays.asList(fl) + )); + } + } + return dataList; } - private List prepareSettingsItems() { + private List prepareSettingsItemsForExport() { List settingsItems = new ArrayList<>(); settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile)); - if (includeAdditionalData) { settingsItems.addAll(prepareAdditionalSettingsItems()); } @@ -273,14 +284,16 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { List settingsItems = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); - List mapSourceWrappers = new ArrayList<>(); + List tileSourceTemplates = new ArrayList<>(); for (Object object : dataToOperate) { if (object instanceof QuickAction) { quickActions.add((QuickAction) object); } else if (object instanceof PoiUIFilter) { poiUIFilters.add((PoiUIFilter) object); } else if (object instanceof TileSourceManager.TileSourceTemplate) { - mapSourceWrappers.add((TileSourceManager.TileSourceTemplate) object); + tileSourceTemplates.add((TileSourceManager.TileSourceTemplate) object); + } else if (object instanceof File) { + settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object)); } } if (!quickActions.isEmpty()) { @@ -289,8 +302,8 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { if (!poiUIFilters.isEmpty()) { settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); } - if (!mapSourceWrappers.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), mapSourceWrappers)); + if (!tileSourceTemplates.isEmpty()) { + settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), tileSourceTemplates)); } return settingsItems; } @@ -300,7 +313,8 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { for (SettingsHelper.SettingsItem item : settingsItems) { containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION) || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS) - || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES); + || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES) + || item.getType().equals(SettingsHelper.SettingsItemType.FILE); if (containsData) { break; } @@ -308,38 +322,62 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { return containsData; } - private void updateDataFromSettingsItems() { + private void updateDataToOperateFromSettingsItems() { List dataList = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); - List mapSourceWrappers = new ArrayList<>(); + List tileSourceTemplates = new ArrayList<>(); + List routingFilesList = new ArrayList<>(); + List renderFilesList = new ArrayList<>(); + for (SettingsHelper.SettingsItem item : settingsItems) { if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) { quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS)) { poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).getPoiUIFilters()); } else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES)) { - mapSourceWrappers.addAll(((SettingsHelper.MapSourcesSettingsItem) item).getMapSources()); + tileSourceTemplates.addAll(((SettingsHelper.MapSourcesSettingsItem) item).getMapSources()); + } else if (item.getType().equals(SettingsHelper.SettingsItemType.FILE)) { + if (item.getName().startsWith("/rendering/")) { + renderFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile()); + } else if (item.getName().startsWith("/routing/")) { + routingFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile()); + } } } + if (!quickActions.isEmpty()) { dataList.add(new AdditionalDataWrapper( AdditionalDataWrapper.Type.QUICK_ACTIONS, quickActions)); + dataToOperate.addAll(quickActions); } if (!poiUIFilters.isEmpty()) { dataList.add(new AdditionalDataWrapper( AdditionalDataWrapper.Type.POI_TYPES, poiUIFilters)); + dataToOperate.addAll(poiUIFilters); } - if (!mapSourceWrappers.isEmpty()) { + if (!tileSourceTemplates.isEmpty()) { dataList.add(new AdditionalDataWrapper( AdditionalDataWrapper.Type.MAP_SOURCES, - mapSourceWrappers + tileSourceTemplates )); + dataToOperate.addAll(tileSourceTemplates); } - for (AdditionalDataWrapper dataWrapper : dataList) { - dataToOperate.addAll(dataWrapper.getItems()); + if (!renderFilesList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE, + renderFilesList + )); + dataToOperate.addAll(renderFilesList); + } + if (!routingFilesList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_ROUTING, + routingFilesList + )); + dataToOperate.addAll(routingFilesList); } adapter.updateList(dataList); } @@ -375,13 +413,12 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { app.showToastMessage(R.string.export_profile_failed); } } - }, prepareSettingsItems()); + }, prepareSettingsItemsForExport()); } } private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) { try { - Context ctx = requireContext(); final Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString())); @@ -391,7 +428,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { startActivity(sendIntent); dismiss(); } catch (Exception e) { - Toast.makeText(context, R.string.export_profile_failed, Toast.LENGTH_SHORT).show(); + Toast.makeText(requireContext(), R.string.export_profile_failed, Toast.LENGTH_SHORT).show(); LOG.error("Share profile error", e); } } @@ -444,17 +481,6 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { this.file = file; } - boolean isContainsInDataToOperate(AdditionalDataWrapper.Type type, Object object) { - return dataToOperate.contains(object); - -// for (AdditionalDataWrapper data : dataList) { -// if (data.getType() == type) { -// return data.getItems().contains(object); -// } -// } -// return false; - } - public enum State { EXPORT, IMPORT @@ -518,7 +544,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View group = convertView; if (group == null) { - LayoutInflater inflater = (LayoutInflater) app.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false); } @@ -545,7 +571,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { if (checkBox.isChecked()) { for (Object object : listItems) { - if (!isContainsInDataToOperate(type, object)) { + if (!dataToOperate.contains(object)) { dataToOperate.add(object); } } @@ -565,7 +591,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { View child = convertView; if (child == null) { - LayoutInflater inflater = (LayoutInflater) app.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); child = inflater.inflate(R.layout.profile_data_list_item_child, parent, false); } final Object currentItem = list.get(groupPosition).getItems().get(childPosition); @@ -582,7 +608,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { divider.setVisibility(isLastChild && !isLastGroup ? View.VISIBLE : View.GONE); CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor))); - checkBox.setChecked(isContainsInDataToOperate(type, currentItem)); + checkBox.setChecked(dataToOperate.contains(currentItem)); checkBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -591,6 +617,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } else { dataToOperate.remove(currentItem); } + notifyDataSetInvalidated(); } }); @@ -611,6 +638,20 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { icon.setVisibility(View.INVISIBLE); icon.setImageResource(R.drawable.ic_action_info_dark); break; + case CUSTOM_RENDER_STYLE: + String renderName = ((File) currentItem).getName(); + renderName = renderName.replace('_', ' ').replaceAll(".render.xml", ""); + title.setText(renderName); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; + case CUSTOM_ROUTING: + String routingName = ((File) currentItem).getName(); + routingName = routingName.replace('_', ' ').replaceAll(".xml", ""); + title.setText(routingName); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; default: return child; } @@ -632,7 +673,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { return R.string.quick_action_map_source_title; case CUSTOM_RENDER_STYLE: return R.string.shared_string_custom_rendering_style; - case ROUTING: + case CUSTOM_ROUTING: return R.string.shared_string_routing; default: return R.string.access_empty_list; diff --git a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java index dab94170ed..64d091269c 100644 --- a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java +++ b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java @@ -343,4 +343,8 @@ public class RendererRegistry { } return null; } + + public Map getExternalRenderers() { + return externalRenderers; + } } From af5efd12b7c248d11df228e8b81aab48e36c0962 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Thu, 6 Feb 2020 19:20:26 +0200 Subject: [PATCH 09/42] refactor / change to ITileSource --- .../main/java/net/osmand/map/ITileSource.java | 2 + .../src/net/osmand/plus/SQLiteTileSource.java | 5 ++ .../src/net/osmand/plus/SettingsHelper.java | 87 +++++++++++-------- .../ExportImportProfileBottomSheet.java | 30 ++++--- 4 files changed, 77 insertions(+), 47 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java b/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java index b33c232c29..6d91b00545 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java @@ -12,6 +12,8 @@ public interface ITileSource { public String getUrlToLoad(int x, int y, int zoom); + public String getUrlTemplate(); + public byte[] getBytes(int x, int y, int zoom, String dirWithTiles) throws IOException; public int getMinimumZoomSupported(); diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index b6ca8f5527..a40019666d 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -117,6 +117,11 @@ public class SQLiteTileSource implements ITileSource { return TileSourceTemplate.buildUrlToLoad(urlTemplate, randomsArray, x, y, zoom); } + @Override + public String getUrlTemplate() { + return this.urlTemplate; + } + @Override public int hashCode() { final int prime = 31; diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 90e978309d..4f9e016f3e 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -13,6 +13,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import net.osmand.PlatformUtil; +import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager; import net.osmand.osm.MapPoiTypes; import net.osmand.osm.PoiCategory; @@ -101,10 +102,6 @@ public class SettingsHelper { void onSettingsExportFinished(@NonNull File file, boolean succeed); } - public interface SettingsPreImportListener { - void onSettingsPreImported(boolean isSuccessful, List items); - } - public SettingsHelper(OsmandApplication app) { this.app = app; } @@ -172,7 +169,7 @@ public class SettingsHelper { @NonNull public abstract String getFileName(); - public Boolean shouldReadInCollecting() { + public Boolean shouldReadOnCollecting() { return false; } @@ -740,9 +737,10 @@ public class SettingsHelper { this.quickActions = quickActions; } - public QuickActionSettingsItem(@NonNull OsmandSettings settings, + public QuickActionSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject jsonObject) throws JSONException { - super(SettingsItemType.QUICK_ACTION, settings, jsonObject); + super(SettingsItemType.QUICK_ACTION, app.getSettings(), jsonObject); + this.app = app; } public List getQuickActions() { @@ -768,7 +766,7 @@ public class SettingsHelper { } @Override - public Boolean shouldReadInCollecting() { + public Boolean shouldReadOnCollecting() { return true; } @@ -882,7 +880,6 @@ public class SettingsHelper { public PoiUiFilterSettingsItem(OsmandApplication app, JSONObject jsonObject) throws JSONException { super(SettingsItemType.POI_UI_FILTERS, app.getSettings(), jsonObject); this.app = app; - readFromJson(jsonObject); } public List getPoiUIFilters() { @@ -912,7 +909,7 @@ public class SettingsHelper { } @Override - public Boolean shouldReadInCollecting() { + public Boolean shouldReadOnCollecting() { return true; } @@ -1004,28 +1001,32 @@ public class SettingsHelper { public static class MapSourcesSettingsItem extends OsmandSettingsItem { - private List mapSources; + private OsmandApplication app; - public MapSourcesSettingsItem(OsmandSettings settings, List mapSources) { - super(SettingsItemType.MAP_SOURCES, settings); + private List mapSources; + + public MapSourcesSettingsItem(OsmandApplication app, List mapSources) { + super(SettingsItemType.MAP_SOURCES, app.getSettings()); + this.app = app; this.mapSources = mapSources; } - public MapSourcesSettingsItem(OsmandSettings settings, JSONObject jsonObject) throws JSONException { - super(SettingsItemType.MAP_SOURCES, settings, jsonObject); + public MapSourcesSettingsItem(OsmandApplication app, JSONObject jsonObject) throws JSONException { + super(SettingsItemType.MAP_SOURCES, app.getSettings(), jsonObject); + this.app = app; } - public List getMapSources() { + public List getMapSources() { return this.mapSources; } @Override public void apply() { if (!mapSources.isEmpty()) { - for (TileSourceManager.TileSourceTemplate template : mapSources) { - boolean writed = getSettings().installTileSource(template); - LOG.info("Temaplate _" + writed); + for (ITileSource template : mapSources) { +// getSettings().installTileSource(template); } + } } @@ -1042,7 +1043,7 @@ public class SettingsHelper { } @Override - public Boolean shouldReadInCollecting() { + public Boolean shouldReadOnCollecting() { return true; } @@ -1081,10 +1082,16 @@ public class SettingsHelper { try { mapSources = new ArrayList<>(); json = new JSONObject(jsonStr); - String items = json.getString("items"); - TileSourceManager manager = new TileSourceManager(); - List templates = manager.parseTemplatesList(items); - mapSources.addAll(templates); + JSONArray items = json.getJSONArray("items"); + for (int i = 0; i < items.length(); i++) { + JSONObject object = items.getJSONObject(i); + String name = object.getString("name"); +// String url = object.getString("url"); + + +// ITileSource template +// mapSources.add(); + } } catch (JSONException e) { throw new IllegalArgumentException("Json parse error", e); } @@ -1098,9 +1105,19 @@ public class SettingsHelper { return new OsmandSettingsItemWriter(this, getSettings()) { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { - TileSourceManager manager = new TileSourceManager(); + JSONArray items = new JSONArray(); if (!mapSources.isEmpty()) { - json.put("items", manager.templatesListToString(mapSources)); + for (ITileSource template : mapSources) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("name", template.getName()); + jsonObject.put("url", template.getUrlTemplate()); + jsonObject.put("ext", template.getUrlTemplate()); + jsonObject.put("minZoom", template.getMinimumZoomSupported()); + jsonObject.put("maxZoom", template.getMaximumZoomSupported()); + jsonObject.put("expire", template.getExpirationTimeMillis()); + items.put(jsonObject); + } + json.put("items", items); } } }; @@ -1164,13 +1181,13 @@ public class SettingsHelper { item = new FileSettingsItem(app, json); break; case QUICK_ACTION: - item = new QuickActionSettingsItem(settings, json); + item = new QuickActionSettingsItem(app, json); break; case POI_UI_FILTERS: item = new PoiUiFilterSettingsItem(app, json); break; case MAP_SOURCES: - item = new MapSourcesSettingsItem(settings, json); + item = new MapSourcesSettingsItem(app, json); break; } return item; @@ -1286,8 +1303,8 @@ public class SettingsHelper { while ((entry = zis.getNextEntry()) != null) { String fileName = entry.getName(); SettingsItem item = itemsFactory.getItemByFileName(fileName); - if (item != null && collecting && item.shouldReadInCollecting() - || item != null && !collecting && !item.shouldReadInCollecting()) { + if (item != null && collecting && item.shouldReadOnCollecting() + || item != null && !collecting && !item.shouldReadOnCollecting()) { try { item.getReader().readFromStream(ois); } catch (IllegalArgumentException e) { @@ -1318,7 +1335,7 @@ public class SettingsHelper { private File file; private String latestChanges; private int version; - private Boolean isCollecting; + private boolean collectOnly; private SettingsImportListener listener; private SettingsImporter importer; @@ -1333,7 +1350,7 @@ public class SettingsHelper { this.latestChanges = latestChanges; this.version = version; importer = new SettingsImporter(app); - isCollecting = true; + collectOnly = true; } ImportAsyncTask(@NonNull File settingsFile, @NonNull List items, String latestChanges, int version, @Nullable SettingsImportListener listener) { @@ -1343,7 +1360,7 @@ public class SettingsHelper { this.latestChanges = latestChanges; this.version = version; importer = new SettingsImporter(app); - isCollecting = false; + collectOnly = false; } @Override @@ -1358,7 +1375,7 @@ public class SettingsHelper { @Override protected List doInBackground(Void... voids) { - if (isCollecting) { + if (collectOnly) { try { return importer.collectItems(file); } catch (IllegalArgumentException e) { @@ -1374,7 +1391,7 @@ public class SettingsHelper { @Override protected void onPostExecute(List items) { - if (isCollecting) { + if (collectOnly) { listener.onSettingsImportFinished(true, false, items); } else { this.items = items; diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index e239ac2a3e..eea5562b21 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -13,7 +13,6 @@ import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; import android.support.v4.widget.CompoundButtonCompat; import android.support.v7.widget.SwitchCompat; -import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -26,10 +25,12 @@ import android.widget.Toast; import net.osmand.AndroidUtils; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; +import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager; import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; +import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.SettingsHelper; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; @@ -231,21 +232,26 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { )); } - List tileSourceTemplates = new ArrayList<>(); - final LinkedHashMap tileSourceEntries = new LinkedHashMap<>(app.getSettings().getTileSourceEntries(false)); + List iTileSources = new ArrayList<>(); + final LinkedHashMap tileSourceEntries = new LinkedHashMap<>(app.getSettings().getTileSourceEntries(true)); for (Map.Entry entry : tileSourceEntries.entrySet()) { File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + entry.getKey()); if (f != null) { - TileSourceManager.TileSourceTemplate template = TileSourceManager.createTileSourceTemplate(f); - if (template != null) { - tileSourceTemplates.add(template); + ITileSource template; + if (f.getName().endsWith(SQLiteTileSource.EXT)) { + template = new SQLiteTileSource(app, f, TileSourceManager.getKnownSourceTemplates()); + } else { + template = TileSourceManager.createTileSourceTemplate(f); + } + if (template != null && template.getUrlTemplate() != null) { + iTileSources.add(template); } } } - if (!tileSourceTemplates.isEmpty()) { + if (!iTileSources.isEmpty()) { dataList.add(new AdditionalDataWrapper( AdditionalDataWrapper.Type.MAP_SOURCES, - tileSourceTemplates + iTileSources )); } @@ -284,7 +290,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { List settingsItems = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); - List tileSourceTemplates = new ArrayList<>(); + List tileSourceTemplates = new ArrayList<>(); for (Object object : dataToOperate) { if (object instanceof QuickAction) { quickActions.add((QuickAction) object); @@ -303,7 +309,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); } if (!tileSourceTemplates.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app.getSettings(), tileSourceTemplates)); + settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates)); } return settingsItems; } @@ -326,7 +332,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { List dataList = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); - List tileSourceTemplates = new ArrayList<>(); + List tileSourceTemplates = new ArrayList<>(); List routingFilesList = new ArrayList<>(); List renderFilesList = new ArrayList<>(); @@ -634,7 +640,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { icon.setImageDrawable(app.getUIUtilities().getIcon(iconRes != 0 ? iconRes : R.drawable.ic_person, profileColor)); break; case MAP_SOURCES: - title.setText(((TileSourceManager.TileSourceTemplate) currentItem).getName()); + title.setText(((ITileSource) currentItem).getName()); icon.setVisibility(View.INVISIBLE); icon.setImageResource(R.drawable.ic_action_info_dark); break; From 6912cb9b8cdead0b27b68e89426687fd14b00dcb Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Fri, 7 Feb 2020 19:11:51 +0200 Subject: [PATCH 10/42] export sql mapsourse --- .../main/java/net/osmand/map/ITileSource.java | 11 ++ .../net/osmand/map/TileSourceManager.java | 15 +++ .../src/net/osmand/plus/SQLiteTileSource.java | 101 +++++++++++++++++- .../src/net/osmand/plus/SettingsHelper.java | 54 ++++++++-- .../ExportImportProfileBottomSheet.java | 5 +- 5 files changed, 173 insertions(+), 13 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java b/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java index 6d91b00545..503467b93b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/ITileSource.java @@ -34,4 +34,15 @@ public interface ITileSource { public void deleteTiles(String path); + public int getAvgSize(); + + public String getRule(); + + public String getRandoms(); + + public boolean isInvertedYTile(); + + public boolean isTimeSupported(); + + public boolean getInversiveZoom(); } diff --git a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java index 5fd510db61..38e8307abb 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java @@ -178,6 +178,16 @@ public class TileSourceManager { return invertedYTile; } + @Override + public boolean isTimeSupported() { + return expirationTimeMillis != -1; + } + + @Override + public boolean getInversiveZoom() { + return false; + } + public void setInvertedYTile(boolean invertedYTile) { this.invertedYTile = invertedYTile; } @@ -414,6 +424,11 @@ public class TileSourceManager { } } } + + @Override + public int getAvgSize() { + return this.avgSize; + } } private static Map readMetaInfoFile(File dir) { diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index a40019666d..c3b84f35f3 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -1,5 +1,6 @@ package net.osmand.plus; +import android.content.ContentValues; import android.database.sqlite.SQLiteDiskIOException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -22,6 +23,10 @@ import java.nio.ByteBuffer; import java.util.Arrays; import java.util.List; +import static net.osmand.IndexConstants.APP_DIR; +import static net.osmand.IndexConstants.SQLITE_EXT; +import static net.osmand.IndexConstants.TILES_INDEX_DIR; + public class SQLiteTileSource implements ITileSource { @@ -33,7 +38,7 @@ public class SQLiteTileSource implements ITileSource { private String urlTemplate = null; private String name; private SQLiteConnection db = null; - private final File file; + private File file = null; private int minZoom = 1; private int maxZoom = 17; private boolean inversiveZoom = true; // BigPlanet @@ -51,6 +56,14 @@ public class SQLiteTileSource implements ITileSource { private OsmandApplication ctx; private boolean onlyReadonlyAvailable = false; + private static final String TILES_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS tiles (" + + "x, " + + "y, " + + "z, " + + "s, " + + "image, " + + "time" + + ")"; public SQLiteTileSource(OsmandApplication ctx, File f, List toFindUrl){ this.ctx = ctx; @@ -72,6 +85,49 @@ public class SQLiteTileSource implements ITileSource { } } + + public SQLiteTileSource(OsmandApplication ctx, String name, int minZoom, int maxZoom, String urlTemplate, + String randoms, boolean isEllipsoid, boolean invertedY, String referer, + boolean timeSupported, long expirationTimeMillis, boolean inversiveZoom) { + this.ctx = ctx; + this.name = name; + this.urlTemplate = urlTemplate; + this.maxZoom = maxZoom; + this.minZoom = minZoom; + this.isEllipsoid = isEllipsoid; + this.expirationTimeMillis = expirationTimeMillis; + this.randoms = randoms; + this.referer = referer; + this.invertedY = invertedY; + this.timeSupported = timeSupported; + this.inversiveZoom = inversiveZoom; + } + + public void createDataBase() { + db = ctx.getSQLiteAPI().getOrCreateDatabase( + ctx.getAppPath(TILES_INDEX_DIR).getAbsolutePath() + "/" + name + SQLITE_EXT, true); + db.execSQL("CREATE TABLE IF NOT EXISTS info (" + + "url " + + ");"); + db.execSQL("INSERT INTO info (url) VALUES ('" + urlTemplate + "');"); + +// db.execSQL("INSERT INTO info VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", +// new Object[]{minZoom, maxZoom, urlTemplate, randoms, isEllipsoid ? 1 : 0, +// invertedY ? 1 : 0, referer, timeSupported ? "yes" : "no", timeSupported ? "yes" : "no", +// getExpirationTimeMinutes(), inversiveZoom ? "BigPlanet" : ""}); + + addInfoColumn("minzoom", String.valueOf(minZoom)); + addInfoColumn("maxzoom", String.valueOf(maxZoom)); + addInfoColumn("randoms", randoms); + addInfoColumn("ellipsoid", isEllipsoid ? "1" : "0"); + addInfoColumn("inverted_y", invertedY ? "1" : "0"); + addInfoColumn("referer", referer); + addInfoColumn("timesupported", timeSupported ? "yes" : "no"); + addInfoColumn("expireminutes", String.valueOf(getExpirationTimeMinutes())); + + db.execSQL(TILES_TABLE_CREATE); + db.close(); + } @Override public int getBitDensity() { @@ -119,7 +175,16 @@ public class SQLiteTileSource implements ITileSource { @Override public String getUrlTemplate() { - return this.urlTemplate; + if (this.urlTemplate != null) { + return this.urlTemplate; + } else { + SQLiteConnection db = getDatabase(); + if (db == null || db.isReadOnly() || urlTemplate == null) { + return null; + } else { + return this.urlTemplate; + } + } } @Override @@ -434,7 +499,37 @@ public class SQLiteTileSource implements ITileSource { } db.execSQL("DELETE FROM tiles"); } - + + @Override + public int getAvgSize() { + return base != null ? base.getAvgSize() : -1; + } + + @Override + public String getRule() { + return this.rule; + } + + @Override + public String getRandoms() { + return this.randoms; + } + + @Override + public boolean isInvertedYTile() { + return this.invertedY; + } + + @Override + public boolean isTimeSupported() { + return this.timeSupported; + } + + @Override + public boolean getInversiveZoom() { + return this.inversiveZoom; + } + /** * Makes method synchronized to give a little more time for get methods and * let all writing attempts to wait outside of this method diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 4f9e016f3e..2ebb252685 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -59,6 +59,7 @@ import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT; +import static net.osmand.IndexConstants.TILES_INDEX_DIR; /* Usage: @@ -1024,9 +1025,12 @@ public class SettingsHelper { public void apply() { if (!mapSources.isEmpty()) { for (ITileSource template : mapSources) { -// getSettings().installTileSource(template); + if (template instanceof TileSourceManager.TileSourceTemplate) { + getSettings().installTileSource((TileSourceManager.TileSourceTemplate) template); + } else { + ((SQLiteTileSource) template).createDataBase(); + } } - } } @@ -1085,12 +1089,32 @@ public class SettingsHelper { JSONArray items = json.getJSONArray("items"); for (int i = 0; i < items.length(); i++) { JSONObject object = items.getJSONObject(i); - String name = object.getString("name"); -// String url = object.getString("url"); + boolean sql = object.optBoolean("sql"); + String name = object.optString("name"); + int minZoom = object.optInt("minZoom", 1); + int maxZoom = object.optInt("maxZoom", 17); + String url = object.optString("url"); + String randoms = object.optString("randoms"); + boolean ellipsoid = object.optBoolean("ellipsoid", false); + boolean invertedY = object.optBoolean("inverted_y", false); + String referer = object.optString("referer"); + boolean timesupported = object.optBoolean("timesupported", false); + long expire = object.optLong("expire"); + boolean inversiveZoom = object.optBoolean("inversiveZoom", false); + String ext = object.optString("ext"); + int tileSize = object.optInt("tileSize"); + int bitDensity = object.optInt("bitDensity"); + int avgSize = object.optInt("avgSize"); + String rule = object.optString("rule"); -// ITileSource template -// mapSources.add(); + ITileSource template; + if (!sql) { + template = new TileSourceManager.TileSourceTemplate(name, url, ext, maxZoom, minZoom, tileSize, bitDensity, avgSize); + } else { + template = new SQLiteTileSource(app, name, minZoom, maxZoom, url, randoms, ellipsoid, invertedY, referer, timesupported, expire, inversiveZoom); + } + mapSources.add(template); } } catch (JSONException e) { throw new IllegalArgumentException("Json parse error", e); @@ -1109,12 +1133,26 @@ public class SettingsHelper { if (!mapSources.isEmpty()) { for (ITileSource template : mapSources) { JSONObject jsonObject = new JSONObject(); + boolean sql = template instanceof SQLiteTileSource; + jsonObject.put("sql", sql); jsonObject.put("name", template.getName()); - jsonObject.put("url", template.getUrlTemplate()); - jsonObject.put("ext", template.getUrlTemplate()); jsonObject.put("minZoom", template.getMinimumZoomSupported()); jsonObject.put("maxZoom", template.getMaximumZoomSupported()); + jsonObject.put("url", template.getUrlTemplate()); + jsonObject.put("randoms", template.getRandoms()); + jsonObject.put("ellipsoid", template.isEllipticYTile()); + jsonObject.put("inverted_y", template.isInvertedYTile()); + jsonObject.put("referer", template.getReferer()); + jsonObject.put("timesupported", template.isTimeSupported()); jsonObject.put("expire", template.getExpirationTimeMillis()); + jsonObject.put("inversiveZoom", template.getInversiveZoom()); + + jsonObject.put("ext", template.getTileFormat()); + jsonObject.put("tileSize", template.getTileSize()); + jsonObject.put("bitDensity", template.getBitDensity()); + jsonObject.put("avgSize", template.getAvgSize()); + jsonObject.put("rule", template.getRule()); + items.put(jsonObject); } json.put("items", items); diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index eea5562b21..710c649586 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -296,8 +296,9 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { quickActions.add((QuickAction) object); } else if (object instanceof PoiUIFilter) { poiUIFilters.add((PoiUIFilter) object); - } else if (object instanceof TileSourceManager.TileSourceTemplate) { - tileSourceTemplates.add((TileSourceManager.TileSourceTemplate) object); + } else if (object instanceof TileSourceManager.TileSourceTemplate + || object instanceof SQLiteTileSource) { + tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object)); } From 148e6a2b1ee13ce59df467888baf0ca1037d51a5 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Mon, 10 Feb 2020 12:08:29 +0200 Subject: [PATCH 11/42] sqlite map sources with urls --- .../src/net/osmand/plus/SQLiteTileSource.java | 23 +++++-------------- .../src/net/osmand/plus/SettingsHelper.java | 4 ++-- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index c3b84f35f3..3771b2c1b0 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -56,14 +56,7 @@ public class SQLiteTileSource implements ITileSource { private OsmandApplication ctx; private boolean onlyReadonlyAvailable = false; - private static final String TILES_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS tiles (" + - "x, " + - "y, " + - "z, " + - "s, " + - "image, " + - "time" + - ")"; + private static final String TILES_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS \"tiles\" (\"x\" INTEGER NOT NULL, \"y\" INTEGER NOT NULL, \"z\" INTEGER NOT NULL, \"s\" INTEGER, \"image\" BLOB, \"time\" INTEGER, PRIMARY KEY (\"x\", \"y\", \"z\"))"; public SQLiteTileSource(OsmandApplication ctx, File f, List toFindUrl){ this.ctx = ctx; @@ -106,18 +99,14 @@ public class SQLiteTileSource implements ITileSource { public void createDataBase() { db = ctx.getSQLiteAPI().getOrCreateDatabase( ctx.getAppPath(TILES_INDEX_DIR).getAbsolutePath() + "/" + name + SQLITE_EXT, true); + db.execSQL("CREATE TABLE IF NOT EXISTS info (" + - "url " + + "minzoom, " + + "maxzoom " + ");"); - db.execSQL("INSERT INTO info (url) VALUES ('" + urlTemplate + "');"); + db.execSQL("INSERT INTO info (minzoom,maxzoom) VALUES ('" + minZoom + "','" + maxZoom + "');"); -// db.execSQL("INSERT INTO info VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", -// new Object[]{minZoom, maxZoom, urlTemplate, randoms, isEllipsoid ? 1 : 0, -// invertedY ? 1 : 0, referer, timeSupported ? "yes" : "no", timeSupported ? "yes" : "no", -// getExpirationTimeMinutes(), inversiveZoom ? "BigPlanet" : ""}); - - addInfoColumn("minzoom", String.valueOf(minZoom)); - addInfoColumn("maxzoom", String.valueOf(maxZoom)); + addInfoColumn("url", urlTemplate); addInfoColumn("randoms", randoms); addInfoColumn("ellipsoid", isEllipsoid ? "1" : "0"); addInfoColumn("inverted_y", invertedY ? "1" : "0"); diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 2ebb252685..f7b4fd492e 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -1091,8 +1091,8 @@ public class SettingsHelper { JSONObject object = items.getJSONObject(i); boolean sql = object.optBoolean("sql"); String name = object.optString("name"); - int minZoom = object.optInt("minZoom", 1); - int maxZoom = object.optInt("maxZoom", 17); + int minZoom = object.optInt("minZoom"); + int maxZoom = object.optInt("maxZoom"); String url = object.optString("url"); String randoms = object.optString("randoms"); boolean ellipsoid = object.optBoolean("ellipsoid", false); From 11e51ef318a4d79c4d3ed5f133fc845c72ac6549 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Mon, 10 Feb 2020 17:18:05 +0200 Subject: [PATCH 12/42] sqlite map sources with urls / screen rotating / quick action apply --- .../src/net/osmand/plus/SQLiteTileSource.java | 9 ++++-- .../src/net/osmand/plus/SettingsHelper.java | 27 ++++++++++++++--- .../ExportImportProfileBottomSheet.java | 29 ++++++++++++++++--- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index 3771b2c1b0..23553bede7 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -1,6 +1,6 @@ package net.osmand.plus; -import android.content.ContentValues; +import android.database.SQLException; import android.database.sqlite.SQLiteDiskIOException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -23,7 +23,6 @@ import java.nio.ByteBuffer; import java.util.Arrays; import java.util.List; -import static net.osmand.IndexConstants.APP_DIR; import static net.osmand.IndexConstants.SQLITE_EXT; import static net.osmand.IndexConstants.TILES_INDEX_DIR; @@ -312,7 +311,11 @@ public class SQLiteTileSource implements ITileSource { private void addInfoColumn(String columnName, String value) { if(!onlyReadonlyAvailable) { - db.execSQL("alter table info add column "+columnName+" TEXT"); + try { + db.execSQL("alter table info add column " + columnName + " TEXT"); + } catch (SQLException e) { + LOG.info("Error adding column " + e); + } db.execSQL("update info set "+columnName+" = '"+value+"'"); } } diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index f7b4fd492e..289662c66d 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -20,6 +20,7 @@ import net.osmand.osm.PoiCategory; import net.osmand.plus.ApplicationMode.ApplicationModeBean; import net.osmand.plus.ApplicationMode.ApplicationModeBuilder; import net.osmand.plus.OsmandSettings.OsmandPreference; +import net.osmand.plus.activities.MapActivity; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.quickaction.QuickActionFactory; @@ -93,6 +94,7 @@ public class SettingsHelper { private boolean importing; private boolean importSuspended; + private boolean collectOnly; private ImportAsyncTask importTask; public interface SettingsImportListener { @@ -113,7 +115,7 @@ public class SettingsHelper { public void setActivity(Activity activity) { this.activity = activity; - if (importing) { + if (importing && !collectOnly) { importTask.processNextItem(); } } @@ -762,7 +764,7 @@ public class SettingsHelper { } } newActions.addAll(quickActions); - getSettings().QUICK_ACTION_LIST.set(factory.quickActionListToString(newActions)); + ((MapActivity) app.getSettingsHelper().getActivity()).getMapLayers().getQuickActionRegistry().updateQuickActions(newActions); } } @@ -1373,7 +1375,6 @@ public class SettingsHelper { private File file; private String latestChanges; private int version; - private boolean collectOnly; private SettingsImportListener listener; private SettingsImporter importer; @@ -1429,10 +1430,10 @@ public class SettingsHelper { @Override protected void onPostExecute(List items) { + this.items = items; if (collectOnly) { listener.onSettingsImportFinished(true, false, items); } else { - this.items = items; if (items != null && items.size() > 0) { processNextItem(); } @@ -1528,6 +1529,24 @@ public class SettingsHelper { processedItems.add(item); processNextItem(); } + + public List getItems() { + return this.items; + } + + public File getFile() { + return this.file; + } + } + + @Nullable + public List getSettingsItems() { + return this.importTask.getItems(); + } + + @Nullable + public File getSettingsFile() { + return this.importTask.getFile(); } @SuppressLint("StaticFieldLeak") diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index 710c649586..b5b7fc34c5 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -63,6 +63,8 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { private static final String STATE_KEY = "EXPORT_IMPORT_DIALOG_STATE_KEY"; + private static final String INCLUDE_ADDITIONAL_DATA_KEY = "INCLUDE_ADDITIONAL_DATA_KEY"; + private boolean includeAdditionalData = false; private boolean containsAdditionalData = false; @@ -89,6 +91,9 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { @Override public void onCreate(Bundle savedInstanceState) { + if (savedInstanceState != null) { + includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY); + } super.onCreate(savedInstanceState); app = requiredMyApplication(); Bundle bundle = getArguments(); @@ -96,6 +101,12 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { this.state = (State) getArguments().getSerializable(STATE_KEY); } if (state == State.IMPORT) { + if (settingsItems == null) { + settingsItems = app.getSettingsHelper().getSettingsItems(); + } + if (file == null) { + file = app.getSettingsHelper().getSettingsFile(); + } containsAdditionalData = checkAdditionalDataContains(); } else { dataList = getAdditionalData(); @@ -105,6 +116,12 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { } } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData); + } + @Override public void createMenuItems(Bundle savedInstanceState) { final Context context = getContext(); @@ -150,7 +167,7 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { listView = additionalDataView.findViewById(R.id.list); SwitchCompat switchItem = additionalDataView.findViewById(R.id.switchItem); switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); - + switchItem.setChecked(includeAdditionalData); switchItem.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -163,8 +180,8 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { setupHeightAndBackground(getView()); } }); - - adapter = new ProfileAdditionalDataAdapter(requiredMyApplication(), dataList, profileColor); + listView.setVisibility(includeAdditionalData ? View.VISIBLE : View.GONE); + adapter = new ProfileAdditionalDataAdapter(app, dataList, profileColor); listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { @Override public void onGroupExpand(int i) { @@ -398,7 +415,11 @@ public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { app.getSettingsHelper().importSettings(file, list, "", 1, new SettingsHelper.SettingsImportListener() { @Override public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { - + if (succeed) { + app.showShortToastMessage(app.getString(R.string.file_imported_successfully, file.getName())); + } else if (empty){ + app.showShortToastMessage(app.getString(R.string.file_import_error, file.getName(), app.getString(R.string.shared_string_unexpected_error))); + } } }); dismiss(); From c8d76dc85c5cd7c9afdb12f7599d6e50830d68df Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Mon, 10 Feb 2020 17:34:19 +0200 Subject: [PATCH 13/42] corrections --- .../java/net/osmand/map/TileSourceManager.java | 14 -------------- OsmAnd/src/net/osmand/plus/SQLiteTileSource.java | 2 +- OsmAnd/src/net/osmand/plus/SettingsHelper.java | 4 ++++ 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java index 38e8307abb..79ee4e7e34 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java @@ -1,7 +1,5 @@ package net.osmand.map; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; import net.osmand.PlatformUtil; import net.osmand.osm.io.NetworkUtils; @@ -20,7 +18,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.lang.reflect.Type; import java.net.URLConnection; import java.text.MessageFormat; import java.util.ArrayList; @@ -707,15 +704,4 @@ public class TileSourceManager { templ.setRandoms(randoms); return templ; } - - public String templatesListToString(List templates) { - return new Gson().toJson(templates); - } - - public List parseTemplatesList(String json) { - Type type = new TypeToken>() { - }.getType(); - ArrayList templates = new Gson().fromJson(json, type); - return templates != null ? templates : new ArrayList(); - } } diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index 23553bede7..391ccfa48a 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -167,7 +167,7 @@ public class SQLiteTileSource implements ITileSource { return this.urlTemplate; } else { SQLiteConnection db = getDatabase(); - if (db == null || db.isReadOnly() || urlTemplate == null) { + if (db == null || urlTemplate == null) { return null; } else { return this.urlTemplate; diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 289662c66d..40177988b1 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -64,8 +64,10 @@ import static net.osmand.IndexConstants.TILES_INDEX_DIR; /* Usage: + SettingsHelper helper = app.getSettingsHelper(); File file = new File(app.getAppPath(null), "settings.zip"); + List items = new ArrayList<>(); items.add(new GlobalSettingsItem(app.getSettings())); items.add(new ProfileSettingsItem(app.getSettings(), ApplicationMode.DEFAULT)); @@ -77,7 +79,9 @@ import static net.osmand.IndexConstants.TILES_INDEX_DIR; items.add(new FileSettingsItem(app, new File(app.getAppPath(RENDERERS_DIR), "default.render.xml"))); items.add(new DataSettingsItem(new byte[] {'t', 'e', 's', 't', '1'}, "data1")); items.add(new DataSettingsItem(new byte[] {'t', 'e', 's', 't', '2'}, "data2")); + helper.exportSettings(file, items); + helper.importSettings(file); */ From 21653be128817ebe1522b8fb925924b277045a27 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Mon, 10 Feb 2020 19:04:45 +0200 Subject: [PATCH 14/42] refactor --- .../net/osmand/map/TileSourceManager.java | 1 - .../src/net/osmand/plus/SQLiteTileSource.java | 68 +- .../plus/profiles/AdditionalDataWrapper.java | 44 +- .../ExportImportProfileBottomSheet.java | 1302 ++++++++--------- 4 files changed, 714 insertions(+), 701 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java index 79ee4e7e34..41f0097f6e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java @@ -1,6 +1,5 @@ package net.osmand.map; - import net.osmand.PlatformUtil; import net.osmand.osm.io.NetworkUtils; import net.osmand.util.Algorithms; diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index 391ccfa48a..cbfbef635a 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -29,10 +29,25 @@ import static net.osmand.IndexConstants.TILES_INDEX_DIR; public class SQLiteTileSource implements ITileSource { - public static final String EXT = IndexConstants.SQLITE_EXT; private static final Log LOG = PlatformUtil.getLog(SQLiteTileSource.class); - + + private static final String MIN_ZOOM = "minzoom"; + private static final String MAX_ZOOM = "maxzoom"; + private static final String URL = "url"; + private static final String RANDOMS = "randoms"; + private static final String ELLIPSOID = "ellipsoid"; + private static final String INVERTED_Y = "inverted_y"; + private static final String REFERER = "referer"; + private static final String TIME_SUPPORTED = "timesupported"; + private static final String EXPIRE_MINUTES = "expireminutes"; + + private static final String TILES_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS tiles (x INTEGER NOT NULL, y INTEGER NOT NULL, z INTEGER NOT NULL, s INTEGER, image BLOB, time INTEGER, PRIMARY KEY (x, y, z))"; + private static final String CREATE_INDEX_X = "CREATE INDEX index_tiles_on_x ON tiles (x)"; + private static final String CREATE_INDEX_Y = "CREATE INDEX index_tiles_on_y ON tiles (y)"; + private static final String CREATE_INDEX_Z = "CREATE INDEX index_tiles_on_z ON tiles (z)"; + private static final String CREATE_INDEX_S = "CREATE INDEX index_tiles_on_s ON tiles (s)"; + private ITileSource base; private String urlTemplate = null; private String name; @@ -55,7 +70,6 @@ public class SQLiteTileSource implements ITileSource { private OsmandApplication ctx; private boolean onlyReadonlyAvailable = false; - private static final String TILES_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS \"tiles\" (\"x\" INTEGER NOT NULL, \"y\" INTEGER NOT NULL, \"z\" INTEGER NOT NULL, \"s\" INTEGER, \"image\" BLOB, \"time\" INTEGER, PRIMARY KEY (\"x\", \"y\", \"z\"))"; public SQLiteTileSource(OsmandApplication ctx, File f, List toFindUrl){ this.ctx = ctx; @@ -100,20 +114,24 @@ public class SQLiteTileSource implements ITileSource { ctx.getAppPath(TILES_INDEX_DIR).getAbsolutePath() + "/" + name + SQLITE_EXT, true); db.execSQL("CREATE TABLE IF NOT EXISTS info (" + - "minzoom, " + - "maxzoom " + + MIN_ZOOM + ", " + + MAX_ZOOM + ");"); - db.execSQL("INSERT INTO info (minzoom,maxzoom) VALUES ('" + minZoom + "','" + maxZoom + "');"); + db.execSQL("INSERT INTO info (" + MIN_ZOOM + "," + MAX_ZOOM + ") VALUES ('" + minZoom + "','" + maxZoom + "');"); - addInfoColumn("url", urlTemplate); - addInfoColumn("randoms", randoms); - addInfoColumn("ellipsoid", isEllipsoid ? "1" : "0"); - addInfoColumn("inverted_y", invertedY ? "1" : "0"); - addInfoColumn("referer", referer); - addInfoColumn("timesupported", timeSupported ? "yes" : "no"); - addInfoColumn("expireminutes", String.valueOf(getExpirationTimeMinutes())); + addInfoColumn(URL, urlTemplate); + addInfoColumn(RANDOMS, randoms); + addInfoColumn(ELLIPSOID, isEllipsoid ? "1" : "0"); + addInfoColumn(INVERTED_Y, invertedY ? "1" : "0"); + addInfoColumn(REFERER, referer); + addInfoColumn(TIME_SUPPORTED, timeSupported ? "yes" : "no"); + addInfoColumn(EXPIRE_MINUTES, String.valueOf(getExpirationTimeMinutes())); db.execSQL(TILES_TABLE_CREATE); + db.execSQL(CREATE_INDEX_X); + db.execSQL(CREATE_INDEX_Y); + db.execSQL(CREATE_INDEX_Z); + db.execSQL(CREATE_INDEX_S); db.close(); } @@ -311,11 +329,11 @@ public class SQLiteTileSource implements ITileSource { private void addInfoColumn(String columnName, String value) { if(!onlyReadonlyAvailable) { - try { - db.execSQL("alter table info add column " + columnName + " TEXT"); - } catch (SQLException e) { - LOG.info("Error adding column " + e); - } + try { + db.execSQL("alter table info add column " + columnName + " TEXT"); + } catch (SQLException e) { + LOG.info("Error adding column " + e); + } db.execSQL("update info set "+columnName+" = '"+value+"'"); } } @@ -499,27 +517,27 @@ public class SQLiteTileSource implements ITileSource { @Override public String getRule() { - return this.rule; + return rule; } @Override public String getRandoms() { - return this.randoms; + return randoms; } @Override public boolean isInvertedYTile() { - return this.invertedY; + return invertedY; } @Override public boolean isTimeSupported() { - return this.timeSupported; + return timeSupported; } @Override public boolean getInversiveZoom() { - return this.inversiveZoom; + return inversiveZoom; } /** @@ -608,8 +626,4 @@ public class SQLiteTileSource implements ITileSource { public String getReferer() { return referer; } - - } - - diff --git a/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java index ac16e83fd4..bb46a92393 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java +++ b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java @@ -4,32 +4,32 @@ import java.util.List; public class AdditionalDataWrapper { - private Type type; + private Type type; - private List items; + private List items; - public AdditionalDataWrapper(Type type, List items) { - this.type = type; - this.items = items; - } + public AdditionalDataWrapper(Type type, List items) { + this.type = type; + this.items = items; + } - public Type getType() { - return type; - } + public Type getType() { + return type; + } - public void setType(Type type) { - this.type = type; - } + public void setType(Type type) { + this.type = type; + } - public List getItems() { - return items; - } + public List getItems() { + return items; + } - public enum Type { - QUICK_ACTIONS, - POI_TYPES, - MAP_SOURCES, - CUSTOM_RENDER_STYLE, - CUSTOM_ROUTING - } + public enum Type { + QUICK_ACTIONS, + POI_TYPES, + MAP_SOURCES, + CUSTOM_RENDER_STYLE, + CUSTOM_ROUTING + } } diff --git a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java index b5b7fc34c5..8a14422a58 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ExportImportProfileBottomSheet.java @@ -57,655 +57,655 @@ import java.util.Map; public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet { - private static final Log LOG = PlatformUtil.getLog(ExportImportProfileBottomSheet.class); - - public static final String TAG = ExportImportProfileBottomSheet.class.getSimpleName(); - - private static final String STATE_KEY = "EXPORT_IMPORT_DIALOG_STATE_KEY"; - - private static final String INCLUDE_ADDITIONAL_DATA_KEY = "INCLUDE_ADDITIONAL_DATA_KEY"; - - private boolean includeAdditionalData = false; - - private boolean containsAdditionalData = false; - - private OsmandApplication app; - - private ApplicationMode profile; - - private State state; - - private List dataList = new ArrayList<>(); - - private List dataToOperate = new ArrayList<>(); - - private List settingsItems; - - private ExpandableListView listView; - - private ProfileAdditionalDataAdapter adapter; - - private SettingsHelper.ProfileSettingsItem profileSettingsItem; - - private File file; - - @Override - public void onCreate(Bundle savedInstanceState) { - if (savedInstanceState != null) { - includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY); - } - super.onCreate(savedInstanceState); - app = requiredMyApplication(); - Bundle bundle = getArguments(); - if (bundle != null) { - this.state = (State) getArguments().getSerializable(STATE_KEY); - } - if (state == State.IMPORT) { - if (settingsItems == null) { - settingsItems = app.getSettingsHelper().getSettingsItems(); - } - if (file == null) { - file = app.getSettingsHelper().getSettingsFile(); - } - containsAdditionalData = checkAdditionalDataContains(); - } else { - dataList = getAdditionalData(); - for (AdditionalDataWrapper dataWrapper : dataList) { - dataToOperate.addAll(dataWrapper.getItems()); - } - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData); - } - - @Override - public void createMenuItems(Bundle savedInstanceState) { - final Context context = getContext(); - if (context == null) { - return; - } - LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); - - profile = state == State.IMPORT ? getAppModeFromSettingsItems() : getAppMode(); - - int profileColor = profile.getIconColorInfo().getColor(nightMode); - int colorNoAlpha = ContextCompat.getColor(context, profileColor); - - Drawable backgroundIcon = UiUtilities.getColoredSelectableDrawable(context, colorNoAlpha, 0.3f); - Drawable[] layers = {new ColorDrawable(UiUtilities.getColorWithAlpha(colorNoAlpha, 0.10f)), backgroundIcon}; - - items.add(new TitleItem(state == State.EXPORT ? - getString(R.string.export_profile) - : getString(R.string.import_profile))); - - BaseBottomSheetItem profileItem = new BottomSheetItemWithCompoundButton.Builder() - .setChecked(true) - .setCompoundButtonColorId(profileColor) - .setButtonTintList(ColorStateList.valueOf(getResolvedColor(profileColor))) - .setDescription(BaseSettingsFragment.getAppModeDescription(context, profile)) - .setIcon(getIcon(profile.getIconRes(), profileColor)) - .setTitle(profile.toHumanString()) - .setBackground(new LayerDrawable(layers)) - .setLayoutId(R.layout.preference_profile_item_with_radio_btn) - .create(); - items.add(profileItem); - - if (state == State.IMPORT && containsAdditionalData || state == State.EXPORT && !dataList.isEmpty()) { - BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder() - .setDescription(state == State.EXPORT ? - getString(R.string.export_profile_dialog_description) - : getString(R.string.import_profile_dialog_description)) - .setLayoutId(R.layout.bottom_sheet_item_pref_info) - .create(); - items.add(descriptionItem); - - final View additionalDataView = inflater.inflate(R.layout.bottom_sheet_item_additional_data, null); - listView = additionalDataView.findViewById(R.id.list); - SwitchCompat switchItem = additionalDataView.findViewById(R.id.switchItem); - switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); - switchItem.setChecked(includeAdditionalData); - switchItem.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - includeAdditionalData = !includeAdditionalData; - listView.setVisibility(includeAdditionalData ? - View.VISIBLE : View.GONE); - if (includeAdditionalData && state == State.IMPORT) { - updateDataToOperateFromSettingsItems(); - } - setupHeightAndBackground(getView()); - } - }); - listView.setVisibility(includeAdditionalData ? View.VISIBLE : View.GONE); - adapter = new ProfileAdditionalDataAdapter(app, dataList, profileColor); - listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { - @Override - public void onGroupExpand(int i) { - setupHeightAndBackground(getView()); - } - }); - listView.setAdapter(adapter); - final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() - .setCustomView(additionalDataView) - .create(); - items.add(titleItem); - } - } - - @Override - protected int getRightBottomButtonTextId() { - return state == State.EXPORT ? R.string.shared_string_export : R.string.shared_string_import; - } - - @Override - protected void onRightBottomButtonClick() { - super.onRightBottomButtonClick(); - if (state == State.EXPORT) { - prepareFile(); - } else { - importSettings(); - } - } - - @Override - protected int getDismissButtonTextId() { - return R.string.shared_string_cancel; - } - - @Override - protected boolean useScrollableItemsContainer() { - return false; - } - - private ApplicationMode getAppModeFromSettingsItems() { - for (SettingsHelper.SettingsItem item : settingsItems) { - if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { - profileSettingsItem = ((SettingsHelper.ProfileSettingsItem) item); - return ((SettingsHelper.ProfileSettingsItem) item).getAppMode(); - } - } - return getAppMode(); - } - - private List getAdditionalData() { - List dataList = new ArrayList<>(); - - QuickActionFactory factory = new QuickActionFactory(); - List actionsList = factory.parseActiveActionsList(app.getSettings().QUICK_ACTION_LIST.get()); - if (!actionsList.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.QUICK_ACTIONS, actionsList)); - } - - List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); - if (!poiList.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.POI_TYPES, - poiList - )); - } - - List iTileSources = new ArrayList<>(); - final LinkedHashMap tileSourceEntries = new LinkedHashMap<>(app.getSettings().getTileSourceEntries(true)); - for (Map.Entry entry : tileSourceEntries.entrySet()) { - File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + entry.getKey()); - if (f != null) { - ITileSource template; - if (f.getName().endsWith(SQLiteTileSource.EXT)) { - template = new SQLiteTileSource(app, f, TileSourceManager.getKnownSourceTemplates()); - } else { - template = TileSourceManager.createTileSourceTemplate(f); - } - if (template != null && template.getUrlTemplate() != null) { - iTileSources.add(template); - } - } - } - if (!iTileSources.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.MAP_SOURCES, - iTileSources - )); - } - - Map externalRenderers = app.getRendererRegistry().getExternalRenderers(); - if (!externalRenderers.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE, - new ArrayList<>(externalRenderers.values()) - )); - } - - File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR); - if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) { - File[] fl = routingProfilesFolder.listFiles(); - if (fl != null && fl.length > 0) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.CUSTOM_ROUTING, - Arrays.asList(fl) - )); - } - } - - return dataList; - } - - private List prepareSettingsItemsForExport() { - List settingsItems = new ArrayList<>(); - settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile)); - if (includeAdditionalData) { - settingsItems.addAll(prepareAdditionalSettingsItems()); - } - return settingsItems; - } - - private List prepareAdditionalSettingsItems() { - List settingsItems = new ArrayList<>(); - List quickActions = new ArrayList<>(); - List poiUIFilters = new ArrayList<>(); - List tileSourceTemplates = new ArrayList<>(); - for (Object object : dataToOperate) { - if (object instanceof QuickAction) { - quickActions.add((QuickAction) object); - } else if (object instanceof PoiUIFilter) { - poiUIFilters.add((PoiUIFilter) object); - } else if (object instanceof TileSourceManager.TileSourceTemplate - || object instanceof SQLiteTileSource) { - tileSourceTemplates.add((ITileSource) object); - } else if (object instanceof File) { - settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object)); - } - } - if (!quickActions.isEmpty()) { - settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); - } - if (!poiUIFilters.isEmpty()) { - settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); - } - if (!tileSourceTemplates.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates)); - } - return settingsItems; - } - - private Boolean checkAdditionalDataContains() { - boolean containsData = false; - for (SettingsHelper.SettingsItem item : settingsItems) { - containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION) - || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS) - || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES) - || item.getType().equals(SettingsHelper.SettingsItemType.FILE); - if (containsData) { - break; - } - } - return containsData; - } - - private void updateDataToOperateFromSettingsItems() { - List dataList = new ArrayList<>(); - List quickActions = new ArrayList<>(); - List poiUIFilters = new ArrayList<>(); - List tileSourceTemplates = new ArrayList<>(); - List routingFilesList = new ArrayList<>(); - List renderFilesList = new ArrayList<>(); - - for (SettingsHelper.SettingsItem item : settingsItems) { - if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) { - quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); - } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS)) { - poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).getPoiUIFilters()); - } else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES)) { - tileSourceTemplates.addAll(((SettingsHelper.MapSourcesSettingsItem) item).getMapSources()); - } else if (item.getType().equals(SettingsHelper.SettingsItemType.FILE)) { - if (item.getName().startsWith("/rendering/")) { - renderFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile()); - } else if (item.getName().startsWith("/routing/")) { - routingFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile()); - } - } - } - - if (!quickActions.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.QUICK_ACTIONS, - quickActions)); - dataToOperate.addAll(quickActions); - } - if (!poiUIFilters.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.POI_TYPES, - poiUIFilters)); - dataToOperate.addAll(poiUIFilters); - } - if (!tileSourceTemplates.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.MAP_SOURCES, - tileSourceTemplates - )); - dataToOperate.addAll(tileSourceTemplates); - } - if (!renderFilesList.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE, - renderFilesList - )); - dataToOperate.addAll(renderFilesList); - } - if (!routingFilesList.isEmpty()) { - dataList.add(new AdditionalDataWrapper( - AdditionalDataWrapper.Type.CUSTOM_ROUTING, - routingFilesList - )); - dataToOperate.addAll(routingFilesList); - } - adapter.updateList(dataList); - } - - private void importSettings() { - List list = new ArrayList<>(); - list.add(profileSettingsItem); - if (includeAdditionalData) { - list.addAll(prepareAdditionalSettingsItems()); - } - app.getSettingsHelper().importSettings(file, list, "", 1, new SettingsHelper.SettingsImportListener() { - @Override - public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { - if (succeed) { - app.showShortToastMessage(app.getString(R.string.file_imported_successfully, file.getName())); - } else if (empty){ - app.showShortToastMessage(app.getString(R.string.file_import_error, file.getName(), app.getString(R.string.shared_string_unexpected_error))); - } - } - }); - dismiss(); - } - - private void prepareFile() { - if (app != null) { - File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); - if (!tempDir.exists()) { - tempDir.mkdirs(); - } - String fileName = profile.toHumanString(); - app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() { - @Override - public void onSettingsExportFinished(@NonNull File file, boolean succeed) { - if (succeed) { - shareProfile(file, profile); - } else { - app.showToastMessage(R.string.export_profile_failed); - } - } - }, prepareSettingsItemsForExport()); - } - } - - private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) { - try { - final Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString())); - sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file)); - sendIntent.setType("*/*"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(sendIntent); - dismiss(); - } catch (Exception e) { - Toast.makeText(requireContext(), R.string.export_profile_failed, Toast.LENGTH_SHORT).show(); - LOG.error("Share profile error", e); - } - } - - public static boolean showInstance(@NonNull FragmentManager fragmentManager, - State state, - Fragment target, - @NonNull ApplicationMode appMode) { - try { - Bundle bundle = new Bundle(); - bundle.putSerializable(STATE_KEY, state); - ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); - fragment.setArguments(bundle); - fragment.setAppMode(appMode); - fragment.setTargetFragment(target, 0); - fragment.show(fragmentManager, TAG); - return true; - } catch (RuntimeException e) { - return false; - } - } - - public static boolean showInstance(@NonNull FragmentManager fragmentManager, - State state, - File file, - List items) { - try { - Bundle bundle = new Bundle(); - bundle.putSerializable(STATE_KEY, state); - ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); - fragment.setArguments(bundle); - fragment.setSettingsItems(items); - fragment.setFile(file); - fragment.show(fragmentManager, TAG); - return true; - } catch (RuntimeException e) { - return false; - } - } - - public void setSettingsItems(List settingsItems) { - this.settingsItems = settingsItems; - } - - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - - public enum State { - EXPORT, - IMPORT - } - - class ProfileAdditionalDataAdapter extends OsmandBaseExpandableListAdapter { - - private OsmandApplication app; - - private List list; - - private int profileColor; - - ProfileAdditionalDataAdapter(OsmandApplication app, List list, int profileColor) { - this.app = app; - this.list = list; - this.profileColor = profileColor; - } - - public void updateList(List list) { - this.list = list; - notifyDataSetChanged(); - } - - @Override - public int getGroupCount() { - return list.size(); - } - - @Override - public int getChildrenCount(int i) { - return list.get(i).getItems().size(); - } - - @Override - public Object getGroup(int i) { - return list.get(i); - } - - @Override - public Object getChild(int groupPosition, int childPosition) { - return list.get(groupPosition).getItems().get(childPosition); - } - - @Override - public long getGroupId(int i) { - return i; - } - - @Override - public long getChildId(int groupPosition, int childPosition) { - return groupPosition * 10000 + childPosition; - } - - @Override - public boolean hasStableIds() { - return false; - } - - @Override - public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { - View group = convertView; - if (group == null) { - LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); - group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false); - } - - boolean isLastGroup = groupPosition == getGroupCount() - 1; - final AdditionalDataWrapper.Type type = list.get(groupPosition).getType(); - - TextView titleTv = group.findViewById(R.id.title_tv); - TextView subTextTv = group.findViewById(R.id.sub_text_tv); - final CheckBox checkBox = group.findViewById(R.id.check_box); - ImageView expandIv = group.findViewById(R.id.explist_indicator); - View divider = group.findViewById(R.id.divider); - - titleTv.setText(getGroupTitle(type)); - divider.setVisibility(isExpanded || isLastGroup ? View.GONE : View.VISIBLE); - CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor))); - - final List listItems = list.get(groupPosition).getItems(); - subTextTv.setText(String.valueOf(listItems.size())); - - checkBox.setChecked(dataToOperate.containsAll(listItems)); - checkBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - - if (checkBox.isChecked()) { - for (Object object : listItems) { - if (!dataToOperate.contains(object)) { - dataToOperate.add(object); - } - } - } else { - dataToOperate.removeAll(listItems); - } - notifyDataSetInvalidated(); - } - }); - - adjustIndicator(app, groupPosition, isExpanded, group, true); - - return group; - } - - @Override - public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { - View child = convertView; - if (child == null) { - LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); - child = inflater.inflate(R.layout.profile_data_list_item_child, parent, false); - } - final Object currentItem = list.get(groupPosition).getItems().get(childPosition); - - - boolean isLastGroup = groupPosition == getGroupCount() - 1; - final AdditionalDataWrapper.Type type = list.get(groupPosition).getType(); - - TextView title = child.findViewById(R.id.title_tv); - final CheckBox checkBox = child.findViewById(R.id.check_box); - ImageView icon = child.findViewById(R.id.icon); - View divider = child.findViewById(R.id.divider); - - divider.setVisibility(isLastChild && !isLastGroup ? View.VISIBLE : View.GONE); - CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor))); - - checkBox.setChecked(dataToOperate.contains(currentItem)); - checkBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (checkBox.isChecked()) { - dataToOperate.add(currentItem); - } else { - dataToOperate.remove(currentItem); - } - notifyDataSetInvalidated(); - } - }); - - switch (type) { - case QUICK_ACTIONS: - title.setText(((QuickAction) currentItem).getName(app.getApplicationContext())); - icon.setVisibility(View.INVISIBLE); - icon.setImageResource(R.drawable.ic_action_info_dark); - break; - case POI_TYPES: - title.setText(((PoiUIFilter) currentItem).getName()); - icon.setVisibility(View.VISIBLE); - int iconRes = RenderingIcons.getBigIconResourceId(((PoiUIFilter) currentItem).getIconId()); - icon.setImageDrawable(app.getUIUtilities().getIcon(iconRes != 0 ? iconRes : R.drawable.ic_person, profileColor)); - break; - case MAP_SOURCES: - title.setText(((ITileSource) currentItem).getName()); - icon.setVisibility(View.INVISIBLE); - icon.setImageResource(R.drawable.ic_action_info_dark); - break; - case CUSTOM_RENDER_STYLE: - String renderName = ((File) currentItem).getName(); - renderName = renderName.replace('_', ' ').replaceAll(".render.xml", ""); - title.setText(renderName); - icon.setVisibility(View.INVISIBLE); - icon.setImageResource(R.drawable.ic_action_info_dark); - break; - case CUSTOM_ROUTING: - String routingName = ((File) currentItem).getName(); - routingName = routingName.replace('_', ' ').replaceAll(".xml", ""); - title.setText(routingName); - icon.setVisibility(View.INVISIBLE); - icon.setImageResource(R.drawable.ic_action_info_dark); - break; - default: - return child; - } - return child; - } - - @Override - public boolean isChildSelectable(int i, int i1) { - return false; - } - - private int getGroupTitle(AdditionalDataWrapper.Type type) { - switch (type) { - case QUICK_ACTIONS: - return R.string.configure_screen_quick_action; - case POI_TYPES: - return R.string.poi_dialog_poi_type; - case MAP_SOURCES: - return R.string.quick_action_map_source_title; - case CUSTOM_RENDER_STYLE: - return R.string.shared_string_custom_rendering_style; - case CUSTOM_ROUTING: - return R.string.shared_string_routing; - default: - return R.string.access_empty_list; - } - } - } + private static final Log LOG = PlatformUtil.getLog(ExportImportProfileBottomSheet.class); + + public static final String TAG = ExportImportProfileBottomSheet.class.getSimpleName(); + + private static final String STATE_KEY = "EXPORT_IMPORT_DIALOG_STATE_KEY"; + + private static final String INCLUDE_ADDITIONAL_DATA_KEY = "INCLUDE_ADDITIONAL_DATA_KEY"; + + private boolean includeAdditionalData = false; + + private boolean containsAdditionalData = false; + + private OsmandApplication app; + + private ApplicationMode profile; + + private State state; + + private List dataList = new ArrayList<>(); + + private List dataToOperate = new ArrayList<>(); + + private List settingsItems; + + private ExpandableListView listView; + + private ProfileAdditionalDataAdapter adapter; + + private SettingsHelper.ProfileSettingsItem profileSettingsItem; + + private File file; + + @Override + public void onCreate(Bundle savedInstanceState) { + if (savedInstanceState != null) { + includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY); + } + super.onCreate(savedInstanceState); + app = requiredMyApplication(); + Bundle bundle = getArguments(); + if (bundle != null) { + this.state = (State) getArguments().getSerializable(STATE_KEY); + } + if (state == State.IMPORT) { + if (settingsItems == null) { + settingsItems = app.getSettingsHelper().getSettingsItems(); + } + if (file == null) { + file = app.getSettingsHelper().getSettingsFile(); + } + containsAdditionalData = checkAdditionalDataContains(); + } else { + dataList = getAdditionalData(); + for (AdditionalDataWrapper dataWrapper : dataList) { + dataToOperate.addAll(dataWrapper.getItems()); + } + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData); + } + + @Override + public void createMenuItems(Bundle savedInstanceState) { + final Context context = getContext(); + if (context == null) { + return; + } + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); + + profile = state == State.IMPORT ? getAppModeFromSettingsItems() : getAppMode(); + + int profileColor = profile.getIconColorInfo().getColor(nightMode); + int colorNoAlpha = ContextCompat.getColor(context, profileColor); + + Drawable backgroundIcon = UiUtilities.getColoredSelectableDrawable(context, colorNoAlpha, 0.3f); + Drawable[] layers = {new ColorDrawable(UiUtilities.getColorWithAlpha(colorNoAlpha, 0.10f)), backgroundIcon}; + + items.add(new TitleItem(state == State.EXPORT ? + getString(R.string.export_profile) + : getString(R.string.import_profile))); + + BaseBottomSheetItem profileItem = new BottomSheetItemWithCompoundButton.Builder() + .setChecked(true) + .setCompoundButtonColorId(profileColor) + .setButtonTintList(ColorStateList.valueOf(getResolvedColor(profileColor))) + .setDescription(BaseSettingsFragment.getAppModeDescription(context, profile)) + .setIcon(getIcon(profile.getIconRes(), profileColor)) + .setTitle(profile.toHumanString()) + .setBackground(new LayerDrawable(layers)) + .setLayoutId(R.layout.preference_profile_item_with_radio_btn) + .create(); + items.add(profileItem); + + if (state == State.IMPORT && containsAdditionalData || state == State.EXPORT && !dataList.isEmpty()) { + BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder() + .setDescription(state == State.EXPORT ? + getString(R.string.export_profile_dialog_description) + : getString(R.string.import_profile_dialog_description)) + .setLayoutId(R.layout.bottom_sheet_item_pref_info) + .create(); + items.add(descriptionItem); + + final View additionalDataView = inflater.inflate(R.layout.bottom_sheet_item_additional_data, null); + listView = additionalDataView.findViewById(R.id.list); + SwitchCompat switchItem = additionalDataView.findViewById(R.id.switchItem); + switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light)); + switchItem.setChecked(includeAdditionalData); + switchItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + includeAdditionalData = !includeAdditionalData; + listView.setVisibility(includeAdditionalData ? + View.VISIBLE : View.GONE); + if (includeAdditionalData && state == State.IMPORT) { + updateDataToOperateFromSettingsItems(); + } + setupHeightAndBackground(getView()); + } + }); + listView.setVisibility(includeAdditionalData ? View.VISIBLE : View.GONE); + adapter = new ProfileAdditionalDataAdapter(app, dataList, profileColor); + listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { + @Override + public void onGroupExpand(int i) { + setupHeightAndBackground(getView()); + } + }); + listView.setAdapter(adapter); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(additionalDataView) + .create(); + items.add(titleItem); + } + } + + @Override + protected int getRightBottomButtonTextId() { + return state == State.EXPORT ? R.string.shared_string_export : R.string.shared_string_import; + } + + @Override + protected void onRightBottomButtonClick() { + super.onRightBottomButtonClick(); + if (state == State.EXPORT) { + prepareFile(); + } else { + importSettings(); + } + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_cancel; + } + + @Override + protected boolean useScrollableItemsContainer() { + return false; + } + + private ApplicationMode getAppModeFromSettingsItems() { + for (SettingsHelper.SettingsItem item : settingsItems) { + if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { + profileSettingsItem = ((SettingsHelper.ProfileSettingsItem) item); + return ((SettingsHelper.ProfileSettingsItem) item).getAppMode(); + } + } + return getAppMode(); + } + + private List getAdditionalData() { + List dataList = new ArrayList<>(); + + QuickActionFactory factory = new QuickActionFactory(); + List actionsList = factory.parseActiveActionsList(app.getSettings().QUICK_ACTION_LIST.get()); + if (!actionsList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, actionsList)); + } + + List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); + if (!poiList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.POI_TYPES, + poiList + )); + } + + List iTileSources = new ArrayList<>(); + final LinkedHashMap tileSourceEntries = new LinkedHashMap<>(app.getSettings().getTileSourceEntries(true)); + for (Map.Entry entry : tileSourceEntries.entrySet()) { + File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + entry.getKey()); + if (f != null) { + ITileSource template; + if (f.getName().endsWith(SQLiteTileSource.EXT)) { + template = new SQLiteTileSource(app, f, TileSourceManager.getKnownSourceTemplates()); + } else { + template = TileSourceManager.createTileSourceTemplate(f); + } + if (template != null && template.getUrlTemplate() != null) { + iTileSources.add(template); + } + } + } + if (!iTileSources.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.MAP_SOURCES, + iTileSources + )); + } + + Map externalRenderers = app.getRendererRegistry().getExternalRenderers(); + if (!externalRenderers.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE, + new ArrayList<>(externalRenderers.values()) + )); + } + + File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR); + if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) { + File[] fl = routingProfilesFolder.listFiles(); + if (fl != null && fl.length > 0) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_ROUTING, + Arrays.asList(fl) + )); + } + } + + return dataList; + } + + private List prepareSettingsItemsForExport() { + List settingsItems = new ArrayList<>(); + settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile)); + if (includeAdditionalData) { + settingsItems.addAll(prepareAdditionalSettingsItems()); + } + return settingsItems; + } + + private List prepareAdditionalSettingsItems() { + List settingsItems = new ArrayList<>(); + List quickActions = new ArrayList<>(); + List poiUIFilters = new ArrayList<>(); + List tileSourceTemplates = new ArrayList<>(); + for (Object object : dataToOperate) { + if (object instanceof QuickAction) { + quickActions.add((QuickAction) object); + } else if (object instanceof PoiUIFilter) { + poiUIFilters.add((PoiUIFilter) object); + } else if (object instanceof TileSourceManager.TileSourceTemplate + || object instanceof SQLiteTileSource) { + tileSourceTemplates.add((ITileSource) object); + } else if (object instanceof File) { + settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object)); + } + } + if (!quickActions.isEmpty()) { + settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); + } + if (!poiUIFilters.isEmpty()) { + settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); + } + if (!tileSourceTemplates.isEmpty()) { + settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates)); + } + return settingsItems; + } + + private Boolean checkAdditionalDataContains() { + boolean containsData = false; + for (SettingsHelper.SettingsItem item : settingsItems) { + containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION) + || item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS) + || item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES) + || item.getType().equals(SettingsHelper.SettingsItemType.FILE); + if (containsData) { + break; + } + } + return containsData; + } + + private void updateDataToOperateFromSettingsItems() { + List dataList = new ArrayList<>(); + List quickActions = new ArrayList<>(); + List poiUIFilters = new ArrayList<>(); + List tileSourceTemplates = new ArrayList<>(); + List routingFilesList = new ArrayList<>(); + List renderFilesList = new ArrayList<>(); + + for (SettingsHelper.SettingsItem item : settingsItems) { + if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) { + quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions()); + } else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS)) { + poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).getPoiUIFilters()); + } else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES)) { + tileSourceTemplates.addAll(((SettingsHelper.MapSourcesSettingsItem) item).getMapSources()); + } else if (item.getType().equals(SettingsHelper.SettingsItemType.FILE)) { + if (item.getName().startsWith("/rendering/")) { + renderFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile()); + } else if (item.getName().startsWith("/routing/")) { + routingFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile()); + } + } + } + + if (!quickActions.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.QUICK_ACTIONS, + quickActions)); + dataToOperate.addAll(quickActions); + } + if (!poiUIFilters.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.POI_TYPES, + poiUIFilters)); + dataToOperate.addAll(poiUIFilters); + } + if (!tileSourceTemplates.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.MAP_SOURCES, + tileSourceTemplates + )); + dataToOperate.addAll(tileSourceTemplates); + } + if (!renderFilesList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE, + renderFilesList + )); + dataToOperate.addAll(renderFilesList); + } + if (!routingFilesList.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.CUSTOM_ROUTING, + routingFilesList + )); + dataToOperate.addAll(routingFilesList); + } + adapter.updateList(dataList); + } + + private void importSettings() { + List list = new ArrayList<>(); + list.add(profileSettingsItem); + if (includeAdditionalData) { + list.addAll(prepareAdditionalSettingsItems()); + } + app.getSettingsHelper().importSettings(file, list, "", 1, new SettingsHelper.SettingsImportListener() { + @Override + public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { + if (succeed) { + app.showShortToastMessage(app.getString(R.string.file_imported_successfully, file.getName())); + } else if (empty) { + app.showShortToastMessage(app.getString(R.string.file_import_error, file.getName(), app.getString(R.string.shared_string_unexpected_error))); + } + } + }); + dismiss(); + } + + private void prepareFile() { + if (app != null) { + File tempDir = app.getAppPath(IndexConstants.TEMP_DIR); + if (!tempDir.exists()) { + tempDir.mkdirs(); + } + String fileName = profile.toHumanString(); + app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() { + @Override + public void onSettingsExportFinished(@NonNull File file, boolean succeed) { + if (succeed) { + shareProfile(file, profile); + } else { + app.showToastMessage(R.string.export_profile_failed); + } + } + }, prepareSettingsItemsForExport()); + } + } + + private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) { + try { + final Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString())); + sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file)); + sendIntent.setType("*/*"); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivity(sendIntent); + dismiss(); + } catch (Exception e) { + Toast.makeText(requireContext(), R.string.export_profile_failed, Toast.LENGTH_SHORT).show(); + LOG.error("Share profile error", e); + } + } + + public static boolean showInstance(@NonNull FragmentManager fragmentManager, + State state, + Fragment target, + @NonNull ApplicationMode appMode) { + try { + Bundle bundle = new Bundle(); + bundle.putSerializable(STATE_KEY, state); + ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); + fragment.setArguments(bundle); + fragment.setAppMode(appMode); + fragment.setTargetFragment(target, 0); + fragment.show(fragmentManager, TAG); + return true; + } catch (RuntimeException e) { + return false; + } + } + + public static boolean showInstance(@NonNull FragmentManager fragmentManager, + State state, + File file, + List items) { + try { + Bundle bundle = new Bundle(); + bundle.putSerializable(STATE_KEY, state); + ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet(); + fragment.setArguments(bundle); + fragment.setSettingsItems(items); + fragment.setFile(file); + fragment.show(fragmentManager, TAG); + return true; + } catch (RuntimeException e) { + return false; + } + } + + public void setSettingsItems(List settingsItems) { + this.settingsItems = settingsItems; + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + + public enum State { + EXPORT, + IMPORT + } + + class ProfileAdditionalDataAdapter extends OsmandBaseExpandableListAdapter { + + private OsmandApplication app; + + private List list; + + private int profileColor; + + ProfileAdditionalDataAdapter(OsmandApplication app, List list, int profileColor) { + this.app = app; + this.list = list; + this.profileColor = profileColor; + } + + public void updateList(List list) { + this.list = list; + notifyDataSetChanged(); + } + + @Override + public int getGroupCount() { + return list.size(); + } + + @Override + public int getChildrenCount(int i) { + return list.get(i).getItems().size(); + } + + @Override + public Object getGroup(int i) { + return list.get(i); + } + + @Override + public Object getChild(int groupPosition, int childPosition) { + return list.get(groupPosition).getItems().get(childPosition); + } + + @Override + public long getGroupId(int i) { + return i; + } + + @Override + public long getChildId(int groupPosition, int childPosition) { + return groupPosition * 10000 + childPosition; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { + View group = convertView; + if (group == null) { + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); + group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false); + } + + boolean isLastGroup = groupPosition == getGroupCount() - 1; + final AdditionalDataWrapper.Type type = list.get(groupPosition).getType(); + + TextView titleTv = group.findViewById(R.id.title_tv); + TextView subTextTv = group.findViewById(R.id.sub_text_tv); + final CheckBox checkBox = group.findViewById(R.id.check_box); + ImageView expandIv = group.findViewById(R.id.explist_indicator); + View divider = group.findViewById(R.id.divider); + + titleTv.setText(getGroupTitle(type)); + divider.setVisibility(isExpanded || isLastGroup ? View.GONE : View.VISIBLE); + CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor))); + + final List listItems = list.get(groupPosition).getItems(); + subTextTv.setText(String.valueOf(listItems.size())); + + checkBox.setChecked(dataToOperate.containsAll(listItems)); + checkBox.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + if (checkBox.isChecked()) { + for (Object object : listItems) { + if (!dataToOperate.contains(object)) { + dataToOperate.add(object); + } + } + } else { + dataToOperate.removeAll(listItems); + } + notifyDataSetInvalidated(); + } + }); + + adjustIndicator(app, groupPosition, isExpanded, group, true); + + return group; + } + + @Override + public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { + View child = convertView; + if (child == null) { + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); + child = inflater.inflate(R.layout.profile_data_list_item_child, parent, false); + } + final Object currentItem = list.get(groupPosition).getItems().get(childPosition); + + + boolean isLastGroup = groupPosition == getGroupCount() - 1; + final AdditionalDataWrapper.Type type = list.get(groupPosition).getType(); + + TextView title = child.findViewById(R.id.title_tv); + final CheckBox checkBox = child.findViewById(R.id.check_box); + ImageView icon = child.findViewById(R.id.icon); + View divider = child.findViewById(R.id.divider); + + divider.setVisibility(isLastChild && !isLastGroup ? View.VISIBLE : View.GONE); + CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor))); + + checkBox.setChecked(dataToOperate.contains(currentItem)); + checkBox.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (checkBox.isChecked()) { + dataToOperate.add(currentItem); + } else { + dataToOperate.remove(currentItem); + } + notifyDataSetInvalidated(); + } + }); + + switch (type) { + case QUICK_ACTIONS: + title.setText(((QuickAction) currentItem).getName(app.getApplicationContext())); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; + case POI_TYPES: + title.setText(((PoiUIFilter) currentItem).getName()); + icon.setVisibility(View.VISIBLE); + int iconRes = RenderingIcons.getBigIconResourceId(((PoiUIFilter) currentItem).getIconId()); + icon.setImageDrawable(app.getUIUtilities().getIcon(iconRes != 0 ? iconRes : R.drawable.ic_person, profileColor)); + break; + case MAP_SOURCES: + title.setText(((ITileSource) currentItem).getName()); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; + case CUSTOM_RENDER_STYLE: + String renderName = ((File) currentItem).getName(); + renderName = renderName.replace('_', ' ').replaceAll(".render.xml", ""); + title.setText(renderName); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; + case CUSTOM_ROUTING: + String routingName = ((File) currentItem).getName(); + routingName = routingName.replace('_', ' ').replaceAll(".xml", ""); + title.setText(routingName); + icon.setVisibility(View.INVISIBLE); + icon.setImageResource(R.drawable.ic_action_info_dark); + break; + default: + return child; + } + return child; + } + + @Override + public boolean isChildSelectable(int i, int i1) { + return false; + } + + private int getGroupTitle(AdditionalDataWrapper.Type type) { + switch (type) { + case QUICK_ACTIONS: + return R.string.configure_screen_quick_action; + case POI_TYPES: + return R.string.poi_dialog_poi_type; + case MAP_SOURCES: + return R.string.quick_action_map_source_title; + case CUSTOM_RENDER_STYLE: + return R.string.shared_string_custom_rendering_style; + case CUSTOM_ROUTING: + return R.string.shared_string_routing; + default: + return R.string.access_empty_list; + } + } + } } From a7034b050b38131febcac38a5ecdf8477dd36ec3 Mon Sep 17 00:00:00 2001 From: vshcherb Date: Thu, 13 Feb 2020 15:50:01 +0100 Subject: [PATCH 15/42] Update SQLiteTileSource.java --- .../src/net/osmand/plus/SQLiteTileSource.java | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index cbfbef635a..b2422d9c3e 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -42,11 +42,6 @@ public class SQLiteTileSource implements ITileSource { private static final String TIME_SUPPORTED = "timesupported"; private static final String EXPIRE_MINUTES = "expireminutes"; - private static final String TILES_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS tiles (x INTEGER NOT NULL, y INTEGER NOT NULL, z INTEGER NOT NULL, s INTEGER, image BLOB, time INTEGER, PRIMARY KEY (x, y, z))"; - private static final String CREATE_INDEX_X = "CREATE INDEX index_tiles_on_x ON tiles (x)"; - private static final String CREATE_INDEX_Y = "CREATE INDEX index_tiles_on_y ON tiles (y)"; - private static final String CREATE_INDEX_Z = "CREATE INDEX index_tiles_on_z ON tiles (z)"; - private static final String CREATE_INDEX_S = "CREATE INDEX index_tiles_on_s ON tiles (s)"; private ITileSource base; private String urlTemplate = null; @@ -113,11 +108,11 @@ public class SQLiteTileSource implements ITileSource { db = ctx.getSQLiteAPI().getOrCreateDatabase( ctx.getAppPath(TILES_INDEX_DIR).getAbsolutePath() + "/" + name + SQLITE_EXT, true); - db.execSQL("CREATE TABLE IF NOT EXISTS info (" + - MIN_ZOOM + ", " + - MAX_ZOOM + - ");"); - db.execSQL("INSERT INTO info (" + MIN_ZOOM + "," + MAX_ZOOM + ") VALUES ('" + minZoom + "','" + maxZoom + "');"); + db.execSQL("CREATE TABLE tiles (x int, y int, z int, s int, image blob, time long, PRIMARY KEY (x,y,z,s))"); + db.execSQL("CREATE INDEX IND on tiles (x,y,z,s)"); + db.execSQL("CREATE TABLE info(tilenumbering,minzoom,maxzoom)"); + db.execSQL("CREATE TABLE android_metadata (locale TEXT)"); + db.execSQL("INSERT INTO info (tilenumbering,minzoom,maxzoom) VALUES ('simple','" + minZoom + "','" + maxZoom + "');"); addInfoColumn(URL, urlTemplate); addInfoColumn(RANDOMS, randoms); @@ -127,11 +122,7 @@ public class SQLiteTileSource implements ITileSource { addInfoColumn(TIME_SUPPORTED, timeSupported ? "yes" : "no"); addInfoColumn(EXPIRE_MINUTES, String.valueOf(getExpirationTimeMinutes())); - db.execSQL(TILES_TABLE_CREATE); - db.execSQL(CREATE_INDEX_X); - db.execSQL(CREATE_INDEX_Y); - db.execSQL(CREATE_INDEX_Z); - db.execSQL(CREATE_INDEX_S); + db.close(); } From 11e08628973d8cd9f8eb029a8812262bef86beab Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 13 Feb 2020 16:04:51 +0100 Subject: [PATCH 16/42] Fix compilation --- .../src/net/osmand/plus/SQLiteTileSource.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index b1e2d5d8cf..88ee8ca3f7 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -39,8 +39,12 @@ public class SQLiteTileSource implements ITileSource { private static final String ELLIPSOID = "ellipsoid"; private static final String INVERTED_Y = "inverted_y"; private static final String REFERER = "referer"; - private static final String TIME_SUPPORTED = "timesupported"; + private static final String TIME_COLUMN = "timecolumn"; private static final String EXPIRE_MINUTES = "expireminutes"; + private static final String RULE = "rule"; + private static final String TILENUMBERING = "tilenumbering"; + private static final String BIG_PLANET_TILE_NUMBERING = "BigPlanet"; + private static final String TILESIZE = "tilesize"; private ITileSource base; private String urlTemplate = null; @@ -118,7 +122,7 @@ public class SQLiteTileSource implements ITileSource { addInfoColumn(ELLIPSOID, isEllipsoid ? "1" : "0"); addInfoColumn(INVERTED_Y, invertedY ? "1" : "0"); addInfoColumn(REFERER, referer); - addInfoColumn(TIME_SUPPORTED, timeSupported ? "yes" : "no"); + addInfoColumn(TIME_COLUMN, timeSupported ? "yes" : "no"); addInfoColumn(EXPIRE_MINUTES, String.valueOf(getExpirationTimeMinutes())); @@ -229,34 +233,34 @@ public class SQLiteTileSource implements ITileSource { if(cursor.moveToFirst()) { String[] columnNames = cursor.getColumnNames(); List list = Arrays.asList(columnNames); - int url = list.indexOf(URL_FIELD); + int url = list.indexOf(URL); if(url != -1) { String template = cursor.getString(url); if(!Algorithms.isEmpty(template)){ urlTemplate = TileSourceTemplate.normalizeUrl(template); } } - int ruleId = list.indexOf("rule"); + int ruleId = list.indexOf(RULE); if(ruleId != -1) { rule = cursor.getString(ruleId); } - int refererId = list.indexOf("referer"); + int refererId = list.indexOf(REFERER); if(refererId != -1) { referer = cursor.getString(refererId); } - int tnumbering = list.indexOf("tilenumbering"); + int tnumbering = list.indexOf(TILENUMBERING); if(tnumbering != -1) { - inversiveZoom = "BigPlanet".equalsIgnoreCase(cursor.getString(tnumbering)); + inversiveZoom = BIG_PLANET_TILE_NUMBERING.equalsIgnoreCase(cursor.getString(tnumbering)); } else { inversiveZoom = true; - addInfoColumn("tilenumbering", "BigPlanet"); + addInfoColumn(TILENUMBERING, BIG_PLANET_TILE_NUMBERING); } - int timecolumn = list.indexOf("timecolumn"); + int timecolumn = list.indexOf(TIME_COLUMN); if (timecolumn != -1) { timeSupported = "yes".equalsIgnoreCase(cursor.getString(timecolumn)); } else { timeSupported = hasTimeColumn(); - addInfoColumn("timecolumn", timeSupported? "yes" : "no"); + addInfoColumn(TIME_COLUMN, timeSupported? "yes" : "no"); } int expireminutes = list.indexOf(EXPIRE_MINUTES); this.expirationTimeMillis = -1; @@ -268,7 +272,7 @@ public class SQLiteTileSource implements ITileSource { } else { addInfoColumn(EXPIRE_MINUTES, "0"); } - int tsColumn = list.indexOf("tilesize"); + int tsColumn = list.indexOf(TILESIZE); this.tileSizeSpecified = tsColumn != -1; if(tileSizeSpecified) { this.tileSize = (int) cursor.getInt(tsColumn); @@ -280,14 +284,14 @@ public class SQLiteTileSource implements ITileSource { this.isEllipsoid = true; } } - int invertedY = list.indexOf("inverted_y"); + int invertedY = list.indexOf(INVERTED_Y); if(invertedY != -1) { int set = (int) cursor.getInt(invertedY); if(set == 1){ this.invertedY = true; } } - int randomsId = list.indexOf("randoms"); + int randomsId = list.indexOf(RANDOMS); if(randomsId != -1) { this.randoms = cursor.getString(randomsId); this.randomsArray = TileSourceTemplate.buildRandomsArray(this.randoms); From b51b8fdd1f58e2fc09aef16f7244d178e470c471 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Thu, 13 Feb 2020 17:25:19 +0200 Subject: [PATCH 17/42] Update Audio icon --- OsmAnd/res/drawable-hdpi/ic_type_audio.png | Bin 1211 -> 0 bytes OsmAnd/res/drawable-mdpi/ic_type_audio.png | Bin 1140 -> 0 bytes OsmAnd/res/drawable-xhdpi/ic_type_audio.png | Bin 1290 -> 0 bytes OsmAnd/res/drawable-xxhdpi/ic_type_audio.png | Bin 1447 -> 0 bytes OsmAnd/res/drawable/ic_type_audio.xml | 9 +++++++++ 5 files changed, 9 insertions(+) delete mode 100644 OsmAnd/res/drawable-hdpi/ic_type_audio.png delete mode 100644 OsmAnd/res/drawable-mdpi/ic_type_audio.png delete mode 100644 OsmAnd/res/drawable-xhdpi/ic_type_audio.png delete mode 100644 OsmAnd/res/drawable-xxhdpi/ic_type_audio.png create mode 100644 OsmAnd/res/drawable/ic_type_audio.xml diff --git a/OsmAnd/res/drawable-hdpi/ic_type_audio.png b/OsmAnd/res/drawable-hdpi/ic_type_audio.png deleted file mode 100644 index 0dcf78638f56ebeb1a7405e31230953a6f503843..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1211 zcmbVMO>7%Q6y7+Zf#QY$;y{GZXwyR~*q>SN+MXpQvAr>|z#+I+iMS;DGaE0-{;)g7 zo2Wvi6_8W`g#$E*Lkl@jT8RrqAoakZl>muD#E%5+0f+<_givlERSL6-9XLciu+r|l znR(y)`QCfGGBx?ck;8+B8HPDhozUuZJ(|3C9-`l0nDuqKJV?f;$#LH%Z9T+H(ee!p zs;)kV>sYrIU-$}-FidakG^WXP?J3ptU0zRg_}C37nqfvp<3Km(F#!gibG!ok=he?y z;8+FrS*0e{f--J86H6gJzBJh|m*!1mv7?WJkyxb$TugKjy9-{V#szlQu1e+PSYW}f z3YjmkdqGXtra;*bF;Ms{XTnS#%o&&=*-E_R<@K{o)y}UIXIxk|Y68bLKWmt8k{)MyC3en_x#M856oQ{V0&I;wm;bUtY?B>*D}wD=##?5kV_de;6&fn w%-G4hmp@HyYv85Kjkg|dZC*UH#*CfnVYat^U+uf3PbI&T>iDGgQEB${KO^alVE_OC diff --git a/OsmAnd/res/drawable-mdpi/ic_type_audio.png b/OsmAnd/res/drawable-mdpi/ic_type_audio.png deleted file mode 100644 index 4a4caeaad3a8bf9d6e081e52b0118b2a046c43e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1140 zcmbVM&1=*^6i=;6t+pb5ONB9BS}>cB&2BcKYu(*+?LxOL+okrP;3S!JLz@qishbuL zZShbAD~N~(FZ~C+=s^%Gh)}9{^B{s?g`&6OLHtCWw7b!Ijv+D^W2tLZOfIgGo9@t|wsD)bSRFDF zsK(GL598rtucEtl3`RP!(Dn$LqB^@m59*@`0}YK>PMThQ_?QNkk*3ciid@mlp^DWr z>7&8PzOp_!s>=r5brN)j3Nc_K3_)m*Ie`+U={36w*+*iQ25TyKG)=DuHC!A3IoC%Z z5lb>UA5Q^Ej`0aOC5R`0!0}0zlUZJ5I9}moh2uf(p@}!&FqM*;ulXXUG+n{iQ&_fI zt;VYHnCp+Qye!KsC$NIR5Dg}na4-xRCpccWprSzcEe~6+10su1bH{O-CXueEV0*>l zhG8eD5k)9tL+G)5jALy(%4c{$Fc1kGfSz{}9kj0EEKx}DAN zNkPgBSuvXxvRR(*mNI!!&Wm|DrzYchK~C1O1t-AJ(NW#EMSRz=nSWxHoR1)O{j%$h z)w^Jz;$k7$s~kC ziV;nYaG^GA!>; zm=YPZ8wE8}4qt0Oe*NldWE%E1UTb*4oIjS^y}+Ti7J4Ql{Fte{+;Ww9yY*cjEHpmt znis95UHx!z+tY{BudWU)-Jh9S-uIo_*Y@nDDPB4-_2kaATk==F;nC-gV)yeMAI|lj zU2fe)x82@3d;RBP>s)r_a1+cnr=}n5nO&tm_P4)j+CKue$LEH=U8YV=HBbi+-CH@z ReVUK{1BLEB^=|h3%x{HsZMOgb diff --git a/OsmAnd/res/drawable-xhdpi/ic_type_audio.png b/OsmAnd/res/drawable-xhdpi/ic_type_audio.png deleted file mode 100644 index 735f0914805cbaa2972096cb7063b00f36eae157..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1290 zcmbVMZD<>19KW>LR|S%p=}Hz%iWYmhdoDTJ++}xH zlXRdi_|h>DSwGC-n58lYgH_#_&=zzmB6DCtsUMWW6s$VL*1=ev4t%ansvpWec--Cd zJpcRs{_p=g-q-t76aE;EVOUe_KqP@y)_oc_qj#$A&)3kh!|6#ohfU2X$`-`BR5JsK zSYFP;1eDeCk!!FW!|F?VGVP?}2PMVK)3S@9OZfs~V_17fsURyu&>=D~s~aJ5Y4&51 z(A5x`^2gbDAq;c+fl&({9_>vkqeBW%$&UR*dr3kH^3aiqQhwO5rBaAo)hnUBD`rSy z72*tq$Tg?Z@jfDKT9EM50ZQR~K|%yH=LbPv*hlaz7hqVxa01105(^}jBdQmPtXZli zB_h$PEp!TzImanT3{xx?>7tJ|tt`U<02r2Mc%DKC$}Ss@T%ruSwWc8gZN<_Hj&2%+ zt5MFFBTk4!p00(EFT~^PiVeG(D3mg$Bo`QtW|@56jcXNcI|=x&8ylkSWVryD1hmZ& zOF{L}T5DvKyZak*fyf)_kfo!d$iop+8OcM#iA6#r`a-L^DyczM6$LFw0YMNcfdf7& z$Y(SP@*I%WjOvG+Qq!{$-!F!NFABJBzPp>_dc>}%0HQ(^gd+i8lm~$tH)hz5Y$&j1 zTSvC5T=u?PDQrR6F|DL&4%fP%FK0TYoihtWIP6wkB--M#q8qO83Aa#daYvw~KM&QY zW#)<1OiTI(UO-mkR8iI_KkpAxg2tj;WJE}5K+UispW#_WCaZk)|7MUuPBCt~{HJ|t zBGi-ac6}JoVSSvSfo8};!*cG!XR{dQX^Ta=lBMr{JN*IvDck(&GY^S>JmCD^I(A|* zI6L;$-Nftk%rwC1$%mio+`DB{@z><3yIU@uxHkXjy{-H4b3fb?PhB6_sr7GP8Ghxe z{SJn&6g{7BU18()?(kS$+e`gzsmAHLZJnO#z1(`GZ|8%zue`f7a8H$%>3D3Dj!XaU%26!8m!+w`1p>%$)={G h8GHi6-@kkwtH-7q=Tf^m&j029onk$`k*V&%%0H$evp)a; diff --git a/OsmAnd/res/drawable-xxhdpi/ic_type_audio.png b/OsmAnd/res/drawable-xxhdpi/ic_type_audio.png deleted file mode 100644 index c6a7816a59441d2cb912f55a950d0049fd86eb80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1447 zcmbVMeM}Q)7_S=`#4vCu4p4JDbh^oXwxwKYas8muY~{1C`iIW@cv~8JcjbD}Lb7Zt zMifoV5`$ZqILDTWb56oCGX}UIHQ^r_*$_X5COFJC2jXIuEiAY@ptwJXf9#UG_ul7z zzvp@0-}5|oxU6J%N^(}RMx#k_7TYV7wOGBARx8h{>7L!nk|`H?X>hHGRwXvDB^IE;q1s3`d`f}$u4Coz&l6a*4#6l6Mr2%(&~2RjI{ zl0PW>MFCPh(u`Oyn_(r>#Ut=RmuuOv5LyySkqnE_L5x6gjOW#JEucek1$dIiis+EL zF$k~<5EAPpR;hvP`UTba zvRbIcbK8OBZvdP_5_xDrX`_FIECB8$I0NlP^rSu?(Rp!23&sEtFU2vqfn-RWrQsz$ z_kR_{l%z1VUH;QPag)-M>g)0_D4XSR0)jF_k}@pJAWCX9t71;O#T~i%dwV~cQ2xR} zUs0!}IBm4coqXcE4T0fpfBm{XYs%5EQ`ny^&%E@pQo2tKLes=*zE%66m))S-KGXUxwZ>8v?!K&%KAvV? zx_5f8%k)i#J9X>!n|lJy{hr3^b?%N&*C$p{#V!B%_8o7QPoUKubFb>}483wD{mi|R zb5ZN&hD5Xb2)}J2{m7*LN(NVS@#KBJ<@nw1_EQ@#mSk6__rM*@=H}cH=2q9Wliy3G zggsYd<*|_fm~RQb)pqGO<~h$eKQ;DAl?lsExIJFj@Od5Vou9q2vD!tU%7Pxytog?jI!%V8L`OArO`&!pNY?~AchiCtI=83*z beQR+|zqO#S_s)-J)nBKxsKkEWx + + From 1691f90ee737f0a2c2ecc3e5627ae5cdc3e19ccc Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 13 Feb 2020 17:33:11 +0100 Subject: [PATCH 18/42] Fix npe --- .../plus/settings/BaseSettingsFragment.java | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java index 322316d88b..bd3bc0ce85 100644 --- a/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java @@ -165,7 +165,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl updateTheme(); View view = super.onCreateView(inflater, container, savedInstanceState); if (view != null) { - if (getPreferenceScreen() != null) { + if (getPreferenceScreen() != null && currentScreenType != null) { PreferenceManager prefManager = getPreferenceManager(); PreferenceScreen preferenceScreen = prefManager.inflateFromResource(prefManager.getContext(), currentScreenType.preferencesResId, null); if (prefManager.setPreferences(preferenceScreen)) { @@ -293,7 +293,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl @ColorRes public int getStatusBarColorId() { boolean nightMode = isNightMode(); - if (currentScreenType.profileDependent) { + if (isProfileDependent()) { View view = getView(); if (view != null && Build.VERSION.SDK_INT >= 23 && !nightMode) { view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); @@ -314,6 +314,10 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl return false; } + public boolean isProfileDependent() { + return currentScreenType != null && currentScreenType.profileDependent; + } + @Override public void onDisplayPreferenceDialog(Preference preference) { FragmentManager fragmentManager = getFragmentManager(); @@ -323,13 +327,13 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl ApplicationMode appMode = getSelectedAppMode(); if (preference instanceof ListPreferenceEx) { - SingleSelectPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, currentScreenType.profileDependent, false); + SingleSelectPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, isProfileDependent(), false); } else if (preference instanceof SwitchPreferenceEx) { - BooleanPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, currentScreenType.profileDependent); + BooleanPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, isProfileDependent()); } else if (preference instanceof EditTextPreference) { EditTextPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode); } else if (preference instanceof MultiSelectBooleanPreference) { - MultiSelectPreferencesBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, currentScreenType.profileDependent); + MultiSelectPreferencesBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, isProfileDependent()); } else { super.onDisplayPreferenceDialog(preference); } @@ -359,7 +363,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl public void recreate() { FragmentActivity activity = getActivity(); - if (activity != null) { + if (activity != null && currentScreenType != null) { Fragment fragment = Fragment.instantiate(activity, currentScreenType.fragmentName); fragment.setArguments(buildArguments()); FragmentManager fm = activity.getSupportFragmentManager(); @@ -386,7 +390,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl titleView.setSingleLine(false); } boolean enabled = preference.isEnabled(); - if (currentScreenType.profileDependent) { + if (isProfileDependent()) { View cb = holder.itemView.findViewById(R.id.switchWidget); if (cb == null) { cb = holder.findViewById(android.R.id.checkbox); @@ -423,22 +427,28 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl AppBarLayout appBarLayout = (AppBarLayout) view.findViewById(R.id.appbar); ViewCompat.setElevation(appBarLayout, 5.0f); - View toolbarContainer = UiUtilities.getInflater(getActivity(), isNightMode()).inflate(currentScreenType.toolbarResId, appBarLayout); + View toolbarContainer = currentScreenType == null ? null : + UiUtilities.getInflater(getActivity(), isNightMode()).inflate(currentScreenType.toolbarResId, appBarLayout); TextView toolbarTitle = (TextView) view.findViewById(R.id.toolbar_title); - toolbarTitle.setText(getPreferenceScreen().getTitle()); + if (toolbarTitle != null) { + toolbarTitle.setText(getPreferenceScreen().getTitle()); + } View closeButton = view.findViewById(R.id.close_button); - closeButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.onBackPressed(); + if (closeButton != null) { + closeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.onBackPressed(); + } } - } - }); - View switchProfile = toolbarContainer.findViewById(R.id.profile_button); + }); + } + + View switchProfile = toolbarContainer == null ? null : toolbarContainer.findViewById(R.id.profile_button); if (switchProfile != null) { switchProfile.setContentDescription(getString(R.string.switch_profile)); switchProfile.setOnClickListener(new View.OnClickListener() { @@ -487,7 +497,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl } View profileButton = view.findViewById(R.id.profile_button); - if (profileButton != null) { + if (profileButton != null && currentScreenType != null) { int toolbarRes = currentScreenType.toolbarResId; int iconColor = getActiveProfileColor(); int bgColor = UiUtilities.getColorWithAlpha(iconColor, 0.1f); @@ -521,7 +531,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl } private void updatePreferencesScreen() { - if (getSelectedAppMode() != null) { + if (getSelectedAppMode() != null && currentScreenType != null) { int resId = currentScreenType.preferencesResId; if (resId != -1) { addPreferencesFromResource(resId); From b499043a2d7e4baddd57a9b21cc5f721f688a149 Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Thu, 13 Feb 2020 19:53:01 +0200 Subject: [PATCH 19/42] Fix Manage Profiles bugs --- .../res/layout/bottom_sheet_dialog_button.xml | 2 + .../layout/bottom_sheet_dialog_button_big.xml | 2 + OsmAnd/res/layout/map_context_menu_button.xml | 2 + .../res/layout/profile_preference_toolbar.xml | 46 ++++++++++++------- ...profile_preference_toolbar_with_switch.xml | 1 - OsmAnd/res/values/strings.xml | 1 + OsmAnd/src/net/osmand/plus/UiUtilities.java | 2 +- .../plus/settings/BaseSettingsFragment.java | 14 ++++-- .../settings/ConfigureProfileFragment.java | 5 ++ .../plus/settings/NavigationFragment.java | 6 --- .../settings/ProfileAppearanceFragment.java | 29 ++++++------ .../plus/widgets/OsmandTextFieldBoxes.java | 10 ++-- 12 files changed, 76 insertions(+), 44 deletions(-) diff --git a/OsmAnd/res/layout/bottom_sheet_dialog_button.xml b/OsmAnd/res/layout/bottom_sheet_dialog_button.xml index 34dfd832f4..f87dee1855 100644 --- a/OsmAnd/res/layout/bottom_sheet_dialog_button.xml +++ b/OsmAnd/res/layout/bottom_sheet_dialog_button.xml @@ -11,6 +11,7 @@ android:id="@+id/button_container" android:layout_width="match_parent" android:layout_height="match_parent" + android:duplicateParentState="true" tools:ignore="UselessParent"> diff --git a/OsmAnd/res/layout/bottom_sheet_dialog_button_big.xml b/OsmAnd/res/layout/bottom_sheet_dialog_button_big.xml index 7a8d1ee9a9..2dff6a2668 100644 --- a/OsmAnd/res/layout/bottom_sheet_dialog_button_big.xml +++ b/OsmAnd/res/layout/bottom_sheet_dialog_button_big.xml @@ -10,6 +10,7 @@ android:id="@+id/button_container" android:layout_width="match_parent" android:layout_height="match_parent" + android:duplicateParentState="true" tools:ignore="UselessParent"> diff --git a/OsmAnd/res/layout/map_context_menu_button.xml b/OsmAnd/res/layout/map_context_menu_button.xml index 131ecabac8..038c8378b9 100644 --- a/OsmAnd/res/layout/map_context_menu_button.xml +++ b/OsmAnd/res/layout/map_context_menu_button.xml @@ -12,6 +12,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:minHeight="@dimen/context_menu_controller_height" + android:duplicateParentState="true" tools:ignore="UselessParent"> diff --git a/OsmAnd/res/layout/profile_preference_toolbar.xml b/OsmAnd/res/layout/profile_preference_toolbar.xml index c21dcd0edb..41596108c1 100644 --- a/OsmAnd/res/layout/profile_preference_toolbar.xml +++ b/OsmAnd/res/layout/profile_preference_toolbar.xml @@ -25,26 +25,40 @@ android:src="@drawable/ic_action_mode_back" android:tint="?attr/default_icon_color" /> - + android:paddingTop="@dimen/content_padding_half" + android:paddingBottom="@dimen/content_padding_half" + android:background="?attr/card_and_list_background_basic" + android:orientation="vertical"> - + + + + diff --git a/OsmAnd/res/layout/profile_preference_toolbar_with_switch.xml b/OsmAnd/res/layout/profile_preference_toolbar_with_switch.xml index 7b7f3dc52a..ee03b0d8f9 100644 --- a/OsmAnd/res/layout/profile_preference_toolbar_with_switch.xml +++ b/OsmAnd/res/layout/profile_preference_toolbar_with_switch.xml @@ -62,7 +62,6 @@ android:paddingLeft="@dimen/content_padding" android:paddingRight="@dimen/content_padding" android:textAppearance="@style/TextAppearance.ContextMenuSubtitle" - android:visibility="gone" tools:text="Some description" /> diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index ddf2c73dee..0251cf49e1 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,7 @@ Thx - Hardy --> + Please provide a name for the profile Open settings Plugin disabled This plugin is a separate application, you will need to remove it separately if you no longer plan to use it.\n\nThe plugin will remain on the device after removing OsmAnd. diff --git a/OsmAnd/src/net/osmand/plus/UiUtilities.java b/OsmAnd/src/net/osmand/plus/UiUtilities.java index 6144decd69..21fecfb2b4 100644 --- a/OsmAnd/src/net/osmand/plus/UiUtilities.java +++ b/OsmAnd/src/net/osmand/plus/UiUtilities.java @@ -369,7 +369,7 @@ public class UiUtilities { activeColor = ContextCompat.getColor(app, appMode.getIconColorInfo().getColor(nightMode)); break; case TOOLBAR: - activeColor = ContextCompat.getColor(app, nightMode ? R.color.text_color_tab_active_dark : R.color.text_color_tab_active_light); + activeColor = Color.WHITE; inactiveColorPrimary = activeColor; inactiveColorSecondary = UiUtilities.getColorWithAlpha(Color.BLACK, 0.25f); break; diff --git a/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java index bd3bc0ce85..ec9863482e 100644 --- a/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java @@ -104,7 +104,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl GLOBAL_SETTINGS(GlobalSettingsFragment.class.getName(), false, R.xml.global_settings, R.layout.global_preference_toolbar), CONFIGURE_PROFILE(ConfigureProfileFragment.class.getName(), true, R.xml.configure_profile, R.layout.profile_preference_toolbar_with_switch), PROXY_SETTINGS(ProxySettingsFragment.class.getName(), false, R.xml.proxy_preferences, R.layout.global_preferences_toolbar_with_switch), - GENERAL_PROFILE(GeneralProfileSettingsFragment.class.getName(), true, R.xml.general_profile_settings, R.layout.profile_preference_toolbar_big), + GENERAL_PROFILE(GeneralProfileSettingsFragment.class.getName(), true, R.xml.general_profile_settings, R.layout.profile_preference_toolbar), NAVIGATION(NavigationFragment.class.getName(), true, R.xml.navigation_settings_new, R.layout.profile_preference_toolbar), COORDINATES_FORMAT(CoordinatesFormatFragment.class.getName(), true, R.xml.coordinates_format, R.layout.profile_preference_toolbar), ROUTE_PARAMETERS(RouteParametersFragment.class.getName(), true, R.xml.route_parameters, R.layout.profile_preference_toolbar), @@ -117,10 +117,10 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl DIALOGS_AND_NOTIFICATIONS_SETTINGS(DialogsAndNotificationsSettingsFragment.class.getName(), false, R.xml.dialogs_and_notifications_preferences, R.layout.global_preferences_toolbar_with_switch), PROFILE_APPEARANCE(ProfileAppearanceFragment.TAG, true, R.xml.profile_appearance, R.layout.profile_preference_toolbar), OPEN_STREET_MAP_EDITING(OsmEditingFragment.class.getName(), false, R.xml.osm_editing, R.layout.global_preference_toolbar), - MULTIMEDIA_NOTES(MultimediaNotesFragment.class.getName(), true, R.xml.multimedia_notes, R.layout.profile_preference_toolbar_big), - MONITORING_SETTINGS(MonitoringSettingsFragment.class.getName(), true, R.xml.monitoring_settings, R.layout.profile_preference_toolbar_big), + MULTIMEDIA_NOTES(MultimediaNotesFragment.class.getName(), true, R.xml.multimedia_notes, R.layout.profile_preference_toolbar), + MONITORING_SETTINGS(MonitoringSettingsFragment.class.getName(), true, R.xml.monitoring_settings, R.layout.profile_preference_toolbar), LIVE_MONITORING(LiveMonitoringFragment.class.getName(), false, R.xml.live_monitoring, R.layout.global_preferences_toolbar_with_switch), - ACCESSIBILITY_SETTINGS(AccessibilitySettingsFragment.class.getName(), true, R.xml.accessibility_settings, R.layout.profile_preference_toolbar_big), + ACCESSIBILITY_SETTINGS(AccessibilitySettingsFragment.class.getName(), true, R.xml.accessibility_settings, R.layout.profile_preference_toolbar), DEVELOPMENT_SETTINGS(DevelopmentSettingsFragment.class.getName(), false, R.xml.development_settings, R.layout.global_preference_toolbar); public final String fragmentName; @@ -435,6 +435,11 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl toolbarTitle.setText(getPreferenceScreen().getTitle()); } + TextView toolbarSubtitle = (TextView) view.findViewById(R.id.toolbar_subtitle); + if (toolbarSubtitle != null) { + toolbarSubtitle.setText(getSelectedAppMode().toHumanString()); + } + View closeButton = view.findViewById(R.id.close_button); if (closeButton != null) { closeButton.setOnClickListener(new View.OnClickListener() { @@ -461,6 +466,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl } } }); + switchProfile.setVisibility(View.GONE); } } diff --git a/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java b/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java index 50b5f82f7e..15cd26df7b 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ConfigureProfileFragment.java @@ -112,6 +112,11 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co updateToolbarSwitch(); } }); + + View switchProfile = view.findViewById(R.id.profile_button); + if (switchProfile != null) { + switchProfile.setVisibility(View.VISIBLE); + } } @Override diff --git a/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java b/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java index 82f80519eb..38a6dbccf9 100644 --- a/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java @@ -50,12 +50,6 @@ public class NavigationFragment extends BaseSettingsFragment { routingProfileDataObjects = getRoutingProfiles(app); } - @Override - protected void createToolbar(LayoutInflater inflater, View view) { - super.createToolbar(inflater, view); - view.findViewById(R.id.profile_button).setVisibility(View.GONE); - } - @Override protected void setupPreferences() { navigationType = findPreference(NAVIGATION_TYPE); diff --git a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java index 7f35a744bd..7db17b5c5e 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java @@ -251,13 +251,6 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { return !profile.equals(changedProfile); } - @Override - protected void createToolbar(LayoutInflater inflater, View view) { - super.createToolbar(inflater, view); - View profileIcon = view.findViewById(R.id.profile_button); - profileIcon.setVisibility(View.VISIBLE); - } - @Override public void onSaveInstanceState(Bundle outState) { saveState(outState); @@ -327,15 +320,16 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { @Override public void afterTextChanged(Editable s) { changedProfile.name = s.toString(); - if (hasNameDuplicate()) { - saveButton.setEnabled(false); - profileNameOtfb.setError(app.getString(R.string.profile_alert_duplicate_name_msg), true); + if (nameIsEmpty()) { + disableSaveButtonWithErrorMessage(app.getString(R.string.please_provide_profile_name_message)); + } else if (hasNameDuplicate()) { + disableSaveButtonWithErrorMessage(app.getString(R.string.profile_alert_duplicate_name_msg)); } else { saveButton.setEnabled(true); } } }); - if (getSelectedAppMode().equals(ApplicationMode.DEFAULT)) { + if (getSelectedAppMode().equals(ApplicationMode.DEFAULT) && !isNewProfile) { profileName.setFocusableInTouchMode(false); profileName.setFocusable(false); } else { @@ -686,13 +680,22 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { private boolean hasNameDuplicate() { for (ApplicationMode m : ApplicationMode.allPossibleValues()) { - if (m.toHumanString().equals(changedProfile.name) && - !m.getStringKey().equals(profile.stringKey)) { + if (m.toHumanString().trim().equals(changedProfile.name.trim()) && + !m.getStringKey().trim().equals(profile.stringKey.trim())) { return true; } } return false; } + + private boolean nameIsEmpty() { + return changedProfile.name.trim().equals(""); + } + + private void disableSaveButtonWithErrorMessage(String errorMessage) { + saveButton.setEnabled(false); + profileNameOtfb.setError(errorMessage, true); + } public boolean isProfileAppearanceChanged(final MapActivity mapActivity) { hideKeyboard(); diff --git a/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java b/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java index 9eb0df286d..7449a29a0c 100644 --- a/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java +++ b/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java @@ -1,9 +1,6 @@ package net.osmand.plus.widgets; import android.content.Context; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.Nullable; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.View; @@ -91,6 +88,13 @@ public class OsmandTextFieldBoxes extends TextFieldBoxes { return editText; } + @Override + protected void makeCursorBlink() { + CharSequence hintCache = this.editText.getHint(); + this.editText.setHint(" "); + this.editText.setHint(hintCache); + } + @Override public void setError(String errorText, boolean giveFocus) { super.setError(errorText, giveFocus); From e9572ccf7e792cf7125ae07b21e3ed2d9a3f40ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Ersen?= Date: Thu, 13 Feb 2020 16:07:42 +0000 Subject: [PATCH 20/42] Translated using Weblate (Turkish) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-tr/strings.xml | 75 ++++++++++++++++---------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/OsmAnd/res/values-tr/strings.xml b/OsmAnd/res/values-tr/strings.xml index 2cf95a6c5d..af4a87f5e5 100644 --- a/OsmAnd/res/values-tr/strings.xml +++ b/OsmAnd/res/values-tr/strings.xml @@ -2,7 +2,7 @@ Değişiklik listesini kapat ZXing Barcode Scanner uygulaması yüklü değil. Google Play\'de ara\? - Yol renk şemasını seç: + Bir yol rengi şeması seçin: Yol renk şeması Hedef yönü göster Konum günlüğü hizmetlerini kullanmak için \"Yolculuk kaydı\" eklentisini etkinleştirin (GPX günlüğü, çevrim içi izleme) @@ -165,7 +165,7 @@ \n - Eksiksiz çevrim dışı işlevsellik (indirilen vektör veya döşeme haritalarını cihazda saklayın) \n - Tüm dünya için kompakt çevrim dışı vektör haritaları mevcuttur \n - Doğrudan uygulamadan ülke veya bölge haritalarını indirin -\n - GPX veya navigasyon rotaları, ilgi noktaları (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması +\n - GPX veya navigasyon rotaları, ilgi çekici noktalar (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması \n - Adresleri ve yerleri çevrim dışı arama (POI\'ler) \n - Orta menzilli mesafeler için çevrim dışı yönlendirme \n - İsteğe bağlı olarak araba, bisiklet ve yaya modları: @@ -191,7 +191,7 @@ \n - Tüm dünya için kompakt çevrim dışı vektör haritaları mevcuttur \n - Doğrudan uygulamadan sınırsız olarak ülke veya bölge haritalarını indirin \n - Çevrim dışı Wikipedia özelliği (Wikipedia POI\'lerini indir), gezip görmek için harikadır -\n - GPX veya navigasyon rotaları, ilgi noktaları (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması +\n - GPX veya navigasyon rotaları, ilgi çekici noktalar (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması \n \n - Adresleri ve yerleri çevrim dışı arama (POI\'ler) \n - Orta menzilli mesafeler için çevrim dışı yönlendirme @@ -203,7 +203,7 @@ \n Gün doğumu:%1$s \nGün batımı:%2$s - Öznitelikleri oluşturma + Görselleştirme özellikleri Harita tarzı Ekran yapılandırma Şeritler @@ -441,14 +441,14 @@ Döner kavşak: %1$d çıkışa girin ve devam edin Tüm arazi alan özelliklerini harita üzerinde şeffaf hale getirin. Çokgenler - işleme modu + Görselleştirme modu Için haritayı optimize et Yakınlaştırma seviyesinden görünüm (eş yükselti eğrisi verisi gerektirir): Eş yükselti eğrilerini göster Haritanın gösterilen detay miktarını artırın. Rota edilen veri Biçim - İÇN (İhtiyaç Noktası) arama + POI (Point of interest - İlgi çekici nokta) arama Koordinatlar Toplu taşıma için ara OsmAnd çevrim dışı yolbul geçici olarak kullanılamıyor. @@ -477,7 +477,7 @@ Vektörel haritalar daha hızlı görüntülenir. Bazı aygıtlarda düzgün çalışmayabilir. Bir ses seçin ve duyuruları oynayarak test edin: OsmAnd gelişimi - Yerel render etme + Yerel görselleştirme Sesli uyarıları test et Bu konum için \'Ayarlar\' (\'Harita dosyalarını yönet\') kısmından çevrim dışı bir vektör haritası indirin veya \'Çevrim içi haritalar\' eklentisine geçin. GPX dosyalarını OSM ye gönder? @@ -586,7 +586,7 @@ Otomatik-sadece merkezi nav Otomatik-navigasyon yaparken sadece merkezi harita görünümü. Haritayı kullanırken görünümü otomatik olarak ortala. - Özel seçenekli vektör renderer etme + Vektör görselleştiriciye özgü seçenekler Üst katman / alt katman Harita kaynağı ayarları Vektör harita ayarları @@ -649,8 +649,8 @@ Sesli uyarılar (kaydedilmiş) POI Verisi TTS sesi - Hata ayıklama bilgisi dönüştürülüyor - Rendering performansını görüntüleyin. + Görselleştirme hata ayıklama bilgisi + Görselleştirme performansını görüntüleyin. Yeni veri(ler) açılıyor… Çevrim içi navigasyon çevrim dışı çalışmamaktadır. Tepe gölgesi katmanı @@ -808,21 +808,21 @@ {0} öğe seçildi İndirilen En hızlı rotayı hesaplamayı etkinleştirin veya yakıt tasarrufu rotası için devre dışı bırakın. - Devamlı işleme + Sürekli görselleştirme Seçilen alan çizilemedi. Konumu kullan… - Oluşturucu yüklendi - Oluşturucu yüklenemedi. - İÇN websitesini göster - İÇN telefonunu göster - süzmek için yazın + Görselleştirici yüklendi + Görselleştirici yüklenemedi. + POI web sitesini göster + POI telefonunu göster + filtrelemek için yazın Toplu taşıma ara Ulaştırma sonuçları (hedef yok): Ulaşım sonuçları (hedefe {0}): Taşıma aramasını sıfırla Tracks klasöründe GPX dosyası bulunamadı GPX verileri okunamadı. - İÇN düzenle + POI düzenle Pusula yönü Hareket yönü Dönme yok (kuzey her zaman yukarı doğru) @@ -870,10 +870,10 @@ Toplu taşıma duraklarını haritada göster. Taşıma duraklarını göster OsmAnd yolbul uygulaması - İÇN verisi güncellendi ({0} yüklendi) + POI güncellendi ({0} yüklendi) Yerel POI listesi güncellenemedi. Sunucudan veri yüklenemedi. - Bu alan için çevrim dışı İÇN verisi mevcut değil + Bu alan için çevrim dışı POI verisi mevcut değil Şehir: {0} Sokak: {0}, {1} Bina: {0}, {1}, {2} @@ -984,7 +984,7 @@ Mark Deniz Gösterilen profilleri seç. Uygulama profilleri - Harita oluşturma + Harita görselleştirme Yürüyüş Motosikletler Tekne @@ -1454,8 +1454,8 @@ Önceki mesafe Sonraki mesafe geçmek için durur - Yakınlaştırma, İÇN\'leri güncellemenizi sağlar - Güncelleme POI + Yakınlaştırma, POI\'leri güncellemenizi sağlar + POI güncelle Sık Kullanılanlar içe aktarıldı Verileri GPX dosyası olarak kaydedin ya da ara noktaları \'Sık Kullanılanlar\'a aktarın\? {0} konumunda Sık Kullanılanlar içeren GPX dosyası bulunamadı @@ -1479,9 +1479,9 @@ OsmAnd Yükle - {1} {2} üzerinden {0} MB \? Yakınlaştırma {0} indirmek {1} fayans ({2} MB) Önceden yükleme için maksimum zoom - Bir kerede görüntü yerine sürekli görüntü oluşturmayı göster. - vektör render - Oluşturma görünümünü seçin + Tek seferde görüntü yerine sürekli görselleştirmeyi görüntüleyin. + Vektör görselleştirici + Görselleştirme görünümünü seçin Yüksek yoğunluklu ekranlarda (döşeme) haritaları uzatma (ve bulanıklaştırma). Dizin Oluşturma adresi … Dizin Oluşturma haritası … @@ -1525,9 +1525,9 @@ Varış bildirisi Varış bildirimini ne yakınlıkta istiyorsun? Alp yürüyüş ölçeği (SAC) - SAC ölçeğine göre yolları oluşturun. + SAC ölçeğine göre yolları görselleştir. Yürüyüş sembolü üst katmanı - OSMC izlerine göre yolları oluşturun. + OSMC izlerine göre yolları görselleştir. GPX Sesli uyarılar müzik çalmayı duraklatır. Müziği duraklat @@ -1727,8 +1727,8 @@ Kuzeye doğru katedilen mesafe doğuya doğru yönelme İndirilemedi, lütfen İnternet bağlantınızı kontrol edin. - Kullanım OpenGL render - Donanım hızlandırmalı OpenGL renderleme kullanın (daha fazla pil kullanabilir, ya da çok eski cihazlarda çalışmayabilir). + OpenGL görselleştirmeyi kullan + Donanım hızlandırmalı OpenGL görselleştirme kullan (daha fazla pil kullanabilir, ya da çok eski cihazlarda çalışmayabilir). Bypass bulunamadı Arama Otobüs, troleybüs, mekik yolları @@ -1885,7 +1885,7 @@ Etkin işaretleyiciler Harita işaretleyicileri Harita işaretleyici - Poligon görüntülemeyi kapatmanız önerilir. + Poligon görselleştirmeyi kapatmanız önerilir. Bağışlar Alıcıların sayısı %1$s , rütbe %2$s , toplam düzenlemeleri %3$s düzenler @@ -1980,7 +1980,7 @@ Yeni klasör ekle Nokta(lar) silindi. Takip et - Waypointler, ilgi noktaları, adlandırılmış özellikler + Waypointler, ilgi çekici noktalar, adlandırılmış özellikler Azami hız Ortalama hız Azami @@ -2773,7 +2773,7 @@ \nTemsil ettiği alan: %1$s x %2$s Boşluktan sonra kayıtları otomatik bölme 6 dakikalık aralıktan sonra yeni segmenti, 2 saatlik aralıktan sonra yeni izlenen yolu veya tarih değiştiyse daha uzun aralıktan sonra yeni dosyayı başlatın. - Derinlik çizgilerini ve noktalarını göster. + Eş derinlik eğrilerini ve noktalarını göster. Bu rotadan geçmek için döner Berberice Uygulama indirimlerini ve özel yerel etkinlik mesajlarını gösterme. @@ -2880,12 +2880,12 @@ Wikipedia ve Wikivoyage makalelerini çevrim dışı olarak okumak için OsmAnd Live üyeliği alın. Link nasıl açılır\? Wikipedia\'yı çevrim dışı olarak oku - Deniz navigasyonu için. Şamandıralar, deniz fenerleri, nehir yolları, deniz şeritleri ve işaretleri, limanlar, deniz kenarı hizmetleri ve eş derinlik çizgileri içermektedir. + Deniz navigasyonu için. Şamandıralar, deniz fenerleri, nehir yolları, deniz şeritleri ve işaretleri, limanlar, deniz kenarı hizmetleri ve eş derinlik eğrilerini içermektedir. Kayak yapmak için. Pistler, telesiyejler, kros kayak yolları vb. içermektedir. İkincil harita nesnelerini karartır. Basit sürüş tarzı. Yumuşak gece modu, eş yükselti eğrileri, turuncu tarzdaki zıtlaştırılmış yollar, ikincil harita nesnelerini karartma. Yürüyüş, doğa yürüyüşü ve doğa bisikleti için. Dış mekanda okunabilir. Zıtlaştırılmış yollar ve doğal nesneler, farklı rota tipleri, gelişmiş eş yükselti eğrisi seçenekleri, ekstra detaylar. Yüzey bütünlüğünün ayarlanması yol kalitesini ayırt eder. Gece modu yok. Eski varsayılan \'Mapnik\' tarzı. \'Mapnik\' ile benzer renkler. - Genel amaçlı stil. Yoğun şehirler temiz bir şekilde gösterilmiştir. Eş yükselti eğrileri, rotalar, yüzey kalitesi, erişim kısıtlamaları, yol kalkanları, SAC ölçeğine göre yol görüntüleme, akarsu sporları öğeleri içermektedir. + Genel amaçlı stil. Yoğun şehirler temiz bir şekilde gösterilmiştir. Eş yükselti eğrileri, rotalar, yüzey kalitesi, erişim kısıtlamaları, yol kalkanları, SAC ölçeğine göre yol görselleştirme, akarsu sporları öğeleri içermektedir. Yüksek zıtlık ve maksimum ayrıntı ile turne tarzı. OsmAnd varsayılan stilinin tüm seçenekleri ile birlikte, mümkün olduğu kadar çok ayrıntıyı, özellikle de yolları, patikaları ve seyahat etmenin diğer yollarını gösterir. Yol tipleri arasındaki \"touring atlas\" ayrımını temizleyin. Gündüz, gece ve dış mekan kullanımı için uygundur. \'Topo\' stiline dayalı arazi sürüşleri ve yeşil uydu görüntüleriyle alt tabaka olarak kullanım için. Ana yol kalınlığı azaltılmış, izlenen yollar, patikalar, bisiklet ve diğer rotaların kalınlığı arttırılmıştır. Yaya ve bisiklet yollarının kontrastını artırmak için varsayılan stilin değiştirilmesi. Eski Mapnik renklerini kullanır. @@ -2922,7 +2922,7 @@ Transferler Yürüyerek Yol - İlgi noktaları (POI) + İlgi çekici noktalar (Points of interest - POI) Haritada veya aşağıdaki listeden navigasyon sırasında kaçınmak istediğiniz bir yol seçin: İzlenecek yol dosyasını seçin %1$s\'de ulaş @@ -3108,7 +3108,7 @@ \n • Konumunuzu ve yönünüzü gösterin \n • İsteğe bağlı olarak resmi pusulaya veya hareket yönünüze göre hizalayın \n • En önemli yerlerinizi Sık Kullanılanlar olarak kaydedin -\n • Çevrenizdeki POI\'leri (ilgi noktaları) görüntüleyin +\n • Çevrenizdeki POI\'leri (points of interest - ilgi çekici noktaları) görüntüleyin \n • Özel çevrim içi döşemeleri, uydu görüntüsünü (Bing\'den), tur/gezinme GPX parkurları gibi farklı üst katmanları ve ayarlanabilir şeffaflığı olan ek katmanları görüntüleyin \n • İsteğe bağlı olarak yer adlarını İngilizce, yerel veya fonetik yazım biçiminde görüntüleyin \n @@ -3223,7 +3223,7 @@ Sadece-klasik rotalarına izin ver Paten yolları olmadan sadece klasik stil için düzenlenmiş rotalar. Buna daha gevşek bir palete sahip daha küçük bir kar arabasıyla düzenlenen rotalar ve kayakçılar tarafından manuel olarak yapılan pistler dahildir. Tercih edilen zorluk - Daha zor ya da daha kolay pistler üzerinde yönlendirme daha kısa ise hala mümkün olmasına rağmen, bu zorluktaki yolları tercih edin. + Bu zorluktaki rotaları tercih et, ancak eğer daha kısa ise daha zor veya daha kolay pistler üzerinden yönlendirmek yine de mümkündür. Pist dışı \'Serbest\' ve \'pist dışı sürüşler\', resmi olmayan yollar ve geçitlerdir. Tipik olarak düzenlenmemiş, bakımı yapılmamış ve akşamları kontrol edilmemiştir. Riski göze alarak girin. Harici giriş cihazları @@ -3483,4 +3483,5 @@ \n Koordinatları kopyala Doğrudan noktaya + Kategoriye göre sırala \ No newline at end of file From 1c45e8b462f1a07f7ad8f3cbbbe8b0d8014b3159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=2E=20R=C3=BCdinger?= Date: Thu, 13 Feb 2020 08:24:06 +0000 Subject: [PATCH 21/42] Translated using Weblate (German) Currently translated at 99.8% (3168 of 3175 strings) --- OsmAnd/res/values-de/strings.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index 9de0a2e924..de2bd1043c 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -2163,7 +2163,7 @@ Lon %2$s Kartenquellen Kartenquelle hinzufügen Die Kartenquelle wurde in „%s“ geändert. - Tastenposition ändern + Schaltflächenposition ändern Favoriten anzeigen Favoriten ausblenden Kategorie, in der der Favorit gespeichert werden soll: @@ -2173,7 +2173,7 @@ Lon %2$s Eine Schaltfläche, um eine OSM-Notiz in der Bildschirmmitte einzufügen. Eine Schaltfläche, um einen POI in der Bildschirmmitte einzufügen. Umschalter, um die Sprachansagen während der Navigation ein- oder auszuschalten. - Taste, um eine Parkposition in der Bildschirmmitte einzufügen. + Eine Schaltfläche, um eine Parkposition in der Bildschirmmitte einzufügen. Dialog zum Bearbeiten anzeigen " gespeichert unter " Schnellaktion in %1$s umbenannt, um Duplikate zu vermeiden. @@ -2182,7 +2182,7 @@ Lon %2$s Umschalter, um POIs auf der Karte ein- oder auszublenden. Objekte erstellen Diese Nachricht wird ins Kommentarfeld eingetragen. - Langes Drücken und Ziehen der Taste ändert ihre Bildschirmposition. + Langes Drücken und Ziehen der Schaltfläche ändert ihre Bildschirmposition. Karten-Overlay wurde in „%s“ geändert. Karten-Underlay wurde in „%s“ geändert. Ungültiger OLC @@ -2194,7 +2194,7 @@ Lon %2$s Aufzeichnungen bei Lücken automatisch trennen Nach 6-minütiger Pause neues Segment, nach 2-stündiger Pause neuen Track und nach Pause mit Datumsänderung neue Datei beginnen. Offener Standortcode (OLC) - Taste, um durch die Liste unten zu blättern. + Eine Schaltfläche, um durch die Liste unten zu blättern. Höhendaten berücksichtigen Faktor im Geländeprofil (über SRTM, ASTER und EU-DEM-Daten). Nautische Tiefenlinien @@ -3527,4 +3527,5 @@ Lon %2$s \n \n Nach Kategorie sortieren + Ihre aufgezeichneten Tracks befinden sich in %1$s oder im OsmAnd-Ordner. \ No newline at end of file From 4ee00b46df9ba68a945d4bd0b93838d639b9ecb5 Mon Sep 17 00:00:00 2001 From: Mr-Update Date: Thu, 13 Feb 2020 21:56:02 +0000 Subject: [PATCH 22/42] Translated using Weblate (German) Currently translated at 99.8% (3168 of 3175 strings) --- OsmAnd/res/values-de/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index de2bd1043c..c1571c743a 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3487,10 +3487,10 @@ Lon %2$s System-App verwenden Auslöseton der Kamera Durch das Zurücksetzen auf die Standardeinstellung wird die Sortierung auf den Standardzustand nach der Installation zurückgesetzt. - Eingabehilfenmodus ist in ihrem System deaktiviert. + Eingabehilfenmodus ist in Ihrem System deaktiviert. Zeitlimit für den Systembildschirm verwenden - Standardmäßig deaktiviert, wenn OsmAnd im Vordergrund läuft, wird der Bildschirm nicht ausgeblendet. -\n + Standardmäßig deaktiviert. Wenn OsmAnd im Vordergrund läuft, wird der Bildschirm nicht ausgeblendet. +\n \nWenn aktiviert, verwendet OsmAnd das Zeitlimit für den Systembildschirm. Online-Aufzeichnung Aufgezeichnete Daten löschen From d096ba2a447c139d0d571772d9f2358cb0cb239f Mon Sep 17 00:00:00 2001 From: Verdulo Date: Wed, 12 Feb 2020 22:36:23 +0000 Subject: [PATCH 23/42] Translated using Weblate (Esperanto) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-eo/strings.xml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index 8f4b883e7a..17099b1d19 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -1844,7 +1844,7 @@ Lon: %2$s Konservi kiel Ĉu forigi tiun ĉi filtrilon\? Forigis filtrilon “%1$s” - Kreis filtrilon “%1$s” + Kreis filtrilon \'%1$s\' retpoŝto Speco de fotila fokuso Fokuso de fotilo: @@ -3460,7 +3460,7 @@ Indikas lokon: %1$s x %2$s" Registritaj estos nur punktoj mezuritaj kun la minimuma precizo (en metroj kiel raportitaj fare de Androido per la GPS‑cirkvitaro). Precizo rilatas al disiĝo de valoro dum ripetaj mezuroj kaj ne ĉiam rilatas al ekzakteco, kiu determinas proksimecon de mezuroj al via vera pozicio. Kromefiko: pro filtri laŭ precizo, iuj punktoj – mezuritaj ekz. sub pontoj aŭ arboj, inter altaj konstruaĵoj, aŭ dum malbonaj veteraj kondiĉoj – povos manki. Konsilo: estas malfacile antaŭscii pri kio estos registra kaj kio estos filtrita, do estus bone ne aktivigi tiun ĉi filtrilon. - Disponebla + Disponeblaj Aldoni propran kategorion Montri nur dum nokto Rekomencigis ĉiujn agordojn pri kromprogramoj. @@ -3482,31 +3482,32 @@ Indikas lokon: %1$s x %2$s" \n \nAktivigu tion ĉi por ke OsmAnd uzu sisteman agordon pri malŝalti ekranon. Forviŝi registritajn datumojn - • profiloj: eblo ŝanĝi ilian ordigon, agordi emblemon por mapo, ŝanĝi ĉiujn agordojn por bazaj profiloj kaj restarigi implicitajn valorojn + • profiloj: eblo ŝanĝi ilian ordigon, agordi emblemon por mapo, ŝanĝi ĉiujn agordojn por bazaj profiloj kaj restarigi implicitajn valorojn \n -\n• aldonis numeron de elveturejo dum navigadi +\n• aldonis numeron de elveturejo dum navigadi \n -\n• rearanĝitaj agordoj pri kromprogramoj +\n• rearanĝitaj agordoj pri kromprogramoj \n -\n• rearanĝita la ekrano de agordoj por rapide agordi ĉiun profilon +\n• rearanĝita ekrano de agordoj por rapide agordi ĉiun profilon \n -\n• aldonis eblon kopii agordojn el alia profilo +\n• aldonis eblon kopii agordojn el alia profilo \n -\n• aldonis eblon ŝanĝi ordigon kaj kaŝi kategoriojn de interesejoj dum serĉi +\n• aldonis eblon ŝanĝi ordigon kaj kaŝi kategoriojn de interesejoj dum serĉi \n -\n• rektigis emblemojn de interesejoj sur la mapo +\n• rektigis emblemojn de interesejoj sur la mapo \n -\n• aldonis informojn pri senleviĝo/sunsubiro al la ekrano “agordi mapon” +\n• aldonis informojn pri senleviĝo/sunsubiro al la ekrano “agordi mapon” \n -\n• aldonis emblemojn de hejmo kaj laboro al la mapo +\n• aldonis emblemojn de hejmo kaj laboro al la mapo \n -\n• aldonis subtenon por plurliniaj priskriboj al la agordoj +\n• aldonis subtenon por plurliniaj priskriboj al la agordoj \n -\n• ĝusta transliterumo al la mapo de Japanujo +\n• ĝusta transliterumo al la mapo de Japanujo \n \n• aldonis mapon de Antarkto \n \n Kopii koordinatojn Rekte al punkto + Ordigi laŭ kategorio \ No newline at end of file From 5d7bfbb7b56e62df6fd0e2520e0aff86105d1ba5 Mon Sep 17 00:00:00 2001 From: Tymofij Lytvynenko Date: Wed, 12 Feb 2020 22:33:37 +0000 Subject: [PATCH 24/42] Translated using Weblate (Ukrainian) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-uk/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml index 0b57560cdc..ae2cad8418 100644 --- a/OsmAnd/res/values-uk/strings.xml +++ b/OsmAnd/res/values-uk/strings.xml @@ -3518,4 +3518,5 @@ \n Скопіювати координати Пряма точка + Впорядкувати за категоріями \ No newline at end of file From 7dd443d8e4cd79c3c3ccb0ea0461869fafb8349b Mon Sep 17 00:00:00 2001 From: Mirco Zorzo Date: Thu, 13 Feb 2020 08:11:54 +0000 Subject: [PATCH 25/42] Translated using Weblate (Italian) Currently translated at 90.8% (2884 of 3175 strings) --- OsmAnd/res/values-it/strings.xml | 68 +++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index 96d9654c17..bf2127f637 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -1482,7 +1482,7 @@ Memoria in proporzione %4$s MB (limite di Android %5$s MB, Dalvik %6$s MB).Cancella tutto La mia posizione Preferiti - Le mie tracce + Tracce Traccia in corso di registrazione Visita dopo Visita prima @@ -3456,4 +3456,70 @@ Rappresenta l\'area: %1$s x %2$s %1$s/%2$s Tramonto alle %1$s Alba alle %1$s + Valuta + Navigazione, accuratezza della registrazione + Annunci + Icona visualizzata da fermi. + Impossibile analizzare il dato geo \'%s\'. + "Questo è un filtro delle basse velocità per non registrare i punti inferiori a una data velocità. Questo può permettere di registrare tracce dall\'aspetto più pulito quando visualizzate sulla mappa." + Effetto collaterale: alle tue tracce mancheranno tutte le sezioni in cui il criterio della velocità non sarà soddisfatto (es. quando spingi la tua bici in una elevata pendenza). Altrettanto non ci saranno informazioni nei periodi di riposo o ristoro. Questo ha effetto su tutte le analisi ed elaborazione dei dati, come quando si prova a determinare la lunghezza totale del tuo percorso, il tempo in movimento, o la velocità media. + Raccomandazione: prova prima a utilizzare il sensore del movimento attraverso la registrazione del filtro del minimo dislocamento (B), potrebbe produrre migliori risultati, e perderai meno dati. Se le tue tracce continuano a essere sporche a basse velocità, prova con valori maggiori di zero. Si prega di notare che alcune misurazioni possono non riportare nessuna velocità (alcuni metodi basti sulle reti), in questi casi non registrerai alcun dato. + Osservazione: controllo velocità > 0 : molti chip GPS riportano un valore di velocità solo se l\'algoritmo determina che tu sei in movimento, e nessuno invece se non lo sei. Quindi utilizzando l\'impostazione > 0 nel filtro, in un certo senso utilizza il sensore di movimento del chip GPS. Ma anche se non filtrati qui nel momento della registrazione, comunque utilizziamo questa caratteristica nell\'analisi dei nostri file GPX per determinare al distanza corretta, es. il valore visualizzato in questo campo è la distanza registrata finché si è in movimento. + Questo registrerà solo punti misurati con un\'accuratezza minima (in metri/piedi, come riportati da Android per il tuo chipset). L\'accuratezza si riferisce alla variabilità di misure ripetute, e non è direttamente correlato alla precisione, che definisce quanto la tua misurazione è vicina alla vera posizione. + Effetto collaterale: come conseguenza del filtraggio per accuratezza, i punti possono essere completamente mancanti per esempio sotto a ponti, alberi, in mezzo a edifici elevati o in certe condizioni meteo. + Raccomandazione: è difficile da predire cosa verrà registrato e cosa no, potrebbe essere preferibile disattivare questo filtro. + Osservazione: se il GPS è stato disattivato poco prima di una registrazione, i primi punti misurati potrebbero avere una minore accuratezza, perciò nel nostro codice noi possiamo voler attendere qualche secondo prima oppure prima di registrare dei punti (o registrare i 3 migliori punti consecutivi, ecc...), ma questo non è ancora implementato . + Questo filtro evita che punti duplicati siano registrati quando lo spostamento è troppo piccolo, crea un migliore aspetto delle tracce che non vengono successivamente elaborate. + Effetto collaterale: periodi di riposo non sono registrati affatto oppure con un singolo punto. Piccoli (reali) movimenti (es. lateralmente, per marcare un possible spegnimento nel tuo viaggio) possono essere scartati dal filtro. Il file contiene meno informazioni per la post-elaborazione e presenta statistiche peggiori filtrando i punti ovviamente ridondanti al momento della registrazione, mantenendo potenzialmente artefatti causati da cattiva ricezione o effetti del chipset GPS. + Raccomandazione: un valore di 5 metri potrebbe funzionare bene se non necessiti di registrare dettagli che hanno una misura inferiore di questo e non vuoi chiaramente registrare dati quando sei fermo. + Tempo tampone + Intervallo di registrazione + Indirizzo web + Specifica l\'indirizzo web con i parametri della sintassi: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}. + Notifiche + Velocità minima + Accuratezza minima + Minimo spostamento + Menu — I miei luoghi — Tracce + Menu — I miei luoghi — Note + Menu — I miei luoghi — Modifiche OSM + Reimposta le impostazioni dei componenti aggiuntivi a quelle preimpostate + Divisione delle registrazioni + Usa l\'app di sistema + Sono otturatore fotocamera + L\'autorizzazione è andata a buon fine + Il ripristino dei valori preimpostati ripristinerà all\'ordine preimpostato dopo l\'installazione l\'ordine di visualizzazione. + La modalità accessibile è disabilitato nel tuo sistema. + Utilizza il salvaschermo di sistema + Disabilitato per preimpostazione, se OsmAnd è eseguito in background, lo schermo non andrà in sospensione. +\n +\nSe abilitato OsmAnd userà le impostazioni di sospensione del sistema. + Elimina i dati registrati + "• Profili: ora puoi cambiare l\'ordine, impostare l\'icona per le mappe, cambiare tutte le impostazioni dei profili di base e reimpostarle a quelle preimpostate +\n +\n • Aggiunto nella navigazione il numero delle uscite +\n +\n • Riorganizzate le impostazioni dei componenti aggiuntivi +\n +\n • Riorganizzate la finestra delle Impostazioni per un veloce accesso a tutti i profili +\n +\n • Aggiunta l\'opzione per copiare le impostazioni da un profilo a un altro +\n +\n • Aggiunta la possibilità di cambiare nella Ricerca l\'ordine delle categorie di PDI o di nasconderle +\n +\n • Corretto l\'allineamento dei icone dei PDI nella mappa +\n +\n • Aggiunti i dati alba/tramonto in Configura la mappa +\n +\n • Aggiunte alla mappa le icone Casa/Lavoro +\n +\n • Aggiunto il supporto per le descrizioni su più linee in Impostazioni +\n +\n • Aggiunto la traslitterazione corretta nella mappa del Giappone +\n +\n • Aggiunto la mappa dell\'Antartide +\n +\n" + Copia le coordinate + Ordina per categoria \ No newline at end of file From f4c5bd1274433892d3f85a5971b339baf2a498a7 Mon Sep 17 00:00:00 2001 From: Ahmad Alfrhood Date: Thu, 13 Feb 2020 13:50:00 +0000 Subject: [PATCH 26/42] Translated using Weblate (Arabic) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-ar/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index 59f5848af5..ea51bb46e2 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -1836,7 +1836,7 @@ حدث استثناء: لم يتم إنشاء الملاحظة. حدث استثناء: لم يتم غلق الملاحظة. لا يمكن إضافة تعليق. - ارتكاب + تقديم حذف إحداثية GPX ؟ تعديل/حذف ألمانية منخفضة @@ -3432,4 +3432,5 @@ \n نسخ الإحداثيات مباشر إلى نقطة + الفرز حسب الفئة \ No newline at end of file From 89005eea9b15707734e7fd9836c9fa397ec2cc47 Mon Sep 17 00:00:00 2001 From: Ldm Public Date: Wed, 12 Feb 2020 21:57:55 +0000 Subject: [PATCH 27/42] Translated using Weblate (French) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-fr/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index 46ff574a27..6f2337876b 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -3498,4 +3498,5 @@ représentant la zone : %1$s x %2$s \n Copier les coordonnées Le plus direct + Trier par catégorie \ No newline at end of file From eb818e674397343849dbba33ef56410b740c2820 Mon Sep 17 00:00:00 2001 From: iman Date: Wed, 12 Feb 2020 21:51:48 +0000 Subject: [PATCH 28/42] Translated using Weblate (Persian) Currently translated at 99.7% (3167 of 3175 strings) --- OsmAnd/res/values-fa/strings.xml | 63 ++++++++++++++++---------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/OsmAnd/res/values-fa/strings.xml b/OsmAnd/res/values-fa/strings.xml index a8f1754768..87800e6a97 100644 --- a/OsmAnd/res/values-fa/strings.xml +++ b/OsmAnd/res/values-fa/strings.xml @@ -560,7 +560,7 @@ در حال استخراج فایل… شبکه ثانیه - دقیقه + min. جزئیات مسیر اصلاح POI حذف POI @@ -753,8 +753,8 @@ نمایه‌کردن POI‏… در حال نمایه‌کردن حمل‌ونقل… خطای ورودی/خروجی - ک‌م - متر + km + m منبع کاشی‌های نقشه هدف سرعت مجاز @@ -1261,8 +1261,8 @@ برچسب‌های لایهٔ POI هنگام ناوبری دکمه‌های بزرگ‌نمایی را نشان بده. نمایش دکمه‌های بزرگ‌نمایی - ترتیب براساس مسافت - ترتیب براساس نام + ترتیب بر اساس مسافت + ترتیب بر اساس نام ابتدا یک فایل GPX را با لمس طولانی انتخاب کنید. یک رد انتخاب کنید فایلی برای دانلود پیدا نشد. لطفاً اتصال اینترنت را بررسی کنید. @@ -1801,7 +1801,7 @@ متوسط کم آب - مخفی‌کردن آب + محدوده‌های آب مرور کلی نزدیکترین شهرها دکمه‌ای برای روشن/خاموش کردن زوم خودکار وابسته به سرعت. @@ -2037,7 +2037,7 @@ ویکی‌پدیا از حدف این %1$d یادداشت مطمئن هستید؟ س - دق‍ + min مخفی شود ظاهر جاده کدِ مکانی باز (OLC) @@ -2680,7 +2680,7 @@ دریایی فردا باز می‌شود، در ساعت تعطیل - کپی‌کردن موقعیت/نام POI + کپی موقعیت/نام POI مکان بی‌نام دیدن یادداشت‌های بسته پنهان/آشکارکردن یادداشت‌های OSM. @@ -2916,7 +2916,7 @@ پیام‌های گفتاری مقصدهای میانی زمان رسیدن: %1$s - مترمکعب + تن ظرفیت عرض @@ -3526,31 +3526,32 @@ \n \nاگر فعال باشد، OsmAnd از تنظیمات دستگاه برای زمان خاموش‌شدن صفحه استفاده می‌کند. پاک‌سازی دادهٔ ضبط‌شده - • پروفایل‌ها: اکنون می‌توانید ترتیب پروفایل‌ها و نماد آن‌ها را تنظیم کنید. تنظیمات پروفایل‌های پایه را تغییر دهید یا آن‌ها را به پیشفرض بازنشانی کنید. -\n -\n • شمارهٔ خروجی به ناوبری افزوده شد -\n -\n • تنظیمات افزونه‌ها بازسازی شد -\n -\n • صفحهٔ تنظیمات برای دسترسی فوری به همهٔ پروفایل‌ها بازسازی شد -\n -\n • گزینه‌ای برای کپی‌کردن تنظیمات از پروفایل دیکر افزوده شد -\n -\n • امکان تغییر، مرتب‌سازی یا مخفی‌کردن دسته‌بندی نقاط توجه (POI) هنگام جست‌وجو افزوده شد -\n -\n • چینش نماد نقاط توجه روی نقشه درست شد -\n -\n • دادهٔ غروب/طلوع خورشید به «پیکربندی نقشه» افزوده شد -\n -\n • نمادهای خانه/کار روی نقشه افزوده شد -\n -\n • از توضیحات چندخطی در تنظیمات پشتیبانی می‌شود -\n -\n • نویسه‌گردانیِ درست به نقشهٔ ژاپن افزوده شد -\n + • پروفایل‌ها: اکنون می‌توانید ترتیب پروفایل‌ها و نماد آن‌ها را تنظیم کنید. تنظیمات پروفایل‌های پایه را تغییر دهید یا آن‌ها را به پیشفرض بازنشانی کنید. +\n +\n • شمارهٔ خروجی به ناوبری افزوده شد +\n +\n • تنظیمات افزونه‌ها بازسازی شد +\n +\n • صفحهٔ تنظیمات برای دسترسی فوری به همهٔ پروفایل‌ها بازسازی شد +\n +\n • گزینه‌ای برای کپی‌کردن تنظیمات از پروفایل دیگر افزوده شد +\n +\n • امکان تغییر، مرتب‌سازی یا مخفی‌کردن دسته‌بندی نقاط توجه (POI) هنگام جست‌وجو افزوده شد +\n +\n • چینش نقاط توجه روی نقشه درست شد +\n +\n • دادهٔ غروب/طلوع خورشید به «پیکربندی نقشه» افزوده شد +\n +\n • نمادهای خانه/محل کار روی نقشه افزوده شد +\n +\n • از توضیحات چندخطی در تنظیمات پشتیبانی می‌شود +\n +\n • نویسه‌گردانیِ درست به نقشهٔ ژاپن افزوده شد +\n \n • نقشهٔ جنوبگان افزوده شد \n \n کپی مختصات مستقیم تا نقطه + ترتیب بر اساس دسته \ No newline at end of file From 9423a3b0246db4d8b3b5f08f4f0c9a431b9bd911 Mon Sep 17 00:00:00 2001 From: Franco Date: Thu, 13 Feb 2020 17:49:35 +0000 Subject: [PATCH 29/42] Translated using Weblate (Spanish (Argentina)) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-es-rAR/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index f97c2b626e..184a5d0210 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -3528,4 +3528,5 @@ Lon %2$s \n Copiar coordenadas Directo al punto + Ordenar por categoría \ No newline at end of file From 9878c5b8855e936a506b0345e28fce0be6d0145f Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Thu, 13 Feb 2020 01:48:16 +0000 Subject: [PATCH 30/42] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-zh-rTW/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml index 87b5740507..396f68e19d 100644 --- a/OsmAnd/res/values-zh-rTW/strings.xml +++ b/OsmAnd/res/values-zh-rTW/strings.xml @@ -3518,4 +3518,5 @@ \n 複製座標 點對點 + 按分類排序 \ No newline at end of file From a88ceafb77fe80f6fa39875b394f3bb77ed3322f Mon Sep 17 00:00:00 2001 From: Boyuan Yang <073plan@gmail.com> Date: Wed, 12 Feb 2020 21:30:58 +0000 Subject: [PATCH 31/42] Translated using Weblate (Chinese (Simplified)) Currently translated at 63.6% (2020 of 3175 strings) --- OsmAnd/res/values-zh-rCN/strings.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-zh-rCN/strings.xml b/OsmAnd/res/values-zh-rCN/strings.xml index debafc2f14..25cd77e024 100644 --- a/OsmAnd/res/values-zh-rCN/strings.xml +++ b/OsmAnd/res/values-zh-rCN/strings.xml @@ -1302,7 +1302,7 @@ 避免阶梯 避开边界穿越 避免穿越边境线进入其它国家 - 指定路线上允许的车辆重量 + 指定路线上允许的车辆重量。 高度限制 指定路线上允许的车辆高度。 Android 4.4 版(KitKat)之后,您无法使用先前的存储文件夹(%s)下载或更新地图。您是否想要修改为允许的存储位置并将所有 OsmAnd 文件复制到新位置? @@ -2810,4 +2810,12 @@ 要将所有配置设置重置为默认值吗? 使用此选项需要授权。 可用 + 宽度限制 + 指定路线上允许的车辆宽度。 + 从文件导入 + 照片尺寸、音频和视频质量 + 用户名和密码 + 使用系统应用程序 + 相机快门声音 + 授权成功 \ No newline at end of file From 9360a44701fb5c504d7a91f5fb95fde582a29ac5 Mon Sep 17 00:00:00 2001 From: Franco Date: Fri, 14 Feb 2020 00:24:46 +0000 Subject: [PATCH 32/42] Translated using Weblate (Spanish (American)) Currently translated at 100.0% (3175 of 3175 strings) --- OsmAnd/res/values-es-rUS/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-es-rUS/strings.xml b/OsmAnd/res/values-es-rUS/strings.xml index 00bf2efa45..c734c88937 100644 --- a/OsmAnd/res/values-es-rUS/strings.xml +++ b/OsmAnd/res/values-es-rUS/strings.xml @@ -3527,4 +3527,5 @@ Lon %2$s \n Copiar coordenadas Directo al punto + Ordenar por categoría \ No newline at end of file From 39bd45d5d2539ae2e3d214fecb69d8f913fc0070 Mon Sep 17 00:00:00 2001 From: Verdulo Date: Wed, 12 Feb 2020 22:49:30 +0000 Subject: [PATCH 33/42] Translated using Weblate (Esperanto) Currently translated at 100.0% (3772 of 3772 strings) --- OsmAnd/res/values-eo/phrases.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OsmAnd/res/values-eo/phrases.xml b/OsmAnd/res/values-eo/phrases.xml index 57cc409e57..40041cdc52 100644 --- a/OsmAnd/res/values-eo/phrases.xml +++ b/OsmAnd/res/values-eo/phrases.xml @@ -2784,7 +2784,7 @@ Hejtado Pumpilo Apliko - Speco + Speco de teleskopo Dresado de Speco de diplomata oficejo Ĉefurbo @@ -2819,7 +2819,7 @@ Speco de ŝirmejo Kameno Sezona - Akvospeco + Speco de akvo Sablobordo Nudeco Rulseĝa alireblo @@ -3087,7 +3087,7 @@ rampulejo Spektoteraso Servo - Motorcikla speco + Speco de motorciklo vendo vendo: ne vendo, brokanto @@ -3508,7 +3508,7 @@ Bankaŭtomato Ŝu-riparejo Vendado sen pakumo - Speco + Speco de elektrosubcentralo jes nur Konduktuba substacio From 05b88bc9409cde8b8bcca8ce957c2f1c81dc6b6d Mon Sep 17 00:00:00 2001 From: Osoitz Date: Thu, 13 Feb 2020 06:15:06 +0000 Subject: [PATCH 34/42] Translated using Weblate (Basque) Currently translated at 96.5% (3641 of 3772 strings) --- OsmAnd/res/values-eu/phrases.xml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-eu/phrases.xml b/OsmAnd/res/values-eu/phrases.xml index 2cc51c8867..2a47a78488 100644 --- a/OsmAnd/res/values-eu/phrases.xml +++ b/OsmAnd/res/values-eu/phrases.xml @@ -92,7 +92,7 @@ Instrumentu musikalak Berri agentzia Optometrista - Janari organikoa + Produktu organikoak Margo denda Animali denda Argazkilaritza denda @@ -3633,4 +3633,20 @@ Dirua ateratzea Mota Aire zabalean + Bizikleta sarbidea: pribatua + Bizikleta sarbidea: oinez + Bizikleta sarbidea: helmuga + Bizikleta sarbidea: malgua + Bizikleta sarbidea: bezeroak + Zaldi sarbidea: pribatua + Zaldi sarbidea: helmuga + Zaldi sarbidea: malgua + Oinezkoentzako sarbidea: bai + Oinezkoentzako sarbidea: pribatua + Oinezkoentzako sarbidea: ez + Oinezkoentzako sarbidea: helmuga + Oinezkoentzako sarbidea: malgua + Oinezkoentzako sarbidea: bezeroak + Mota + Egoera \ No newline at end of file From b7fec04e1d8f329a8392baf4300bbb94e6a984da Mon Sep 17 00:00:00 2001 From: ace shadow Date: Thu, 13 Feb 2020 22:05:23 +0000 Subject: [PATCH 35/42] Translated using Weblate (Slovak) Currently translated at 93.3% (3520 of 3772 strings) --- OsmAnd/res/values-sk/phrases.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/res/values-sk/phrases.xml b/OsmAnd/res/values-sk/phrases.xml index 7f69d58dc8..7cdc719113 100644 --- a/OsmAnd/res/values-sk/phrases.xml +++ b/OsmAnd/res/values-sk/phrases.xml @@ -2233,7 +2233,7 @@ Kone nepovolené Zvieratá povolené Zvieratá nepovolené - Typ: vojenský cintorín + Typ: vojnový hrob Typ: mohyla Typ: skalná jaskyňa Typ: hypogeum From 41e304725984983a304e5c291de8056317b1ff75 Mon Sep 17 00:00:00 2001 From: Mr-Update Date: Wed, 12 Feb 2020 21:11:50 +0000 Subject: [PATCH 36/42] Translated using Weblate (German) Currently translated at 100.0% (267 of 267 strings) Translation: OsmAnd/Telegram Translate-URL: https://hosted.weblate.org/projects/osmand/telegram/de/ --- OsmAnd-telegram/res/values-de/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd-telegram/res/values-de/strings.xml b/OsmAnd-telegram/res/values-de/strings.xml index a926d6c87b..d269b7e9cb 100644 --- a/OsmAnd-telegram/res/values-de/strings.xml +++ b/OsmAnd-telegram/res/values-de/strings.xml @@ -268,4 +268,5 @@ Letzte Aktualisierung von Telegram: vor %1$s Letzte Antwort: vor %1$s vor %1$s + ERR \ No newline at end of file From 07557b2c4af486db879db1da1c18be7199c7ae62 Mon Sep 17 00:00:00 2001 From: iman Date: Thu, 13 Feb 2020 08:27:25 +0000 Subject: [PATCH 37/42] Translated using Weblate (Persian) Currently translated at 27.0% (72 of 267 strings) Translation: OsmAnd/Telegram Translate-URL: https://hosted.weblate.org/projects/osmand/telegram/fa/ --- OsmAnd-telegram/res/values-fa/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd-telegram/res/values-fa/strings.xml b/OsmAnd-telegram/res/values-fa/strings.xml index 96295820c3..8c21e50557 100644 --- a/OsmAnd-telegram/res/values-fa/strings.xml +++ b/OsmAnd-telegram/res/values-fa/strings.xml @@ -38,8 +38,8 @@ yd ft mi - ک‌م - متر + km + m nmi min/m min/km From ad427985b2ce7d9efb5826170d6e2f105b91f9e5 Mon Sep 17 00:00:00 2001 From: Nazar Date: Fri, 14 Feb 2020 16:20:30 +0200 Subject: [PATCH 38/42] Fix "gray bar at the bottom of the screen" --- .../mapcontextmenu/editors/PointEditorFragment.java | 9 ++++----- .../osmand/plus/profiles/EditProfilesFragment.java | 10 +++++----- .../plus/quickaction/QuickActionListFragment.java | 11 ++++++----- .../osmand/plus/settings/BaseSettingsFragment.java | 9 +++------ 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java index 81b5166d85..649f6d8787 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java @@ -167,6 +167,10 @@ public abstract class PointEditorFragment extends BaseOsmAndFragment { descriptionEdit.setHint(R.string.access_hint_enter_description); } + if (Build.VERSION.SDK_INT >= 21) { + AndroidUtils.addStatusBarPadding21v(app, view); + } + return view; } @@ -234,11 +238,6 @@ public abstract class PointEditorFragment extends BaseOsmAndFragment { return R.color.status_bar_color_light; } - @Override - protected boolean isFullScreenAllowed() { - return false; - } - private void hideKeyboard() { FragmentActivity activity = getActivity(); if (activity != null) { diff --git a/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java b/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java index fa2901b583..e81d4fbfda 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java +++ b/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java @@ -2,6 +2,7 @@ package net.osmand.plus.profiles; import android.annotation.SuppressLint; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -174,12 +175,11 @@ public class EditProfilesFragment extends BaseOsmAndFragment { } }); - return mainView; - } + if (Build.VERSION.SDK_INT >= 21) { + AndroidUtils.addStatusBarPadding21v(app, mainView); + } - @Override - protected boolean isFullScreenAllowed() { - return false; + return mainView; } @Override diff --git a/OsmAnd/src/net/osmand/plus/quickaction/QuickActionListFragment.java b/OsmAnd/src/net/osmand/plus/quickaction/QuickActionListFragment.java index 998a1464a1..a64cc46979 100644 --- a/OsmAnd/src/net/osmand/plus/quickaction/QuickActionListFragment.java +++ b/OsmAnd/src/net/osmand/plus/quickaction/QuickActionListFragment.java @@ -3,6 +3,7 @@ package net.osmand.plus.quickaction; import android.content.DialogInterface; import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -24,6 +25,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import net.osmand.AndroidUtils; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; @@ -73,6 +75,10 @@ public class QuickActionListFragment extends BaseOsmAndFragment implements Quick } }); + if (Build.VERSION.SDK_INT >= 21) { + AndroidUtils.addStatusBarPadding21v(getContext(), view); + } + return view; } @@ -145,11 +151,6 @@ public class QuickActionListFragment extends BaseOsmAndFragment implements Quick quickActionRegistry.setUpdatesListener(null); } - @Override - protected boolean isFullScreenAllowed() { - return false; - } - @Override public int getStatusBarColorId() { return isLightContent ? R.color.status_bar_color_light : R.color.status_bar_color_dark; diff --git a/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java index ec9863482e..af4b019860 100644 --- a/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/BaseSettingsFragment.java @@ -178,6 +178,9 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl createToolbar(inflater, view); setDivider(null); view.setBackgroundColor(ContextCompat.getColor(app, getBackgroundColorRes())); + if (Build.VERSION.SDK_INT >= 21) { + AndroidUtils.addStatusBarPadding21v(app, view); + } } return view; } @@ -250,9 +253,6 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl activity.getWindow().setStatusBarColor(ContextCompat.getColor(activity, colorId)); } } - if (activity instanceof MapActivity) { - ((MapActivity) activity).exitFromFullScreen(getView()); - } } } } @@ -271,9 +271,6 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl if (!(activity instanceof MapActivity) && statusBarColor != -1) { activity.getWindow().setStatusBarColor(statusBarColor); } - if (activity instanceof MapActivity) { - ((MapActivity) activity).enterToFullScreen(); - } } } } From 7d5e139210a3c361fc8c7f5e7191ef9ed93fecad Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 14 Feb 2020 16:53:25 +0200 Subject: [PATCH 39/42] Preferences ui fixes --- .../plus/profiles/SelectProfileBottomSheetDialogFragment.java | 4 ++-- OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java | 4 ++-- .../net/osmand/plus/settings/ProfileAppearanceFragment.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java index f968291d6e..52e7d56d75 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java @@ -181,7 +181,7 @@ public class SelectProfileBottomSheetDialogFragment extends MenuBottomSheetDialo int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; int iconDefaultColorResId = nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light; - View itemView = View.inflate(getContext(), R.layout.bottom_sheet_item_with_descr_and_radio_btn, null); + View itemView = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.bottom_sheet_item_with_descr_and_radio_btn, null); TextView tvTitle = itemView.findViewById(R.id.title); TextView tvDescription = itemView.findViewById(R.id.description); ImageView ivIcon = itemView.findViewById(R.id.icon); @@ -239,7 +239,7 @@ public class SelectProfileBottomSheetDialogFragment extends MenuBottomSheetDialo if (type.equals(TYPE_NAV_PROFILE)) { profiles.addAll(NavigationFragment.getSortedRoutingProfiles(app)); } else if (type.equals(TYPE_BASE_APP_PROFILE)) { - profiles.addAll(NavigationFragment.getBaseProfiles(app)); + profiles.addAll(NavigationFragment.getBaseProfiles()); } else { LOG.error("Check data type!"); dismiss(); diff --git a/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java b/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java index 38a6dbccf9..2bcf275ae3 100644 --- a/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java @@ -241,9 +241,9 @@ public class NavigationFragment extends BaseSettingsFragment { return profilesObjects; } - public static List getBaseProfiles(Context ctx) { + public static List getBaseProfiles() { List profiles = new ArrayList<>(); - for (ApplicationMode mode : ApplicationMode.getDefaultValues()) { + for (ApplicationMode mode : ApplicationMode.allPossibleValues()) { if (mode != ApplicationMode.DEFAULT) { profiles.add(new ProfileDataObject(mode.toHumanString(), mode.getDescription(), mode.getStringKey(), mode.getIconRes(), false, mode.getIconColorInfo())); diff --git a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java index 7db17b5c5e..81a9261487 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java @@ -348,7 +348,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { selectNavTypeBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (getSelectedAppMode().isCustomProfile()) { + if (isNewProfile) { hideKeyboard(); final SelectProfileBottomSheetDialogFragment fragment = new SelectProfileBottomSheetDialogFragment(); Bundle bundle = new Bundle(); From 52b79b7f6e4ba97daa8f146c0e952ac3f57ce767 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 14 Feb 2020 17:21:48 +0200 Subject: [PATCH 40/42] Fix select profile theme bug --- .../SelectProfileBottomSheetDialogFragment.java | 6 +++--- .../osmand/plus/settings/MainSettingsFragment.java | 2 ++ .../net/osmand/plus/settings/NavigationFragment.java | 12 +++++++----- .../plus/settings/ProfileAppearanceFragment.java | 2 ++ .../bottomsheets/BasePreferenceBottomSheet.java | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java index 52e7d56d75..6b737143b7 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java @@ -22,7 +22,6 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem; @@ -30,6 +29,7 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.settings.MainSettingsFragment; import net.osmand.plus.settings.NavigationFragment; import net.osmand.plus.settings.ProfileAppearanceFragment; +import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet; import org.apache.commons.logging.Log; @@ -38,7 +38,7 @@ import java.util.List; import static net.osmand.plus.helpers.ImportHelper.ImportType.ROUTING; -public class SelectProfileBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { +public class SelectProfileBottomSheetDialogFragment extends BasePreferenceBottomSheet { private static final Log LOG = PlatformUtil .getLog(SelectProfileBottomSheetDialogFragment.class); @@ -239,7 +239,7 @@ public class SelectProfileBottomSheetDialogFragment extends MenuBottomSheetDialo if (type.equals(TYPE_NAV_PROFILE)) { profiles.addAll(NavigationFragment.getSortedRoutingProfiles(app)); } else if (type.equals(TYPE_BASE_APP_PROFILE)) { - profiles.addAll(NavigationFragment.getBaseProfiles()); + profiles.addAll(NavigationFragment.getBaseProfiles(app)); } else { LOG.error("Check data type!"); dismiss(); diff --git a/OsmAnd/src/net/osmand/plus/settings/MainSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/MainSettingsFragment.java index 8c7c50a435..ca6f0dcdab 100644 --- a/OsmAnd/src/net/osmand/plus/settings/MainSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/MainSettingsFragment.java @@ -118,6 +118,8 @@ public class MainSettingsFragment extends BaseSettingsFragment { Bundle bundle = new Bundle(); bundle.putString(DIALOG_TYPE, TYPE_BASE_APP_PROFILE); dialog.setArguments(bundle); + dialog.setUsedOnMap(false); + dialog.setAppMode(getSelectedAppMode()); if (getActivity() != null) { getActivity().getSupportFragmentManager().beginTransaction() .add(dialog, "select_base_profile").commitAllowingStateLoss(); diff --git a/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java b/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java index 2bcf275ae3..ba7b3ab808 100644 --- a/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/NavigationFragment.java @@ -1,12 +1,9 @@ package net.osmand.plus.settings; -import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v7.preference.Preference; import android.support.v7.preference.SwitchPreferenceCompat; -import android.view.LayoutInflater; -import android.view.View; import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmandApplication; @@ -113,6 +110,7 @@ public class NavigationFragment extends BaseSettingsFragment { bundle.putString(DIALOG_TYPE, TYPE_NAV_PROFILE); dialog.setArguments(bundle); dialog.setUsedOnMap(false); + dialog.setAppMode(getSelectedAppMode()); if (getActivity() != null) { getActivity().getSupportFragmentManager().beginTransaction() .add(dialog, "select_nav_type").commitAllowingStateLoss(); @@ -241,11 +239,15 @@ public class NavigationFragment extends BaseSettingsFragment { return profilesObjects; } - public static List getBaseProfiles() { + public static List getBaseProfiles(OsmandApplication app) { List profiles = new ArrayList<>(); for (ApplicationMode mode : ApplicationMode.allPossibleValues()) { if (mode != ApplicationMode.DEFAULT) { - profiles.add(new ProfileDataObject(mode.toHumanString(), mode.getDescription(), + String description = mode.getDescription(); + if (Algorithms.isEmpty(description)) { + description = getAppModeDescription(app, mode); + } + profiles.add(new ProfileDataObject(mode.toHumanString(), description, mode.getStringKey(), mode.getIconRes(), false, mode.getIconColorInfo())); } } diff --git a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java index 81a9261487..c2c4f25439 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java @@ -352,6 +352,8 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { hideKeyboard(); final SelectProfileBottomSheetDialogFragment fragment = new SelectProfileBottomSheetDialogFragment(); Bundle bundle = new Bundle(); + fragment.setUsedOnMap(false); + fragment.setAppMode(getSelectedAppMode()); if (getSelectedAppMode() != null) { bundle.putString(SELECTED_KEY, getSelectedAppMode().getRoutingProfile()); } diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BasePreferenceBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BasePreferenceBottomSheet.java index f6ae08a36c..c40c2739dd 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BasePreferenceBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BasePreferenceBottomSheet.java @@ -24,7 +24,7 @@ public abstract class BasePreferenceBottomSheet extends MenuBottomSheetDialogFra private ApplicationMode appMode; private boolean profileDependent; - protected void setAppMode(ApplicationMode appMode) { + public void setAppMode(ApplicationMode appMode) { this.appMode = appMode; } From b72678ddac554091bde1425a2f9c2fce853f1f3a Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 14 Feb 2020 18:37:17 +0200 Subject: [PATCH 41/42] Fix custom parent ui --- .../osmand/plus/settings/ProfileAppearanceFragment.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java index c2c4f25439..8c950fea45 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ProfileAppearanceFragment.java @@ -634,11 +634,8 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { } private void setupBaseProfileView(String stringKey) { - for (ApplicationMode am : ApplicationMode.getDefaultValues()) { - if (am.getStringKey().equals(stringKey)) { - baseProfileName.setText(Algorithms.capitalizeFirstLetter(am.toHumanString())); - } - } + ApplicationMode mode = ApplicationMode.valueOfStringKey(stringKey, ApplicationMode.DEFAULT); + baseProfileName.setText(Algorithms.capitalizeFirstLetter(mode.toHumanString())); } private boolean saveProfile() { From 5ef358001a25968eea4cbeb66da01e008b4cc2da Mon Sep 17 00:00:00 2001 From: max-klaus Date: Sat, 15 Feb 2020 12:49:52 +0300 Subject: [PATCH 42/42] Fix #8365 --- OsmAnd/src/net/osmand/plus/routing/RouteProvider.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index f24a47851a..b5e07bc9a4 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -259,9 +259,11 @@ public class RouteProvider { // first of all check tracks if (!useIntermediatePointsRTE) { for (Track tr : file.tracks) { - for (TrkSegment tkSeg : tr.segments) { - for (WptPt pt : tkSeg.points) { - points.add(createLocation(pt)); + if (!tr.generalTrack) { + for (TrkSegment tkSeg : tr.segments) { + for (WptPt pt : tkSeg.points) { + points.add(createLocation(pt)); + } } } }