Merge pull request #10235 from osmandapp/markers_export_fixes

Export/Import: Subitems Bottom Sheet
This commit is contained in:
alex-osm 2020-11-21 14:57:36 +03:00 committed by GitHub
commit 62eb37cb34
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 623 additions and 188 deletions

View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/bottom_sheet_title_height"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding"
android:paddingRight="@dimen/wikilink_bottom_sheet_padding"
android:paddingBottom="@dimen/wikilink_bottom_sheet_padding">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:minHeight="@dimen/default_title_line_height"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
app:lineHeight="@dimen/default_title_line_height"
app:typeface="@string/font_roboto_medium"
tools:text="Some title" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:letterSpacing="@dimen/description_letter_spacing"
android:minHeight="@dimen/default_desc_line_height"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
app:lineHeight="@dimen/default_desc_line_height"
app:typeface="@string/font_roboto_regular"
tools:text="Some description" />
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/selected_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:minHeight="@dimen/default_title_line_height"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
app:lineHeight="@dimen/default_title_line_height"
app:typeface="@string/font_roboto_regular"
tools:text="5/6" />
</LinearLayout>
<LinearLayout
android:id="@+id/select_all_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="@dimen/bottom_sheet_list_item_height"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:ellipsize="end"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:minHeight="@dimen/default_title_line_height"
android:text="@string/shared_string_select_all"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_list_text_size"
app:lineHeight="@dimen/default_title_line_height"
app:typeface="@string/font_roboto_medium" />
<net.osmand.view.ThreeStateCheckbox
android:id="@+id/check_box"
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center"
android:clickable="false"
android:enabled="false"
android:focusable="false" />
</LinearLayout>
</LinearLayout>

View file

@ -11,6 +11,8 @@
Thx - Hardy
-->
<string name="select_items_for_import">Select items that will be imported.</string>
<string name="select_groups_for_import">Select groups that will be imported.</string>
<string name="export_not_enough_space">There is not enough space</string>
<string name="export_not_enough_space_descr">Your device only has %1$s free. Please free up some space or unselect some items to export.</string>
<string name="file_size_needed_for_import">Needed for import</string>

View file

@ -1083,6 +1083,7 @@ public class MapMarkersHelper {
String creationDateStr = point.getExtensionsToRead().get(CREATION_DATE);
marker.visitedDate = parseTime(visitedDateStr, format);
marker.creationDate = parseTime(creationDateStr, format);
marker.history = history;
marker.nextKey = history ? MapMarkersDbHelper.HISTORY_NEXT_VALUE : MapMarkersDbHelper.TAIL_NEXT_VALUE;
mapMarkers.add(marker);

View file

@ -87,7 +87,7 @@ public class HistoryMarkersSettingsItem extends CollectionSettingsItem<MapMarker
}
for (MapMarker marker : appliedItems) {
markersHelper.moveMapMarkerToHistory(marker);
markersHelper.addMarker(marker);
}
}
}
@ -96,7 +96,7 @@ public class HistoryMarkersSettingsItem extends CollectionSettingsItem<MapMarker
public boolean isDuplicate(@NonNull MapMarker mapMarker) {
for (MapMarker marker : existingItems) {
if (marker.equals(mapMarker)
&& Algorithms.objectEquals(marker.getOriginalPointDescription(), mapMarker.getOriginalPointDescription())) {
&& Algorithms.objectEquals(marker.getOnlyName(), mapMarker.getOnlyName())) {
return true;
}
}
@ -114,10 +114,13 @@ public class HistoryMarkersSettingsItem extends CollectionSettingsItem<MapMarker
int number = 0;
while (true) {
number++;
String name = item.getOnlyName() + "_" + number;
String name = item.getOnlyName() + " " + number;
PointDescription description = new PointDescription(PointDescription.POINT_TYPE_LOCATION, name);
MapMarker renamedMarker = new MapMarker(item.point, description, item.getColor(), item.selected, item.index);
MapMarker renamedMarker = new MapMarker(item.point, description, item.colorIndex, item.selected, item.index);
if (!isDuplicate(renamedMarker)) {
renamedMarker.history = true;
renamedMarker.visitedDate = item.visitedDate;
renamedMarker.creationDate = item.creationDate;
renamedMarker.nextKey = MapMarkersDbHelper.HISTORY_NEXT_VALUE;
return renamedMarker;
}

View file

@ -96,7 +96,7 @@ public class MarkersSettingsItem extends CollectionSettingsItem<MapMarker> {
public boolean isDuplicate(@NonNull MapMarker mapMarker) {
for (MapMarker marker : existingItems) {
if (marker.equals(mapMarker)
&& Algorithms.objectEquals(marker.getOriginalPointDescription(), mapMarker.getOriginalPointDescription())) {
&& Algorithms.objectEquals(marker.getOnlyName(), mapMarker.getOnlyName())) {
return true;
}
}
@ -114,10 +114,13 @@ public class MarkersSettingsItem extends CollectionSettingsItem<MapMarker> {
int number = 0;
while (true) {
number++;
String name = item.getOnlyName() + "_" + number;
String name = item.getOnlyName() + " " + number;
PointDescription description = new PointDescription(PointDescription.POINT_TYPE_LOCATION, name);
MapMarker renamedMarker = new MapMarker(item.point, description, item.getColor(), item.selected, item.index);
MapMarker renamedMarker = new MapMarker(item.point, description, item.colorIndex, item.selected, item.index);
if (!isDuplicate(renamedMarker)) {
renamedMarker.history = false;
renamedMarker.visitedDate = item.visitedDate;
renamedMarker.creationDate = item.creationDate;
renamedMarker.nextKey = MapMarkersDbHelper.TAIL_NEXT_VALUE;
return renamedMarker;
}

View file

@ -43,7 +43,7 @@ import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.settings.backend.ExportSettingsCategory;
import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.fragments.ExportDataObject;
import net.osmand.plus.settings.fragments.SettingsCategoryItems;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -472,13 +472,11 @@ public class SettingsHelper {
}
public List<SettingsItem> getFilteredSettingsItems(List<ExportSettingsType> settingsTypes, boolean globalExport) {
Map<ExportSettingsCategory, List<ExportDataObject>> dataList = getAdditionalData(globalExport);
Map<ExportSettingsType, List<?>> typesMap = new HashMap<>();
for (List<ExportDataObject> objects : dataList.values()) {
for (ExportDataObject exportObject : objects) {
typesMap.put(exportObject.getType(), exportObject.getItems());
}
}
typesMap.putAll(getSettingsItems(globalExport));
typesMap.putAll(getMyPlacesItems());
typesMap.putAll(getResourcesItems());
return getFilteredSettingsItems(typesMap, settingsTypes);
}
@ -499,67 +497,64 @@ public class SettingsHelper {
return settingsItems;
}
public Map<ExportSettingsCategory, List<ExportDataObject>> getAdditionalData(boolean globalExport) {
Map<ExportSettingsCategory, List<ExportDataObject>> dataList = new LinkedHashMap<>();
public Map<ExportSettingsCategory, SettingsCategoryItems> getAdditionalData(boolean globalExport) {
Map<ExportSettingsCategory, SettingsCategoryItems> dataList = new LinkedHashMap<>();
List<ExportDataObject> settingsItems = getSettingsItems(globalExport);
List<ExportDataObject> myPlacesItems = getMyPlacesItems();
List<ExportDataObject> resourcesItems = getResourcesItems();
Map<ExportSettingsType, List<?>> settingsItems = getSettingsItems(globalExport);
Map<ExportSettingsType, List<?>> myPlacesItems = getMyPlacesItems();
Map<ExportSettingsType, List<?>> resourcesItems = getResourcesItems();
if (!settingsItems.isEmpty()) {
sortExportSettingsObjects(settingsItems);
dataList.put(ExportSettingsCategory.SETTINGS, settingsItems);
dataList.put(ExportSettingsCategory.SETTINGS, new SettingsCategoryItems(settingsItems));
}
if (!myPlacesItems.isEmpty()) {
sortExportSettingsObjects(myPlacesItems);
dataList.put(ExportSettingsCategory.MY_PLACES, myPlacesItems);
dataList.put(ExportSettingsCategory.MY_PLACES, new SettingsCategoryItems(myPlacesItems));
}
if (!resourcesItems.isEmpty()) {
sortExportSettingsObjects(resourcesItems);
dataList.put(ExportSettingsCategory.RESOURCES, resourcesItems);
dataList.put(ExportSettingsCategory.RESOURCES, new SettingsCategoryItems(resourcesItems));
}
return dataList;
}
private List<ExportDataObject> getSettingsItems(boolean globalExport) {
List<ExportDataObject> settingsItems = new ArrayList<>();
private Map<ExportSettingsType, List<?>> getSettingsItems(boolean globalExport) {
Map<ExportSettingsType, List<?>> settingsItems = new LinkedHashMap<>();
if (globalExport) {
List<ApplicationModeBean> appModeBeans = new ArrayList<>();
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
appModeBeans.add(mode.toModeBean());
}
settingsItems.add(new ExportDataObject(ExportSettingsType.PROFILE, appModeBeans));
settingsItems.put(ExportSettingsType.PROFILE, appModeBeans);
}
settingsItems.add(new ExportDataObject(ExportSettingsType.GLOBAL, Collections.singletonList(new GlobalSettingsItem(app.getSettings()))));
settingsItems.put(ExportSettingsType.GLOBAL, Collections.singletonList(new GlobalSettingsItem(app.getSettings())));
QuickActionRegistry registry = app.getQuickActionRegistry();
List<QuickAction> actionsList = registry.getQuickActions();
if (!actionsList.isEmpty()) {
settingsItems.add(new ExportDataObject(ExportSettingsType.QUICK_ACTIONS, actionsList));
settingsItems.put(ExportSettingsType.QUICK_ACTIONS, actionsList);
}
List<PoiUIFilter> poiList = app.getPoiFilters().getUserDefinedPoiFilters(false);
if (!poiList.isEmpty()) {
settingsItems.add(new ExportDataObject(ExportSettingsType.POI_TYPES, poiList));
settingsItems.put(ExportSettingsType.POI_TYPES, poiList);
}
List<HistoryEntry> historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false);
if (!historyEntries.isEmpty()) {
settingsItems.add(new ExportDataObject(ExportSettingsType.SEARCH_HISTORY, historyEntries));
settingsItems.put(ExportSettingsType.SEARCH_HISTORY, historyEntries);
}
Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads();
if (!impassableRoads.isEmpty()) {
settingsItems.add(new ExportDataObject(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values())));
settingsItems.put(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values()));
}
return settingsItems;
}
private List<ExportDataObject> getMyPlacesItems() {
List<ExportDataObject> myPlacesItems = new ArrayList<>();
private Map<ExportSettingsType, List<?>> getMyPlacesItems() {
Map<ExportSettingsType, List<?>> myPlacesItems = new LinkedHashMap<>();
List<FavoriteGroup> favoriteGroups = app.getFavorites().getFavoriteGroups();
if (!favoriteGroups.isEmpty()) {
myPlacesItems.add(new ExportDataObject(ExportSettingsType.FAVORITES, favoriteGroups));
myPlacesItems.put(ExportSettingsType.FAVORITES, favoriteGroups);
}
File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR);
List<GPXInfo> gpxInfoList = GpxUiHelper.getSortedGPXFilesInfo(gpxDir, null, true);
@ -572,18 +567,18 @@ public class SettingsHelper {
}
}
if (!files.isEmpty()) {
myPlacesItems.add(new ExportDataObject(ExportSettingsType.TRACKS, files));
myPlacesItems.put(ExportSettingsType.TRACKS, files);
}
}
OsmEditingPlugin osmEditingPlugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
if (osmEditingPlugin != null) {
List<OsmNotesPoint> notesPointList = osmEditingPlugin.getDBBug().getOsmbugsPoints();
if (!notesPointList.isEmpty()) {
myPlacesItems.add(new ExportDataObject(ExportSettingsType.OSM_NOTES, notesPointList));
myPlacesItems.put(ExportSettingsType.OSM_NOTES, notesPointList);
}
List<OpenstreetmapPoint> editsPointList = osmEditingPlugin.getDBPOI().getOpenstreetmapPoints();
if (!editsPointList.isEmpty()) {
myPlacesItems.add(new ExportDataObject(ExportSettingsType.OSM_EDITS, editsPointList));
myPlacesItems.put(ExportSettingsType.OSM_EDITS, editsPointList);
}
}
AudioVideoNotesPlugin plugin = OsmandPlugin.getPlugin(AudioVideoNotesPlugin.class);
@ -596,7 +591,7 @@ public class SettingsHelper {
}
}
if (!files.isEmpty()) {
myPlacesItems.add(new ExportDataObject(ExportSettingsType.MULTIMEDIA_NOTES, files));
myPlacesItems.put(ExportSettingsType.MULTIMEDIA_NOTES, files);
}
}
List<MapMarker> mapMarkers = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(false);
@ -605,7 +600,7 @@ public class SettingsHelper {
String groupId = ExportSettingsType.ACTIVE_MARKERS.name();
MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE);
markersGroup.setMarkers(mapMarkers);
myPlacesItems.add(new ExportDataObject(ExportSettingsType.ACTIVE_MARKERS, Collections.singletonList(markersGroup)));
myPlacesItems.put(ExportSettingsType.ACTIVE_MARKERS, Collections.singletonList(markersGroup));
}
List<MapMarker> markersHistory = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(true);
if (!markersHistory.isEmpty()) {
@ -613,23 +608,23 @@ public class SettingsHelper {
String groupId = ExportSettingsType.HISTORY_MARKERS.name();
MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE);
markersGroup.setMarkers(markersHistory);
myPlacesItems.add(new ExportDataObject(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup)));
myPlacesItems.put(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup));
}
return myPlacesItems;
}
private List<ExportDataObject> getResourcesItems() {
List<ExportDataObject> resourcesItems = new ArrayList<>();
private Map<ExportSettingsType, List<?>> getResourcesItems() {
Map<ExportSettingsType, List<?>> resourcesItems = new LinkedHashMap<>();
Map<String, File> externalRenderers = app.getRendererRegistry().getExternalRenderers();
if (!externalRenderers.isEmpty()) {
resourcesItems.add(new ExportDataObject(ExportSettingsType.CUSTOM_RENDER_STYLE, new ArrayList<>(externalRenderers.values())));
resourcesItems.put(ExportSettingsType.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) {
resourcesItems.add(new ExportDataObject(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl)));
resourcesItems.put(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl));
}
}
List<ITileSource> iTileSources = new ArrayList<>();
@ -649,22 +644,22 @@ public class SettingsHelper {
}
}
if (!iTileSources.isEmpty()) {
resourcesItems.add(new ExportDataObject(ExportSettingsType.MAP_SOURCES, iTileSources));
resourcesItems.put(ExportSettingsType.MAP_SOURCES, iTileSources);
}
List<LocalIndexInfo> localIndexInfoList = getLocalIndexData();
List<File> files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA,
LocalIndexType.SRTM_DATA, LocalIndexType.WIKI_DATA);
if (!files.isEmpty()) {
sortLocalFiles(files);
resourcesItems.add(new ExportDataObject(ExportSettingsType.OFFLINE_MAPS, files));
resourcesItems.put(ExportSettingsType.OFFLINE_MAPS, files);
}
files = getFilesByType(localIndexInfoList, LocalIndexType.TTS_VOICE_DATA);
if (!files.isEmpty()) {
resourcesItems.add(new ExportDataObject(ExportSettingsType.TTS_VOICE, files));
resourcesItems.put(ExportSettingsType.TTS_VOICE, files);
}
files = getFilesByType(localIndexInfoList, LocalIndexType.VOICE_DATA);
if (!files.isEmpty()) {
resourcesItems.add(new ExportDataObject(ExportSettingsType.VOICE, files));
resourcesItems.put(ExportSettingsType.VOICE, files);
}
return resourcesItems;
@ -793,35 +788,32 @@ public class SettingsHelper {
return settingsItems;
}
public static Map<ExportSettingsCategory, List<ExportDataObject>> getSettingsToOperateByCategory(List<SettingsItem> items, boolean importComplete) {
Map<ExportSettingsCategory, List<ExportDataObject>> exportMap = new LinkedHashMap<>();
public static Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsToOperateByCategory(List<SettingsItem> items, boolean importComplete) {
Map<ExportSettingsCategory, SettingsCategoryItems> exportMap = new LinkedHashMap<>();
Map<ExportSettingsType, List<?>> settingsToOperate = getSettingsToOperate(items, importComplete);
List<ExportDataObject> settingsItems = new ArrayList<>();
List<ExportDataObject> myPlacesItems = new ArrayList<>();
List<ExportDataObject> resourcesItems = new ArrayList<>();
Map<ExportSettingsType, List<?>> settingsItems = new LinkedHashMap<>();
Map<ExportSettingsType, List<?>> myPlacesItems = new LinkedHashMap<>();
Map<ExportSettingsType, List<?>> resourcesItems = new LinkedHashMap<>();
for (Map.Entry<ExportSettingsType, List<?>> entry : settingsToOperate.entrySet()) {
ExportSettingsType type = entry.getKey();
if (type.isSettingsCategory()) {
settingsItems.add(new ExportDataObject(type, entry.getValue()));
settingsItems.put(type, entry.getValue());
} else if (type.isMyPlacesCategory()) {
myPlacesItems.add(new ExportDataObject(type, entry.getValue()));
myPlacesItems.put(type, entry.getValue());
} else if (type.isResourcesCategory()) {
resourcesItems.add(new ExportDataObject(type, entry.getValue()));
resourcesItems.put(type, entry.getValue());
}
}
if (!settingsItems.isEmpty()) {
sortExportSettingsObjects(settingsItems);
exportMap.put(ExportSettingsCategory.SETTINGS, settingsItems);
exportMap.put(ExportSettingsCategory.SETTINGS, new SettingsCategoryItems(settingsItems));
}
if (!myPlacesItems.isEmpty()) {
sortExportSettingsObjects(myPlacesItems);
exportMap.put(ExportSettingsCategory.MY_PLACES, myPlacesItems);
exportMap.put(ExportSettingsCategory.MY_PLACES, new SettingsCategoryItems(myPlacesItems));
}
if (!resourcesItems.isEmpty()) {
sortExportSettingsObjects(resourcesItems);
exportMap.put(ExportSettingsCategory.RESOURCES, resourcesItems);
exportMap.put(ExportSettingsCategory.RESOURCES, new SettingsCategoryItems(resourcesItems));
}
return exportMap;
@ -1017,15 +1009,4 @@ public class SettingsHelper {
}
});
}
private static void sortExportSettingsObjects(List<ExportDataObject> items) {
Collections.sort(items, new Comparator<ExportDataObject>() {
@Override
public int compare(ExportDataObject lhs, ExportDataObject rhs) {
int order1 = lhs.getType().ordinal();
int order2 = rhs.getType().ordinal();
return (order1 < order2) ? -1 : ((order1 == order2) ? 0 : 1);
}
});
}
}

View file

@ -14,22 +14,22 @@ import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource;
import net.osmand.plus.FavouritesDbHelper.FavoriteGroup;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.ProfileIconColors;
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -157,9 +157,9 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter<RecyclerView
} else if (currentItem instanceof FavoriteGroup) {
itemHolder.title.setText(((FavoriteGroup) currentItem).getDisplayName(app));
itemHolder.icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_favorite, activeColorRes));
} else if (currentItem instanceof MapMarkersGroup) {
MapMarkersGroup markersGroup = (MapMarkersGroup) currentItem;
itemHolder.title.setText(markersGroup.getName());
} else if (currentItem instanceof MapMarker) {
MapMarker mapMarker = (MapMarker) currentItem;
itemHolder.title.setText(mapMarker.getName(app));
itemHolder.icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_flag, activeColorRes));
} else if (currentItem instanceof HistoryEntry) {
itemHolder.title.setText(((HistoryEntry) currentItem).getName().getName());

View file

@ -1,26 +0,0 @@
package net.osmand.plus.settings.fragments;
import androidx.annotation.NonNull;
import net.osmand.plus.settings.backend.ExportSettingsType;
import java.util.List;
public class ExportDataObject {
private ExportSettingsType type;
private List<?> items;
public ExportDataObject(@NonNull ExportSettingsType type, @NonNull List<?> items) {
this.type = type;
this.items = items;
}
public ExportSettingsType getType() {
return type;
}
public List<?> getItems() {
return items;
}
}

View file

@ -0,0 +1,321 @@
package net.osmand.plus.settings.fragments;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager.TileSourceTemplate;
import net.osmand.plus.FavouritesDbHelper.FavoriteGroup;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Builder;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.osmedit.OsmNotesPoint;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.ProfileIconColors;
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem;
import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener;
import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox;
import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.view.ThreeStateCheckbox.State.CHECKED;
import static net.osmand.view.ThreeStateCheckbox.State.MISC;
import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED;
public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
public static final String TAG = ExportItemsBottomSheet.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(ExportItemsBottomSheet.class);
private OsmandApplication app;
private UiUtilities uiUtilities;
private ExportSettingsType type;
private List<Object> allItems;
private List<Object> selectedItems = new ArrayList<>();
private TextView selectedSize;
private ThreeStateCheckbox checkBox;
private int activeColorRes;
private int secondaryColorRes;
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
uiUtilities = app.getUIUtilities();
activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
items.add(createTitleItem());
items.add(new SimpleDividerItem(app));
for (Object object : allItems) {
final BottomSheetItemWithCompoundButton[] item = new BottomSheetItemWithCompoundButton[1];
Builder builder = (BottomSheetItemWithCompoundButton.Builder) new Builder()
.setChecked(selectedItems.contains(object))
.setButtonTintList(AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes))
.setLayoutId(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = !item[0].isChecked();
item[0].setChecked(checked);
if (checked) {
selectedItems.add(item[0].getTag());
} else {
selectedItems.remove(item[0].getTag());
}
updateTitleView();
}
})
.setTag(object);
setupBottomSheetItem(builder, object);
item[0] = (BottomSheetItemWithCompoundButton) builder.create();
items.add(item[0]);
}
}
private BaseBottomSheetItem createTitleItem() {
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.settings_group_title, null);
checkBox = view.findViewById(R.id.check_box);
selectedSize = view.findViewById(R.id.selected_size);
TextView textView = view.findViewById(R.id.title);
textView.setText(type.getTitleId());
view.findViewById(R.id.select_all_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkBox.performClick();
boolean checked = checkBox.getState() == CHECKED;
if (checked) {
selectedItems.addAll(allItems);
} else {
selectedItems.clear();
}
updateTitleView();
updateItems(checked);
}
});
setupDescription(view);
updateTitleView();
return new SimpleBottomSheetItem.Builder().setCustomView(view).create();
}
private void updateTitleView() {
if (Algorithms.isEmpty(selectedItems)) {
checkBox.setState(UNCHECKED);
} else {
checkBox.setState(selectedItems.containsAll(allItems) ? CHECKED : MISC);
}
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
selectedSize.setText(getString(R.string.ltr_or_rtl_combine_via_slash, selectedItems.size(), allItems.size()));
}
private void updateItems(boolean checked) {
for (BaseBottomSheetItem item : items) {
if (item instanceof BottomSheetItemWithCompoundButton) {
((BottomSheetItemWithCompoundButton) item).setChecked(checked);
}
}
}
@Override
protected int getDismissButtonTextId() {
return R.string.shared_string_cancel;
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected void onRightBottomButtonClick() {
Fragment target = getTargetFragment();
if (target instanceof OnItemSelectedListener) {
OnItemSelectedListener listener = (OnItemSelectedListener) target;
listener.onItemsSelected(type, selectedItems);
}
dismiss();
}
public static void showInstance(@NonNull ExportSettingsType type, List<Object> selectedItems, List<?> allItems, @NonNull FragmentManager fm, @Nullable Fragment target) {
try {
if (!fm.isStateSaved() && fm.findFragmentByTag(TAG) == null) {
ExportItemsBottomSheet fragment = new ExportItemsBottomSheet();
fragment.type = type;
fragment.allItems = (List<Object>) allItems;
if (selectedItems != null) {
fragment.selectedItems.addAll(selectedItems);
}
fragment.setTargetFragment(target, 0);
fragment.show(fm, TAG);
}
} catch (RuntimeException e) {
LOG.error("showInstance", e);
}
}
private String setupDescription(View view) {
TextView description = view.findViewById(R.id.description);
if (type == ExportSettingsType.FAVORITES) {
description.setText(R.string.select_groups_for_import);
} else {
description.setText(R.string.select_items_for_import);
}
return null;
}
private void setupBottomSheetItem(BottomSheetItemWithCompoundButton.Builder builder, Object object) {
if (object instanceof ApplicationModeBean) {
ApplicationModeBean modeBean = (ApplicationModeBean) object;
String profileName = modeBean.userProfileName;
if (Algorithms.isEmpty(profileName)) {
ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
profileName = getString(appMode.getNameKeyResource());
}
builder.setTitle(profileName);
String routingProfile = "";
String routingProfileValue = modeBean.routingProfile;
if (!routingProfileValue.isEmpty()) {
try {
routingProfile = getString(RoutingProfilesResources.valueOf(routingProfileValue.toUpperCase()).getStringRes());
routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfile);
} catch (IllegalArgumentException e) {
routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfileValue);
LOG.error("Error trying to get routing resource for " + routingProfileValue + "\n" + e);
}
}
if (!Algorithms.isEmpty(routingProfile)) {
builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, getString(R.string.nav_type_hint), routingProfile));
} else {
builder.setDescription(getString(R.string.profile_type_base_string));
}
int profileIconRes = AndroidUtils.getDrawableId(app, modeBean.iconName);
ProfileIconColors iconColor = modeBean.iconColor;
builder.setIcon(uiUtilities.getIcon(profileIconRes, iconColor.getColor(nightMode)));
} else if (object instanceof QuickAction) {
QuickAction quickAction = (QuickAction) object;
builder.setTitle(quickAction.getName(app));
builder.setIcon(uiUtilities.getIcon(quickAction.getIconRes(), activeColorRes));
} else if (object instanceof PoiUIFilter) {
PoiUIFilter poiUIFilter = (PoiUIFilter) object;
builder.setTitle(poiUIFilter.getName());
int iconRes = RenderingIcons.getBigIconResourceId(poiUIFilter.getIconId());
builder.setIcon(uiUtilities.getIcon(iconRes != 0 ? iconRes : R.drawable.ic_action_user, activeColorRes));
} else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) {
ITileSource tileSource = (ITileSource) object;
builder.setTitle(tileSource.getName());
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_map, activeColorRes));
} else if (object instanceof File) {
setupBottomSheetItemForFile(builder, (File) object);
} else if (object instanceof FileSettingsItem) {
FileSettingsItem fileSettingsItem = (FileSettingsItem) object;
setupBottomSheetItemForFile(builder, fileSettingsItem.getFile());
} else if (object instanceof AvoidRoadInfo) {
AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) object;
builder.setTitle(avoidRoadInfo.name);
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_alert, activeColorRes));
} else if (object instanceof OsmNotesPoint) {
OsmNotesPoint osmNotesPoint = (OsmNotesPoint) object;
builder.setTitle(osmNotesPoint.getText());
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_osm_note_add, activeColorRes));
} else if (object instanceof OpenstreetmapPoint) {
OpenstreetmapPoint openstreetmapPoint = (OpenstreetmapPoint) object;
builder.setTitle(OsmEditingPlugin.getTitle(openstreetmapPoint, app));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_info_dark, activeColorRes));
} else if (object instanceof FavoriteGroup) {
FavoriteGroup group = (FavoriteGroup) object;
builder.setTitle(group.getDisplayName(app));
int color = group.getColor() == 0 ? ContextCompat.getColor(app, R.color.color_favorite) : group.getColor();
builder.setIcon(uiUtilities.getPaintedIcon(R.drawable.ic_action_folder, color));
} else if (object instanceof GlobalSettingsItem) {
GlobalSettingsItem globalSettingsItem = (GlobalSettingsItem) object;
builder.setTitle(globalSettingsItem.getPublicName(app));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_settings, activeColorRes));
} else if (object instanceof MapMarkersGroup) {
MapMarkersGroup markersGroup = (MapMarkersGroup) object;
if (ExportSettingsType.ACTIVE_MARKERS.name().equals(markersGroup.getId())) {
builder.setTitle(getString(R.string.map_markers));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_flag, activeColorRes));
} else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) {
builder.setTitle(getString(R.string.map_markers));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes));
}
} else if (object instanceof HistoryEntry) {
HistoryEntry historyEntry = (HistoryEntry) object;
builder.setTitle(historyEntry.getName().getName());
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes));
}
}
private void setupBottomSheetItemForFile(Builder builder, File file) {
FileSettingsItem.FileSubtype fileSubtype = FileSettingsItem.FileSubtype.getSubtypeByPath(app, file.getPath());
builder.setTitle(file.getName());
if (file.getAbsolutePath().contains(IndexConstants.RENDERERS_DIR)) {
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_map_style, activeColorRes));
} else if (file.getAbsolutePath().contains(IndexConstants.ROUTING_PROFILES_DIR)) {
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
} else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) {
builder.setTitle(GpxUiHelper.getGpxTitle(file.getName()));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
} else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) {
int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file);
if (iconId == -1) {
iconId = R.drawable.ic_action_photo_dark;
}
builder.setIcon(uiUtilities.getIcon(iconId, activeColorRes));
} else if (fileSubtype.isMap()
|| fileSubtype == FileSettingsItem.FileSubtype.TTS_VOICE
|| fileSubtype == FileSettingsItem.FileSubtype.VOICE) {
builder.setTitle(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName()));
builder.setIcon(uiUtilities.getIcon(fileSubtype.getIconId(), activeColorRes));
}
}
}

View file

@ -21,6 +21,7 @@ import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.settings.backend.ExportSettingsCategory;
import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox;
import org.apache.commons.logging.Log;
@ -28,8 +29,6 @@ import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -44,9 +43,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
private final OsmandApplication app;
private final UiUtilities uiUtilities;
private List<ExportSettingsCategory> itemsTypes = new ArrayList<>();
private Map<ExportSettingsType, List<?>> selectedItemsMap = new HashMap<>();
private Map<ExportSettingsCategory, List<ExportDataObject>> itemsMap = new LinkedHashMap<>();
private List<ExportSettingsCategory> itemsTypes;
private Map<ExportSettingsType, List<?>> selectedItemsMap;
private Map<ExportSettingsCategory, SettingsCategoryItems> itemsMap;
private final OnItemSelectedListener listener;
@ -73,7 +72,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false);
}
final ExportSettingsCategory category = itemsTypes.get(groupPosition);
final List<ExportDataObject> items = itemsMap.get(category);
final SettingsCategoryItems items = itemsMap.get(category);
String title = app.getString(category.getTitleId());
TextView titleTv = group.findViewById(R.id.title_tv);
@ -83,9 +82,8 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
subTextTv.setText(getCategoryDescr(category));
int selectedTypes = 0;
for (int i = 0; i < items.size(); i++) {
ExportDataObject object = items.get(i);
if (selectedItemsMap.containsKey(object.getType())) {
for (ExportSettingsType type : items.getTypes()) {
if (!Algorithms.isEmpty(selectedItemsMap.get(type))) {
selectedTypes++;
}
}
@ -93,7 +91,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
if (selectedTypes == 0) {
checkBox.setState(UNCHECKED);
} else {
checkBox.setState(selectedTypes == items.size() ? CHECKED : MISC);
checkBox.setState(selectedTypes == items.getTypes().size() ? CHECKED : MISC);
}
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
@ -103,17 +101,6 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
public void onClick(View view) {
checkBox.performClick();
boolean selected = checkBox.getState() == CHECKED;
if (selected) {
for (ExportDataObject object : items) {
if (!selectedItemsMap.containsKey(object.getType())) {
selectedItemsMap.put(object.getType(), object.getItems());
}
}
} else {
for (ExportDataObject object : items) {
selectedItemsMap.remove(object.getType());
}
}
if (listener != null) {
listener.onCategorySelected(category, selected);
}
@ -136,26 +123,29 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
if (child == null) {
child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false);
}
final ExportDataObject currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition);
List<?> selectedItems = selectedItemsMap.get(currentItem.getType());
final ExportSettingsCategory category = itemsTypes.get(groupPosition);
final SettingsCategoryItems categoryItems = itemsMap.get(category);
final ExportSettingsType type = categoryItems.getTypes().get(childPosition);
final List<?> items = categoryItems.getItemsForType(type);
List<?> selectedItems = selectedItemsMap.get(type);
TextView titleTv = child.findViewById(R.id.title_tv);
titleTv.setText(currentItem.getType().getTitleId());
titleTv.setText(type.getTitleId());
TextView subTextTv = child.findViewById(R.id.sub_text_tv);
subTextTv.setText(getSelectedTypeDescr(currentItem));
subTextTv.setText(getSelectedTypeDescr(type, items));
ImageView icon = child.findViewById(R.id.explist_indicator);
setupIcon(icon, currentItem.getType().getIconRes(), selectedItems != null);
setupIcon(icon, type.getIconRes(), !Algorithms.isEmpty(selectedItems));
final ThreeStateCheckbox checkBox = child.findViewById(R.id.check_box);
if (selectedItems == null) {
checkBox.setState(UNCHECKED);
} else if (selectedItems.containsAll(currentItem.getItems())) {
} else if (selectedItems.containsAll(items)) {
checkBox.setState(CHECKED);
} else {
boolean contains = false;
for (Object object : currentItem.getItems()) {
for (Object object : items) {
if (selectedItems.contains(object)) {
contains = true;
break;
@ -163,7 +153,14 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
}
checkBox.setState(contains ? MISC : UNCHECKED);
}
child.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onTypeClicked(category, type);
}
}
});
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
child.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() {
@ -171,13 +168,8 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
public void onClick(View view) {
checkBox.performClick();
boolean selected = checkBox.getState() == CHECKED;
if (selected) {
selectedItemsMap.put(currentItem.getType(), currentItem.getItems());
} else {
selectedItemsMap.remove(currentItem.getType());
}
if (listener != null) {
listener.onTypeSelected(currentItem.getType(), selected);
listener.onItemsSelected(type, selected ? items : new ArrayList<>());
}
notifyDataSetChanged();
}
@ -195,7 +187,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
@Override
public int getChildrenCount(int i) {
return itemsMap.get(itemsTypes.get(i)).size();
return itemsMap.get(itemsTypes.get(i)).getTypes().size();
}
@Override
@ -205,7 +197,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
@Override
public Object getChild(int groupPosition, int childPosition) {
return itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition);
SettingsCategoryItems categoryItems = itemsMap.get(itemsTypes.get(groupPosition));
ExportSettingsType type = categoryItems.getTypes().get(groupPosition);
return categoryItems.getItemsForType(type).get(childPosition);
}
@Override
@ -237,19 +231,15 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
}
}
public void updateSettingsList(Map<ExportSettingsCategory, List<ExportDataObject>> itemsMap) {
public void updateSettingsItems(Map<ExportSettingsCategory, SettingsCategoryItems> itemsMap,
Map<ExportSettingsType, List<?>> selectedItemsMap) {
this.itemsMap = itemsMap;
this.itemsTypes = new ArrayList<>(itemsMap.keySet());
this.selectedItemsMap = selectedItemsMap;
Collections.sort(itemsTypes);
notifyDataSetChanged();
}
public void clearSettingsList() {
this.itemsMap.clear();
this.itemsTypes.clear();
notifyDataSetChanged();
}
public boolean hasSelectedData() {
return !selectedItemsMap.isEmpty();
}
@ -265,21 +255,20 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
private String getCategoryDescr(ExportSettingsCategory category) {
long itemsSize = 0;
int selectedTypes = 0;
List<ExportDataObject> items = itemsMap.get(category);
for (int i = 0; i < items.size(); i++) {
ExportDataObject object = items.get(i);
if (selectedItemsMap.containsKey(object.getType())) {
SettingsCategoryItems items = itemsMap.get(category);
for (ExportSettingsType type : items.getTypes()) {
if (!Algorithms.isEmpty(selectedItemsMap.get(type))) {
selectedTypes++;
itemsSize += calculateItemsSize(object.getItems());
itemsSize += calculateItemsSize(items.getItemsForType(type));
}
}
String description;
if (selectedTypes == 0) {
description = app.getString(R.string.shared_string_none);
} else if (selectedTypes == items.size()) {
} else if (selectedTypes == items.getTypes().size()) {
description = app.getString(R.string.shared_string_all);
} else {
description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size()));
description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.getTypes().size()));
}
String formattedSize = AndroidUtils.formatSize(app, itemsSize);
return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize);
@ -297,12 +286,11 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
return itemsSize;
}
private String getSelectedTypeDescr(ExportDataObject dataObject) {
private String getSelectedTypeDescr(ExportSettingsType type, List<?> items) {
long itemsSize = 0;
int selectedTypes = 0;
List<?> items = dataObject.getItems();
List<?> selectedItems = selectedItemsMap.get(dataObject.getType());
List<?> selectedItems = selectedItemsMap.get(type);
if (selectedItems != null) {
for (int i = 0; i < items.size(); i++) {
Object object = items.get(i);
@ -333,9 +321,11 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
interface OnItemSelectedListener {
void onItemsSelected(ExportSettingsType type, List<?> selectedItems);
void onCategorySelected(ExportSettingsCategory type, boolean selected);
void onTypeSelected(ExportSettingsType type, boolean selected);
void onTypeClicked(ExportSettingsCategory category, ExportSettingsType type);
}
}

View file

@ -50,7 +50,10 @@ import org.apache.commons.logging.Log;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -74,7 +77,9 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy", Locale.US);
private OsmandApplication app;
private Map<ExportSettingsCategory, List<ExportDataObject>> dataList;
private Map<ExportSettingsType, List<?>> selectedItemsMap = new HashMap<>();
private Map<ExportSettingsCategory, SettingsCategoryItems> dataList = new LinkedHashMap<>();
private ProgressDialog progress;
private ApplicationMode appMode;
@ -179,7 +184,7 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem
});
adapter = new ExportSettingsAdapter(app, this, nightMode);
adapter.updateSettingsList(dataList);
adapter.updateSettingsItems(dataList, selectedItemsMap);
expandableList.setAdapter(adapter);
CollapsingToolbarLayout toolbarLayout = root.findViewById(R.id.toolbar_layout);
@ -292,15 +297,32 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem
}
@Override
public void onCategorySelected(ExportSettingsCategory type, boolean selected) {
public void onCategorySelected(ExportSettingsCategory category, boolean selected) {
SettingsCategoryItems categoryItems = dataList.get(category);
for (ExportSettingsType type : categoryItems.getTypes()) {
List<?> selectedItems = selected ? categoryItems.getItemsForType(type) : new ArrayList<>();
selectedItemsMap.put(type, selectedItems);
}
updateAvailableSpace();
}
@Override
public void onTypeSelected(ExportSettingsType type, boolean selected) {
public void onItemsSelected(ExportSettingsType type, List<?> selectedItems) {
selectedItemsMap.put(type, selectedItems);
adapter.notifyDataSetChanged();
updateAvailableSpace();
}
@Override
public void onTypeClicked(ExportSettingsCategory category, ExportSettingsType type) {
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null && type != ExportSettingsType.GLOBAL && type != ExportSettingsType.SEARCH_HISTORY) {
List<Object> items = (List<Object>) dataList.get(category).getItemsForType(type);
List<Object> selectedItems = (List<Object>) selectedItemsMap.get(type);
ExportItemsBottomSheet.showInstance(type, selectedItems, items, fragmentManager, this);
}
}
private void prepareFile() {
if (app != null) {
exportingStarted = true;

View file

@ -33,13 +33,12 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmNotesPoint;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.SettingsHelper;
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask;
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportType;
@ -72,7 +71,7 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment {
private SettingsHelper settingsHelper;
public static void showInstance(@NonNull FragmentManager fm, List<? super Object> duplicatesList,
List<SettingsItem> settingsItems, File file, Fragment targetFragment) {
List<SettingsItem> settingsItems, File file, Fragment targetFragment) {
ImportDuplicatesFragment fragment = new ImportDuplicatesFragment();
fragment.setTargetFragment(targetFragment, 0);
fragment.setDuplicatesList(duplicatesList);
@ -203,8 +202,8 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment {
List<File> ttsVoiceFilesList = new ArrayList<>();
List<File> voiceFilesList = new ArrayList<>();
List<File> mapFilesList = new ArrayList<>();
List<MapMarkersGroup> markersGroups = new ArrayList<>();
List<MapMarkersGroup> markersHistoryGroups = new ArrayList<>();
List<MapMarker> mapMarkers = new ArrayList<>();
List<MapMarker> mapMarkersGroups = new ArrayList<>();
List<HistoryEntry> historyEntries = new ArrayList<>();
for (Object object : duplicatesList) {
@ -242,12 +241,12 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment {
osmNotesPointList.add((OsmNotesPoint) object);
} else if (object instanceof OpenstreetmapPoint) {
osmEditsPointList.add((OpenstreetmapPoint) object);
} else if (object instanceof MapMarkersGroup) {
MapMarkersGroup markersGroup = (MapMarkersGroup) object;
if (ExportSettingsType.ACTIVE_MARKERS.name().equals(markersGroup.getId())) {
markersGroups.add(markersGroup);
} else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) {
markersHistoryGroups.add(markersGroup);
} else if (object instanceof MapMarker) {
MapMarker mapMarker = (MapMarker) object;
if (mapMarker.history) {
mapMarkers.add(mapMarker);
} else {
mapMarkersGroups.add(mapMarker);
}
} else if (object instanceof HistoryEntry) {
historyEntries.add((HistoryEntry) object);
@ -313,13 +312,13 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment {
duplicates.add(getString(R.string.local_indexes_cat_voice));
duplicates.addAll(voiceFilesList);
}
if (!markersGroups.isEmpty()) {
if (!mapMarkers.isEmpty()) {
duplicates.add(getString(R.string.map_markers));
duplicates.addAll(markersGroups);
duplicates.addAll(mapMarkers);
}
if (!markersHistoryGroups.isEmpty()) {
if (!mapMarkersGroups.isEmpty()) {
duplicates.add(getString(R.string.markers_history));
duplicates.addAll(markersHistoryGroups);
duplicates.addAll(mapMarkersGroups);
}
return duplicates;
}

View file

@ -38,6 +38,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
@ -54,7 +55,6 @@ import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem;
import net.osmand.plus.settings.backend.backup.FavoritesSettingsItem;
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem;
import net.osmand.plus.settings.backend.backup.SearchHistorySettingsItem;
import net.osmand.plus.settings.backend.backup.HistoryMarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem;
import net.osmand.plus.settings.backend.backup.MarkersSettingsItem;
@ -63,12 +63,12 @@ import net.osmand.plus.settings.backend.backup.OsmNotesSettingsItem;
import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem;
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem;
import net.osmand.plus.settings.backend.backup.SearchHistorySettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsHelper;
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask;
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportType;
import net.osmand.plus.settings.backend.backup.SettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsItemType;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -134,7 +134,7 @@ public class ImportSettingsFragment extends BaseOsmAndFragment {
inflater = UiUtilities.getInflater(app, nightMode);
View root = inflater.inflate(R.layout.fragment_import, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
TextViewEx continueBtn = root.findViewById(R.id.continue_button);
View continueBtn = root.findViewById(R.id.continue_button);
toolbarLayout = root.findViewById(R.id.toolbar_layout);
expandableList = root.findViewById(R.id.list);
buttonsContainer = root.findViewById(R.id.buttons_container);
@ -145,6 +145,7 @@ public class ImportSettingsFragment extends BaseOsmAndFragment {
description = header.findViewById(R.id.description);
description.setText(R.string.select_data_to_import);
expandableList.addHeaderView(header);
UiUtilities.setupDialogButton(nightMode, continueBtn, DialogButtonType.PRIMARY, getString(R.string.shared_string_continue));
continueBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

View file

@ -0,0 +1,30 @@
package net.osmand.plus.settings.fragments;
import androidx.annotation.NonNull;
import net.osmand.plus.settings.backend.ExportSettingsType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class SettingsCategoryItems {
private final Map<ExportSettingsType, List<?>> itemsMap;
public SettingsCategoryItems(@NonNull Map<ExportSettingsType, List<?>> itemsMap) {
this.itemsMap = itemsMap;
}
public List<ExportSettingsType> getTypes() {
return new ArrayList<>(itemsMap.keySet());
}
public List<?> getItemsForType(ExportSettingsType type) {
return itemsMap.get(type);
}
public Map<ExportSettingsType, List<?>> getItemsMap() {
return itemsMap;
}
}