Download all button implementation

This commit is contained in:
nazar-kutz 2021-02-12 21:38:28 +02:00
parent 9f42fc48df
commit 357ab00ed6
17 changed files with 763 additions and 249 deletions

View file

@ -10,6 +10,7 @@ import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
import net.osmand.data.LatLon;
import net.osmand.data.QuadRect;
import net.osmand.data.QuadTree;
import net.osmand.map.WorldRegion.RegionBoundingBox;
import net.osmand.util.Algorithms;
import net.osmand.util.MapAlgorithms;
import net.osmand.util.MapUtils;
@ -436,6 +437,7 @@ public class OsmandRegions {
cx /= object.getPointsLength();
cy /= object.getPointsLength();
rd.regionCenter = new LatLon(MapUtils.get31LatitudeY((int) cy), MapUtils.get31LongitudeX((int) cx));
rd.boundingBox = findBoundingBox(object);
}
rd.regionParentFullName = mapIndexFields.get(mapIndexFields.parentFullName, object);
@ -461,6 +463,43 @@ public class OsmandRegions {
return rd;
}
private RegionBoundingBox findBoundingBox(BinaryMapDataObject object) {
if (object.getPointsLength() == 0) {
return new RegionBoundingBox(0, 0, 0, 0);
}
double currentX = object.getPoint31XTile(0);
double currentY = object.getPoint31YTile(0);
double minX = currentX;
double maxX = currentX;
double minY = currentY;
double maxY = currentY;
if (object.getPointsLength() > 1) {
for (int i = 1; i < object.getPointsLength(); i++) {
currentX = object.getPoint31XTile(i);
currentY = object.getPoint31YTile(i);
if (currentX > maxX) {
maxX = currentX;
} else if (currentX < minX) {
minX = currentX;
}
if (currentY > maxY) {
maxY = currentY;
} else if (currentY < minY) {
minY = currentY;
}
}
}
minX = MapUtils.get31LongitudeX((int) minX);
maxX = MapUtils.get31LongitudeX((int) maxX);
double revertedMinY = MapUtils.get31LatitudeY((int) maxY);
double revertedMaxY = MapUtils.get31LatitudeY((int) minY);
return new RegionBoundingBox(minX, maxX, revertedMinY, revertedMaxY);
}
private String getSearchIndex(BinaryMapDataObject object) {
MapIndex mi = object.getMapIndex();
TIntObjectIterator<String> it = object.getObjectNames().iterator();

View file

@ -40,6 +40,7 @@ public class WorldRegion implements Serializable {
protected String regionDownloadName;
protected boolean regionMapDownload;
protected LatLon regionCenter;
protected RegionBoundingBox boundingBox;
public static class RegionParams {
protected String regionLeftHandDriving;
@ -182,4 +183,32 @@ public class WorldRegion implements Serializable {
}
return res;
}
public static boolean isFirstRegionInsideTheSecond(WorldRegion first,
WorldRegion second) {
RegionBoundingBox bbox1 = first.boundingBox;
RegionBoundingBox bbox2 = second.boundingBox;
if ((bbox1.minX > bbox2.minX) && (bbox1.maxX < bbox2.maxX)) {
if ((bbox1.minY > bbox2.minY) && (bbox1.maxY < bbox2.maxY)) {
return true;
}
}
return false;
}
public static class RegionBoundingBox {
double minX;
double maxX;
double minY;
double maxY;
public RegionBoundingBox(double minX, double maxX, double minY, double maxY) {
this.minX = minX;
this.maxX = maxX;
this.minY = minY;
this.maxY = maxY;
}
}
}

View file

@ -12,6 +12,8 @@
-->
<string name="delete_number_files_question">Delete %1$d files?</string>
<string name="shared_strings_all_regions">All regions</string>
<string name="activity_type_car_name">Car</string>
<string name="activity_type_motorbike_name">Motorbike</string>
<string name="activity_type_offroad_name">Off-road</string>

View file

@ -17,7 +17,7 @@ public class AbstractDownloadActivity extends ActionBarProgressActivity {
downloadValidationManager.startDownload(this, indexItem);
}
public void makeSureUserCancelDownload(IndexItem item) {
public void makeSureUserCancelDownload(DownloadItem item) {
downloadValidationManager.makeSureUserCancelDownload(this, item);
}
}

View file

@ -56,7 +56,8 @@ public class CustomIndexItem extends IndexItem {
}
@Override
public File getTargetFile(OsmandApplication ctx) {
@NonNull
public File getTargetFile(@NonNull OsmandApplication ctx) {
String basename = getTranslatedBasename();
if (!Algorithms.isEmpty(subfolder)) {
basename = subfolder + "/" + basename;

View file

@ -1,7 +1,6 @@
package net.osmand.plus.download;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;

View file

@ -18,6 +18,7 @@ import java.io.IOException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
@ -113,6 +114,10 @@ public class DownloadActivityType {
public static DownloadActivityType getIndexType(String tagName) {
return byTag.get(tagName);
}
public static Collection<DownloadActivityType> values() {
return byTag.values();
}
protected static String addVersionToExt(String ext, int version) {
return "_" + version + ext;
@ -318,7 +323,7 @@ public class DownloadActivityType {
}
}
public String getVisibleDescription(IndexItem indexItem, Context ctx) {
public String getVisibleDescription(DownloadItem downloadItem, Context ctx) {
if (this == SRTM_COUNTRY_FILE) {
return ctx.getString(R.string.download_srtm_maps);
} else if (this == WIKIPEDIA_FILE) {
@ -337,20 +342,20 @@ public class DownloadActivityType {
return "";
}
public String getVisibleName(IndexItem indexItem, Context ctx, OsmandRegions osmandRegions, boolean includingParent) {
public String getVisibleName(DownloadItem downloadItem, Context ctx, OsmandRegions osmandRegions, boolean includingParent) {
if (this == VOICE_FILE) {
String fileName = indexItem.fileName;
String fileName = downloadItem.getFileName();
if (fileName.endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP)) {
return FileNameTranslationHelper.getVoiceName(ctx, getBasename(indexItem));
return FileNameTranslationHelper.getVoiceName(ctx, getBasename(downloadItem));
} else if (fileName.endsWith(IndexConstants.TTSVOICE_INDEX_EXT_JS)) {
return FileNameTranslationHelper.getVoiceName(ctx, getBasename(indexItem));
return FileNameTranslationHelper.getVoiceName(ctx, getBasename(downloadItem));
}
return getBasename(indexItem);
return getBasename(downloadItem);
}
if (this == FONT_FILE) {
return FileNameTranslationHelper.getFontName(ctx, getBasename(indexItem));
return FileNameTranslationHelper.getFontName(ctx, getBasename(downloadItem));
}
final String basename = getBasename(indexItem);
final String basename = getBasename(downloadItem);
if (basename.endsWith(FileNameTranslationHelper.WIKI_NAME)) {
return FileNameTranslationHelper.getWikiName(ctx, basename);
}
@ -442,8 +447,8 @@ public class DownloadActivityType {
}
public String getBasename(IndexItem indexItem) {
String fileName = indexItem.fileName;
public String getBasename(DownloadItem downloadItem) {
String fileName = downloadItem.getFileName();
if (fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT)) {
return fileName.substring(0, fileName.length() - IndexConstants.EXTRA_ZIP_EXT.length());
}
@ -458,7 +463,7 @@ public class DownloadActivityType {
if (fileName.endsWith(IndexConstants.SQLITE_EXT)) {
return fileName.substring(0, fileName.length() - IndexConstants.SQLITE_EXT.length());
}
if (indexItem.getType() == WIKIVOYAGE_FILE &&
if (downloadItem.getType() == WIKIVOYAGE_FILE &&
fileName.endsWith(IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT)) {
return fileName.substring(0, fileName.length() - IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT.length());
}

View file

@ -239,6 +239,16 @@ public class DownloadIndexesThread {
}
}
public void cancelDownload(DownloadItem item) {
if (item instanceof MultipleIndexItem) {
MultipleIndexItem multipleIndexItem = (MultipleIndexItem) item;
cancelDownload(multipleIndexItem.getAllIndexes());
} else if (item instanceof IndexItem) {
IndexItem indexItem = (IndexItem) item;
cancelDownload(indexItem);
}
}
public void cancelDownload(IndexItem item) {
app.logMapDownloadEvent("cancel", item);
if (currentDownloadingItem == item) {

View file

@ -0,0 +1,76 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import net.osmand.map.OsmandRegions;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import java.io.File;
import java.util.List;
import java.util.Locale;
public abstract class DownloadItem {
protected DownloadActivityType type;
protected DownloadResourceGroup relatedGroup;
public DownloadItem(DownloadActivityType type) {
this.type = type;
}
public DownloadActivityType getType() {
return type;
}
public void setRelatedGroup(DownloadResourceGroup relatedGroup) {
this.relatedGroup = relatedGroup;
}
public DownloadResourceGroup getRelatedGroup() {
return relatedGroup;
}
@NonNull
public String getSizeDescription(Context ctx) {
String pattern = ctx.getString(R.string.ltr_or_rtl_combine_via_space);
String size = String.format(Locale.US, "%.2f", getSizeToDownloadInMb());
return String.format(pattern, size, "MB");
}
public String getVisibleName(Context ctx, OsmandRegions osmandRegions) {
return type.getVisibleName(this, ctx, osmandRegions, true);
}
public String getVisibleName(Context ctx, OsmandRegions osmandRegions, boolean includingParent) {
return type.getVisibleName(this, ctx, osmandRegions, includingParent);
}
public String getVisibleDescription(OsmandApplication clctx) {
return type.getVisibleDescription(this, clctx);
}
public String getBasename() {
return type.getBasename(this);
}
protected abstract double getSizeToDownloadInMb();
public abstract double getArchiveSizeMB();
public abstract boolean isDownloaded();
public abstract boolean isOutdated();
public abstract boolean hasActualDataToDownload();
public abstract boolean isDownloading(DownloadIndexesThread thread);
public abstract String getFileName();
@NonNull
public abstract List<File> getDownloadedFiles(OsmandApplication app);
}

View file

@ -8,6 +8,7 @@ import net.osmand.map.OsmandRegions;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.Collections;
@ -20,8 +21,8 @@ public class DownloadResourceGroup {
private final DownloadResourceGroupType type;
private final DownloadResourceGroup parentGroup;
// ASSERT: individualResources are not empty if and only if groups are empty
private final List<IndexItem> individualResources;
// ASSERT: individualDisplayItems are not empty if and only if groups are empty
private final List<DownloadItem> individualDownloadItems;
private final List<DownloadResourceGroup> groups;
protected final String id;
@ -107,10 +108,10 @@ public class DownloadResourceGroup {
public DownloadResourceGroup(DownloadResourceGroup parentGroup, DownloadResourceGroupType type, String id) {
boolean flat = type.containsIndexItem();
if (flat) {
this.individualResources = new ArrayList<IndexItem>();
this.individualDownloadItems = new ArrayList<DownloadItem>();
this.groups = null;
} else {
this.individualResources = null;
this.individualDownloadItems = null;
this.groups = new ArrayList<DownloadResourceGroup>();
}
this.id = id;
@ -173,7 +174,7 @@ public class DownloadResourceGroup {
DownloadResourceGroup regionMaps = getSubGroupById(DownloadResourceGroupType.REGION_MAPS.getDefaultId());
if(regionMaps != null && regionMaps.size() == 1 && parentGroup != null && parentGroup.getParentGroup() != null &&
isEmpty(getSubGroupById(DownloadResourceGroupType.SUBREGIONS.getDefaultId()))) {
IndexItem item = regionMaps.individualResources.get(0);
IndexItem item = regionMaps.getIndividualResources().get(0);
DownloadResourceGroup screenParent = parentGroup.getParentGroup();
if(item.getType() == DownloadActivityType.HILLSHADE_FILE) {
DownloadResourceGroup hillshades =
@ -183,7 +184,7 @@ public class DownloadResourceGroup {
screenParent.addGroup(hillshades);
}
hillshades.addItem(item);
regionMaps.individualResources.remove(0);
regionMaps.individualDownloadItems.remove(0);
} else if (item.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) {
DownloadResourceGroup hillshades = screenParent
.getSubGroupById(DownloadResourceGroupType.SRTM_HEADER.getDefaultId());
@ -192,7 +193,7 @@ public class DownloadResourceGroup {
screenParent.addGroup(hillshades);
}
hillshades.addItem(item);
regionMaps.individualResources.remove(0);
regionMaps.individualDownloadItems.remove(0);
}
}
@ -221,35 +222,38 @@ public class DownloadResourceGroup {
}
}
groups.add(g);
if (g.individualResources != null) {
final net.osmand.Collator collator = OsmAndCollator.primaryCollator();
final OsmandApplication app = getRoot().app;
final OsmandRegions osmandRegions = app.getRegions();
Collections.sort(g.individualResources, new Comparator<IndexItem>() {
@Override
public int compare(IndexItem lhs, IndexItem rhs) {
int lli = lhs.getType().getOrderIndex();
int rri = rhs.getType().getOrderIndex();
if(lli < rri) {
return -1;
} else if(lli > rri) {
return 1;
}
sortDownloadItems(g.individualDownloadItems);
}
return collator.compare(lhs.getVisibleName(app.getApplicationContext(), osmandRegions),
rhs.getVisibleName(app.getApplicationContext(), osmandRegions));
protected void sortDownloadItems(List<DownloadItem> items) {
if (Algorithms.isEmpty(items)) return;
final net.osmand.Collator collator = OsmAndCollator.primaryCollator();
final OsmandApplication app = getRoot().app;
final OsmandRegions osmandRegions = app.getRegions();
Collections.sort(items, new Comparator<DownloadItem>() {
@Override
public int compare(DownloadItem firstItem, DownloadItem secondItem) {
int firstOrder = firstItem.getType().getOrderIndex();
int secondOrder = secondItem.getType().getOrderIndex();
if(firstOrder < secondOrder) {
return -1;
} else if(firstOrder > secondOrder) {
return 1;
}
});
}
String firstName = firstItem.getVisibleName(app, osmandRegions);
String secondName = secondItem.getVisibleName(app, osmandRegions);
return collator.compare(firstName, secondName);
}
});
}
public void addItem(IndexItem i) {
public void addItem(DownloadItem i) {
i.setRelatedGroup(this);
individualResources.add(i);
individualDownloadItems.add(i);
}
public boolean isEmpty() {
return isEmpty(individualResources) && isEmpty(groups);
return isEmpty(individualDownloadItems) && isEmpty(groups);
}
private boolean isEmpty(List<?> l) {
@ -265,7 +269,7 @@ public class DownloadResourceGroup {
}
public int size() {
return groups != null ? groups.size() : individualResources.size();
return groups != null ? groups.size() : individualDownloadItems.size();
}
public DownloadResourceGroup getGroupByIndex(int ind) {
@ -275,9 +279,9 @@ public class DownloadResourceGroup {
return null;
}
public IndexItem getItemByIndex(int ind) {
if (individualResources != null && ind >= 0 && ind < individualResources.size()) {
return individualResources.get(ind);
public DownloadItem getItemByIndex(int ind) {
if (individualDownloadItems != null && ind >= 0 && ind < individualDownloadItems.size()) {
return individualDownloadItems.get(ind);
}
return null;
}
@ -306,8 +310,20 @@ public class DownloadResourceGroup {
}
public List<IndexItem> getIndividualResources() {
List<IndexItem> individualResources = new ArrayList<>();
if (individualDownloadItems != null) {
for (DownloadItem item : individualDownloadItems) {
if (item instanceof IndexItem) {
individualResources.add((IndexItem) item);
}
}
}
return individualResources;
}
public List<DownloadItem> getIndividualDownloadItems() {
return individualDownloadItems;
}
public WorldRegion getRegion() {
return region;

View file

@ -25,10 +25,14 @@ import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.REGION_MAPS;
public class DownloadResources extends DownloadResourceGroup {
private static final String TAG = DownloadResources.class.getSimpleName();
@ -40,7 +44,7 @@ public class DownloadResources extends DownloadResourceGroup {
private Map<String, String> indexFileNames = new LinkedHashMap<>();
private Map<String, String> indexActivatedFileNames = new LinkedHashMap<>();
private List<IndexItem> rawResources;
private Map<WorldRegion, List<IndexItem> > groupByRegion;
private Map<WorldRegion, List<IndexItem>> groupByRegion;
private List<IndexItem> itemsToUpdate = new ArrayList<>();
public static final String WORLD_SEAMARKS_KEY = "world_seamarks";
public static final String WORLD_SEAMARKS_NAME = "World_seamarks";
@ -55,7 +59,7 @@ public class DownloadResources extends DownloadResourceGroup {
this.region = app.getRegions().getWorldRegion();
this.app = app;
}
public List<IndexItem> getItemsToUpdate() {
return itemsToUpdate;
}
@ -260,7 +264,7 @@ public class DownloadResources extends DownloadResourceGroup {
}
private Map<String, String> listWithAlternatives(final java.text.DateFormat dateFormat, File file,
final String ext, final Map<String, String> files) {
final String ext, final Map<String, String> files) {
if (file.isDirectory()) {
file.list(new FilenameFilter() {
@Override
@ -292,7 +296,7 @@ public class DownloadResources extends DownloadResourceGroup {
}
return file;
}
private void prepareFilesToUpdate() {
List<IndexItem> filtered = rawResources;
if (filtered != null) {
@ -307,7 +311,7 @@ public class DownloadResources extends DownloadResourceGroup {
}
}
}
protected boolean prepareData(List<IndexItem> resources) {
this.rawResources = resources;
@ -332,18 +336,18 @@ public class DownloadResources extends DownloadResourceGroup {
DownloadResourceGroup nauticalMapsGroup = new DownloadResourceGroup(this, DownloadResourceGroupType.NAUTICAL_MAPS_GROUP);
DownloadResourceGroup nauticalMapsScreen = new DownloadResourceGroup(nauticalMapsGroup, DownloadResourceGroupType.NAUTICAL_MAPS);
DownloadResourceGroup nauticalMaps = new DownloadResourceGroup(nauticalMapsGroup, DownloadResourceGroupType.NAUTICAL_MAPS_HEADER);
DownloadResourceGroup wikivoyageMapsGroup = new DownloadResourceGroup(this, DownloadResourceGroupType.TRAVEL_GROUP);
DownloadResourceGroup wikivoyageMapsScreen = new DownloadResourceGroup(wikivoyageMapsGroup, DownloadResourceGroupType.WIKIVOYAGE_MAPS);
DownloadResourceGroup wikivoyageMaps = new DownloadResourceGroup(wikivoyageMapsGroup, DownloadResourceGroupType.WIKIVOYAGE_HEADER);
Map<WorldRegion, List<IndexItem> > groupByRegion = new LinkedHashMap<WorldRegion, List<IndexItem>>();
Map<WorldRegion, List<IndexItem>> groupByRegion = new LinkedHashMap<>();
OsmandRegions regs = app.getRegions();
for (IndexItem ii : resources) {
if (ii.getType() == DownloadActivityType.VOICE_FILE) {
if (ii.getFileName().endsWith(IndexConstants.TTSVOICE_INDEX_EXT_JS)){
if (ii.getFileName().endsWith(IndexConstants.TTSVOICE_INDEX_EXT_JS)) {
voiceTTS.addItem(ii);
} else if (ii.getFileName().endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP)){
} else if (ii.getFileName().endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP)) {
voiceRec.addItem(ii);
}
continue;
@ -377,7 +381,7 @@ public class DownloadResources extends DownloadResourceGroup {
groupByRegion.get(wg).add(ii);
} else {
if (ii.getFileName().startsWith("World_")) {
if (ii.getFileName().toLowerCase().startsWith(WORLD_SEAMARKS_KEY) ||
if (ii.getFileName().toLowerCase().startsWith(WORLD_SEAMARKS_KEY) ||
ii.getFileName().toLowerCase().startsWith(WORLD_SEAMARKS_OLD_KEY)) {
nauticalMaps.addItem(ii);
} else {
@ -402,22 +406,22 @@ public class DownloadResources extends DownloadResourceGroup {
LinkedList<DownloadResourceGroup> parent = new LinkedList<DownloadResourceGroup>();
DownloadResourceGroup worldSubregions = new DownloadResourceGroup(this, DownloadResourceGroupType.SUBREGIONS);
addGroup(worldSubregions);
for(WorldRegion rg : region.getSubregions()) {
for (WorldRegion rg : region.getSubregions()) {
queue.add(rg);
parent.add(worldSubregions);
}
while(!queue.isEmpty()) {
while (!queue.isEmpty()) {
WorldRegion reg = queue.pollFirst();
DownloadResourceGroup parentGroup = parent.pollFirst();
List<WorldRegion> subregions = reg.getSubregions();
DownloadResourceGroup mainGrp = new DownloadResourceGroup(parentGroup, DownloadResourceGroupType.REGION, reg.getRegionId());
mainGrp.region = reg;
parentGroup.addGroup(mainGrp);
List<IndexItem> list = groupByRegion.get(reg);
if(list != null) {
DownloadResourceGroup flatFiles = new DownloadResourceGroup(mainGrp, DownloadResourceGroupType.REGION_MAPS);
for(IndexItem ii : list) {
if (list != null) {
DownloadResourceGroup flatFiles = new DownloadResourceGroup(mainGrp, REGION_MAPS);
for (IndexItem ii : list) {
flatFiles.addItem(ii);
}
mainGrp.addGroup(flatFiles);
@ -425,10 +429,10 @@ public class DownloadResources extends DownloadResourceGroup {
DownloadResourceGroup subRegions = new DownloadResourceGroup(mainGrp, DownloadResourceGroupType.SUBREGIONS);
mainGrp.addGroup(subRegions);
// add to processing queue
for(WorldRegion rg : subregions) {
for (WorldRegion rg : subregions) {
queue.add(rg);
parent.add(subRegions);
}
}
}
// Possible improvements
// 1. if there is no subregions no need to create resource group REGIONS_MAPS - objection raise diversity and there is no value
@ -455,8 +459,8 @@ public class DownloadResources extends DownloadResourceGroup {
}
otherGroup.addGroup(voiceScreenTTS);
otherGroup.addGroup(voiceScreenRec);
if (fonts.getIndividualResources() != null) {
otherGroup.addGroup(fontScreen);
}
@ -465,9 +469,87 @@ public class DownloadResources extends DownloadResourceGroup {
createHillshadeSRTMGroups();
trimEmptyGroups();
updateLoadedFiles();
collectMultipleIndexesItems(region);
return true;
}
private void collectMultipleIndexesItems(@NonNull WorldRegion region) {
List<WorldRegion> subRegions = region.getSubregions();
if (Algorithms.isEmpty(subRegions)) return;
DownloadResourceGroup group = getRegionMapsGroup(region);
if (group != null) {
boolean listModified = false;
List<IndexItem> indexesList = group.getIndividualResources();
for (DownloadActivityType type : DownloadActivityType.values()) {
if (!doesListContainIndexWithType(indexesList, type)) {
List<IndexItem> indexesFromSubRegions = collectIndexesOfType(subRegions, type);
if (indexesFromSubRegions != null) {
group.addItem(new MultipleIndexItem(region, indexesFromSubRegions, type));
listModified = true;
}
}
}
if (listModified) {
sortDownloadItems(group.getIndividualDownloadItems());
}
}
for (WorldRegion subRegion : subRegions) {
collectMultipleIndexesItems(subRegion);
}
}
private DownloadResourceGroup getRegionMapsGroup(WorldRegion region) {
DownloadResourceGroup group = getRegionGroup(region);
if (group != null) {
return group.getSubGroupById(REGION_MAPS.getDefaultId());
}
return null;
}
@Nullable
private List<IndexItem> collectIndexesOfType(@NonNull List<WorldRegion> regions,
@NonNull DownloadActivityType type) {
Map<WorldRegion, IndexItem> collectedIndexes = new LinkedHashMap<>();
for (WorldRegion region : regions) {
List<IndexItem> regionIndexes = getIndexItems(region);
boolean found = false;
if (regionIndexes != null) {
for (IndexItem index : regionIndexes) {
if (index.getType() == type) {
found = true;
collectedIndexes.put(region, index);
break;
}
}
}
if (!found) return null;
}
return removeDuplicates(collectedIndexes);
}
private List<IndexItem> removeDuplicates(Map<WorldRegion, IndexItem> collectedIndexes) {
List<WorldRegion> regions = new ArrayList<>(collectedIndexes.keySet());
// collect duplicates
Set<WorldRegion> duplicates = new HashSet<>();
for (int i = 0; i < regions.size() - 1; i++) {
WorldRegion firstRegion = regions.get(i);
for (int j = i + 1; j < regions.size(); j++) {
WorldRegion secondRegion = regions.get(j);
if (WorldRegion.isFirstRegionInsideTheSecond(firstRegion, secondRegion)) {
duplicates.add(firstRegion);
} else if (WorldRegion.isFirstRegionInsideTheSecond(secondRegion, firstRegion)) {
duplicates.add(secondRegion);
}
}
}
// remove duplicates
for (WorldRegion key : duplicates) {
collectedIndexes.remove(key);
}
return new ArrayList<>(collectedIndexes.values());
}
private void buildRegionsGroups(WorldRegion region, DownloadResourceGroup group) {
LinkedList<WorldRegion> queue = new LinkedList<WorldRegion>();
LinkedList<DownloadResourceGroup> parent = new LinkedList<DownloadResourceGroup>();
@ -485,7 +567,7 @@ public class DownloadResources extends DownloadResourceGroup {
CustomRegion customRegion = (CustomRegion) reg;
List<IndexItem> indexItems = customRegion.loadIndexItems();
if (!Algorithms.isEmpty(indexItems)) {
DownloadResourceGroup flatFiles = new DownloadResourceGroup(mainGrp, DownloadResourceGroupType.REGION_MAPS);
DownloadResourceGroup flatFiles = new DownloadResourceGroup(mainGrp, REGION_MAPS);
for (IndexItem ii : indexItems) {
flatFiles.addItem(ii);
}
@ -557,7 +639,11 @@ public class DownloadResources extends DownloadResourceGroup {
return res;
}
public static List<IndexItem> findIndexItemsAt(OsmandApplication app, List<String> names, DownloadActivityType type, boolean includeDownloaded, int limit) {
public static List<IndexItem> findIndexItemsAt(OsmandApplication app,
List<String> names,
DownloadActivityType type,
boolean includeDownloaded,
int limit) {
List<IndexItem> res = new ArrayList<>();
OsmandRegions regions = app.getRegions();
DownloadIndexesThread downloadThread = app.getDownloadThread();
@ -573,8 +659,12 @@ public class DownloadResources extends DownloadResourceGroup {
return res;
}
private static boolean isIndexItemDownloaded(DownloadIndexesThread downloadThread, DownloadActivityType type, WorldRegion downloadRegion, List<IndexItem> res) {
List<IndexItem> otherIndexItems = new ArrayList<>(downloadThread.getIndexes().getIndexItems(downloadRegion));
private static boolean isIndexItemDownloaded(DownloadIndexesThread downloadThread,
DownloadActivityType type,
WorldRegion downloadRegion,
List<IndexItem> res) {
List<IndexItem> otherIndexItems =
new ArrayList<>(downloadThread.getIndexes().getIndexItems(downloadRegion));
for (IndexItem indexItem : otherIndexItems) {
if (indexItem.getType() == type && indexItem.isDownloaded()) {
return true;
@ -584,8 +674,24 @@ public class DownloadResources extends DownloadResourceGroup {
&& isIndexItemDownloaded(downloadThread, type, downloadRegion.getSuperregion(), res);
}
private static boolean addIndexItem(DownloadIndexesThread downloadThread, DownloadActivityType type, WorldRegion downloadRegion, List<IndexItem> res) {
List<IndexItem> otherIndexItems = new ArrayList<>(downloadThread.getIndexes().getIndexItems(downloadRegion));
private boolean doesListContainIndexWithType(List<IndexItem> indexItems,
DownloadActivityType type) {
if (indexItems != null) {
for (IndexItem indexItem : indexItems) {
if (indexItem.getType() == type) {
return true;
}
}
}
return false;
}
private static boolean addIndexItem(DownloadIndexesThread downloadThread,
DownloadActivityType type,
WorldRegion downloadRegion,
List<IndexItem> res) {
List<IndexItem> otherIndexItems =
new ArrayList<>(downloadThread.getIndexes().getIndexItems(downloadRegion));
for (IndexItem indexItem : otherIndexItems) {
if (indexItem.getType() == type
&& !res.contains(indexItem)) {

View file

@ -192,7 +192,7 @@ public class DownloadValidationManager {
}
public void makeSureUserCancelDownload(FragmentActivity ctx, final IndexItem item) {
public void makeSureUserCancelDownload(FragmentActivity ctx, final DownloadItem item) {
AlertDialog.Builder bld = new AlertDialog.Builder(ctx);
bld.setTitle(ctx.getString(R.string.shared_string_cancel));
bld.setMessage(R.string.confirm_interrupt_download);

View file

@ -1,12 +1,9 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.map.OsmandRegions;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.helpers.FileNameTranslationHelper;
@ -16,9 +13,11 @@ import org.apache.commons.logging.Log;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class IndexItem implements Comparable<IndexItem> {
public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
private static final Log log = PlatformUtil.getLog(IndexItem.class);
String description;
@ -27,43 +26,44 @@ public class IndexItem implements Comparable<IndexItem> {
long timestamp;
long contentSize;
long containerSize;
DownloadActivityType type;
boolean extra;
// Update information
boolean outdated;
boolean downloaded;
long localTimestamp;
DownloadResourceGroup relatedGroup;
public IndexItem(String fileName, String description, long timestamp, String size, long contentSize,
long containerSize, @NonNull DownloadActivityType tp) {
public IndexItem(String fileName,
String description,
long timestamp,
String size,
long contentSize,
long containerSize,
@NonNull DownloadActivityType type) {
super(type);
this.fileName = fileName;
this.description = description;
this.timestamp = timestamp;
this.size = size;
this.contentSize = contentSize;
this.containerSize = containerSize;
this.type = tp;
}
public DownloadActivityType getType() {
return type;
}
public void setRelatedGroup(DownloadResourceGroup relatedGroup) {
this.relatedGroup = relatedGroup;
}
public DownloadResourceGroup getRelatedGroup() {
return relatedGroup;
}
@Override
public String getFileName() {
return fileName;
}
@NonNull
@Override
public List<File> getDownloadedFiles(OsmandApplication app) {
File targetFile = getTargetFile(app);
List<File> result = new ArrayList<>();
if (targetFile.exists()) {
result.add(targetFile);
}
return result;
}
public String getDescription() {
return description;
@ -89,10 +89,14 @@ public class IndexItem implements Comparable<IndexItem> {
return ((double)containerSize) / (1 << 20);
}
public String getSizeDescription(Context ctx) {
return ctx.getString(R.string.ltr_or_rtl_combine_via_space, size, "MB");
@Override
protected double getSizeToDownloadInMb() {
try {
return Double.parseDouble(size);
} catch (Exception e) {
return 0;
}
}
public DownloadEntry createDownloadEntry(OsmandApplication ctx) {
String fileName = this.fileName;
@ -132,11 +136,8 @@ public class IndexItem implements Comparable<IndexItem> {
return type.getTargetFileName(this);
}
public String getBasename() {
return type.getBasename(this);
}
public File getTargetFile(OsmandApplication ctx) {
@NonNull
public File getTargetFile(@NonNull OsmandApplication ctx) {
String basename = getTranslatedBasename();
return new File(type.getDownloadFolder(ctx, this), basename + type.getUnzipExtension(ctx, this));
}
@ -190,7 +191,7 @@ public class IndexItem implements Comparable<IndexItem> {
&& getType() != DownloadActivityType.HILLSHADE_FILE
&& getType() != DownloadActivityType.SLOPE_FILE;
}
public void setOutdated(boolean outdated) {
this.outdated = outdated;
}
@ -198,7 +199,12 @@ public class IndexItem implements Comparable<IndexItem> {
public void setDownloaded(boolean downloaded) {
this.downloaded = downloaded;
}
@Override
public boolean hasActualDataToDownload() {
return !isDownloaded() || isOutdated();
}
public void setLocalTimestamp(long localTimestamp) {
this.localTimestamp = localTimestamp;
}
@ -211,20 +217,11 @@ public class IndexItem implements Comparable<IndexItem> {
return downloaded;
}
public String getVisibleName(Context ctx, OsmandRegions osmandRegions) {
return type.getVisibleName(this, ctx, osmandRegions, true);
@Override
public boolean isDownloading(DownloadIndexesThread thread) {
return thread.isDownloading(this);
}
public String getVisibleName(Context ctx, OsmandRegions osmandRegions, boolean includingParent) {
return type.getVisibleName(this, ctx, osmandRegions, includingParent);
}
public String getVisibleDescription(OsmandApplication clctx) {
return type.getVisibleDescription(this, clctx);
}
public String getDate(java.text.DateFormat format) {
return format.format(new Date(timestamp));
}

View file

@ -0,0 +1,122 @@
package net.osmand.plus.download;
import androidx.annotation.NonNull;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MultipleIndexItem extends DownloadItem {
private final List<IndexItem> items;
public MultipleIndexItem(@NonNull WorldRegion region,
@NonNull List<IndexItem> items,
@NonNull DownloadActivityType type) {
super(type);
this.items = items;
}
public List<IndexItem> getAllIndexes() {
return items;
}
@Override
public boolean isOutdated() {
for (IndexItem item : items) {
if (item.isOutdated()) {
return true;
}
}
return false;
}
@Override
public boolean isDownloaded() {
for (IndexItem item : items) {
if (item.isDownloaded()) {
return true;
}
}
return false;
}
@Override
public boolean isDownloading(DownloadIndexesThread thread) {
for (IndexItem item : items) {
if (thread.isDownloading(item)) {
return true;
}
}
return false;
}
@Override
public String getFileName() {
// The file name is used in many places.
// But in the case of a Multiple Indexes element it's not use in most cases.
// File is not created for Multiple Indexes element,
// and all file names are available in internal IndexItem elements.
// The only one place where a filename may be needed
// is to generate the base and display names.
// Since these names are generated based on the filename.
// But now we don't need a name for display,
// because on all screens where we now use multiple elements item,
// for display used a type name instead of a file name.
// Later, if you need a file name,
// you can try to create it based on the WorldRegion
// and file name of one of the internal IndexItem elements.
return "";
}
@NonNull
@Override
public List<File> getDownloadedFiles(OsmandApplication app) {
List<File> result = new ArrayList<>();
for (IndexItem item : items) {
result.addAll(item.getDownloadedFiles(app));
}
return result;
}
public List<IndexItem> getIndexesToDownload() {
List<IndexItem> indexesToDownload = new ArrayList<>();
for (IndexItem item : items) {
if (item.hasActualDataToDownload()) {
indexesToDownload.add(item);
}
}
return indexesToDownload;
}
@Override
public boolean hasActualDataToDownload() {
return getIndexesToDownload().size() > 0;
}
@Override
public double getSizeToDownloadInMb() {
double totalSizeMb = 0.0d;
for (IndexItem item : items) {
if (item.hasActualDataToDownload()) {
totalSizeMb += Double.parseDouble(item.size);
}
}
return totalSizeMb;
}
@Override
public double getArchiveSizeMB() {
double result = 0.0d;
for (IndexItem item : items) {
result += item.getArchiveSizeMB();
}
return result;
}
}

View file

@ -10,9 +10,9 @@ import android.widget.TextView;
import net.osmand.plus.R;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
import net.osmand.plus.download.CustomIndexItem;
import net.osmand.plus.download.DownloadItem;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadResourceGroup;
import net.osmand.plus.download.IndexItem;
import java.util.ArrayList;
import java.util.List;
@ -52,9 +52,9 @@ public class DownloadResourceGroupAdapter extends OsmandBaseExpandableListAdapte
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
final Object child = getChild(groupPosition, childPosition);
if (child instanceof IndexItem) {
if (child instanceof DownloadItem) {
IndexItem item = (IndexItem) child;
DownloadItem item = (DownloadItem) child;
DownloadResourceGroup group = getGroupObj(groupPosition);
ItemViewHolder viewHolder;
if (convertView != null && convertView.getTag() instanceof ItemViewHolder) {

View file

@ -17,11 +17,14 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.core.view.ViewCompat;
import net.osmand.map.OsmandRegions;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
@ -31,11 +34,13 @@ import net.osmand.plus.activities.PluginsFragment;
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
import net.osmand.plus.download.CityItem;
import net.osmand.plus.download.CustomIndexItem;
import net.osmand.plus.download.DownloadItem;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.download.DownloadResourceGroup;
import net.osmand.plus.download.DownloadResources;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.MultipleIndexItem;
import net.osmand.plus.download.ui.LocalIndexesFragment.LocalIndexOperationTask;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.inapp.InAppPurchaseHelper;
@ -43,6 +48,8 @@ import net.osmand.util.Algorithms;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
public class ItemViewHolder {
@ -137,24 +144,24 @@ public class ItemViewHolder {
depthContoursPurchased = InAppPurchaseHelper.isDepthContoursPurchased(context.getMyApplication());
}
public void bindIndexItem(final IndexItem indexItem) {
bindIndexItem(indexItem, null);
public void bindIndexItem(final DownloadItem downloadItem) {
bindIndexItem(downloadItem, null);
}
public void bindIndexItem(final IndexItem indexItem, final String cityName) {
public void bindIndexItem(final DownloadItem downloadItem, final String cityName) {
initAppStatusVariables();
boolean isDownloading = context.getDownloadThread().isDownloading(indexItem);
boolean isDownloading = downloadItem.isDownloading(context.getDownloadThread());
int progress = -1;
if (context.getDownloadThread().getCurrentDownloadingItem() == indexItem) {
if (context.getDownloadThread().getCurrentDownloadingItem() == downloadItem) {
progress = context.getDownloadThread().getCurrentDownloadingItemProgress();
}
boolean disabled = checkDisabledAndClickAction(indexItem);
boolean disabled = checkDisabledAndClickAction(downloadItem);
/// name and left item
String name;
if(showTypeInName) {
name = indexItem.getType().getString(context);
name = downloadItem.getType().getString(context);
} else {
name = indexItem.getVisibleName(context, context.getMyApplication().getRegions(), showParentRegionName);
name = downloadItem.getVisibleName(context, context.getMyApplication().getRegions(), showParentRegionName);
}
String text = (!Algorithms.isEmpty(cityName) && !cityName.equals(name) ? cityName + "\n" : "") + name;
nameTextView.setText(text);
@ -164,43 +171,78 @@ public class ItemViewHolder {
nameTextView.setTextColor(textColorSecondary);
}
int color = textColorSecondary;
if(indexItem.isDownloaded() && !isDownloading) {
int colorId = indexItem.isOutdated() ? R.color.color_distance : R.color.color_ok;
if(downloadItem.isDownloaded() && !isDownloading) {
int colorId = downloadItem.isOutdated() ? R.color.color_distance : R.color.color_ok;
color = context.getResources().getColor(colorId);
}
if (indexItem.isDownloaded()) {
if (downloadItem.isDownloaded()) {
leftImageView.setImageDrawable(getContentIcon(context,
indexItem.getType().getIconResource(), color));
downloadItem.getType().getIconResource(), color));
} else if (disabled) {
leftImageView.setImageDrawable(getContentIcon(context,
indexItem.getType().getIconResource(), textColorSecondary));
downloadItem.getType().getIconResource(), textColorSecondary));
} else {
leftImageView.setImageDrawable(getContentIcon(context,
indexItem.getType().getIconResource()));
downloadItem.getType().getIconResource()));
}
descrTextView.setTextColor(textColorSecondary);
if (!isDownloading) {
progressBar.setVisibility(View.GONE);
descrTextView.setVisibility(View.VISIBLE);
if (indexItem instanceof CustomIndexItem && (((CustomIndexItem) indexItem).getSubName(context) != null)) {
descrTextView.setText(((CustomIndexItem) indexItem).getSubName(context));
} else if (indexItem.getType() == DownloadActivityType.DEPTH_CONTOUR_FILE && !depthContoursPurchased) {
if (downloadItem instanceof CustomIndexItem && (((CustomIndexItem) downloadItem).getSubName(context) != null)) {
descrTextView.setText(((CustomIndexItem) downloadItem).getSubName(context));
} else if (downloadItem.getType() == DownloadActivityType.DEPTH_CONTOUR_FILE && !depthContoursPurchased) {
descrTextView.setText(context.getString(R.string.depth_contour_descr));
} else if ((indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE
|| indexItem.getType() == DownloadActivityType.HILLSHADE_FILE
|| indexItem.getType() == DownloadActivityType.SLOPE_FILE) && srtmDisabled) {
} else if ((downloadItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE
|| downloadItem.getType() == DownloadActivityType.HILLSHADE_FILE
|| downloadItem.getType() == DownloadActivityType.SLOPE_FILE) && srtmDisabled) {
if (showTypeInName) {
descrTextView.setText("");
} else {
descrTextView.setText(indexItem.getType().getString(context));
descrTextView.setText(downloadItem.getType().getString(context));
}
} else if (showTypeInDesc) {
descrTextView.setText(indexItem.getType().getString(context) +
"" + indexItem.getSizeDescription(context) +
"" + (showRemoteDate ? indexItem.getRemoteDate(dateFormat) : indexItem.getLocalDate(dateFormat)));
} else if (downloadItem instanceof MultipleIndexItem) {
MultipleIndexItem item = (MultipleIndexItem) downloadItem;
String allRegionsHeader = context.getString(R.string.shared_strings_all_regions);
String regionsHeader = context.getString(R.string.regions);
String allRegionsCount = String.valueOf(item.getAllIndexes().size());
String leftToDownloadCount = String.valueOf(item.getIndexesToDownload().size());
String header;
String count;
if (item.hasActualDataToDownload()) {
if (!item.isDownloaded()) {
header = allRegionsHeader;
count = leftToDownloadCount;
} else {
header = regionsHeader;
count = String.format(
context.getString(R.string.ltr_or_rtl_combine_via_slash),
leftToDownloadCount,
allRegionsCount);
}
} else {
header = allRegionsHeader;
count = allRegionsCount;
}
String fullDescription =
context.getString(R.string.ltr_or_rtl_combine_via_colon, header, count);
if (item.hasActualDataToDownload()) {
fullDescription = context.getString(
R.string.ltr_or_rtl_combine_via_bold_point, fullDescription,
item.getSizeDescription(context));
}
descrTextView.setText(fullDescription);
} else {
descrTextView.setText(indexItem.getSizeDescription(context) + "" +
(showRemoteDate ? indexItem.getRemoteDate(dateFormat) : indexItem.getLocalDate(dateFormat)));
IndexItem item = (IndexItem) downloadItem;
String pattern = context.getString(R.string.ltr_or_rtl_combine_via_bold_point);
String type = item.getType().getString(context);
String size = item.getSizeDescription(context);
String date = showRemoteDate ? item.getRemoteDate(dateFormat) : item.getLocalDate(dateFormat);
String fullDescription = String.format(pattern, size, date);
if (showTypeInDesc) {
fullDescription = String.format(pattern, type, fullDescription);
}
descrTextView.setText(fullDescription);
}
} else {
@ -209,18 +251,19 @@ public class ItemViewHolder {
progressBar.setProgress(progress);
if (showProgressInDesc) {
double mb = indexItem.getArchiveSizeMB();
double mb = downloadItem.getArchiveSizeMB();
String v ;
if (progress != -1) {
v = context.getString(R.string.value_downloaded_of_max, mb * progress / 100, mb);
} else {
v = context.getString(R.string.file_size_in_mb, mb);
}
if(showTypeInDesc && indexItem.getType() == DownloadActivityType.ROADS_FILE) {
descrTextView.setText(indexItem.getType().getString(context) + "" + v);
} else {
descrTextView.setText(v);
String fullDescription = v;
if(showTypeInDesc && downloadItem.getType() == DownloadActivityType.ROADS_FILE) {
fullDescription = context.getString(R.string.ltr_or_rtl_combine_via_bold_point,
downloadItem.getType().getString(context), fullDescription);
}
descrTextView.setText(fullDescription);
descrTextView.setVisibility(View.VISIBLE);
} else {
descrTextView.setVisibility(View.GONE);
@ -241,44 +284,7 @@ public class ItemViewHolder {
}
}
protected void download(IndexItem indexItem, DownloadResourceGroup parentOptional) {
boolean handled = false;
if(parentOptional != null) {
WorldRegion region = DownloadResourceGroup.getRegion(parentOptional);
context.setDownloadItem(region, indexItem.getTargetFile(context.getMyApplication()).getAbsolutePath());
}
if (indexItem.getType() == DownloadActivityType.ROADS_FILE && parentOptional != null) {
for (IndexItem ii : parentOptional.getIndividualResources()) {
if (ii.getType() == DownloadActivityType.NORMAL_FILE) {
if (ii.isDownloaded()) {
handled = true;
confirmDownload(indexItem);
}
break;
}
}
}
if(!handled) {
context.startDownload(indexItem);
}
}
private void confirmDownload(final IndexItem indexItem) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.are_you_sure);
builder.setMessage(R.string.confirm_download_roadmaps);
builder.setNegativeButton(R.string.shared_string_cancel, null).setPositiveButton(
R.string.shared_string_download, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (indexItem != null) {
context.startDownload(indexItem);
}
}
});
builder.show();
}
private boolean checkDisabledAndClickAction(final IndexItem item) {
private boolean checkDisabledAndClickAction(final DownloadItem item) {
RightButtonAction clickAction = getClickAction(item);
boolean disabled = clickAction != RightButtonAction.DOWNLOAD;
OnClickListener action = getRightButtonAction(item, clickAction);
@ -290,15 +296,15 @@ public class ItemViewHolder {
} else {
rightButton.setVisibility(View.GONE);
rightImageButton.setVisibility(View.VISIBLE);
final boolean isDownloading = context.getDownloadThread().isDownloading(item);
final boolean isDownloading = item.isDownloading(context.getDownloadThread());
if (isDownloading) {
rightImageButton.setImageDrawable(getContentIcon(context, R.drawable.ic_action_remove_dark));
rightImageButton.setContentDescription(context.getString(R.string.shared_string_cancel));
} else if(item.isDownloaded() && !item.isOutdated()) {
} else if(!item.hasActualDataToDownload()) {
rightImageButton.setImageDrawable(getContentIcon(context, R.drawable.ic_overflow_menu_white));
rightImageButton.setContentDescription(context.getString(R.string.shared_string_more));
} else {
rightImageButton.setImageDrawable(getContentIcon(context, R.drawable.ic_action_import));
rightImageButton.setImageDrawable(getContentIcon(context, getDownloadActionIconId(item)));
rightImageButton.setContentDescription(context.getString(R.string.shared_string_download));
}
rightImageButton.setOnClickListener(action);
@ -307,31 +313,37 @@ public class ItemViewHolder {
return disabled;
}
private int getDownloadActionIconId(@NonNull DownloadItem item) {
return item instanceof MultipleIndexItem ?
R.drawable.ic_action_multi_download :
R.drawable.ic_action_import;
}
@SuppressLint("DefaultLocale")
public RightButtonAction getClickAction(final IndexItem indexItem) {
public RightButtonAction getClickAction(final DownloadItem item) {
RightButtonAction clickAction = RightButtonAction.DOWNLOAD;
if (indexItem.getBasename().toLowerCase().equals(DownloadResources.WORLD_SEAMARKS_KEY)
if (item.getBasename().toLowerCase().equals(DownloadResources.WORLD_SEAMARKS_KEY)
&& nauticalPluginDisabled) {
clickAction = RightButtonAction.ASK_FOR_SEAMARKS_PLUGIN;
} else if ((indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE
|| indexItem.getType() == DownloadActivityType.HILLSHADE_FILE
|| indexItem.getType() == DownloadActivityType.SLOPE_FILE) && srtmDisabled) {
} else if ((item.getType() == DownloadActivityType.SRTM_COUNTRY_FILE
|| item.getType() == DownloadActivityType.HILLSHADE_FILE
|| item.getType() == DownloadActivityType.SLOPE_FILE) && srtmDisabled) {
if (srtmNeedsInstallation) {
clickAction = RightButtonAction.ASK_FOR_SRTM_PLUGIN_PURCHASE;
} else {
clickAction = RightButtonAction.ASK_FOR_SRTM_PLUGIN_ENABLE;
}
} else if (indexItem.getType() == DownloadActivityType.WIKIPEDIA_FILE
} else if (item.getType() == DownloadActivityType.WIKIPEDIA_FILE
&& !Version.isPaidVersion(context.getMyApplication())) {
clickAction = RightButtonAction.ASK_FOR_FULL_VERSION_PURCHASE;
} else if (indexItem.getType() == DownloadActivityType.DEPTH_CONTOUR_FILE && !depthContoursPurchased) {
} else if (item.getType() == DownloadActivityType.DEPTH_CONTOUR_FILE && !depthContoursPurchased) {
clickAction = RightButtonAction.ASK_FOR_DEPTH_CONTOURS_PURCHASE;
}
return clickAction;
}
public OnClickListener getRightButtonAction(final IndexItem item, final RightButtonAction clickAction) {
public OnClickListener getRightButtonAction(final DownloadItem item, final RightButtonAction clickAction) {
if (clickAction != RightButtonAction.DOWNLOAD) {
return new View.OnClickListener() {
@Override
@ -370,7 +382,7 @@ public class ItemViewHolder {
}
};
} else {
final boolean isDownloading = context.getDownloadThread().isDownloading(item);
final boolean isDownloading = item.isDownloading(context.getDownloadThread());
return new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -380,8 +392,8 @@ public class ItemViewHolder {
} else {
context.makeSureUserCancelDownload(item);
}
} else if(item.isDownloaded() && !item.isOutdated()){
contextMenu(v, item, item.getRelatedGroup());
} else if(!item.hasActualDataToDownload()){
showContextMenu(v, item, item.getRelatedGroup());
} else {
download(item, item.getRelatedGroup());
}
@ -390,52 +402,21 @@ public class ItemViewHolder {
}
}
protected void contextMenu(View v, final IndexItem indexItem, final DownloadResourceGroup parentOptional) {
final PopupMenu optionsMenu = new PopupMenu(context, v);
protected void showContextMenu(View v,
final DownloadItem downloadItem,
final DownloadResourceGroup parentOptional) {
OsmandApplication app = context.getMyApplication();
PopupMenu optionsMenu = new PopupMenu(context, v);
MenuItem item;
final File fl = indexItem.getTargetFile(context.getMyApplication());
if (fl.exists()) {
item = optionsMenu.getMenu().add(R.string.shared_string_remove).setIcon(
context.getMyApplication().getUIUtilities().getThemedIcon(R.drawable.ic_action_remove_dark));
final List<File> downloadedFiles = downloadItem.getDownloadedFiles(app);
if (!Algorithms.isEmpty(downloadedFiles)) {
item = optionsMenu.getMenu().add(R.string.shared_string_remove)
.setIcon(getThemedIcon(context, R.drawable.ic_action_remove_dark));
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
LocalIndexType tp = LocalIndexType.MAP_DATA;
if (indexItem.getType() == DownloadActivityType.HILLSHADE_FILE) {
tp = LocalIndexType.TILES_DATA;
} else if (indexItem.getType() == DownloadActivityType.SLOPE_FILE) {
tp = LocalIndexType.TILES_DATA;
} else if (indexItem.getType() == DownloadActivityType.ROADS_FILE) {
tp = LocalIndexType.MAP_DATA;
} else if (indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) {
tp = LocalIndexType.SRTM_DATA;
} else if (indexItem.getType() == DownloadActivityType.WIKIPEDIA_FILE) {
tp = LocalIndexType.MAP_DATA;
} else if (indexItem.getType() == DownloadActivityType.WIKIVOYAGE_FILE) {
tp = LocalIndexType.MAP_DATA;
} else if (indexItem.getType() == DownloadActivityType.TRAVEL_FILE) {
tp = LocalIndexType.MAP_DATA;
} else if (indexItem.getType() == DownloadActivityType.FONT_FILE) {
tp = LocalIndexType.FONT_DATA;
} else if (indexItem.getType() == DownloadActivityType.VOICE_FILE) {
tp = indexItem.getBasename().contains("tts") ? LocalIndexType.TTS_VOICE_DATA
: LocalIndexType.VOICE_DATA;
}
final LocalIndexInfo info = new LocalIndexInfo(tp, fl, false, context.getMyApplication());
AlertDialog.Builder confirm = new AlertDialog.Builder(context);
confirm.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new LocalIndexOperationTask(context, null, LocalIndexOperationTask.DELETE_OPERATION)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, info);
}
});
confirm.setNegativeButton(R.string.shared_string_no, null);
String fn = FileNameTranslationHelper.getFileName(context, context.getMyApplication().getRegions(),
indexItem.getVisibleName(context, context.getMyApplication().getRegions()));
confirm.setMessage(context.getString(R.string.delete_confirmation_msg, fn));
confirm.show();
confirmRemove(downloadItem, downloadedFiles);
return true;
}
});
@ -445,14 +426,144 @@ public class ItemViewHolder {
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
download(indexItem, parentOptional);
download(downloadItem, parentOptional);
return true;
}
});
optionsMenu.show();
}
protected void download(DownloadItem item, DownloadResourceGroup parentOptional) {
boolean handled = false;
if (parentOptional != null && item instanceof IndexItem) {
IndexItem indexItem = (IndexItem) item;
WorldRegion region = DownloadResourceGroup.getRegion(parentOptional);
context.setDownloadItem(region, indexItem.getTargetFile(context.getMyApplication()).getAbsolutePath());
}
if (item.getType() == DownloadActivityType.ROADS_FILE && parentOptional != null) {
for (IndexItem ii : parentOptional.getIndividualResources()) {
if (ii.getType() == DownloadActivityType.NORMAL_FILE) {
if (ii.isDownloaded()) {
handled = true;
confirmDownload(item);
}
break;
}
}
}
if(!handled) {
startDownload(item);
}
}
private void confirmDownload(final DownloadItem item) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.are_you_sure);
builder.setMessage(R.string.confirm_download_roadmaps);
builder.setNegativeButton(R.string.shared_string_cancel, null).setPositiveButton(
R.string.shared_string_download, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (item != null) {
startDownload(item);
}
}
});
builder.show();
}
private void startDownload(DownloadItem item) {
if (item instanceof MultipleIndexItem) {
MultipleIndexItem multipleIndexItem = (MultipleIndexItem) item;
List<IndexItem> indexes;
if (multipleIndexItem.hasActualDataToDownload()) {
// download left regions
indexes = multipleIndexItem.getIndexesToDownload();
} else {
// download all regions again
indexes = multipleIndexItem.getAllIndexes();
}
IndexItem[] indexesArray = new IndexItem[indexes.size()];
context.startDownload(indexes.toArray(indexesArray));
} else if (item instanceof IndexItem) {
IndexItem indexItem = (IndexItem) item;
context.startDownload(indexItem);
}
}
private void confirmRemove(@NonNull final DownloadItem downloadItem,
@NonNull final List<File> downloadedFiles) {
OsmandApplication app = context.getMyApplication();
AlertDialog.Builder confirm = new AlertDialog.Builder(context);
String message;
if (downloadedFiles.size() > 1) {
message = context.getString(R.string.delete_number_files_question, downloadedFiles.size());
} else {
OsmandRegions regions = app.getRegions();
String visibleName = downloadItem.getVisibleName(context, regions);
String fileName = FileNameTranslationHelper.getFileName(context, regions, visibleName);
message = context.getString(R.string.delete_confirmation_msg, fileName);
}
confirm.setMessage(message);
confirm.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
LocalIndexType type = getLocalIndexType(downloadItem);
remove(type, downloadedFiles);
}
});
confirm.setNegativeButton(R.string.shared_string_no, null);
confirm.show();
}
private void remove(@NonNull LocalIndexType type,
@NonNull List<File> filesToDelete) {
OsmandApplication app = context.getMyApplication();
LocalIndexOperationTask removeTask = new LocalIndexOperationTask(
context,
null,
LocalIndexOperationTask.DELETE_OPERATION);
LocalIndexInfo[] params = new LocalIndexInfo[filesToDelete.size()];
for (int i = 0; i < filesToDelete.size(); i++) {
File file = filesToDelete.get(i);
params[i] = new LocalIndexInfo(type, file, false, app);
}
removeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
}
@NonNull
private LocalIndexType getLocalIndexType(@NonNull DownloadItem downloadItem) {
LocalIndexType type = LocalIndexType.MAP_DATA;
if (downloadItem.getType() == DownloadActivityType.HILLSHADE_FILE) {
type = LocalIndexType.TILES_DATA;
} else if (downloadItem.getType() == DownloadActivityType.SLOPE_FILE) {
type = LocalIndexType.TILES_DATA;
} else if (downloadItem.getType() == DownloadActivityType.ROADS_FILE) {
type = LocalIndexType.MAP_DATA;
} else if (downloadItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) {
type = LocalIndexType.SRTM_DATA;
} else if (downloadItem.getType() == DownloadActivityType.WIKIPEDIA_FILE) {
type = LocalIndexType.MAP_DATA;
} else if (downloadItem.getType() == DownloadActivityType.WIKIVOYAGE_FILE) {
type = LocalIndexType.MAP_DATA;
} else if (downloadItem.getType() == DownloadActivityType.TRAVEL_FILE) {
type = LocalIndexType.MAP_DATA;
} else if (downloadItem.getType() == DownloadActivityType.FONT_FILE) {
type = LocalIndexType.FONT_DATA;
} else if (downloadItem.getType() == DownloadActivityType.VOICE_FILE) {
type = downloadItem.getBasename().contains("tts") ? LocalIndexType.TTS_VOICE_DATA
: LocalIndexType.VOICE_DATA;
}
return type;
}
private Drawable getThemedIcon(DownloadActivity context, int resourceId) {
return context.getMyApplication().getUIUtilities().getThemedIcon(resourceId);
}
private Drawable getContentIcon(DownloadActivity context, int resourceId) {
return context.getMyApplication().getUIUtilities().getThemedIcon(resourceId);
}

View file

@ -153,7 +153,8 @@ public class UpdatesIndexFragment extends OsmAndListFragment implements Download
for (IndexItem indexItem : indexItems) {
downloadsSize += indexItem.getSize();
}
String updateAllText = getActivity().getString(R.string.update_all, downloadsSize >> 20);
String updateAllText = getActivity().getString(
R.string.update_all, String.valueOf(downloadsSize >> 20));
updateAllButton.setText(updateAllText);
updateAllButton.setOnClickListener(new View.OnClickListener() {
@Override