OSDN Git Service

New fso and global actions "Compress" and "Compress selection" + CleanUp
authorjruesga <jorge@ruesga.com>
Fri, 19 Oct 2012 23:38:23 +0000 (01:38 +0200)
committerjruesga <jorge@ruesga.com>
Fri, 19 Oct 2012 23:38:23 +0000 (01:38 +0200)
33 files changed:
res/layout/option_list_item.xml
res/menu/actions.xml
res/values/arrays.xml
res/values/strings.xml
res/xml/command_list.xml
src/com/cyanogenmod/explorer/activities/NavigationActivity.java
src/com/cyanogenmod/explorer/activities/SearchActivity.java
src/com/cyanogenmod/explorer/activities/preferences/SettingsPreferences.java
src/com/cyanogenmod/explorer/adapters/CheckableListAdapter.java
src/com/cyanogenmod/explorer/adapters/SimpleMenuListAdapter.java
src/com/cyanogenmod/explorer/adapters/TwoColumnsMenuListAdapter.java
src/com/cyanogenmod/explorer/commands/ExecutableCreator.java
src/com/cyanogenmod/explorer/commands/shell/CompressCommand.java
src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java
src/com/cyanogenmod/explorer/commands/shell/UncompressCommand.java
src/com/cyanogenmod/explorer/preferences/CompressionMode.java [new file with mode: 0644]
src/com/cyanogenmod/explorer/preferences/UncompressionMode.java [new file with mode: 0644]
src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java
src/com/cyanogenmod/explorer/ui/dialogs/AssociationsDialog.java
src/com/cyanogenmod/explorer/ui/dialogs/ChooseConsoleDialog.java
src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java
src/com/cyanogenmod/explorer/ui/policy/BookmarksActionPolicy.java
src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java
src/com/cyanogenmod/explorer/ui/policy/CopyMoveActionPolicy.java
src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java
src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java
src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java
src/com/cyanogenmod/explorer/util/CommandHelper.java
src/com/cyanogenmod/explorer/util/DialogHelper.java
src/com/cyanogenmod/explorer/util/FileHelper.java
src/com/cyanogenmod/explorer/util/StorageHelper.java
tests/src/com/cyanogenmod/explorer/commands/shell/CompressCommandTest.java
tests/src/com/cyanogenmod/explorer/commands/shell/UncompressCommandTest.java

index 66f6ce6..90cf16e 100644 (file)
@@ -16,7 +16,7 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="wrap_content"
   android:layout_height="@dimen/default_row_height"
-  android:background="@drawable/holo_list_selector_deseleted" >
+  android:background="@drawable/holo_selector" >
 
   <ImageView
     android:id="@+id/option_list_item_check"
index a8d9d19..ace7698 100644 (file)
       android:showAsAction="ifRoom"
       android:title="@string/actions_menu_delete_selection"/>
     <item
+      android:id="@+id/mnu_actions_compress_selection"
+      android:showAsAction="ifRoom"
+      android:title="@string/actions_menu_compress_selection"/>
+    <item
       android:id="@+id/mnu_actions_create_link_global"
       android:showAsAction="ifRoom"
       android:title="@string/actions_menu_create_link"/>
       android:showAsAction="ifRoom"
       android:title="@string/actions_menu_rename"/>
     <item
+      android:id="@+id/mnu_actions_compress"
+      android:showAsAction="ifRoom"
+      android:title="@string/actions_menu_compress"/>
+    <item
       android:id="@+id/mnu_actions_extract"
       android:showAsAction="ifRoom"
       android:title="@string/actions_menu_extract"/>
index f11b0a0..97366f6 100644 (file)
     <item>2</item>
   </string-array>
 
+  <!-- Compression modes -->
+  <!-- Note: Archive modes must be before that compression modes -->
+  <string-array name="compression_modes_labels" translable="false">
+    <item>@string/compression_mode_tar</item>
+    <item>@string/compression_mode_tar_gzip</item>
+    <item>@string/compression_mode_tar_gzip2</item>
+    <item>@string/compression_mode_tar_bzip</item>
+    <item>@string/compression_mode_gzip</item>
+    <item>@string/compression_mode_bzip</item>
+  </string-array>
+
 </resources>
\ No newline at end of file
index bf37f50..e416338 100644 (file)
   <!-- Create copy regexp -->
   <string name="create_copy_regexp">
     <xliff:g id="name">%1$s</xliff:g> - copy<xliff:g id="extension">%2$s</xliff:g></string>
+  <!-- New compressed file -->
+  <string name="create_new_compress_file_regexp">
+    <xliff:g id="name">%1$s</xliff:g> - new<xliff:g id="extension">%2$s</xliff:g></string>
 
   <!-- Waiting dialog * Performing operation message -->
   <string name="waiting_dialog_msg">Performing operation&#8230;</string>
   <!-- Waiting dialog * Extracting message -->
   <string name="waiting_dialog_extracting_msg">
     <![CDATA[<b>File</b>]]> <xliff:g id="file">%1$s</xliff:g></string>
+  <!-- Waiting dialog * Extracting title -->
+  <string name="waiting_dialog_compressing_title">Compressing&#8230;</string>
+  <!-- Waiting dialog * Extracting message -->
+  <string name="waiting_dialog_compressing_msg">
+    <![CDATA[<b>File</b>]]> <xliff:g id="file">%1$s</xliff:g></string>
   <!-- Waiting dialog * Initializing the dialog -->
-  <string name="waiting_dialog_extracting_analizing_msg">
+  <string name="waiting_dialog_analizing_msg">
     <![CDATA[<b>Analizing&#8230;</b>]]></string>
+  <!-- Extracting * Success message -->
+  <string name="msgs_extracting_success">
+    The extracting operation was completed successfully. The data was extracted to
+    <xliff:g id="destination">%1$s</xliff:g></string>
+  <!-- Compressing * Success message -->
+  <string name="msgs_compressing_success">
+    The compressing operation was completed successfully. The data was compressed to
+    <xliff:g id="destination">%1$s</xliff:g></string>
 
   <!-- Actions Dialog * Title -->
   <string name="actions_dialog_title">Actions</string>
   <string name="actions_menu_move_selection">Move selection</string>
   <!-- Actions Dialog * Menu * Delete selection -->
   <string name="actions_menu_delete_selection">Delete selection</string>
+  <!-- Actions Dialog * Menu * Compress selection -->
+  <string name="actions_menu_compress_selection">Compress selection</string>
   <!-- Actions Dialog * Menu * Create link -->
   <string name="actions_menu_create_link">Create link</string>
   <!-- Actions Dialog * Menu * Add to bookmarks the current folder -->
   <string name="actions_menu_execute">Execute</string>
   <!-- Actions Dialog * Menu * Send -->
   <string name="actions_menu_send">Send</string>
+  <!-- Actions Dialog * Menu * Compress -->
+  <string name="actions_menu_compress">Compress</string>
   <!-- Actions Dialog * Menu * Extract -->
   <string name="actions_menu_extract">Extract</string>
   <!-- Actions Dialog * Menu * Share -->
   <string name="category_video">VIDEO</string>
   <string name="category_security">SECURITY</string>
 
+  <!-- Compression modes dialog title -->
+  <string name="compression_mode_title">Compression mode</string>
+  <!-- Compression modes -->
+  <string name="compression_mode_tar" translatable="false">Tar (tar)</string>
+  <string name="compression_mode_tar_gzip" translatable="false">Tar/Gzip (tar.gz)</string>
+  <string name="compression_mode_tar_gzip2" translatable="false">Tar/Gzip (tgz)</string>
+  <string name="compression_mode_tar_bzip" translatable="false">Tar/Bzip (tar.bz2)</string>
+  <string name="compression_mode_gzip" translatable="false">Gzip (gz)</string>
+  <string name="compression_mode_bzip" translatable="false">Bzip (bz2)</string>
+
   <!-- Preferences title -->
   <string name="pref">Settings</string>
   <!-- Preferences * General title -->
index b2959c3..9d339c6 100644 (file)
@@ -93,7 +93,7 @@
   <command commandId="terminate" commandPath="/system/bin/kill" commandArgs="%1$s" />
 
   <!-- Compress -->
-  <command commandId="compress" commandPath="/system/xbin/tar" commandArgs="-%1$scvf %2$s [@]" />
+  <command commandId="tar" commandPath="/system/xbin/tar" commandArgs="-%1$scvf %2$s [@]" />
   <command commandId="gzip" commandPath="/system/bin/gzip" commandArgs="%1$s" />
   <command commandId="bzip" commandPath="/system/xbin/bzip2" commandArgs="-f %1$s" />
 
index 25c8f9e..8932f42 100644 (file)
@@ -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();
index 20b8d93..9e1ece7 100644 (file)
@@ -695,7 +695,8 @@ public class SearchActivity extends Activity
     @SuppressWarnings("static-method")
     private List<String> filterQuery(List<String> original) {
         List<String> dst = new ArrayList<String>(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);
index 26f920c..cdc60f2 100644 (file)
@@ -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;
             }
index cc43240..b5435c8 100644 (file)
@@ -136,4 +136,17 @@ public class CheckableListAdapter extends ArrayAdapter<CheckableListAdapter.Chec
         return v;
     }
 
+    /**
+     * Method that sets the selected item
+     *
+     * @param position The position of the selected item
+     */
+    public void setSelectedItem(int position) {
+        int cc = getCount();
+        for (int i = 0; i < cc; i++) {
+            getItem(i).mChecked = (i == position);
+            notifyDataSetChanged();
+        }
+    }
+
 }
index 2a01550..159846d 100644 (file)
@@ -65,7 +65,8 @@ public class SimpleMenuListAdapter extends BaseAdapter {
         this(context, menuResourceId);
 
         //Remove all item menus that no belongs to the group
-        for (int i = this.mMenu.size() - 1; i >= 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());
index 75105cd..ad595a9 100644 (file)
@@ -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());
index e54c7d5..ce377ee 100644 (file)
 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;
 
 }
index 9025503..20e29fb 100644 (file)
@@ -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 <code>CompressionMode</code>
+         * Constructor of <code>Mode</code>
          *
          * @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;
+    }
 }
index 3bf0587..10f2ae1 100644 (file)
@@ -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$
         }
index c7c4c2b..a16ea02 100644 (file)
@@ -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 <code>UncompressionMode</code>
+         * Constructor of <code>Mode</code>
          *
          * @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
      * </ul>
      *
      * @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. <code>null</code> if no mode found
+     * @return Mode The uncompression mode. <code>null</code> 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 (file)
index 0000000..a68ece1
--- /dev/null
@@ -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 <code>CompressionMode</code>
+     *
+     * @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 (file)
index 0000000..2d99fab
--- /dev/null
@@ -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 <code>UncompressionMode</code>
+     *
+     * @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;
+    }
+}
index 2118b03..f280ac3 100644 (file)
@@ -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<FileSystemObject> items, FileSystemObject directory) {
         List<LinkedResource> resources =
                 new ArrayList<LinkedResource>(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());
index 082a92c..08dec3b 100644 (file)
@@ -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);
                     }
                 }
             }
index 2343af1..952f334 100644 (file)
@@ -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;
index 21cfb4b..77eb631 100644 (file)
@@ -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;
 
 
@@ -51,6 +52,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
          *
          * @return Spanned The text to show in the progress
@@ -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();
@@ -139,6 +154,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
index 6afe0df..a925341 100644 (file)
@@ -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) {
index b41ed3d..bcae907 100644 (file)
@@ -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<String> 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<String>(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<FileSystemObject> 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<FileSystemObject> items = new ArrayList<FileSystemObject>();
+        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<FileSystemObject> 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<FileSystemObject> 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<String> 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<String> 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<FileSystemObject> 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<String> validLabels = new ArrayList<String>();
+            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
index 3a49c1f..974aa16 100644 (file)
@@ -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<FileSystemObject> 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<LinkedResource> files, List<FileSystemObject> 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<LinkedResource> 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();
index d66cb95..adf94dd 100644 (file)
@@ -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<FileSystemObject> 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
index 8168015..9e12759 100644 (file)
@@ -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);
     }
 
     /**
index 1d43a8c..b9b2cc8 100644 (file)
@@ -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;
         }
 
index c094f18..5b19408 100644 (file)
@@ -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.
      * <code>null</code> 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
index da7c19e..8375c1d 100644 (file)
@@ -22,13 +22,22 @@ 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.
@@ -36,6 +45,22 @@ import com.cyanogenmod.explorer.R;
 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 <code>DialogHelper</code>.
      */
     private DialogHelper() {
@@ -128,6 +153,72 @@ public final class DialogHelper {
     }
 
     /**
+     * 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<CheckableListAdapter.CheckableItem> items =
+                new ArrayList<CheckableListAdapter.CheckableItem>(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}.
      *
      * @param context The current context
@@ -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);
     }
 
 }
index a377f9f..dcedcc5 100644 (file)
@@ -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<FileSystemObject> files, final FileSystemObject fso) {
+            final Context ctx, final List<FileSystemObject> 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());
+    }
 }
index cc5321e..99afcde 100644 (file)
@@ -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;
index 12d093c..5dcedc5 100644 (file)
@@ -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);
     }
 
     /**
index adcf06e..3517718 100644 (file)
@@ -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**/
                         }