Merge pull request #10855 from osmandapp/DownloadAllButton
Download all button implementation
This commit is contained in:
commit
ff272c35c1
23 changed files with 1195 additions and 268 deletions
|
@ -436,6 +436,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 +462,43 @@ public class OsmandRegions {
|
|||
return rd;
|
||||
}
|
||||
|
||||
private QuadRect findBoundingBox(BinaryMapDataObject object) {
|
||||
if (object.getPointsLength() == 0) {
|
||||
return new QuadRect(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 QuadRect(minX, revertedMinY, maxX, revertedMaxY);
|
||||
}
|
||||
|
||||
private String getSearchIndex(BinaryMapDataObject object) {
|
||||
MapIndex mi = object.getMapIndex();
|
||||
TIntObjectIterator<String> it = object.getObjectNames().iterator();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.osmand.map;
|
||||
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -40,6 +41,7 @@ public class WorldRegion implements Serializable {
|
|||
protected String regionDownloadName;
|
||||
protected boolean regionMapDownload;
|
||||
protected LatLon regionCenter;
|
||||
protected QuadRect boundingBox;
|
||||
|
||||
public static class RegionParams {
|
||||
protected String regionLeftHandDriving;
|
||||
|
@ -182,4 +184,11 @@ public class WorldRegion implements Serializable {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean containsRegion(WorldRegion region) {
|
||||
if (this.boundingBox != null && region.boundingBox != null) {
|
||||
return this.boundingBox.contains(region.boundingBox);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -127,6 +127,17 @@ public class Algorithms {
|
|||
return def;
|
||||
}
|
||||
|
||||
public static double parseDoubleSilently(String input, double def) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
return Double.parseDouble(input);
|
||||
} catch (NumberFormatException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static String getFileNameWithoutExtension(File f) {
|
||||
return getFileNameWithoutExtension(f.getName());
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
android:paddingBottom="@dimen/content_padding_small">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/check_box_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
|
|
|
@ -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="restart">Restart</string>
|
||||
<string name="elevation_data_descr">Routing could avoid strong uphills</string>
|
||||
<string name="map_orientation_threshold_descr">Don\'t rotate map view if speed is less than a threshold</string>
|
||||
|
|
|
@ -380,7 +380,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
|||
AndroidUiHelper.updateVisibility(dismissButton, buttonTextId != DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
private void setupRightButton() {
|
||||
protected void setupRightButton() {
|
||||
rightButton = buttonsContainer.findViewById(R.id.right_bottom_button);
|
||||
rightButton.getLayoutParams().height = getRightButtonHeight();
|
||||
int buttonTextId = getRightBottomButtonTextId();
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
package net.osmand.plus.base;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.widget.CompoundButtonCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
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.util.Algorithms;
|
||||
import net.osmand.view.ThreeStateCheckbox;
|
||||
|
||||
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 SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragment {
|
||||
|
||||
private OsmandApplication app;
|
||||
private UiUtilities uiUtilities;
|
||||
|
||||
private TextView title;
|
||||
private TextView description;
|
||||
private TextView applyButtonTitle;
|
||||
private TextView checkBoxTitle;
|
||||
private TextView selectedSize;
|
||||
private ThreeStateCheckbox checkBox;
|
||||
|
||||
private int activeColorRes;
|
||||
private int secondaryColorRes;
|
||||
|
||||
private final List<SelectableItem> allItems = new ArrayList<>();
|
||||
private final List<SelectableItem> selectedItems = new ArrayList<>();
|
||||
private SelectionUpdateListener selectionUpdateListener;
|
||||
private OnApplySelectionListener onApplySelectionListener;
|
||||
|
||||
public static final String TAG = SelectMultipleItemsBottomSheet.class.getSimpleName();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
|
||||
View mainView = super.onCreateView(inflater, parent, savedInstanceState);
|
||||
onSelectedItemsChanged();
|
||||
return mainView;
|
||||
}
|
||||
|
||||
@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));
|
||||
createListItems();
|
||||
}
|
||||
|
||||
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);
|
||||
checkBoxTitle = view.findViewById(R.id.check_box_title);
|
||||
description = view.findViewById(R.id.description);
|
||||
selectedSize = view.findViewById(R.id.selected_size);
|
||||
title = view.findViewById(R.id.title);
|
||||
View selectAllButton = view.findViewById(R.id.select_all_button);
|
||||
selectAllButton.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();
|
||||
}
|
||||
onSelectedItemsChanged();
|
||||
updateItems(checked);
|
||||
}
|
||||
});
|
||||
return new SimpleBottomSheetItem.Builder().setCustomView(view).create();
|
||||
}
|
||||
|
||||
private void createListItems() {
|
||||
for (final SelectableItem item : allItems) {
|
||||
boolean checked = selectedItems.contains(item);
|
||||
final BottomSheetItemWithCompoundButton[] uiItem = new BottomSheetItemWithCompoundButton[1];
|
||||
final Builder builder = (BottomSheetItemWithCompoundButton.Builder) new Builder();
|
||||
builder.setChecked(checked)
|
||||
.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 = !uiItem[0].isChecked();
|
||||
uiItem[0].setChecked(checked);
|
||||
SelectableItem tag = (SelectableItem) uiItem[0].getTag();
|
||||
if (checked) {
|
||||
selectedItems.add(tag);
|
||||
} else {
|
||||
selectedItems.remove(tag);
|
||||
}
|
||||
onSelectedItemsChanged();
|
||||
}
|
||||
})
|
||||
.setTag(item);
|
||||
setupListItem(builder, item);
|
||||
uiItem[0] = builder.create();
|
||||
items.add(uiItem[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupRightButton() {
|
||||
super.setupRightButton();
|
||||
applyButtonTitle = rightButton.findViewById(R.id.button_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRightBottomButtonClick() {
|
||||
if (onApplySelectionListener != null) {
|
||||
onApplySelectionListener.onSelectionApplied(selectedItems);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
private void onSelectedItemsChanged() {
|
||||
updateSelectAllButton();
|
||||
updateSelectedSizeView();
|
||||
updateApplyButtonEnable();
|
||||
if (selectionUpdateListener != null) {
|
||||
selectionUpdateListener.onSelectionUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightBottomButtonTextId() {
|
||||
return R.string.shared_string_apply;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useVerticalButtons() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setupListItem(Builder builder, SelectableItem item) {
|
||||
builder.setTitle(item.title);
|
||||
builder.setDescription(item.description);
|
||||
builder.setIcon(uiUtilities.getIcon(item.iconId, activeColorRes));
|
||||
}
|
||||
|
||||
private void updateSelectAllButton() {
|
||||
String checkBoxTitle;
|
||||
if (Algorithms.isEmpty(selectedItems)) {
|
||||
checkBox.setState(UNCHECKED);
|
||||
checkBoxTitle = getString(R.string.shared_string_select_all);
|
||||
} else {
|
||||
checkBox.setState(selectedItems.containsAll(allItems) ? CHECKED : MISC);
|
||||
checkBoxTitle = getString(R.string.shared_string_deselect_all);
|
||||
}
|
||||
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
|
||||
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
|
||||
this.checkBoxTitle.setText(checkBoxTitle);
|
||||
}
|
||||
|
||||
private void updateSelectedSizeView() {
|
||||
String selected = String.valueOf(selectedItems.size());
|
||||
String all = String.valueOf(allItems.size());
|
||||
selectedSize.setText(getString(R.string.ltr_or_rtl_combine_via_slash, selected, all));
|
||||
}
|
||||
|
||||
private void updateApplyButtonEnable() {
|
||||
if (Algorithms.isEmpty(selectedItems)) {
|
||||
rightButton.setEnabled(false);
|
||||
} else {
|
||||
rightButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateItems(boolean checked) {
|
||||
for (BaseBottomSheetItem item : items) {
|
||||
if (item instanceof BottomSheetItemWithCompoundButton) {
|
||||
((BottomSheetItemWithCompoundButton) item).setChecked(checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTitle(@NonNull String title) {
|
||||
this.title.setText(title);
|
||||
}
|
||||
|
||||
public void setDescription(@NonNull String description) {
|
||||
this.description.setText(description);
|
||||
}
|
||||
|
||||
public void setConfirmButtonTitle(@NonNull String confirmButtonTitle) {
|
||||
applyButtonTitle.setText(confirmButtonTitle);
|
||||
}
|
||||
|
||||
private void setItems(List<SelectableItem> allItems) {
|
||||
if (!Algorithms.isEmpty(allItems)) {
|
||||
this.allItems.addAll(allItems);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSelectedItems(List<SelectableItem> selected) {
|
||||
if (!Algorithms.isEmpty(selected)) {
|
||||
this.selectedItems.addAll(selected);
|
||||
}
|
||||
}
|
||||
|
||||
public List<SelectableItem> getSelectedItems() {
|
||||
return selectedItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (requireActivity().isChangingConfigurations()) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public static SelectMultipleItemsBottomSheet showInstance(@NonNull AppCompatActivity activity,
|
||||
@NonNull List<SelectableItem> items,
|
||||
@Nullable List<SelectableItem> selected,
|
||||
boolean usedOnMap) {
|
||||
SelectMultipleItemsBottomSheet fragment = new SelectMultipleItemsBottomSheet();
|
||||
fragment.setUsedOnMap(usedOnMap);
|
||||
fragment.setItems(items);
|
||||
fragment.setSelectedItems(selected);
|
||||
FragmentManager fm = activity.getSupportFragmentManager();
|
||||
fragment.show(fm, TAG);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public void setSelectionUpdateListener(SelectionUpdateListener selectionUpdateListener) {
|
||||
this.selectionUpdateListener = selectionUpdateListener;
|
||||
}
|
||||
|
||||
public void setOnApplySelectionListener(OnApplySelectionListener onApplySelectionListener) {
|
||||
this.onApplySelectionListener = onApplySelectionListener;
|
||||
}
|
||||
|
||||
public interface SelectionUpdateListener {
|
||||
void onSelectionUpdate();
|
||||
}
|
||||
|
||||
public interface OnApplySelectionListener {
|
||||
void onSelectionApplied(List<SelectableItem> selectedItems);
|
||||
}
|
||||
|
||||
public static class SelectableItem {
|
||||
private String title;
|
||||
private String description;
|
||||
private int iconId;
|
||||
private Object object;
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setIconId(int iconId) {
|
||||
this.iconId = iconId;
|
||||
}
|
||||
|
||||
public void setObject(Object object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2,6 +2,8 @@ package net.osmand.plus.download;
|
|||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.map.OsmandRegions;
|
||||
|
@ -18,6 +20,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;
|
||||
|
@ -114,6 +117,10 @@ public class DownloadActivityType {
|
|||
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 +325,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 +344,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);
|
||||
}
|
||||
|
@ -441,9 +448,11 @@ public class DownloadActivityType {
|
|||
return fileName;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getBasename(@NonNull DownloadItem downloadItem) {
|
||||
String fileName = downloadItem.getFileName();
|
||||
if (Algorithms.isEmpty(fileName)) return fileName;
|
||||
|
||||
public String getBasename(IndexItem indexItem) {
|
||||
String fileName = indexItem.fileName;
|
||||
if (fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT)) {
|
||||
return fileName.substring(0, fileName.length() - IndexConstants.EXTRA_ZIP_EXT.length());
|
||||
}
|
||||
|
@ -458,7 +467,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());
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
81
OsmAnd/src/net/osmand/plus/download/DownloadItem.java
Normal file
81
OsmAnd/src/net/osmand/plus/download/DownloadItem.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
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) {
|
||||
return getFormattedMb(ctx, getSizeToDownloadInMb());
|
||||
}
|
||||
|
||||
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 ctx) {
|
||||
return type.getVisibleDescription(this, ctx);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
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(@NonNull DownloadIndexesThread thread);
|
||||
|
||||
public abstract String getFileName();
|
||||
|
||||
@NonNull
|
||||
public abstract List<File> getDownloadedFiles(@NonNull OsmandApplication app);
|
||||
|
||||
@NonNull
|
||||
public static String getFormattedMb(@NonNull Context ctx, double sizeInMb) {
|
||||
String size = String.format(Locale.US, "%.2f", sizeInMb);
|
||||
return ctx.getString(R.string.ltr_or_rtl_combine_via_space, size, "MB");
|
||||
}
|
||||
|
||||
}
|
|
@ -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: individualDownloadItems 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) {
|
||||
sortDownloadItems(g.individualDownloadItems);
|
||||
}
|
||||
|
||||
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(g.individualResources, new Comparator<IndexItem>() {
|
||||
Collections.sort(items, new Comparator<DownloadItem>() {
|
||||
@Override
|
||||
public int compare(IndexItem lhs, IndexItem rhs) {
|
||||
int lli = lhs.getType().getOrderIndex();
|
||||
int rri = rhs.getType().getOrderIndex();
|
||||
if(lli < rri) {
|
||||
public int compare(DownloadItem firstItem, DownloadItem secondItem) {
|
||||
int firstOrder = firstItem.getType().getOrderIndex();
|
||||
int secondOrder = secondItem.getType().getOrderIndex();
|
||||
if(firstOrder < secondOrder) {
|
||||
return -1;
|
||||
} else if(lli > rri) {
|
||||
} else if(firstOrder > secondOrder) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return collator.compare(lhs.getVisibleName(app.getApplicationContext(), osmandRegions),
|
||||
rhs.getVisibleName(app.getApplicationContext(), osmandRegions));
|
||||
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,9 +310,21 @@ 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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
@ -337,7 +341,7 @@ public class DownloadResources extends DownloadResourceGroup {
|
|||
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) {
|
||||
|
@ -416,7 +420,7 @@ public class DownloadResources extends DownloadResourceGroup {
|
|||
|
||||
List<IndexItem> list = groupByRegion.get(reg);
|
||||
if (list != null) {
|
||||
DownloadResourceGroup flatFiles = new DownloadResourceGroup(mainGrp, DownloadResourceGroupType.REGION_MAPS);
|
||||
DownloadResourceGroup flatFiles = new DownloadResourceGroup(mainGrp, REGION_MAPS);
|
||||
for (IndexItem ii : list) {
|
||||
flatFiles.addItem(ii);
|
||||
}
|
||||
|
@ -465,9 +469,85 @@ 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();
|
||||
List<WorldRegion> regionsToCollect = removeDuplicateRegions(subRegions);
|
||||
for (DownloadActivityType type : DownloadActivityType.values()) {
|
||||
if (!doesListContainIndexWithType(indexesList, type)) {
|
||||
List<IndexItem> indexesFromSubRegions = collectIndexesOfType(regionsToCollect, 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) {
|
||||
List<IndexItem> collectedIndexes = new ArrayList<>();
|
||||
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.add(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) return null;
|
||||
}
|
||||
return collectedIndexes;
|
||||
}
|
||||
|
||||
private List<WorldRegion> removeDuplicateRegions(List<WorldRegion> regions) {
|
||||
Set<WorldRegion> duplicates = new HashSet<>();
|
||||
for (int i = 0; i < regions.size() - 1; i++) {
|
||||
WorldRegion r1 = regions.get(i);
|
||||
for (int j = i + 1; j < regions.size(); j++) {
|
||||
WorldRegion r2 = regions.get(j);
|
||||
if (r1.containsRegion(r2)) {
|
||||
duplicates.add(r2);
|
||||
} else if (r2.containsRegion(r1)) {
|
||||
duplicates.add(r1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (WorldRegion region : duplicates) {
|
||||
regions.remove(region);
|
||||
}
|
||||
return regions;
|
||||
}
|
||||
|
||||
private void buildRegionsGroups(WorldRegion region, DownloadResourceGroup group) {
|
||||
LinkedList<WorldRegion> queue = new LinkedList<WorldRegion>();
|
||||
LinkedList<DownloadResourceGroup> parent = new LinkedList<DownloadResourceGroup>();
|
||||
|
@ -485,7 +565,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 +637,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 +657,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 +672,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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
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;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Collections;
|
||||
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 +27,43 @@ 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(@NonNull OsmandApplication app) {
|
||||
File targetFile = getTargetFile(app);
|
||||
if (targetFile.exists()) {
|
||||
return Collections.singletonList(targetFile);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
|
@ -89,11 +89,11 @@ 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() {
|
||||
return Algorithms.parseDoubleSilently(size, 0.0);
|
||||
}
|
||||
|
||||
|
||||
public DownloadEntry createDownloadEntry(OsmandApplication ctx) {
|
||||
String fileName = this.fileName;
|
||||
File parent = type.getDownloadFolder(ctx, this);
|
||||
|
@ -132,11 +132,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));
|
||||
}
|
||||
|
@ -170,6 +167,10 @@ public class IndexItem implements Comparable<IndexItem> {
|
|||
return "";
|
||||
}
|
||||
|
||||
public String getDate(@NonNull DateFormat dateFormat, boolean remote) {
|
||||
return remote ? getRemoteDate(dateFormat) : getLocalDate(dateFormat);
|
||||
}
|
||||
|
||||
public String getRemoteDate(DateFormat dateFormat) {
|
||||
if(timestamp <= 0) {
|
||||
return "";
|
||||
|
@ -178,7 +179,7 @@ public class IndexItem implements Comparable<IndexItem> {
|
|||
}
|
||||
|
||||
|
||||
public String getLocalDate(DateFormat dateFormat) {
|
||||
private String getLocalDate(@NonNull DateFormat dateFormat) {
|
||||
if(localTimestamp <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
@ -199,6 +200,11 @@ public class IndexItem implements Comparable<IndexItem> {
|
|||
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(@NonNull 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));
|
||||
}
|
||||
|
|
122
OsmAnd/src/net/osmand/plus/download/MultipleIndexItem.java
Normal file
122
OsmAnd/src/net/osmand/plus/download/MultipleIndexItem.java
Normal 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(@NonNull 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(@NonNull 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 += item.getSizeToDownloadInMb();
|
||||
}
|
||||
}
|
||||
return totalSizeMb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getArchiveSizeMB() {
|
||||
double result = 0.0d;
|
||||
for (IndexItem item : items) {
|
||||
result += item.getArchiveSizeMB();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
113
OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java
Normal file
113
OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java
Normal file
|
@ -0,0 +1,113 @@
|
|||
package net.osmand.plus.download;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import net.osmand.map.OsmandRegions;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.base.SelectMultipleItemsBottomSheet;
|
||||
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.OnApplySelectionListener;
|
||||
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectableItem;
|
||||
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectionUpdateListener;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MultipleIndexesUiHelper {
|
||||
|
||||
public static void showDialog(@NonNull MultipleIndexItem multipleIndexItem,
|
||||
@NonNull AppCompatActivity activity,
|
||||
@NonNull final OsmandApplication app,
|
||||
@NonNull DateFormat dateFormat,
|
||||
boolean showRemoteDate,
|
||||
@NonNull final SelectItemsToDownloadListener listener) {
|
||||
List<IndexItem> indexesToDownload = getIndexesToDownload(multipleIndexItem);
|
||||
List<SelectableItem> allItems = new ArrayList<>();
|
||||
List<SelectableItem> selectedItems = new ArrayList<>();
|
||||
OsmandRegions osmandRegions = app.getRegions();
|
||||
for (IndexItem indexItem : multipleIndexItem.getAllIndexes()) {
|
||||
SelectableItem selectableItem = new SelectableItem();
|
||||
selectableItem.setTitle(indexItem.getVisibleName(app, osmandRegions));
|
||||
|
||||
String size = indexItem.getSizeDescription(app);
|
||||
String date = indexItem.getDate(dateFormat, showRemoteDate);
|
||||
String description = app.getString(R.string.ltr_or_rtl_combine_via_bold_point, size, date);
|
||||
selectableItem.setDescription(description);
|
||||
|
||||
selectableItem.setIconId(indexItem.getType().getIconResource());
|
||||
selectableItem.setObject(indexItem);
|
||||
allItems.add(selectableItem);
|
||||
|
||||
if (indexesToDownload.contains(indexItem)) {
|
||||
selectedItems.add(selectableItem);
|
||||
}
|
||||
}
|
||||
|
||||
final SelectMultipleItemsBottomSheet dialog =
|
||||
SelectMultipleItemsBottomSheet.showInstance(activity, allItems, selectedItems, true);
|
||||
|
||||
dialog.setSelectionUpdateListener(new SelectionUpdateListener() {
|
||||
@Override
|
||||
public void onSelectionUpdate() {
|
||||
dialog.setTitle(app.getString(R.string.welmode_download_maps));
|
||||
String total = app.getString(R.string.shared_string_total);
|
||||
double sizeToDownload = getDownloadSizeInMb(dialog.getSelectedItems());
|
||||
String size = DownloadItem.getFormattedMb(app, sizeToDownload);
|
||||
String description =
|
||||
app.getString(R.string.ltr_or_rtl_combine_via_colon, total, size);
|
||||
dialog.setDescription(description);
|
||||
String btnTitle = app.getString(R.string.shared_string_download);
|
||||
if (sizeToDownload > 0) {
|
||||
btnTitle = app.getString(R.string.ltr_or_rtl_combine_via_dash, btnTitle, size);
|
||||
}
|
||||
dialog.setConfirmButtonTitle(btnTitle);
|
||||
}
|
||||
});
|
||||
|
||||
dialog.setOnApplySelectionListener(new OnApplySelectionListener() {
|
||||
@Override
|
||||
public void onSelectionApplied(List<SelectableItem> selectedItems) {
|
||||
List<IndexItem> indexItems = new ArrayList<>();
|
||||
for (SelectableItem item : selectedItems) {
|
||||
Object obj = item.getObject();
|
||||
if (obj instanceof IndexItem) {
|
||||
indexItems.add((IndexItem) obj);
|
||||
}
|
||||
}
|
||||
listener.onItemsToDownloadSelected(indexItems);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static List<IndexItem> getIndexesToDownload(MultipleIndexItem multipleIndexItem) {
|
||||
if (multipleIndexItem.hasActualDataToDownload()) {
|
||||
// download left regions
|
||||
return multipleIndexItem.getIndexesToDownload();
|
||||
} else {
|
||||
// download all regions again
|
||||
return multipleIndexItem.getAllIndexes();
|
||||
}
|
||||
}
|
||||
|
||||
private static double getDownloadSizeInMb(@NonNull List<SelectableItem> selectableItems) {
|
||||
List<IndexItem> indexItems = new ArrayList<>();
|
||||
for (SelectableItem i : selectableItems) {
|
||||
Object obj = i.getObject();
|
||||
if (obj instanceof IndexItem) {
|
||||
indexItems.add((IndexItem) obj);
|
||||
}
|
||||
}
|
||||
double totalSizeMb = 0.0d;
|
||||
for (IndexItem item : indexItems) {
|
||||
totalSizeMb += item.getSizeToDownloadInMb();
|
||||
}
|
||||
return totalSizeMb;
|
||||
}
|
||||
|
||||
public interface SelectItemsToDownloadListener {
|
||||
void onItemsToDownloadSelected(List<IndexItem> items);
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -35,6 +35,7 @@ import net.osmand.plus.download.DownloadActivity;
|
|||
import net.osmand.plus.download.DownloadActivity.BannerAndDownloadFreeVersion;
|
||||
import net.osmand.plus.download.DownloadActivityType;
|
||||
import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
|
||||
import net.osmand.plus.download.DownloadItem;
|
||||
import net.osmand.plus.download.DownloadResourceGroup;
|
||||
import net.osmand.plus.download.DownloadResources;
|
||||
import net.osmand.plus.download.DownloadValidationManager;
|
||||
|
@ -504,10 +505,10 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
|
|||
|
||||
DownloadItemFragment downloadItemFragment = DownloadItemFragment.createInstance(regionId, childPosition);
|
||||
((DownloadActivity) getActivity()).showDialog(getActivity(), downloadItemFragment);
|
||||
} else if (child instanceof IndexItem) {
|
||||
IndexItem indexItem = (IndexItem) child;
|
||||
} else if (child instanceof DownloadItem) {
|
||||
DownloadItem downloadItem = (DownloadItem) child;
|
||||
ItemViewHolder vh = (ItemViewHolder) v.getTag();
|
||||
OnClickListener ls = vh.getRightButtonAction(indexItem, vh.getClickAction(indexItem));
|
||||
OnClickListener ls = vh.getRightButtonAction(downloadItem, vh.getClickAction(downloadItem));
|
||||
ls.onClick(v);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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,15 @@ 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.MultipleIndexesUiHelper;
|
||||
import net.osmand.plus.download.MultipleIndexesUiHelper.SelectItemsToDownloadListener;
|
||||
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 +50,7 @@ import net.osmand.util.Algorithms;
|
|||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemViewHolder {
|
||||
|
||||
|
@ -137,24 +145,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 +172,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 {
|
||||
descrTextView.setText(indexItem.getSizeDescription(context) + " • " +
|
||||
(showRemoteDate ? indexItem.getRemoteDate(dateFormat) : indexItem.getLocalDate(dateFormat)));
|
||||
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 {
|
||||
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 = item.getDate(dateFormat, showRemoteDate);
|
||||
String fullDescription = String.format(pattern, size, date);
|
||||
if (showTypeInDesc) {
|
||||
fullDescription = String.format(pattern, type, fullDescription);
|
||||
}
|
||||
descrTextView.setText(fullDescription);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -209,18 +252,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 +285,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 +297,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 +314,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 +383,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 +393,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 +403,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(getContentIcon(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,7 +427,7 @@ public class ItemViewHolder {
|
|||
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
download(indexItem, parentOptional);
|
||||
download(downloadItem, parentOptional);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
@ -453,6 +435,135 @@ public class ItemViewHolder {
|
|||
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) {
|
||||
selectIndexesToDownload((MultipleIndexItem) item);
|
||||
} else if (item instanceof IndexItem) {
|
||||
IndexItem indexItem = (IndexItem) item;
|
||||
context.startDownload(indexItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectIndexesToDownload(MultipleIndexItem item) {
|
||||
OsmandApplication app = context.getMyApplication();
|
||||
MultipleIndexesUiHelper.showDialog(item, context, app, dateFormat, showRemoteDate,
|
||||
new SelectItemsToDownloadListener() {
|
||||
@Override
|
||||
public void onItemsToDownloadSelected(List<IndexItem> indexes) {
|
||||
IndexItem[] indexesArray = new IndexItem[indexes.size()];
|
||||
context.startDownload(indexes.toArray(indexesArray));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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 getContentIcon(DownloadActivity context, int resourceId) {
|
||||
return context.getMyApplication().getUIUtilities().getThemedIcon(resourceId);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue