From 8e2c09f68280d4648e7a799f4ae367d60e9e7727 Mon Sep 17 00:00:00 2001 From: jruesga Date: Sat, 20 Oct 2012 01:38:23 +0200 Subject: New fso and global actions "Compress" and "Compress selection" + CleanUp --- res/layout/option_list_item.xml | 2 +- res/menu/actions.xml | 8 + res/values/arrays.xml | 11 + res/values/strings.xml | 32 +- res/xml/command_list.xml | 2 +- .../explorer/activities/NavigationActivity.java | 3 +- .../explorer/activities/SearchActivity.java | 3 +- .../preferences/SettingsPreferences.java | 5 +- .../explorer/adapters/CheckableListAdapter.java | 13 + .../explorer/adapters/SimpleMenuListAdapter.java | 3 +- .../adapters/TwoColumnsMenuListAdapter.java | 3 +- .../explorer/commands/ExecutableCreator.java | 6 +- .../explorer/commands/shell/CompressCommand.java | 103 ++++- .../commands/shell/ShellExecutableCreator.java | 6 +- .../explorer/commands/shell/UncompressCommand.java | 88 ++-- .../explorer/preferences/CompressionMode.java | 67 +++ .../explorer/preferences/UncompressionMode.java | 87 ++++ .../explorer/ui/dialogs/ActionsDialog.java | 21 +- .../explorer/ui/dialogs/AssociationsDialog.java | 4 +- .../explorer/ui/dialogs/ChooseConsoleDialog.java | 8 +- .../explorer/ui/policy/ActionsPolicy.java | 29 +- .../explorer/ui/policy/BookmarksActionPolicy.java | 9 +- .../explorer/ui/policy/CompressActionPolicy.java | 494 ++++++++++++++++++++- .../explorer/ui/policy/CopyMoveActionPolicy.java | 27 +- .../explorer/ui/policy/DeleteActionPolicy.java | 10 +- .../explorer/ui/policy/InfoActionPolicy.java | 3 +- .../explorer/ui/policy/IntentsActionPolicy.java | 3 +- .../cyanogenmod/explorer/util/CommandHelper.java | 8 +- .../cyanogenmod/explorer/util/DialogHelper.java | 93 +++- src/com/cyanogenmod/explorer/util/FileHelper.java | 52 ++- .../cyanogenmod/explorer/util/StorageHelper.java | 3 +- .../commands/shell/CompressCommandTest.java | 12 +- .../commands/shell/UncompressCommandTest.java | 2 +- 33 files changed, 1085 insertions(+), 135 deletions(-) create mode 100644 src/com/cyanogenmod/explorer/preferences/CompressionMode.java create mode 100644 src/com/cyanogenmod/explorer/preferences/UncompressionMode.java diff --git a/res/layout/option_list_item.xml b/res/layout/option_list_item.xml index 66f6ce6e..90cf16ec 100644 --- a/res/layout/option_list_item.xml +++ b/res/layout/option_list_item.xml @@ -16,7 +16,7 @@ + android:background="@drawable/holo_selector" > + + 2 + + + + @string/compression_mode_tar + @string/compression_mode_tar_gzip + @string/compression_mode_tar_gzip2 + @string/compression_mode_tar_bzip + @string/compression_mode_gzip + @string/compression_mode_bzip + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index bf37f50a..e4163383 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -394,6 +394,9 @@ %1$s - copy%2$s + + + %1$s - new%2$s Performing operation… @@ -419,9 +422,22 @@ File]]> %1$s + + Compressing… + + + File]]> %1$s - + Analizing…]]> + + + The extracting operation was completed successfully. The data was extracted to + %1$s + + + The compressing operation was completed successfully. The data was compressed to + %1$s Actions @@ -447,6 +463,8 @@ Move selection Delete selection + + Compress selection Create link @@ -459,6 +477,8 @@ Execute Send + + Compress Extract @@ -559,6 +579,16 @@ VIDEO SECURITY + + Compression mode + + Tar (tar) + Tar/Gzip (tar.gz) + Tar/Gzip (tgz) + Tar/Bzip (tar.bz2) + Gzip (gz) + Bzip (bz2) + Settings diff --git a/res/xml/command_list.xml b/res/xml/command_list.xml index b2959c30..9d339c6e 100644 --- a/res/xml/command_list.xml +++ b/res/xml/command_list.xml @@ -93,7 +93,7 @@ - + diff --git a/src/com/cyanogenmod/explorer/activities/NavigationActivity.java b/src/com/cyanogenmod/explorer/activities/NavigationActivity.java index 25c8f9e7..8932f422 100644 --- a/src/com/cyanogenmod/explorer/activities/NavigationActivity.java +++ b/src/com/cyanogenmod/explorer/activities/NavigationActivity.java @@ -1222,7 +1222,8 @@ public class NavigationActivity extends Activity */ private void removeFromHistory(FileSystemObject fso) { if (this.mHistory != null) { - for (int i = this.mHistory.size()-1; i >= 0 ; i--) { + int cc = this.mHistory.size(); + for (int i = cc-1; i >= 0 ; i--) { History history = this.mHistory.get(i); if (history.getItem() instanceof NavigationViewInfoParcelable) { String p0 = fso.getFullPath(); diff --git a/src/com/cyanogenmod/explorer/activities/SearchActivity.java b/src/com/cyanogenmod/explorer/activities/SearchActivity.java index 20b8d936..9e1ece7f 100644 --- a/src/com/cyanogenmod/explorer/activities/SearchActivity.java +++ b/src/com/cyanogenmod/explorer/activities/SearchActivity.java @@ -695,7 +695,8 @@ public class SearchActivity extends Activity @SuppressWarnings("static-method") private List filterQuery(List original) { List dst = new ArrayList(original); - for (int i = dst.size() - 1; i >= 0; i--) { + int cc = dst.size(); + for (int i = cc - 1; i >= 0; i--) { String query = dst.get(i); if (query == null || query.trim().length() < MIN_CHARS_SEARCH) { dst.remove(i); diff --git a/src/com/cyanogenmod/explorer/activities/preferences/SettingsPreferences.java b/src/com/cyanogenmod/explorer/activities/preferences/SettingsPreferences.java index 26f920ca..cdc60f2e 100644 --- a/src/com/cyanogenmod/explorer/activities/preferences/SettingsPreferences.java +++ b/src/com/cyanogenmod/explorer/activities/preferences/SettingsPreferences.java @@ -38,6 +38,7 @@ import com.cyanogenmod.explorer.preferences.ExplorerSettings; import com.cyanogenmod.explorer.preferences.ObjectStringIdentifier; import com.cyanogenmod.explorer.preferences.Preferences; import com.cyanogenmod.explorer.providers.RecentSearchesContentProvider; +import com.cyanogenmod.explorer.util.DialogHelper; import java.util.List; @@ -298,10 +299,10 @@ public class SettingsPreferences extends PreferenceActivity { clearRecentSearchTerms(); // Advise the user - Toast.makeText( + DialogHelper.showToast( getActivity(), getActivity().getString(R.string.pref_remove_saved_search_terms_msg), - Toast.LENGTH_SHORT).show(); + Toast.LENGTH_SHORT); } return false; } diff --git a/src/com/cyanogenmod/explorer/adapters/CheckableListAdapter.java b/src/com/cyanogenmod/explorer/adapters/CheckableListAdapter.java index cc432407..b5435c88 100644 --- a/src/com/cyanogenmod/explorer/adapters/CheckableListAdapter.java +++ b/src/com/cyanogenmod/explorer/adapters/CheckableListAdapter.java @@ -136,4 +136,17 @@ public class CheckableListAdapter extends ArrayAdapter= 0; i--) { + int cc = this.mMenu.size(); + for (int i = cc - 1; i >= 0; i--) { MenuItem menuItem = this.mMenu.getItem(i); if (menuItem.getGroupId() != menuGroupResourceId) { this.mMenu.removeItem(menuItem.getItemId()); diff --git a/src/com/cyanogenmod/explorer/adapters/TwoColumnsMenuListAdapter.java b/src/com/cyanogenmod/explorer/adapters/TwoColumnsMenuListAdapter.java index 75105cd1..ad595a9b 100644 --- a/src/com/cyanogenmod/explorer/adapters/TwoColumnsMenuListAdapter.java +++ b/src/com/cyanogenmod/explorer/adapters/TwoColumnsMenuListAdapter.java @@ -92,7 +92,8 @@ public class TwoColumnsMenuListAdapter extends SimpleMenuListAdapter */ private void removeSeparators() { Menu menu = getMenu(); - for (int i = menu.size() - 1; i >= 0; i--) { + int cc = menu.size(); + for (int i = cc - 1; i >= 0; i--) { MenuItem menuItem = menu.getItem(i); if (menuItem.getTitle() == null || menuItem.getTitle().length() == 0) { menu.removeItem(menuItem.getItemId()); diff --git a/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java b/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java index e54c7d56..ce377ee0 100644 --- a/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java +++ b/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java @@ -17,13 +17,13 @@ package com.cyanogenmod.explorer.commands; import com.cyanogenmod.explorer.commands.ListExecutable.LIST_MODE; -import com.cyanogenmod.explorer.commands.shell.CompressCommand.CompressionMode; import com.cyanogenmod.explorer.console.CommandNotFoundException; import com.cyanogenmod.explorer.model.Group; import com.cyanogenmod.explorer.model.MountPoint; import com.cyanogenmod.explorer.model.Permissions; import com.cyanogenmod.explorer.model.Query; import com.cyanogenmod.explorer.model.User; +import com.cyanogenmod.explorer.preferences.CompressionMode; /** * A interface that defines methods for create {@link Executable} objects. @@ -412,12 +412,14 @@ public interface ExecutableCreator { * Method that creates an executable for uncompress file system objects. * * @param src The compressed file + * @param dst The destination file of folder (if null this method resolve with the best + * fit based on the src) * @param asyncResultListener The listener where to return partial results * @return UncompressExecutable A {@link UncompressExecutable} executable implementation reference * @throws CommandNotFoundException If the executable can't be created */ UncompressExecutable createUncompressExecutable( - String src, AsyncResultListener asyncResultListener) + String src, String dst, AsyncResultListener asyncResultListener) throws CommandNotFoundException; } diff --git a/src/com/cyanogenmod/explorer/commands/shell/CompressCommand.java b/src/com/cyanogenmod/explorer/commands/shell/CompressCommand.java index 9025503e..20e29fb5 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/CompressCommand.java +++ b/src/com/cyanogenmod/explorer/commands/shell/CompressCommand.java @@ -22,6 +22,10 @@ import com.cyanogenmod.explorer.commands.SIGNAL; import com.cyanogenmod.explorer.console.CommandNotFoundException; import com.cyanogenmod.explorer.console.ExecutionException; import com.cyanogenmod.explorer.console.InsufficientPermissionsException; +import com.cyanogenmod.explorer.preferences.CompressionMode; +import com.cyanogenmod.explorer.util.FileHelper; + +import java.io.File; /** * A class for compress file system objects @@ -35,39 +39,68 @@ public class CompressCommand extends AsyncResultProgram implements CompressExecu /** * An enumeration of implemented compression modes. */ - public enum CompressionMode { + private enum Mode { + /** + * Archive using Tar algorithm + */ + A_TAR(TAR_ID, "", CompressionMode.A_TAR), //$NON-NLS-1$ + /** + * Archive and compress using Gzip algorithm + */ + AC_GZIP(TAR_ID, "z", CompressionMode.AC_GZIP), //$NON-NLS-1$ + /** + * Archive and compress using Gzip algorithm + */ + AC_GZIP2(TAR_ID, "z", CompressionMode.AC_GZIP2), //$NON-NLS-1$ /** - * Without compression + * Archive and compress using Bzip algorithm */ - NONE("", "", ""), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + AC_BZIP(TAR_ID, "j", CompressionMode.AC_BZIP), //$NON-NLS-1$ /** * Compress using Gzip algorithm */ - GZIP(GZIP_ID, "z", "gz"), //$NON-NLS-1$ //$NON-NLS-2$ + C_GZIP(GZIP_ID, "z", CompressionMode.C_GZIP), //$NON-NLS-1$ /** * Compress using Bzip algorithm */ - BZIP(BZIP_ID, "j", "bz2"); //$NON-NLS-1$ //$NON-NLS-2$ + C_BZIP(BZIP_ID, "j", CompressionMode.C_BZIP); //$NON-NLS-1$ - String mId; - String mFlag; - String mExtension; + final String mId; + final String mFlag; + final CompressionMode mMode; /** - * Constructor of CompressionMode + * Constructor of Mode * * @param id The command identifier * @param flag The tar compression flag - * @param extension The file extension + * @param mode The compression mode */ - private CompressionMode(String id, String flag, String extension) { + private Mode(String id, String flag, CompressionMode mode) { this.mId = id; this.mFlag = flag; - this.mExtension = extension; + this.mMode = mode; + } + + /** + * Method that return the mode from his compression mode + * + * @param mode The compression mode + * @return Mode The mode + */ + public static Mode fromCompressionMode(CompressionMode mode) { + Mode[] modes = Mode.values(); + int cc = modes.length; + for (int i = 0; i < cc; i++) { + if (modes[i].mMode.compareTo(mode) == 0) { + return modes[i]; + } + } + return null; } } - private static final String TAR_ID = "compress"; //$NON-NLS-1$ + private static final String TAR_ID = "tar"; //$NON-NLS-1$ private static final String GZIP_ID = "gzip"; //$NON-NLS-1$ private static final String BZIP_ID = "bzip"; //$NON-NLS-1$ @@ -89,8 +122,12 @@ public class CompressCommand extends AsyncResultProgram implements CompressExecu public CompressCommand( CompressionMode mode, String dst, String[] src, AsyncResultListener asyncResultListener) throws InvalidCommandDefinitionException { - super(TAR_ID, asyncResultListener, new String[]{mode.mFlag, dst}); - addExpandedArguments(src, true); + super(TAR_ID, asyncResultListener, + new String[]{Mode.fromCompressionMode(mode).mFlag, dst}); + + //Convert the arguments from absolute to relative + addExpandedArguments( + convertAbsolutePathsToRelativePaths(dst, src), true); // Create the output file this.mOutFile = dst; @@ -108,7 +145,11 @@ public class CompressCommand extends AsyncResultProgram implements CompressExecu public CompressCommand( CompressionMode mode, String src, AsyncResultListener asyncResultListener) throws InvalidCommandDefinitionException { - super(mode.mId, asyncResultListener, resolveArguments(mode, src)); + super(Mode.fromCompressionMode(mode).mId, asyncResultListener, resolveArguments(mode, src)); + if (Mode.fromCompressionMode(mode).mMode.mArchive) { + throw new InvalidCommandDefinitionException( + "Unsupported compression mode"); //$NON-NLS-1$ + } // Create the output file this.mOutFile = resolveOutputFile(mode, src); @@ -150,7 +191,8 @@ public class CompressCommand extends AsyncResultProgram implements CompressExecu lines[0] = this.mPartial + lines[0]; // Return all the lines, except the last - for (int i = 0; i < lines.length-1; i++) { + int cc = lines.length; + for (int i = 0; i < cc-1; i++) { if (getAsyncResultListener() != null) { getAsyncResultListener().onPartialResult(lines[i]); } @@ -223,8 +265,8 @@ public class CompressCommand extends AsyncResultProgram implements CompressExecu */ private static String[] resolveArguments(CompressionMode mode, String src) { switch (mode) { - case GZIP: - case BZIP: + case C_GZIP: + case C_BZIP: return new String[]{src}; default: return new String[]{}; @@ -239,4 +281,27 @@ public class CompressCommand extends AsyncResultProgram implements CompressExecu private static String resolveOutputFile(CompressionMode mode, String src) { return String.format("%s.%s", src, mode.mExtension); //$NON-NLS-1$ } + + /** + * Method that converts the absolute paths of the source files to relative paths + * + * @param dst The destination compressed file + * @param src The source uncompressed files + * @return String[] The array of relative paths + */ + private static String[] convertAbsolutePathsToRelativePaths(String dst, String[] src) { + File parent = new File(dst).getParentFile(); + String p = File.separator; + if (parent != null) { + p = parent.getAbsolutePath(); + } + + // Converts every path + String[] out = new String[src.length]; + int cc = src.length; + for (int i = 0; i < cc; i++) { + out[i] = FileHelper.toRelativePath(src[i], p); + } + return out; + } } diff --git a/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java b/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java index 3bf05878..10f2ae1a 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java +++ b/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java @@ -47,7 +47,6 @@ import com.cyanogenmod.explorer.commands.ResolveLinkExecutable; import com.cyanogenmod.explorer.commands.SIGNAL; import com.cyanogenmod.explorer.commands.SendSignalExecutable; import com.cyanogenmod.explorer.commands.WriteExecutable; -import com.cyanogenmod.explorer.commands.shell.CompressCommand.CompressionMode; import com.cyanogenmod.explorer.console.CommandNotFoundException; import com.cyanogenmod.explorer.console.shell.ShellConsole; import com.cyanogenmod.explorer.model.Group; @@ -55,6 +54,7 @@ import com.cyanogenmod.explorer.model.MountPoint; import com.cyanogenmod.explorer.model.Permissions; import com.cyanogenmod.explorer.model.Query; import com.cyanogenmod.explorer.model.User; +import com.cyanogenmod.explorer.preferences.CompressionMode; /** * A class for create shell {@link "Executable"} objects. @@ -523,11 +523,11 @@ public class ShellExecutableCreator implements ExecutableCreator { */ @Override public UncompressCommand createUncompressExecutable( - String src, + String src, String dst, AsyncResultListener asyncResultListener) throws CommandNotFoundException { try { - return new UncompressCommand(src, asyncResultListener); + return new UncompressCommand(src, dst, asyncResultListener); } catch (InvalidCommandDefinitionException icdEx) { throw new CommandNotFoundException("UncompressCommand", icdEx); //$NON-NLS-1$ } diff --git a/src/com/cyanogenmod/explorer/commands/shell/UncompressCommand.java b/src/com/cyanogenmod/explorer/commands/shell/UncompressCommand.java index c7c4c2b0..a16ea02d 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/UncompressCommand.java +++ b/src/com/cyanogenmod/explorer/commands/shell/UncompressCommand.java @@ -22,6 +22,7 @@ import com.cyanogenmod.explorer.commands.UncompressExecutable; import com.cyanogenmod.explorer.console.CommandNotFoundException; import com.cyanogenmod.explorer.console.ExecutionException; import com.cyanogenmod.explorer.console.InsufficientPermissionsException; +import com.cyanogenmod.explorer.preferences.UncompressionMode; import com.cyanogenmod.explorer.util.FileHelper; import java.io.File; @@ -40,70 +41,67 @@ public class UncompressCommand extends AsyncResultProgram implements UncompressE /** * An enumeration of implemented uncompression modes. */ - public enum UncompressionMode { + private enum Mode { /** * Uncompress using Tar algorithm */ - A_UNTAR(UNTAR_ID, "", "tar", true), //$NON-NLS-1$ //$NON-NLS-2$ + A_UNTAR(UNTAR_ID, "", UncompressionMode.A_UNTAR), //$NON-NLS-1$ /** * Uncompress using Tar algorithm */ - A_UNZIP(UNZIP_ID, "", "zip", true), //$NON-NLS-1$ //$NON-NLS-2$ + A_UNZIP(UNZIP_ID, "", UncompressionMode.A_UNZIP), //$NON-NLS-1$ /** * Uncompress using Gzip algorithm */ - AC_GUNZIP(UNTAR_ID, "z", "tar.gz", true), //$NON-NLS-1$ //$NON-NLS-2$ + AC_GUNZIP(UNTAR_ID, "z", UncompressionMode.AC_GUNZIP), //$NON-NLS-1$ /** * Uncompress using Gzip algorithm */ - AC_GUNZIP2(UNTAR_ID, "z", "tgz", true), //$NON-NLS-1$ //$NON-NLS-2$ + AC_GUNZIP2(UNTAR_ID, "z", UncompressionMode.AC_GUNZIP2), //$NON-NLS-1$ /** * Uncompress using Bzip algorithm */ - AC_BUNZIP(UNTAR_ID, "j", "tar.bz2", true), //$NON-NLS-1$ //$NON-NLS-2$ + AC_BUNZIP(UNTAR_ID, "j", UncompressionMode.AC_BUNZIP), //$NON-NLS-1$ /** * Uncompress using Lzma algorithm */ - AC_UNLZMA(UNTAR_ID, "a", "tar.lzma", true), //$NON-NLS-1$ //$NON-NLS-2$ + AC_UNLZMA(UNTAR_ID, "a", UncompressionMode.AC_UNLZMA), //$NON-NLS-1$ /** * Uncompress using Gzip algorithm */ - C_GUNZIP(GUNZIP_ID, "", "gz", false), //$NON-NLS-1$ //$NON-NLS-2$ + C_GUNZIP(GUNZIP_ID, "", UncompressionMode.C_GUNZIP), //$NON-NLS-1$ /** * Uncompress using Bzip algorithm */ - C_BUNZIP(BUNZIP_ID, "", "bz2", false), //$NON-NLS-1$ //$NON-NLS-2$ + C_BUNZIP(BUNZIP_ID, "", UncompressionMode.C_BUNZIP), //$NON-NLS-1$ /** * Uncompress using Lzma algorithm */ - C_UNLZMA(UNLZMA_ID, "", "lzma", false), //$NON-NLS-1$ //$NON-NLS-2$ + C_UNLZMA(UNLZMA_ID, "", UncompressionMode.C_UNLZMA), //$NON-NLS-1$ /** * Uncompress using Unix compress algorithm */ - C_UNCOMPRESS(UNCOMPRESS_ID, "", "Z", false), //$NON-NLS-1$ //$NON-NLS-2$ + C_UNCOMPRESS(UNCOMPRESS_ID, "", UncompressionMode.C_UNCOMPRESS), //$NON-NLS-1$ /** * Uncompress using Unix compress algorithm */ - C_UNXZ(UNXZ_ID, "", "xz", false); //$NON-NLS-1$ //$NON-NLS-2$ + C_UNXZ(UNXZ_ID, "", UncompressionMode.C_UNXZ); //$NON-NLS-1$ - String mId; - String mFlag; - String mExtension; - boolean mArchive; + final String mId; + final String mFlag; + UncompressionMode mMode; /** - * Constructor of UncompressionMode + * Constructor of Mode * * @param id The command identifier * @param flag The tar compression flag - * @param extension The file extension - * @param archive If the file is an archive or archive-compressed + * @param mode The uncompressed mode */ - private UncompressionMode(String id, String flag, String extension, boolean archive) { + private Mode(String id, String flag, UncompressionMode mode) { this.mId = id; this.mFlag = flag; - this.mExtension = extension; - this.mArchive = archive; + this.mMode = mode; } } @@ -132,24 +130,30 @@ public class UncompressCommand extends AsyncResultProgram implements UncompressE * * * @param src The archive-compressed file + * @param dst The destination file of folder (if null this method resolve with the best + * fit based on the src) * @param asyncResultListener The partial result listener * @throws InvalidCommandDefinitionException If the command has an invalid definition */ public UncompressCommand( - String src, AsyncResultListener asyncResultListener) + String src, String dst, AsyncResultListener asyncResultListener) throws InvalidCommandDefinitionException { - super(resolveId(src), asyncResultListener, resolveArguments(src)); + super(resolveId(src), asyncResultListener, resolveArguments(src, dst)); // Check that have a valid - UncompressionMode mode = getMode(src); + Mode mode = getMode(src); if (mode == null) { throw new InvalidCommandDefinitionException( "Unsupported uncompress mode"); //$NON-NLS-1$ } // Retrieve information about the uncompress process - this.mOutFile = resolveOutputFile(src); - this.mIsArchive = mode.mArchive; + if (dst != null) { + this.mOutFile = dst; + } else { + this.mOutFile = resolveOutputFile(src); + } + this.mIsArchive = mode.mMode.mArchive; } /** @@ -269,7 +273,7 @@ public class UncompressCommand extends AsyncResultProgram implements UncompressE * @return String The identifier of the command */ private static String resolveId(String src) { - UncompressionMode mode = getMode(src); + Mode mode = getMode(src); if (mode != null) { return mode.mId; } @@ -279,11 +283,16 @@ public class UncompressCommand extends AsyncResultProgram implements UncompressE /** * Method that resolves the arguments for the uncompression * + * @param src The source file + * @param dst The destination file * @return String[] The arguments */ - private static String[] resolveArguments(String src) { - String dst = resolveOutputFile(src); - UncompressionMode mode = getMode(src); + private static String[] resolveArguments(String src, String dst) { + String out = dst; + if (out == null) { + out = resolveOutputFile(src); + } + Mode mode = getMode(src); if (mode != null) { switch (mode) { case A_UNTAR: @@ -291,10 +300,10 @@ public class UncompressCommand extends AsyncResultProgram implements UncompressE case AC_GUNZIP2: case AC_BUNZIP: case AC_UNLZMA: - return new String[]{mode.mFlag, dst, src}; + return new String[]{mode.mFlag, out, src}; case A_UNZIP: - return new String[]{dst, src}; + return new String[]{out, src}; case C_GUNZIP: case C_BUNZIP: @@ -325,14 +334,15 @@ public class UncompressCommand extends AsyncResultProgram implements UncompressE * Method that returns the uncompression mode from the compressed file * * @param src The compressed file - * @return UncompressionMode The uncompression mode. null if no mode found + * @return Mode The uncompression mode. null if no mode found */ - private static UncompressionMode getMode(String src) { + private static Mode getMode(String src) { String extension = FileHelper.getExtension(src); - UncompressionMode[] modes = UncompressionMode.values(); - for (int i = 0; i < modes.length; i++) { - UncompressionMode mode = modes[i]; - if (mode.mExtension.compareTo(extension) == 0) { + Mode[] modes = Mode.values(); + int cc = modes.length; + for (int i = 0; i < cc; i++) { + Mode mode = modes[i]; + if (mode.mMode.mExtension.compareTo(extension) == 0) { return mode; } } diff --git a/src/com/cyanogenmod/explorer/preferences/CompressionMode.java b/src/com/cyanogenmod/explorer/preferences/CompressionMode.java new file mode 100644 index 00000000..a68ece1c --- /dev/null +++ b/src/com/cyanogenmod/explorer/preferences/CompressionMode.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.explorer.preferences; + +/** + * An enumeration of all implemented compression modes. + */ +public enum CompressionMode { + /** + * Archive using Tar algorithm + */ + A_TAR("tar", true), //$NON-NLS-1$ + /** + * Archive and compress using Gzip algorithm + */ + AC_GZIP("tar.gz", true), //$NON-NLS-1$ + /** + * Archive and compress using Gzip algorithm + */ + AC_GZIP2("tgz", true), //$NON-NLS-1$ + /** + * Archive and compress using Bzip algorithm + */ + AC_BZIP("tar.bz2", true), //$NON-NLS-1$ + /** + * Compress using Gzip algorithm + */ + C_GZIP("gz", false), //$NON-NLS-1$ + /** + * Compress using Bzip algorithm + */ + C_BZIP("bz2", false); //$NON-NLS-1$ + + /** + * The file extension + */ + public final String mExtension; + /** + * If the file is an archive or archive-compressed (true) or a compressed file (false) + */ + public final boolean mArchive; + + /** + * Constructor of CompressionMode + * + * @param extension The output extension + * @param archive If the output is an archive or archive-compressed + */ + private CompressionMode(String extension, boolean archive) { + this.mExtension = extension; + this.mArchive = archive; + } +} diff --git a/src/com/cyanogenmod/explorer/preferences/UncompressionMode.java b/src/com/cyanogenmod/explorer/preferences/UncompressionMode.java new file mode 100644 index 00000000..2d99fab5 --- /dev/null +++ b/src/com/cyanogenmod/explorer/preferences/UncompressionMode.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.explorer.preferences; + +/** + * An enumeration of all implemented uncompression modes. + */ +public enum UncompressionMode { + /** + * Uncompress using Tar algorithm + */ + A_UNTAR("tar", true), //$NON-NLS-1$ + /** + * Uncompress using Tar algorithm + */ + A_UNZIP("zip", true), //$NON-NLS-1$ + /** + * Uncompress using Gzip algorithm + */ + AC_GUNZIP("tar.gz", true), //$NON-NLS-1$ + /** + * Uncompress using Gzip algorithm + */ + AC_GUNZIP2("tgz", true), //$NON-NLS-1$ + /** + * Uncompress using Bzip algorithm + */ + AC_BUNZIP("tar.bz2", true), //$NON-NLS-1$ + /** + * Uncompress using Lzma algorithm + */ + AC_UNLZMA("tar.lzma", true), //$NON-NLS-1$ + /** + * Uncompress using Gzip algorithm + */ + C_GUNZIP("gz", false), //$NON-NLS-1$ + /** + * Uncompress using Bzip algorithm + */ + C_BUNZIP("bz2", false), //$NON-NLS-1$ + /** + * Uncompress using Lzma algorithm + */ + C_UNLZMA("lzma", false), //$NON-NLS-1$ + /** + * Uncompress using Unix compress algorithm + */ + C_UNCOMPRESS("Z", false), //$NON-NLS-1$ + /** + * Uncompress using Unix compress algorithm + */ + C_UNXZ("xz", false); //$NON-NLS-1$ + + /** + * The file extension + */ + public final String mExtension; + /** + * If the file is an archive or archive-compressed (true) or a compressed file (false) + */ + public final boolean mArchive; + + /** + * Constructor of UncompressionMode + * + * @param extension The file extension + * @param archive If the file is an archive or archive-compressed + */ + private UncompressionMode(String extension, boolean archive) { + this.mExtension = extension; + this.mArchive = archive; + } +} diff --git a/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java b/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java index 2118b036..f280ac38 100644 --- a/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java +++ b/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java @@ -314,6 +314,24 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen this.mFso, this.mOnRequestRefreshListener); break; + //- Compress + case R.id.mnu_actions_compress: + if (this.mOnSelectionListener != null) { + CompressActionPolicy.compress( + this.mContext, + this.mFso, + this.mOnSelectionListener, + this.mOnRequestRefreshListener); + } + break; + case R.id.mnu_actions_compress_selection: + if (this.mOnSelectionListener != null) { + CompressActionPolicy.compress( + this.mContext, + this.mOnSelectionListener, + this.mOnRequestRefreshListener); + } + break; //- Create copy case R.id.mnu_actions_create_copy: @@ -603,7 +621,8 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen List items, FileSystemObject directory) { List resources = new ArrayList(items.size()); - for (int i = 0; i < items.size(); i++) { + int cc = items.size(); + for (int i = 0; i < cc; i++) { FileSystemObject fso = items.get(i); File src = new File(fso.getFullPath()); File dst = new File(directory.getFullPath(), fso.getName()); diff --git a/src/com/cyanogenmod/explorer/ui/dialogs/AssociationsDialog.java b/src/com/cyanogenmod/explorer/ui/dialogs/AssociationsDialog.java index 082a92c8..08dec3b1 100644 --- a/src/com/cyanogenmod/explorer/ui/dialogs/AssociationsDialog.java +++ b/src/com/cyanogenmod/explorer/ui/dialogs/AssociationsDialog.java @@ -421,10 +421,10 @@ public class AssociationsDialog implements OnItemClickListener { } catch (Exception e) { // Capture the exception ExceptionUtil.translateException(this.mContext, e, true, false); - Toast.makeText( + DialogHelper.showToast( this.mContext, R.string.msgs_action_association_failed, - Toast.LENGTH_SHORT).show(); + Toast.LENGTH_SHORT); } } } diff --git a/src/com/cyanogenmod/explorer/ui/dialogs/ChooseConsoleDialog.java b/src/com/cyanogenmod/explorer/ui/dialogs/ChooseConsoleDialog.java index 2343af1c..952f334d 100644 --- a/src/com/cyanogenmod/explorer/ui/dialogs/ChooseConsoleDialog.java +++ b/src/com/cyanogenmod/explorer/ui/dialogs/ChooseConsoleDialog.java @@ -21,6 +21,7 @@ import android.content.Context; import android.util.Log; import android.view.View; import android.view.ViewGroup.LayoutParams; +import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.LinearLayout; @@ -89,10 +90,12 @@ public class ChooseConsoleDialog implements OnItemClickListener { //Create the list view ListView listView = new ListView(context); LinearLayout.LayoutParams params = - new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); listView.setLayoutParams(params); listView.setAdapter(adapter); listView.setOnItemClickListener(this); + listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); //Create the dialog this.mDialog = DialogHelper.createDialog( @@ -114,6 +117,9 @@ public class ChooseConsoleDialog implements OnItemClickListener { */ @Override public void onItemClick(AdapterView parent, View view, int position, long id) { + try { + ((CheckableListAdapter)((ListView)parent).getAdapter()).setSelectedItem(position); + } catch (Exception e) {/**NON BLOCK**/} this.mDialog.dismiss(); boolean ret = false; Boolean superuser = Boolean.FALSE; diff --git a/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java index 21cfb4b0..77eb6312 100644 --- a/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java +++ b/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java @@ -23,6 +23,7 @@ import android.widget.Toast; import com.cyanogenmod.explorer.R; import com.cyanogenmod.explorer.ui.dialogs.MessageProgressDialog; +import com.cyanogenmod.explorer.util.DialogHelper; import com.cyanogenmod.explorer.util.ExceptionUtil; @@ -50,6 +51,13 @@ public abstract class ActionsPolicy { */ int getDialogTitle(); + /** + * Method that returns if the dialog is cancelable + * + * @return boolean If the dialog is cancelable + */ + boolean isDialogCancelable(); + /** * Method invoked when need to update the progress of the dialog * @@ -99,12 +107,19 @@ public abstract class ActionsPolicy { @Override protected void onPreExecute() { // Create the waiting dialog while doing some stuff on background + final BackgroundAsyncTask task = this; this.mDialog = new MessageProgressDialog( this.mCtx, - R.drawable.ic_holo_light_operation, - R.string.waiting_dialog_copying_title, + this.mCallable.getDialogIcon(), + this.mCallable.getDialogTitle(), R.string.waiting_dialog_msg, - false); + this.mCallable.isDialogCancelable()); + this.mDialog.setOnCancelListener(new MessageProgressDialog.OnCancelListener() { + @Override + public boolean onCancel() { + return task.cancel(true); + } + }); Spanned progress = this.mCallable.requestProgress(); this.mDialog.setProgress(progress); this.mDialog.show(); @@ -138,6 +153,12 @@ public abstract class ActionsPolicy { } } + @Override + protected void onCancelled() { + //Operation complete. + this.mCallable.onSuccess(); + } + @Override protected void onProgressUpdate(Spanned... values) { this.mDialog.setProgress(values[0]); @@ -159,6 +180,6 @@ public abstract class ActionsPolicy { * @hide */ protected static void showOperationSuccessMsg(Context ctx) { - Toast.makeText(ctx, R.string.msgs_success, Toast.LENGTH_SHORT).show(); + DialogHelper.showToast(ctx, R.string.msgs_success, Toast.LENGTH_SHORT); } } \ No newline at end of file diff --git a/src/com/cyanogenmod/explorer/ui/policy/BookmarksActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/BookmarksActionPolicy.java index 6afe0dff..a9253412 100644 --- a/src/com/cyanogenmod/explorer/ui/policy/BookmarksActionPolicy.java +++ b/src/com/cyanogenmod/explorer/ui/policy/BookmarksActionPolicy.java @@ -24,6 +24,7 @@ import com.cyanogenmod.explorer.model.Bookmark; import com.cyanogenmod.explorer.model.Bookmark.BOOKMARK_TYPE; import com.cyanogenmod.explorer.model.FileSystemObject; import com.cyanogenmod.explorer.preferences.Bookmarks; +import com.cyanogenmod.explorer.util.DialogHelper; import com.cyanogenmod.explorer.util.ExceptionUtil; /** @@ -45,16 +46,16 @@ public final class BookmarksActionPolicy extends ActionsPolicy { bookmark = Bookmarks.addBookmark(ctx, bookmark); if (bookmark == null) { // The operation fails - Toast.makeText( + DialogHelper.showToast( ctx, R.string.msgs_operation_failure, - Toast.LENGTH_SHORT).show(); + Toast.LENGTH_SHORT); } else { // Success - Toast.makeText( + DialogHelper.showToast( ctx, R.string.bookmarks_msgs_add_success, - Toast.LENGTH_SHORT).show(); + Toast.LENGTH_SHORT); } } catch (Exception e) { diff --git a/src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java index b41ed3d8..bcae907c 100644 --- a/src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java +++ b/src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java @@ -21,16 +21,20 @@ import android.content.Context; import android.content.DialogInterface; import android.text.Html; import android.text.Spanned; +import android.widget.Toast; import com.cyanogenmod.explorer.ExplorerApplication; import com.cyanogenmod.explorer.R; import com.cyanogenmod.explorer.commands.AsyncResultListener; +import com.cyanogenmod.explorer.commands.CompressExecutable; import com.cyanogenmod.explorer.commands.UncompressExecutable; import com.cyanogenmod.explorer.console.ConsoleBuilder; import com.cyanogenmod.explorer.console.ExecutionException; import com.cyanogenmod.explorer.console.RelaunchableException; import com.cyanogenmod.explorer.listeners.OnRequestRefreshListener; +import com.cyanogenmod.explorer.listeners.OnSelectionListener; import com.cyanogenmod.explorer.model.FileSystemObject; +import com.cyanogenmod.explorer.preferences.CompressionMode; import com.cyanogenmod.explorer.util.CommandHelper; import com.cyanogenmod.explorer.util.DialogHelper; import com.cyanogenmod.explorer.util.ExceptionUtil; @@ -38,6 +42,8 @@ import com.cyanogenmod.explorer.util.ExceptionUtil.OnRelaunchCommandResult; import com.cyanogenmod.explorer.util.FileHelper; import com.cyanogenmod.explorer.util.FixedQueue; +import java.io.File; +import java.util.ArrayList; import java.util.List; /** @@ -50,7 +56,6 @@ public final class CompressActionPolicy extends ActionsPolicy { */ private static class CompressListener implements AsyncResultListener { - Object mSync; final FixedQueue mQueue; boolean mEnd; Throwable mCause; @@ -61,23 +66,18 @@ public final class CompressActionPolicy extends ActionsPolicy { public CompressListener() { super(); this.mEnd = false; - this.mSync = new Object(); this.mQueue = new FixedQueue(2); //Holds only one item this.mCause = null; } @Override public void onPartialResult(Object result) { - synchronized (this.mSync) { - this.mQueue.insert((String)result); - } + this.mQueue.insert((String)result); } @Override public void onException(Exception cause) { - synchronized (this.mSync) { - this.mCause = cause; - } + this.mCause = cause; } @Override @@ -88,9 +88,389 @@ public final class CompressActionPolicy extends ActionsPolicy { @Override public void onAsyncExitCode(int exitCode) { - synchronized (this.mSync) { - this.mEnd = true; + this.mEnd = true; + } + } + + /** + * Method that compresses the list of files of the selection. + * + * @param ctx The current context + * @param onSelectionListener The listener for obtain selection information (required) + * @param onRequestRefreshListener The listener for request a refresh (optional) + * @hide + */ + public static void compress( + final Context ctx, + final OnSelectionListener onSelectionListener, + final OnRequestRefreshListener onRequestRefreshListener) { + + // Retrieve the current selection + final List selection = onSelectionListener.onRequestSelectedFiles(); + if (selection != null && selection.size() > 0) { + // Show a dialog to allow the user make the compression mode choice + AlertDialog dialog = DialogHelper.createSingleChoiceDialog( + ctx, R.drawable.ic_holo_light_compress, R.string.compression_mode_title, + getSupportedCompressionModesLabels(ctx, selection), + CompressionMode.AC_GZIP.ordinal(), + new DialogHelper.OnSelectChoiceListener() { + @Override + public void onSelectChoice(int choice) { + // Do the compression + compress( + ctx, + getCompressionModeFromUserChoice(choice), + selection, + onSelectionListener, + onRequestRefreshListener); + } + + @Override + public void onNoSelectChoice() {/**NON BLOCK**/} + }); + dialog.show(); + } + } + + /** + * Method that compresses an uncompressed file. + * + * @param ctx The current context + * @param fso The compressed file + * @param onSelectionListener The listener for obtain selection information (required) + * @param onRequestRefreshListener The listener for request a refresh (optional) + * @hide + */ + public static void compress( + final Context ctx, final FileSystemObject fso, + final OnSelectionListener onSelectionListener, + final OnRequestRefreshListener onRequestRefreshListener) { + + // Create a list with the item + final List items = new ArrayList(); + items.add(fso); + + // Show a dialog to allow the user make the compression mode choice + AlertDialog dialog = DialogHelper.createSingleChoiceDialog( + ctx, R.drawable.ic_holo_light_compress, R.string.compression_mode_title, + getSupportedCompressionModesLabels(ctx, items), + CompressionMode.AC_GZIP.ordinal(), + new DialogHelper.OnSelectChoiceListener() { + @Override + public void onSelectChoice(int choice) { + // Do the compression + compress( + ctx, + getCompressionModeFromUserChoice(choice), + items, + onSelectionListener, + onRequestRefreshListener); + } + + @Override + public void onNoSelectChoice() {/**NON BLOCK**/} + }); + dialog.show(); + } + + + /** + * Method that compresses some uncompressed files or folders + * + * @param ctx The current context + * @param mode The compression mode + * @param fsos The list of files to compress + * @param onSelectionListener The listener for obtain selection information (required) + * @param onRequestRefreshListener The listener for request a refresh (optional) + * @hide + */ + static void compress( + final Context ctx, final CompressionMode mode, final List fsos, + final OnSelectionListener onSelectionListener, + final OnRequestRefreshListener onRequestRefreshListener) { + + // The callable interface + final BackgroundCallable callable = new BackgroundCallable() { + // The current items + final Context mCtx = ctx; + final CompressionMode mMode = mode; + final List mFsos = fsos; + final OnRequestRefreshListener mOnRequestRefreshListener = onRequestRefreshListener; + + final Object mSync = new Object(); + Throwable mCause; + CompressExecutable cmd = null; + + final CompressListener mListener = + new CompressListener(); + private String mMsg; + private boolean mStarted = false; + + @Override + public int getDialogTitle() { + return R.string.waiting_dialog_compressing_title; + } + @Override + public int getDialogIcon() { + return R.drawable.ic_holo_light_operation; + } + @Override + public boolean isDialogCancelable() { + return true; } + + @Override + public Spanned requestProgress() { + // Initializing the dialog + if (!this.mStarted) { + String progress = + this.mCtx.getResources(). + getString( + R.string.waiting_dialog_analizing_msg); + return Html.fromHtml(progress); + } + + // Return the current operation + String msg = (this.mMsg == null) ? "" : this.mMsg; //$NON-NLS-1$ + String progress = + this.mCtx.getResources(). + getString( + R.string.waiting_dialog_compressing_msg, + msg); + return Html.fromHtml(progress); + } + + @Override + public void onSuccess() { + try { + if (this.cmd != null && this.cmd.isCancelable() && !this.cmd.isCanceled()) { + this.cmd.cancel(); + } + } catch (Exception e) {/**NON BLOCK**/} + + //Operation complete. Refresh + if (this.mOnRequestRefreshListener != null) { + // The reference is not the same, so refresh the complete navigation view + this.mOnRequestRefreshListener.onRequestRefresh(null); + } + if (this.cmd != null) { + showOperationSuccessMsg( + ctx, + R.string.msgs_extracting_success, + this.cmd.getOutCompressedFile()); + } else { + ActionsPolicy.showOperationSuccessMsg(ctx); + } + } + + @Override + public void doInBackground(Object... params) throws Throwable { + this.mCause = null; + this.mStarted = true; + + // This method expect to receive + // 1.- BackgroundAsyncTask + BackgroundAsyncTask task = (BackgroundAsyncTask)params[0]; + String out = null; + try { + // Archive or Archive-Compression + if (this.mMode.mArchive) { + // Convert the list to an array of full paths + String[] src = new String[this.mFsos.size()]; + int cc = this.mFsos.size(); + for (int i = 0; i < cc; i++) { + src[i] = this.mFsos.get(i).getFullPath(); + } + + // Use the current directory name for create the compressed file + String curDirName = + new File(onSelectionListener.onRequestCurrentDir()).getName(); + if (src.length == 1) { + // But only one file is passed, then used the name of unique file + curDirName = FileHelper.getName(this.mFsos.get(0).getName()); + } + String name = + String.format( + "%s.%s", curDirName, this.mMode.mExtension); //$NON-NLS-1$ + String newName = + FileHelper.createNonExistingName( + ctx, + onSelectionListener.onRequestCurrentItems(), + name, + R.string.create_new_compress_file_regexp); + String newNameAbs = + new File( + onSelectionListener.onRequestCurrentDir(), + newName).getAbsolutePath(); + + // Do the compression + this.cmd = + CommandHelper.compress( + ctx, + this.mMode, + newNameAbs, + src, + this.mListener, null); + + // Compression + } else { + // Only the first item from the list is valid. If there are more in the + // list, then discard them + String src = this.mFsos.get(0).getFullPath(); + + // Do the compression + this.cmd = + CommandHelper.compress( + ctx, + this.mMode, + src, + this.mListener, null); + } + out = this.cmd.getOutCompressedFile(); + + // Request paint the + this.mListener.mQueue.insert(out); + task.onRequestProgress(); + + // Don't use an active blocking because this suppose that all message + // will be processed by the UI. Instead, refresh with a delay and + // display the active file + while (!this.mListener.mEnd) { + // Sleep to don't saturate the UI thread + Thread.sleep(50L); + + List msgs = this.mListener.mQueue.peekAll(); + if (msgs.size() > 0) { + this.mMsg = msgs.get(msgs.size()-1); + task.onRequestProgress(); + } + } + + // Dialog is ended. Force the last redraw + List msgs = this.mListener.mQueue.peekAll(); + if (msgs.size() > 0) { + this.mMsg = msgs.get(msgs.size()-1); + task.onRequestProgress(); + } + + } catch (Exception e) { + // Need to be relaunched? + if (e instanceof RelaunchableException) { + OnRelaunchCommandResult rl = new OnRelaunchCommandResult() { + @Override + @SuppressWarnings("unqualified-field-access") + public void onSuccess() { + synchronized (mSync) { + mSync.notify(); + } + } + + @Override + @SuppressWarnings("unqualified-field-access") + public void onFailed(Throwable cause) { + mCause = cause; + synchronized (mSync) { + mSync.notify(); + } + } + @Override + @SuppressWarnings("unqualified-field-access") + public void onCanceled() { + synchronized (mSync) { + mSync.notify(); + } + } + }; + + // Translate the exception (and wait for the result) + ExceptionUtil.translateException(ctx, e, false, true, rl); + synchronized (this.mSync) { + this.mSync.wait(); + } + + // Persist the exception? + if (this.mCause != null) { + // The exception must be elevated + throw this.mCause; + } + + } else { + // The exception must be elevated + throw e; + } + } + + + // Any exception? + if (this.mListener.mCause != null) { + throw this.mListener.mCause; + } + + // Check that the operation was completed retrieving the extracted file or folder + boolean failed = true; + try { + CommandHelper.getFileInfo(ctx, out, false, null); + + // Failed. The file exists + failed = false; + + } catch (Throwable e) { + // Operation complete successfully + } + if (failed) { + throw new ExecutionException( + String.format( + "Failed to compress file(s) to: %s", out)); //$NON-NLS-1$ + } + } + }; + final BackgroundAsyncTask task = new BackgroundAsyncTask(ctx, callable); + + // Check if the output exists. When the mode is archive, this method generate a new + // name based in the current directory. When the mode is compressed then the name + // is the name of the file to compress without extension. In this case the name should + // be validate prior to compress + boolean askUser = false; + try { + if (!mode.mArchive) { + // Only the first item from the list is valid. If there are more in the + // list, then discard them + String src = fsos.get(0).getFullPath(); + CompressExecutable ucmd = + ExplorerApplication.getBackgroundConsole(). + getExecutableFactory().newCreator(). + createCompressExecutable(mode, src, null); + String dst = ucmd.getOutCompressedFile(); + FileSystemObject info = CommandHelper.getFileInfo(ctx, dst, null); + if (info != null) { + askUser = true; + } + } + } catch (Exception e) {/**NON BLOCK**/} + + // Ask the user because the destination file or folder exists + if (askUser) { + //Show a dialog asking the user for overwrite the files + AlertDialog dialog = + DialogHelper.createTwoButtonsQuestionDialog( + ctx, + android.R.string.cancel, + R.string.overwrite, + ctx.getString(R.string.msgs_overwrite_files), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface alertDialog, int which) { + // NEGATIVE (overwrite) POSITIVE (cancel) + if (which == DialogInterface.BUTTON_NEGATIVE) { + // Execute background task + task.execute(task); + } + } + }); + dialog.show(); + } else { + // Execute background task + task.execute(task); } } @@ -115,6 +495,7 @@ public final class CompressActionPolicy extends ActionsPolicy { final Object mSync = new Object(); Throwable mCause; + UncompressExecutable cmd; final CompressListener mListener = new CompressListener(); @@ -129,6 +510,10 @@ public final class CompressActionPolicy extends ActionsPolicy { public int getDialogIcon() { return R.drawable.ic_holo_light_operation; } + @Override + public boolean isDialogCancelable() { + return true; + } @Override public Spanned requestProgress() { @@ -137,7 +522,7 @@ public final class CompressActionPolicy extends ActionsPolicy { String progress = this.mCtx.getResources(). getString( - R.string.waiting_dialog_extracting_analizing_msg); + R.string.waiting_dialog_analizing_msg); return Html.fromHtml(progress); } @@ -153,12 +538,25 @@ public final class CompressActionPolicy extends ActionsPolicy { @Override public void onSuccess() { + try { + if (this.cmd != null && this.cmd.isCancelable() && !this.cmd.isCanceled()) { + this.cmd.cancel(); + } + } catch (Exception e) {/**NON BLOCK**/} + //Operation complete. Refresh if (this.mOnRequestRefreshListener != null) { // The reference is not the same, so refresh the complete navigation view this.mOnRequestRefreshListener.onRequestRefresh(null); } - ActionsPolicy.showOperationSuccessMsg(ctx); + if (this.cmd != null) { + showOperationSuccessMsg( + ctx, + R.string.msgs_extracting_success, + this.cmd.getOutUncompressedFile()); + } else { + ActionsPolicy.showOperationSuccessMsg(ctx); + } } @Override @@ -171,12 +569,13 @@ public final class CompressActionPolicy extends ActionsPolicy { BackgroundAsyncTask task = (BackgroundAsyncTask)params[0]; String out = null; try { - UncompressExecutable cmd = - CommandHelper.uncompress( - ctx, - this.mFso.getFullPath(), - this.mListener, null); - out = cmd.getOutUncompressedFile(); + this.cmd = + CommandHelper.uncompress( + ctx, + this.mFso.getFullPath(), + null, + this.mListener, null); + out = this.cmd.getOutUncompressedFile(); // Request paint the this.mListener.mQueue.insert(out); @@ -283,7 +682,7 @@ public final class CompressActionPolicy extends ActionsPolicy { UncompressExecutable ucmd = ExplorerApplication.getBackgroundConsole(). getExecutableFactory().newCreator(). - createUncompressExecutable(fso.getFullPath(), null); + createUncompressExecutable(fso.getFullPath(), null, null); String dst = ucmd.getOutUncompressedFile(); FileSystemObject info = CommandHelper.getFileInfo(ctx, dst, null); if (info != null) { @@ -334,7 +733,7 @@ public final class CompressActionPolicy extends ActionsPolicy { // make the extraction String ext = FileHelper.getExtension(fso); if (ConsoleBuilder.isPrivileged() && ext.compareTo("zip") == 0) { //$NON-NLS-1$ - AlertDialog dialog =DialogHelper.createYesNoDialog( + AlertDialog dialog = DialogHelper.createYesNoDialog( ctx, R.string.security_warning_extract, new DialogInterface.OnClickListener() { @Override @@ -351,4 +750,59 @@ public final class CompressActionPolicy extends ActionsPolicy { task.execute(task); } } + + /** + * Method that returns the supported compression modes + * + * @param ctx The current context + * @param fsos The list of file system objects to compress + * @return String[] An array with the compression mode labels + */ + private static String[] getSupportedCompressionModesLabels( + Context ctx, List fsos) { + String[] labels = ctx.getResources().getStringArray(R.array.compression_modes_labels); + if (fsos.size() > 1 || (fsos.size() == 1 && FileHelper.isDirectory(fsos.get(0)))) { + // If more that a file is requested, compression is not available + // The same applies if the unique item is a folder + ArrayList validLabels = new ArrayList(); + CompressionMode[] values = CompressionMode.values(); + int cc = values.length; + for (int i = 0; i < cc; i++) { + if (values[i].mArchive) { + validLabels.add(labels[i]); + } + } + labels = validLabels.toArray(new String[]{}); + } + return labels; + } + + /** + * Method that returns the compression mode from the user choice + * + * @param choice The choice of the user + * @return CompressionMode The compression mode + */ + static CompressionMode getCompressionModeFromUserChoice(int choice) { + CompressionMode[] values = CompressionMode.values(); + int cc = values.length; + for (int i = 0; i < cc; i++) { + if (values[i].ordinal() == choice) { + return values[i]; + } + } + return null; + } + + /** + * Method that shows a message when the operation is complete successfully + * + * @param ctx The current context + * @param res The resource identifier + * @param dst The destination output + * @hide + */ + protected static void showOperationSuccessMsg(Context ctx, int res, String dst) { + DialogHelper.showToast(ctx, ctx.getString(res, dst), Toast.LENGTH_LONG); + } } \ No newline at end of file diff --git a/src/com/cyanogenmod/explorer/ui/policy/CopyMoveActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/CopyMoveActionPolicy.java index 3a49c1f1..974aa162 100644 --- a/src/com/cyanogenmod/explorer/ui/policy/CopyMoveActionPolicy.java +++ b/src/com/cyanogenmod/explorer/ui/policy/CopyMoveActionPolicy.java @@ -41,7 +41,7 @@ import java.util.List; * A class with the convenience methods for resolve copy/move related actions */ public final class CopyMoveActionPolicy extends ActionsPolicy { - + /** * @hide */ @@ -51,7 +51,7 @@ public final class CopyMoveActionPolicy extends ActionsPolicy { RENAME, CREATE_COPY, } - + /** * A class that holds a relationship between a source {@link File} and @@ -132,7 +132,9 @@ public final class CopyMoveActionPolicy extends ActionsPolicy { // Create a non-existing name List curFiles = onSelectionListener.onRequestCurrentItems(); - String newName = FileHelper.createNonExistingName(ctx, curFiles, fso); + String newName = + FileHelper.createNonExistingName( + ctx, curFiles, fso.getName(), R.string.create_copy_regexp); final File dst = new File(fso.getParent(), newName); File src = new File(fso.getFullPath()); @@ -221,7 +223,8 @@ public final class CopyMoveActionPolicy extends ActionsPolicy { // 2.- All the destination files must have the same parent and it must be currentDirectory, // and not be null final String currentDirectory = onSelectionListener.onRequestCurrentDir(); - for (int i = 0; i < files.size(); i++) { + int cc = files.size(); + for (int i = 0; i < cc; i++) { LinkedResource linkedRes = files.get(i); if (linkedRes.mSrc == null || linkedRes.mDst == null) { AlertDialog dialog = @@ -267,6 +270,10 @@ public final class CopyMoveActionPolicy extends ActionsPolicy { public int getDialogIcon() { return R.drawable.ic_holo_light_operation; } + @Override + public boolean isDialogCancelable() { + return false; + } @Override public Spanned requestProgress() { @@ -304,7 +311,8 @@ public final class CopyMoveActionPolicy extends ActionsPolicy { // 1.- BackgroundAsyncTask BackgroundAsyncTask task = (BackgroundAsyncTask)params[0]; - for (int i = 0; i < this.mFiles.size(); i++) { + int cc2 = this.mFiles.size(); + for (int i = 0; i < cc2; i++) { File src = this.mFiles.get(i).mSrc; File dst = this.mFiles.get(i).mDst; @@ -444,8 +452,10 @@ public final class CopyMoveActionPolicy extends ActionsPolicy { private static boolean isOverwriteNeeded( List files, List currentFiles) { boolean askUser = false; - for (int i = 0; i < currentFiles.size(); i++) { - for (int j = 0; j < files.size(); j++) { + int cc = currentFiles.size(); + for (int i = 0; i < cc; i++) { + int cc2 = files.size(); + for (int j = 0; j < cc2; j++) { FileSystemObject dst1 = currentFiles.get(i); File dst2 = files.get(j).mDst; @@ -479,7 +489,8 @@ public final class CopyMoveActionPolicy extends ActionsPolicy { */ private static boolean checkMoveConsistency( Context ctx, List files, String currentDirectory) { - for (int i = 0; i < files.size(); i++) { + int cc = files.size(); + for (int i = 0; i < cc; i++) { LinkedResource linkRes = files.get(i); String src = linkRes.mSrc.getAbsolutePath(); String dst = linkRes.mDst.getAbsolutePath(); diff --git a/src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java index d66cb956..adf94dd3 100644 --- a/src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java +++ b/src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java @@ -145,6 +145,10 @@ public final class DeleteActionPolicy extends ActionsPolicy { public int getDialogIcon() { return R.drawable.ic_holo_light_operation; } + @Override + public boolean isDialogCancelable() { + return false; + } @Override public Spanned requestProgress() { @@ -177,7 +181,8 @@ public final class DeleteActionPolicy extends ActionsPolicy { // 1.- BackgroundAsyncTask BackgroundAsyncTask task = (BackgroundAsyncTask)params[0]; - for (int i = 0; i < this.mFiles.size(); i++) { + int cc = this.mFiles.size(); + for (int i = 0; i < cc; i++) { FileSystemObject fso = this.mFiles.get(i); doOperation(this.mCtx, fso); @@ -293,7 +298,8 @@ public final class DeleteActionPolicy extends ActionsPolicy { */ private static boolean checkRemoveConsistency( Context ctx, List files, String currentDirectory) { - for (int i = 0; i < files.size(); i++) { + int cc = files.size(); + for (int i = 0; i < cc; i++) { FileSystemObject fso = files.get(i); // 1.- Current directory can't be deleted diff --git a/src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java index 81680153..9e127598 100644 --- a/src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java +++ b/src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java @@ -23,6 +23,7 @@ import android.widget.Toast; import com.cyanogenmod.explorer.listeners.OnRequestRefreshListener; import com.cyanogenmod.explorer.model.FileSystemObject; import com.cyanogenmod.explorer.ui.dialogs.FsoPropertiesDialog; +import com.cyanogenmod.explorer.util.DialogHelper; /** * A class with the convenience methods for resolve the display of info actions @@ -37,7 +38,7 @@ public final class InfoActionPolicy extends ActionsPolicy { */ public static void showContentDescription(final Context ctx, final FileSystemObject fso) { String contentDescription = fso.getFullPath(); - Toast.makeText(ctx, contentDescription, Toast.LENGTH_SHORT).show(); + DialogHelper.showToast(ctx, contentDescription, Toast.LENGTH_SHORT); } /** diff --git a/src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java index 1d43a8c1..b9b2cc86 100644 --- a/src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java +++ b/src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java @@ -26,6 +26,7 @@ import android.widget.Toast; import com.cyanogenmod.explorer.R; import com.cyanogenmod.explorer.model.FileSystemObject; import com.cyanogenmod.explorer.ui.dialogs.AssociationsDialog; +import com.cyanogenmod.explorer.util.DialogHelper; import com.cyanogenmod.explorer.util.ExceptionUtil; import com.cyanogenmod.explorer.util.MimeTypeHelper; @@ -140,7 +141,7 @@ public final class IntentsActionPolicy extends ActionsPolicy { // No registered application if (info.size() == 0) { - Toast.makeText(ctx, R.string.msgs_not_registered_app, Toast.LENGTH_SHORT).show(); + DialogHelper.showToast(ctx, R.string.msgs_not_registered_app, Toast.LENGTH_SHORT); return; } diff --git a/src/com/cyanogenmod/explorer/util/CommandHelper.java b/src/com/cyanogenmod/explorer/util/CommandHelper.java index c094f185..5b194088 100644 --- a/src/com/cyanogenmod/explorer/util/CommandHelper.java +++ b/src/com/cyanogenmod/explorer/util/CommandHelper.java @@ -53,7 +53,6 @@ import com.cyanogenmod.explorer.commands.SyncResultExecutable; import com.cyanogenmod.explorer.commands.UncompressExecutable; import com.cyanogenmod.explorer.commands.WritableExecutable; import com.cyanogenmod.explorer.commands.WriteExecutable; -import com.cyanogenmod.explorer.commands.shell.CompressCommand.CompressionMode; import com.cyanogenmod.explorer.commands.shell.InvalidCommandDefinitionException; import com.cyanogenmod.explorer.console.CommandNotFoundException; import com.cyanogenmod.explorer.console.Console; @@ -74,6 +73,7 @@ import com.cyanogenmod.explorer.model.Permissions; import com.cyanogenmod.explorer.model.Query; import com.cyanogenmod.explorer.model.SearchResult; import com.cyanogenmod.explorer.model.User; +import com.cyanogenmod.explorer.preferences.CompressionMode; import java.io.FileNotFoundException; import java.io.IOException; @@ -1296,6 +1296,8 @@ public final class CommandHelper { * * @param context The current context (needed if console == null) * @param src The file to compress + * @param dst The destination file of folder (if null this method resolve with the best + * fit based on the src) * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console @@ -1313,7 +1315,7 @@ public final class CommandHelper { * @see CompressExecutable */ public static UncompressExecutable uncompress( - Context context, String src, + Context context, String src, String dst, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, @@ -1323,7 +1325,7 @@ public final class CommandHelper { UncompressExecutable executable1 = c.getExecutableFactory().newCreator(). - createUncompressExecutable(src, asyncResultListener); + createUncompressExecutable(src, dst, asyncResultListener); // Prior to write to disk the data, ensure that can write to the disk using // createFile or createFolder method diff --git a/src/com/cyanogenmod/explorer/util/DialogHelper.java b/src/com/cyanogenmod/explorer/util/DialogHelper.java index da7c19e2..8375c1d9 100644 --- a/src/com/cyanogenmod/explorer/util/DialogHelper.java +++ b/src/com/cyanogenmod/explorer/util/DialogHelper.java @@ -22,19 +22,44 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.AbsListView; +import android.widget.AdapterView; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ListPopupWindow; +import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.cyanogenmod.explorer.R; +import com.cyanogenmod.explorer.adapters.CheckableListAdapter; + +import java.util.ArrayList; +import java.util.List; /** * A helper class with useful methods for deal with dialogs. */ public final class DialogHelper { + /** + * An interface to listen the selection make for the user. + */ + public interface OnSelectChoiceListener { + /** + * Method invoked when the user select an option + * + * @param choice The selected option + */ + public void onSelectChoice(int choice); + /** + * Method invoked when the user not select any option + */ + public void onNoSelectChoice(); + } + /** * Constructor of DialogHelper. */ @@ -127,6 +152,72 @@ public final class DialogHelper { return builder.create(); } + /** + * Method that creates a new {@link AlertDialog} for choice between single options. + * + * @param context The current context + * @param icon The icon resource + * @param title The resource identifier of the title of the alert dialog + * @param options An array with the options + * @param defOption The default option + * @param onSelectChoiceListener The listener for user choice + * @return AlertDialog The alert dialog reference + */ + public static AlertDialog createSingleChoiceDialog( + Context context, int icon, int title, + String[] options, int defOption, + final OnSelectChoiceListener onSelectChoiceListener) { + //Create the alert dialog + final StringBuffer item = new StringBuffer().append(defOption); + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setCustomTitle(createTitle(context, icon, context.getString(title))); + + // Create the adapter + List items = + new ArrayList(options.length); + int cc = options.length; + for (int i = 0; i < cc; i++) { + boolean checked = (i == defOption); + items.add(new CheckableListAdapter.CheckableItem(options[i], true, checked)); + } + final CheckableListAdapter adapter = new CheckableListAdapter(context, items); + + // Create the list view and set as view + final ListView listView = new ListView(context); + LinearLayout.LayoutParams params = + new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + listView.setLayoutParams(params); + listView.setAdapter(adapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + item.delete(0, item.length()); + item.append(position); + adapter.setSelectedItem(position); + } + }); + adapter.setSelectedItem(defOption); + listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); + builder.setView(listView); + + builder.setNegativeButton(context.getString(R.string.cancel), new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onSelectChoiceListener.onNoSelectChoice(); + dialog.cancel(); + } + }); + builder.setPositiveButton(context.getString(R.string.ok), new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onSelectChoiceListener.onSelectChoice(Integer.parseInt(item.toString())); + dialog.dismiss(); + } + }); + return builder.create(); + } + /** * Method that creates a new YES/NO {@link AlertDialog}. * @@ -380,7 +471,7 @@ public final class DialogHelper { * @param duration How long to display the message. */ public static void showToast(Context context, int msgResourceId, int duration) { - Toast.makeText(context, msgResourceId, duration).show(); + showToast(context, context.getString(msgResourceId), duration); } } diff --git a/src/com/cyanogenmod/explorer/util/FileHelper.java b/src/com/cyanogenmod/explorer/util/FileHelper.java index a377f9fc..dcedcc51 100644 --- a/src/com/cyanogenmod/explorer/util/FileHelper.java +++ b/src/com/cyanogenmod/explorer/util/FileHelper.java @@ -258,7 +258,8 @@ public final class FileHelper { } // Exceptions to the general extraction method - for (int i = 0; i < COMPRESSED_TAR.length; i++) { + int cc = COMPRESSED_TAR.length; + for (int i = 0; i < cc; i++) { if (name.endsWith("." + COMPRESSED_TAR[i])) { //$NON-NLS-1$ return COMPRESSED_TAR[i]; } @@ -468,7 +469,8 @@ public final class FileHelper { ExplorerSettings showSymlinksPref = ExplorerSettings.SETTINGS_SHOW_SYMLINKS; //Remove all unnecessary files (no required by the user) - for (int i = files.size() - 1; i >= 0; i--) { + int cc = files.size(); + for (int i = cc - 1; i >= 0; i--) { FileSystemObject file = files.get(i); //Hidden files @@ -652,13 +654,16 @@ public final class FileHelper { * * @param ctx The current context * @param files The list of files of the current directory - * @param fso The file system object + * @param attemptedName The attempted name + * @param regexp The resource of the regular expression to create the new name * @return String The new non-existing name */ public static String createNonExistingName( - final Context ctx, final List files, final FileSystemObject fso) { + final Context ctx, final List files, + final String attemptedName, int regexp) { // Find a non-exiting name - String newName = fso.getName(); + String newName = attemptedName; + if (!isNameExists(files, newName)) return newName; do { String name = FileHelper.getName(newName); String ext = FileHelper.getExtension(newName); @@ -667,7 +672,7 @@ public final class FileHelper { } else { ext = String.format(".%s", ext); //$NON-NLS-1$ } - newName = ctx.getString(R.string.create_copy_regexp, name, ext); + newName = ctx.getString(regexp, name, ext); } while (isNameExists(files, newName)); return newName; } @@ -715,11 +720,44 @@ public final class FileHelper { return false; } String ext = getExtension(fso); - for (int i = 0; i < VALID.length; i++) { + int cc = VALID.length; + for (int i = 0; i < cc; i++) { if (VALID[i].compareTo(ext) == 0) { return true; } } return false; } + + /** + * Method that converts an absolute path to a relative path + * + * @param path The absolute path to convert + * @param relativeTo The absolute path from which make path relative to (a folder) + * @return String The relative path + */ + public static String toRelativePath(String path, String relativeTo) { + // Normalize the paths + File f1 = new File(path); + File f2 = new File(relativeTo); + String s1 = f1.getAbsolutePath(); + String s2 = f2.getAbsolutePath(); + if (!s2.endsWith(File.separator)) { + s2 = s2 + File.separator; + } + + // If s2 contains s1 then the relative is replace of the start of the path + if (s1.startsWith(s2)) { + return s1.substring(s2.length()); + } + + StringBuffer relative = new StringBuffer(); + do { + File f3 = new File(s2); + relative.append(String.format("..%s", File.separator)); //$NON-NLS-1$ + s2 = f3.getParent() + File.separator; + } while (!s1.startsWith(s2) && !s1.startsWith(new File(s2).getAbsolutePath())); + s2 = new File(s2).getAbsolutePath(); + return relative.toString() + s1.substring(s2.length()); + } } diff --git a/src/com/cyanogenmod/explorer/util/StorageHelper.java b/src/com/cyanogenmod/explorer/util/StorageHelper.java index cc5321ee..99afcdef 100644 --- a/src/com/cyanogenmod/explorer/util/StorageHelper.java +++ b/src/com/cyanogenmod/explorer/util/StorageHelper.java @@ -106,7 +106,8 @@ public final class StorageHelper { public static boolean isPathInStorageVolume(String path) { StorageVolume[] volumes = getStorageVolumes(ExplorerApplication.getInstance().getApplicationContext()); - for (int i = 0; i < volumes.length; i++) { + int cc = volumes.length; + for (int i = 0; i < cc; i++) { StorageVolume vol = volumes[i]; if (path.startsWith(vol.getPath())) { return true; diff --git a/tests/src/com/cyanogenmod/explorer/commands/shell/CompressCommandTest.java b/tests/src/com/cyanogenmod/explorer/commands/shell/CompressCommandTest.java index 12d093c6..5dcedc54 100644 --- a/tests/src/com/cyanogenmod/explorer/commands/shell/CompressCommandTest.java +++ b/tests/src/com/cyanogenmod/explorer/commands/shell/CompressCommandTest.java @@ -22,7 +22,7 @@ import android.util.Log; import com.cyanogenmod.explorer.commands.AsyncResultListener; import com.cyanogenmod.explorer.commands.CompressExecutable; -import com.cyanogenmod.explorer.commands.shell.CompressCommand.CompressionMode; +import com.cyanogenmod.explorer.preferences.CompressionMode; import com.cyanogenmod.explorer.util.CommandHelper; /** @@ -81,7 +81,7 @@ public class CompressCommandTest extends AbstractConsoleTest { */ @LargeTest public void testArchiveTAR() throws Exception { - testArchiveAndCompress(CompressionMode.NONE, TAR_OUTFILE); + testArchiveAndCompress(CompressionMode.A_TAR, TAR_OUTFILE); } /** @@ -91,7 +91,7 @@ public class CompressCommandTest extends AbstractConsoleTest { */ @LargeTest public void testArchiveCompressGZIP() throws Exception { - testArchiveAndCompress(CompressionMode.GZIP, TAR_GZIP_OUTFILE); + testArchiveAndCompress(CompressionMode.AC_GZIP, TAR_GZIP_OUTFILE); } /** @@ -101,7 +101,7 @@ public class CompressCommandTest extends AbstractConsoleTest { */ @LargeTest public void testArchiveCompressBZIP() throws Exception { - testArchiveAndCompress(CompressionMode.BZIP, TAR_BZIP_OUTFILE); + testArchiveAndCompress(CompressionMode.AC_BZIP, TAR_BZIP_OUTFILE); } /** @@ -111,7 +111,7 @@ public class CompressCommandTest extends AbstractConsoleTest { */ @LargeTest public void testCompressGZIP() throws Exception { - testCompress(CompressionMode.GZIP); + testCompress(CompressionMode.C_GZIP); } /** @@ -121,7 +121,7 @@ public class CompressCommandTest extends AbstractConsoleTest { */ @LargeTest public void testCompressBZIP() throws Exception { - testCompress(CompressionMode.BZIP); + testCompress(CompressionMode.C_BZIP); } /** diff --git a/tests/src/com/cyanogenmod/explorer/commands/shell/UncompressCommandTest.java b/tests/src/com/cyanogenmod/explorer/commands/shell/UncompressCommandTest.java index adcf06eb..3517718c 100644 --- a/tests/src/com/cyanogenmod/explorer/commands/shell/UncompressCommandTest.java +++ b/tests/src/com/cyanogenmod/explorer/commands/shell/UncompressCommandTest.java @@ -183,7 +183,7 @@ public class UncompressCommandTest extends AbstractConsoleTest { this.mNormalEnd = false; cmd = CommandHelper.uncompress( - getContext(), src, new AsyncResultListener() { + getContext(), src, null, new AsyncResultListener() { public void onAsyncStart() { /**NON BLOCK**/ } -- cgit v1.2.3