diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesAdapter.java b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesAdapter.java index dea6ebcc92..2a7ce05c22 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesAdapter.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesAdapter.java @@ -21,10 +21,12 @@ import java.util.List; public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter { + private final static int TYPE_CATEGORY_ITEM = 0; + private final static int TYPE_ACTION_FOOTER = 1; + private final static int TYPE_ACTION_HEADER = 2; private final static int HEADER_POSITION = 0; - private final static int TYPE_ACTION_HEADER = 0; - private final static int TYPE_CATEGORY_ITEM = 1; - private final static int TYPE_ACTION_ADD = 2; + @NonNull + private final BookmarkCategoriesPageResProvider mResProvider; @Nullable private OnItemLongClickListener mLongClickListener; @Nullable @@ -37,6 +39,7 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter categories) { super(context.getApplicationContext(), categories); + mResProvider = new BookmarkCategoriesPageResProvider.Default(); } public void setOnClickListener(@Nullable OnItemClickListener listener) @@ -64,10 +67,10 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter 0 ? (count + 1 /* header */ + 1 /* footer */) : 0; } private class LongClickListener implements View.OnLongClickListener @@ -220,13 +219,13 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter 0) + out.write(buf, 0, len); + + context.getContentResolver().delete(from, null, null); + return true; + } } catch (IOException e) { - LOGGER.e(TAG, "Failed to copy or delete downloaded map file from " + downloadedFileUri.toString() + - " to " + dstPath + ". Exception ", e); + LOGGER.e(TAG, "Failed to copy or delete downloaded map file from " + from.toString() + + " to " + to + ". Exception ", e); return false; } } diff --git a/android/src/com/mapswithme/maps/settings/StoragePathFragment.java b/android/src/com/mapswithme/maps/settings/StoragePathFragment.java index 748fa245a8..59a43a1674 100644 --- a/android/src/com/mapswithme/maps/settings/StoragePathFragment.java +++ b/android/src/com/mapswithme/maps/settings/StoragePathFragment.java @@ -11,15 +11,11 @@ import android.widget.TextView; import androidx.appcompat.app.AlertDialog; -import com.mapswithme.maps.BuildConfig; -import com.mapswithme.maps.Framework; import com.mapswithme.maps.R; import com.mapswithme.maps.base.OnBackPressListener; import com.mapswithme.util.Constants; -import com.mapswithme.util.StorageUtils; import com.mapswithme.util.Utils; -import java.io.File; import java.util.List; import java.util.Locale; @@ -85,23 +81,9 @@ public class StoragePathFragment extends BaseSettingsFragment mPathManager.stopExternalStorageWatching(); } - static long getWritableDirSize() - { - final File writableDir = new File(Framework.nativeGetWritableDir()); - if (BuildConfig.DEBUG) - { - if (!writableDir.exists()) - throw new IllegalStateException("Writable directory doesn't exits, can't get size."); - if (!writableDir.isDirectory()) - throw new IllegalStateException("Writable directory isn't a directory, can't get size."); - } - - return StorageUtils.getDirSizeRecursively(writableDir, StoragePathManager.MOVABLE_FILES_FILTER); - } - private void updateList() { - long dirSize = getWritableDirSize(); + long dirSize = StorageUtils.getWritableDirSize(); mHeader.setText(getString(R.string.maps) + ": " + getSizeString(dirSize)); if (mAdapter != null) diff --git a/android/src/com/mapswithme/maps/settings/StoragePathManager.java b/android/src/com/mapswithme/maps/settings/StoragePathManager.java index 9895a80aca..9397f2985b 100644 --- a/android/src/com/mapswithme/maps/settings/StoragePathManager.java +++ b/android/src/com/mapswithme/maps/settings/StoragePathManager.java @@ -22,7 +22,6 @@ import com.mapswithme.maps.R; import com.mapswithme.maps.dialog.DialogUtils; import com.mapswithme.maps.downloader.MapManager; import com.mapswithme.util.Config; -import com.mapswithme.util.StorageUtils; import com.mapswithme.util.concurrency.ThreadPool; import com.mapswithme.util.concurrency.UiThread; import com.mapswithme.util.log.Logger; diff --git a/android/src/com/mapswithme/maps/settings/StorageUtils.java b/android/src/com/mapswithme/maps/settings/StorageUtils.java new file mode 100644 index 0000000000..6d00ad9c05 --- /dev/null +++ b/android/src/com/mapswithme/maps/settings/StorageUtils.java @@ -0,0 +1,165 @@ +package com.mapswithme.maps.settings; + +import com.mapswithme.maps.BuildConfig; +import com.mapswithme.maps.Framework; +import com.mapswithme.util.Constants; +import com.mapswithme.util.Utils; +import com.mapswithme.util.log.Logger; +import com.mapswithme.util.log.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.util.ArrayList; + +final class StorageUtils +{ + private StorageUtils() {} + + private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.STORAGE); + private static final String TAG = StorageUtils.class.getSimpleName(); + + /** + * Check if directory is writable. On some devices with KitKat (eg, Samsung S4) simple File.canWrite() returns + * true for some actually read only directories on sdcard. + * see https://code.google.com/p/android/issues/detail?id=66369 for details + * + * @param path path to ckeck + * @return result + */ + @SuppressWarnings("ResultOfMethodCallIgnored") + static boolean isDirWritable(String path) + { + File f = new File(path, "mapsme_test_dir"); + f.mkdir(); + if (!f.exists()) + return false; + + f.delete(); + return true; + } + + static long getFreeBytesAtPath(String path) + { + long size = 0; + try + { + size = new File(path).getFreeSpace(); + } catch (RuntimeException e) + { + e.printStackTrace(); + } + + return size; + } + + static void copyFile(File source, File dest) throws IOException + { + int maxChunkSize = 10 * Constants.MB; // move file by smaller chunks to avoid OOM. + FileChannel inputChannel = null, outputChannel = null; + try + { + inputChannel = new FileInputStream(source).getChannel(); + outputChannel = new FileOutputStream(dest).getChannel(); + long totalSize = inputChannel.size(); + + for (long currentPosition = 0; currentPosition < totalSize; currentPosition += maxChunkSize) + { + outputChannel.position(currentPosition); + outputChannel.transferFrom(inputChannel, currentPosition, maxChunkSize); + } + } finally + { + Utils.closeSafely(inputChannel); + Utils.closeSafely(outputChannel); + } + } + + private static long getDirSizeRecursively(File file, FilenameFilter fileFilter) + { + if (file.isDirectory()) + { + long dirSize = 0; + for (File child : file.listFiles()) + dirSize += getDirSizeRecursively(child, fileFilter); + + return dirSize; + } + + if (fileFilter.accept(file.getParentFile(), file.getName())) + return file.length(); + + return 0; + } + + static long getWritableDirSize() + { + final File writableDir = new File(Framework.nativeGetWritableDir()); + if (BuildConfig.DEBUG) + { + if (!writableDir.exists()) + throw new IllegalStateException("Writable directory doesn't exits, can't get size."); + if (!writableDir.isDirectory()) + throw new IllegalStateException("Writable directory isn't a directory, can't get size."); + } + + return getDirSizeRecursively(writableDir, StoragePathManager.MOVABLE_FILES_FILTER); + } + + /** + * Recursively lists all movable files in the directory. + */ + static void listFilesRecursively(File dir, String prefix, FilenameFilter filter, ArrayList relPaths) + { + File[] list = dir.listFiles(); + if (list == null) + return; + + for (File file : list) + { + if (file.isDirectory()) + { + listFilesRecursively(file, prefix + file.getName() + File.separator, filter, relPaths); + continue; + } + String name = file.getName(); + if (filter.accept(dir, name)) + relPaths.add(prefix + name); + } + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + private static void removeEmptyDirectories(File dir) + { + for (File file : dir.listFiles()) + { + if (!file.isDirectory()) + continue; + removeEmptyDirectories(file); + file.delete(); + } + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + static boolean removeFilesInDirectory(File dir, File[] files) + { + try + { + for (File file : files) + { + if (file != null) + file.delete(); + } + removeEmptyDirectories(dir); + return true; + } catch (Exception e) + { + e.printStackTrace(); + return false; + } + } + +} diff --git a/android/src/com/mapswithme/util/StorageUtils.java b/android/src/com/mapswithme/util/StorageUtils.java index d29a2a7b24..7245230379 100644 --- a/android/src/com/mapswithme/util/StorageUtils.java +++ b/android/src/com/mapswithme/util/StorageUtils.java @@ -17,15 +17,7 @@ import com.mapswithme.util.log.Logger; import com.mapswithme.util.log.LoggerFactory; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FilenameFilter; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.channels.FileChannel; -import java.util.ArrayList; public class StorageUtils { @@ -171,163 +163,4 @@ public class StorageUtils return FileProvider.getUriForFile(context.getApplicationContext(), BuildConfig.FILE_PROVIDER_AUTHORITY, new File(path)); } - - /** - * Copy data from a URI into a local file. - * @param context context - * @param from a source URI. - * @param to a destination file - * @return true on success and false if the provider recently crashed. - * @throws IOException - if I/O error occurs. - */ - public static boolean copyFile(@NonNull Context context, @NonNull Uri from, @NonNull File to) throws IOException - { - try (InputStream in = context.getContentResolver().openInputStream(from)) - { - if (in == null) - return false; - - try (OutputStream out = new FileOutputStream(to)) - { - byte[] buf = new byte[4 * 1024]; - int len; - while ((len = in.read(buf)) > 0) - out.write(buf, 0, len); - - return true; - } - } - } - - /** - * Copy the contents of the source file to the target file. - * @param from a source file - * @param to a destination file - * @throws IOException - if I/O error occurs. - */ - static void copyFile(File from, File to) throws IOException - { - int maxChunkSize = 10 * Constants.MB; // move file by smaller chunks to avoid OOM. - FileChannel inputChannel = null, outputChannel = null; - try - { - inputChannel = new FileInputStream(from).getChannel(); - outputChannel = new FileOutputStream(to).getChannel(); - long totalSize = inputChannel.size(); - - for (long currentPosition = 0; currentPosition < totalSize; currentPosition += maxChunkSize) - { - outputChannel.position(currentPosition); - outputChannel.transferFrom(inputChannel, currentPosition, maxChunkSize); - } - } finally - { - Utils.closeSafely(inputChannel); - Utils.closeSafely(outputChannel); - } - } - - /** - * Recursively lists all movable files in the directory. - */ - public static void listFilesRecursively(File dir, String prefix, FilenameFilter filter, ArrayList relPaths) - { - File[] list = dir.listFiles(); - if (list == null) - return; - - for (File file : list) - { - if (file.isDirectory()) - { - listFilesRecursively(file, prefix + file.getName() + File.separator, filter, relPaths); - continue; - } - String name = file.getName(); - if (filter.accept(dir, name)) - relPaths.add(prefix + name); - } - } - - /** - * Check if directory is writable. On some devices with KitKat (eg, Samsung S4) simple File.canWrite() returns - * true for some actually read only directories on sdcard. - * see https://code.google.com/p/android/issues/detail?id=66369 for details - * - * @param path path to ckeck - * @return result - */ - @SuppressWarnings("ResultOfMethodCallIgnored") - public static boolean isDirWritable(String path) - { - File f = new File(path, "mapsme_test_dir"); - f.mkdir(); - if (!f.exists()) - return false; - - f.delete(); - return true; - } - - public static long getFreeBytesAtPath(String path) - { - long size = 0; - try - { - size = new File(path).getFreeSpace(); - } catch (RuntimeException e) - { - e.printStackTrace(); - } - - return size; - } - - public static long getDirSizeRecursively(File file, FilenameFilter fileFilter) - { - if (file.isDirectory()) - { - long dirSize = 0; - for (File child : file.listFiles()) - dirSize += getDirSizeRecursively(child, fileFilter); - - return dirSize; - } - - if (fileFilter.accept(file.getParentFile(), file.getName())) - return file.length(); - - return 0; - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - public static void removeEmptyDirectories(File dir) - { - for (File file : dir.listFiles()) - { - if (!file.isDirectory()) - continue; - removeEmptyDirectories(file); - file.delete(); - } - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - public static boolean removeFilesInDirectory(File dir, File[] files) - { - try - { - for (File file : files) - { - if (file != null) - file.delete(); - } - removeEmptyDirectories(dir); - return true; - } catch (Exception e) - { - e.printStackTrace(); - return false; - } - } } diff --git a/qt/res/MapsWithMe.desktop b/qt/res/OrganicMaps.desktop similarity index 57% rename from qt/res/MapsWithMe.desktop rename to qt/res/OrganicMaps.desktop index 953b6b9305..21cf1ba5d1 100644 --- a/qt/res/MapsWithMe.desktop +++ b/qt/res/OrganicMaps.desktop @@ -1,13 +1,13 @@ [Desktop Entry] Type=Application -Name=MapsWithMe +Name=Organic Maps Version=1.0 GenericName=Detailed Offline Maps of the World GenericName[ru]=Подробная оффлайновая карта мира -Icon=/usr/share/MapsWithMe/logo.png -TryExec=/usr/bin/MapsWithMe -Exec=/usr/bin/MapsWithMe +Icon=organicmaps +TryExec=OMaps +Exec=OMaps Terminal=false StartupNotify=false Categories=Qt;Education;Science;Geography;Geoscience -Keywords=Maps;Offline Maps;Minsk;London;Briefcase;Case;MapsWithMe;OSM;OpenStreetMap;Map +Keywords=Maps;Offline Maps;Minsk;London;Briefcase;Case;OMaps;OrganicMaps;OSM;OpenStreetMap;Map diff --git a/qt/res/logo.png b/qt/res/logo.png index bab2c6992d..25a1149f26 100644 Binary files a/qt/res/logo.png and b/qt/res/logo.png differ