aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjruesga <jorge@ruesga.com>2012-10-19 18:24:02 +0200
committerjruesga <jorge@ruesga.com>2012-10-19 18:24:02 +0200
commitf4fbedb64c6349d9dff731c3dd5ad14f0b5f6c3c (patch)
tree4743219ed1c3c7e9ce73f532c9980ea3d0daa6ed /src
parent54e70eae6bdedc0f11fbd36e576162b8ba1e63b0 (diff)
Reorganize ActionsPolicy to make it clearly
Diffstat (limited to 'src')
-rw-r--r--src/com/cyanogenmod/explorer/activities/SearchActivity.java11
-rw-r--r--src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java66
-rw-r--r--src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java4
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java1559
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/BookmarksActionPolicy.java65
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java354
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/CopyMoveActionPolicy.java509
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java311
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/ExecutionActionPolicy.java111
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java70
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java167
-rw-r--r--src/com/cyanogenmod/explorer/ui/policy/NewActionPolicy.java234
-rw-r--r--src/com/cyanogenmod/explorer/ui/widgets/NavigationView.java13
13 files changed, 1885 insertions, 1589 deletions
diff --git a/src/com/cyanogenmod/explorer/activities/SearchActivity.java b/src/com/cyanogenmod/explorer/activities/SearchActivity.java
index de653a4..20b8d93 100644
--- a/src/com/cyanogenmod/explorer/activities/SearchActivity.java
+++ b/src/com/cyanogenmod/explorer/activities/SearchActivity.java
@@ -68,7 +68,8 @@ import com.cyanogenmod.explorer.providers.RecentSearchesContentProvider;
import com.cyanogenmod.explorer.tasks.SearchResultDrawingAsyncTask;
import com.cyanogenmod.explorer.ui.dialogs.ActionsDialog;
import com.cyanogenmod.explorer.ui.dialogs.MessageProgressDialog;
-import com.cyanogenmod.explorer.ui.policy.ActionsPolicy;
+import com.cyanogenmod.explorer.ui.policy.InfoActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.IntentsActionPolicy;
import com.cyanogenmod.explorer.ui.widgets.ButtonItem;
import com.cyanogenmod.explorer.util.CommandHelper;
import com.cyanogenmod.explorer.util.DialogHelper;
@@ -822,19 +823,19 @@ public class SearchActivity extends Activity
// Show content description
if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.SHOW_CONTENT_DESCRIPTION) == 0) {
- ActionsPolicy.showContentDescription(this, fso);
+ InfoActionPolicy.showContentDescription(this, fso);
}
// Open with
else if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.OPEN_WITH) == 0) {
- ActionsPolicy.openFileSystemObject(this, fso, true);
+ IntentsActionPolicy.openFileSystemObject(this, fso, true);
}
// Show properties
else if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.SHOW_PROPERTIES) == 0) {
- ActionsPolicy.showPropertiesDialog(this, fso, this);
+ InfoActionPolicy.showPropertiesDialog(this, fso, this);
}
// Show actions
@@ -966,7 +967,7 @@ public class SearchActivity extends Activity
} else {
// Open the file here, so when focus back to the app, the search activity
// its in top of the stack
- ActionsPolicy.openFileSystemObject(this, fso, false);
+ IntentsActionPolicy.openFileSystemObject(this, fso, false);
return;
}
} else {
diff --git a/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java b/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java
index d83f7df..2118b03 100644
--- a/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java
+++ b/src/com/cyanogenmod/explorer/ui/dialogs/ActionsDialog.java
@@ -37,8 +37,16 @@ import com.cyanogenmod.explorer.adapters.TwoColumnsMenuListAdapter;
import com.cyanogenmod.explorer.listeners.OnRequestRefreshListener;
import com.cyanogenmod.explorer.listeners.OnSelectionListener;
import com.cyanogenmod.explorer.model.FileSystemObject;
-import com.cyanogenmod.explorer.ui.policy.ActionsPolicy;
-import com.cyanogenmod.explorer.ui.policy.ActionsPolicy.LinkedResource;
+import com.cyanogenmod.explorer.model.SystemFile;
+import com.cyanogenmod.explorer.ui.policy.BookmarksActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.CompressActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.CopyMoveActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.CopyMoveActionPolicy.LinkedResource;
+import com.cyanogenmod.explorer.ui.policy.DeleteActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.ExecutionActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.InfoActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.IntentsActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.NewActionPolicy;
import com.cyanogenmod.explorer.util.DialogHelper;
import com.cyanogenmod.explorer.util.FileHelper;
import com.cyanogenmod.explorer.util.MimeTypeHelper;
@@ -116,7 +124,8 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
//Create the list view
this.mListView = new ListView(context);
LinearLayout.LayoutParams params =
- new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
this.mListView.setLayoutParams(params);
this.mListView.setAdapter(adapter);
@@ -209,7 +218,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
//- Delete
case R.id.mnu_actions_delete:
- ActionsPolicy.removeFileSystemObject(
+ DeleteActionPolicy.removeFileSystemObject(
this.mContext,
this.mFso,
this.mOnSelectionListener,
@@ -243,21 +252,21 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
//- Open
case R.id.mnu_actions_open:
- ActionsPolicy.openFileSystemObject(this.mContext, this.mFso, false);
+ IntentsActionPolicy.openFileSystemObject(this.mContext, this.mFso, false);
break;
//- Open with
case R.id.mnu_actions_open_with:
- ActionsPolicy.openFileSystemObject(this.mContext, this.mFso, true);
+ IntentsActionPolicy.openFileSystemObject(this.mContext, this.mFso, true);
break;
//- Execute
case R.id.mnu_actions_execute:
- ActionsPolicy.execute(this.mContext, this.mFso);
+ ExecutionActionPolicy.execute(this.mContext, this.mFso);
break;
//- Send
case R.id.mnu_actions_send:
- ActionsPolicy.sendFileSystemObject(this.mContext, this.mFso);
+ IntentsActionPolicy.sendFileSystemObject(this.mContext, this.mFso);
break;
@@ -266,7 +275,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
if (this.mOnSelectionListener != null) {
List<FileSystemObject> selection =
this.mOnSelectionListener.onRequestSelectedFiles();
- ActionsPolicy.copyFileSystemObjects(
+ CopyMoveActionPolicy.copyFileSystemObjects(
this.mContext,
createLinkedResource(selection, this.mFso),
this.mOnSelectionListener,
@@ -278,7 +287,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
if (this.mOnSelectionListener != null) {
List<FileSystemObject> selection =
this.mOnSelectionListener.onRequestSelectedFiles();
- ActionsPolicy.moveFileSystemObjects(
+ CopyMoveActionPolicy.moveFileSystemObjects(
this.mContext,
createLinkedResource(selection, this.mFso),
this.mOnSelectionListener,
@@ -290,7 +299,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
if (this.mOnSelectionListener != null) {
List<FileSystemObject> selection =
this.mOnSelectionListener.onRequestSelectedFiles();
- ActionsPolicy.removeFileSystemObjects(
+ DeleteActionPolicy.removeFileSystemObjects(
this.mContext,
selection,
this.mOnSelectionListener,
@@ -300,7 +309,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
//- Uncompress
case R.id.mnu_actions_extract:
- ActionsPolicy.uncompress(
+ CompressActionPolicy.uncompress(
this.mContext,
this.mFso,
this.mOnRequestRefreshListener);
@@ -310,7 +319,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
case R.id.mnu_actions_create_copy:
// Create a copy of the fso
if (this.mOnSelectionListener != null) {
- ActionsPolicy.createCopyFileSystemObject(
+ CopyMoveActionPolicy.createCopyFileSystemObject(
this.mContext,
this.mFso,
this.mOnSelectionListener,
@@ -321,13 +330,13 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
//- Add to bookmarks
case R.id.mnu_actions_add_to_bookmarks:
case R.id.mnu_actions_add_to_bookmarks_current_folder:
- ActionsPolicy.addToBookmarks(this.mContext, this.mFso);
+ BookmarksActionPolicy.addToBookmarks(this.mContext, this.mFso);
break;
//- Properties
case R.id.mnu_actions_properties:
case R.id.mnu_actions_properties_current_folder:
- ActionsPolicy.showPropertiesDialog(
+ InfoActionPolicy.showPropertiesDialog(
this.mContext, this.mFso, this.mOnRequestRefreshListener);
break;
@@ -414,7 +423,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
case R.id.mnu_actions_rename:
// Rename the fso
if (ActionsDialog.this.mOnSelectionListener != null) {
- ActionsPolicy.renameFileSystemObject(
+ CopyMoveActionPolicy.renameFileSystemObject(
ActionsDialog.this.mContext,
inputNameDialog.mFso,
name,
@@ -427,7 +436,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
case R.id.mnu_actions_create_link_global:
// Create a link to the fso
if (ActionsDialog.this.mOnSelectionListener != null) {
- ActionsPolicy.createSymlink(
+ NewActionPolicy.createSymlink(
ActionsDialog.this.mContext,
inputNameDialog.mFso,
name,
@@ -471,12 +480,12 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
void createNewFileSystemObject(final int menuId, final String name) {
switch (menuId) {
case R.id.mnu_actions_new_directory:
- ActionsPolicy.createNewDirectory(
+ NewActionPolicy.createNewDirectory(
this.mContext, name,
this.mOnSelectionListener, this.mOnRequestRefreshListener);
break;
case R.id.mnu_actions_new_file:
- ActionsPolicy.createNewFile(
+ NewActionPolicy.createNewFile(
this.mContext, name,
this.mOnSelectionListener, this.mOnRequestRefreshListener);
break;
@@ -560,7 +569,22 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
// Compress/Uncompress (only when selection is available)
if (this.mOnSelectionListener != null) {
- //Uncompress
+ //Compress
+ if (this.mGlobal) {
+ List<FileSystemObject> selection = null;
+ if (this.mOnSelectionListener != null) {
+ selection = this.mOnSelectionListener.onRequestSelectedFiles();
+ }
+ if (selection == null || selection.size() == 0) {
+ menu.removeItem(R.id.mnu_actions_compress_selection);
+ }
+ } else {
+ // Ignore for system files
+ if (this.mFso instanceof SystemFile) {
+ menu.removeItem(R.id.mnu_actions_compress);
+ }
+ }
+ //Uncompress (Only supported files)
if (!this.mGlobal && !FileHelper.isSupportedUncompressedFile(this.mFso)) {
menu.removeItem(R.id.mnu_actions_extract);
}
@@ -578,7 +602,7 @@ public class ActionsDialog implements OnItemClickListener, OnItemLongClickListen
private static List<LinkedResource> createLinkedResource(
List<FileSystemObject> items, FileSystemObject directory) {
List<LinkedResource> resources =
- new ArrayList<ActionsPolicy.LinkedResource>(items.size());
+ new ArrayList<LinkedResource>(items.size());
for (int i = 0; i < items.size(); i++) {
FileSystemObject fso = items.get(i);
File src = new File(fso.getFullPath());
diff --git a/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java b/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java
index efc0970..2697418 100644
--- a/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java
+++ b/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java
@@ -379,12 +379,12 @@ public class FsoPropertiesDialog
try {
if (this.mFso instanceof Symlink && ((Symlink) this.mFso).getLinkRef() != null) {
this.mFolderUsageExecutable =
- (FolderUsageExecutable)CommandHelper.getFolderUsage(
+ CommandHelper.getFolderUsage(
this.mContext,
((Symlink) this.mFso).getLinkRef().getFullPath(), this, null);
} else {
this.mFolderUsageExecutable =
- (FolderUsageExecutable)CommandHelper.getFolderUsage(
+ CommandHelper.getFolderUsage(
this.mContext, this.mFso.getFullPath(), this, null);
}
} catch (Exception cause) {
diff --git a/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java
index 2fc8679..21cfb4b 100644
--- a/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java
+++ b/src/com/cyanogenmod/explorer/ui/policy/ActionsPolicy.java
@@ -16,91 +16,26 @@
package com.cyanogenmod.explorer.ui.policy;
-import android.app.AlertDialog;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
import android.os.AsyncTask;
-import android.text.Html;
import android.text.Spanned;
-import android.util.Log;
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.ExecExecutable;
-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.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.ui.dialogs.AssociationsDialog;
-import com.cyanogenmod.explorer.ui.dialogs.ExecutionDialog;
-import com.cyanogenmod.explorer.ui.dialogs.FsoPropertiesDialog;
import com.cyanogenmod.explorer.ui.dialogs.MessageProgressDialog;
-import com.cyanogenmod.explorer.util.CommandHelper;
-import com.cyanogenmod.explorer.util.DialogHelper;
import com.cyanogenmod.explorer.util.ExceptionUtil;
-import com.cyanogenmod.explorer.util.ExceptionUtil.OnRelaunchCommandResult;
-import com.cyanogenmod.explorer.util.FileHelper;
-import com.cyanogenmod.explorer.util.FixedQueue;
-import com.cyanogenmod.explorer.util.MimeTypeHelper;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
/**
* A class with the convenience methods for resolve actions
*/
-public final class ActionsPolicy {
-
- /**
- * A class that holds a relationship between a source {@link File} and
- * his destination {@link File}
- */
- public static class LinkedResource implements Comparable<LinkedResource> {
- final File mSrc;
- final File mDst;
-
- /**
- * Constructor of <code>LinkedResource</code>
- *
- * @param src The source file system object
- * @param dst The destination file system object
- */
- public LinkedResource(File src, File dst) {
- super();
- this.mSrc = src;
- this.mDst = dst;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int compareTo(LinkedResource another) {
- return this.mSrc.compareTo(another.mSrc);
- }
- }
+public abstract class ActionsPolicy {
/**
* An interface for using in conjunction with AsyncTask for have
* a
*/
- private interface BackgroundCallable {
+ protected interface BackgroundCallable {
/**
* Method that returns the resource identifier of the icon of the dialog
*
@@ -142,7 +77,7 @@ public final class ActionsPolicy {
*
* @see BackgroundCallable
*/
- private static class BackgroundAsyncTask
+ protected static class BackgroundAsyncTask
extends AsyncTask<Object, Spanned, Throwable> {
private final Context mCtx;
@@ -217,1499 +152,13 @@ public final class ActionsPolicy {
}
}
-
- /**
- * A class that holds a listener of the execution of a program
- */
- private static class ExecutionListener implements AsyncResultListener {
-
- private final ExecutionDialog mDialog;
-
- /**
- * Constructor of <code>ExecutionListener</code>
- *
- * @param dialog The console dialog
- */
- public ExecutionListener(ExecutionDialog dialog) {
- super();
- this.mDialog = dialog;
- }
-
- @Override
- public void onPartialResult(Object result) {
- this.mDialog.onAppendData((String)result);
- }
-
- @Override
- public void onException(Exception cause) {
- this.mDialog.onAppendData(ExceptionUtil.toStackTrace(cause));
- }
-
- @Override
- public void onAsyncStart() {
- this.mDialog.onStart();
- }
-
- @Override
- public void onAsyncEnd(boolean canceled) {/**NON BLOCK**/}
-
- @Override
- public void onAsyncExitCode(int exitCode) {
- this.mDialog.onEnd(exitCode);
- }
- }
-
- /**
- * A class that holds a listener for compression/uncompression operations
- */
- private static class CompressListener implements AsyncResultListener {
-
- Object mSync;
- final FixedQueue<String> mQueue;
- boolean mEnd;
- Throwable mCause;
-
- /**
- * Constructor of <code>CompressListener</code>
- */
- 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);
- }
- }
-
- @Override
- public void onException(Exception cause) {
- synchronized (this.mSync) {
- this.mCause = cause;
- }
- }
-
- @Override
- public void onAsyncStart() {/**NON BLOCK**/}
-
- @Override
- public void onAsyncEnd(boolean canceled) {/**NON BLOCK**/}
-
- @Override
- public void onAsyncExitCode(int exitCode) {
- synchronized (this.mSync) {
- this.mEnd = true;
- }
- }
- }
-
- /**
- * @hide
- */
- private enum COPY_MOVE_OPERATION {
- COPY,
- MOVE,
- RENAME,
- CREATE_COPY,
- }
-
-
- private static final String TAG = "ActionPolicy"; //$NON-NLS-1$
-
- private static boolean DEBUG = false;
-
- /**
- * Constructor of <code>ActionsPolicy</code>.
- */
- private ActionsPolicy() {
- super();
- }
-
- /**
- * Method that show a {@link Toast} with the content description of a {@link FileSystemObject}.
- *
- * @param ctx The current context
- * @param fso The file system object
- */
- public static void showContentDescription(final Context ctx, final FileSystemObject fso) {
- String contentDescription = fso.getFullPath();
- Toast.makeText(ctx, contentDescription, Toast.LENGTH_SHORT).show();
- }
-
- /**
- * Method that show a new dialog for show {@link FileSystemObject} properties.
- *
- * @param ctx The current context
- * @param fso The file system object
- * @param onRequestRefreshListener The listener for request a refresh after properties
- * of the {@link FileSystemObject} were changed (optional)
- */
- public static void showPropertiesDialog(
- final Context ctx, final FileSystemObject fso,
- final OnRequestRefreshListener onRequestRefreshListener) {
- //Show a the filesystem info dialog
- final FsoPropertiesDialog dialog = new FsoPropertiesDialog(ctx, fso);
- dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dlg) {
- // Any change?
- if (dialog.isHasChanged()) {
- if (onRequestRefreshListener != null) {
- onRequestRefreshListener.onRequestRefresh(dialog.getFso());
- }
- }
- }
- });
- dialog.show();
- }
-
- /**
- * Method that opens a {@link FileSystemObject} with the default registered application
- * by the system, or ask the user for select a registered application.
- *
- * @param ctx The current context
- * @param fso The file system object
- * @param choose If allow the user to select the application to open with
- */
- public static void openFileSystemObject(
- final Context ctx, final FileSystemObject fso, final boolean choose) {
- try {
- // Create the intent to
- Intent intent = new Intent();
- intent.setAction(android.content.Intent.ACTION_VIEW);
-
- // Obtain the mime/type and passed it to intent
- String mime = MimeTypeHelper.getMimeType(ctx, fso);
- File file = new File(fso.getFullPath());
- if (mime != null) {
- intent.setDataAndType(Uri.fromFile(file), mime);
- } else {
- intent.setData(Uri.fromFile(file));
- }
-
- // Resolve the intent
- resolveIntent(
- ctx,
- intent,
- choose,
- R.drawable.ic_holo_light_open,
- R.string.associations_dialog_openwith_title,
- R.string.associations_dialog_openwith_action,
- true);
-
- } catch (Exception e) {
- ExceptionUtil.translateException(ctx, e);
- }
- }
-
- /**
- * Method that sends a {@link FileSystemObject} with the default registered application
- * by the system, or ask the user for select a registered application.
- *
- * @param ctx The current context
- * @param fso The file system object
- */
- public static void sendFileSystemObject(
- final Context ctx, final FileSystemObject fso) {
- try {
- // Create the intent to
- Intent intent = new Intent();
- intent.setAction(android.content.Intent.ACTION_SEND);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.setType(MimeTypeHelper.getMimeType(ctx, fso));
- Uri uri = Uri.fromFile(new File(fso.getFullPath()));
- intent.putExtra(Intent.EXTRA_STREAM, uri);
-
- // Resolve the intent
- resolveIntent(
- ctx,
- intent,
- false,
- R.drawable.ic_holo_light_send,
- R.string.associations_dialog_sendwith_title,
- R.string.associations_dialog_sendwith_action,
- false);
-
- } catch (Exception e) {
- ExceptionUtil.translateException(ctx, e);
- }
- }
-
- /**
- * Method that resolve
- *
- * @param ctx The current context
- * @param intent The intent to resolve
- * @param choose If allow the user to select the application to select the registered
- * application. If no preferred app or more than one exists the dialog is shown.
- * @param icon The icon of the dialog
- * @param title The title of the dialog
- * @param action The button title of the dialog
- * @param allowPreferred If allow the user to mark the selected app as preferred
- */
- private static void resolveIntent(
- Context ctx, Intent intent, boolean choose,
- int icon, int title, int action, boolean allowPreferred) {
- //Retrieve the activities that can handle the file
- final PackageManager packageManager = ctx.getPackageManager();
- if (DEBUG) {
- intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
- }
- List<ResolveInfo> info =
- packageManager.
- queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
- // Retrieve the preferred activity that can handle the file
- final ResolveInfo mPreferredInfo = packageManager.resolveActivity(intent, 0);
-
- // No registered application
- if (info.size() == 0) {
- Toast.makeText(ctx, R.string.msgs_not_registered_app, Toast.LENGTH_SHORT).show();
- return;
- }
-
- // Is a simple open and we have an application that can handle the file?
- if (!choose &&
- ((mPreferredInfo != null && mPreferredInfo.match != 0) || info.size() == 1)) {
- ctx.startActivity(intent);
- return;
- }
-
- // Otherwise, we have to show the open with dialog
- AssociationsDialog dialog =
- new AssociationsDialog(
- ctx,
- icon,
- ctx.getString(title),
- ctx.getString(action),
- intent,
- info,
- mPreferredInfo,
- allowPreferred);
- dialog.show();
- }
-
- /**
- * Method that adds the {@link FileSystemObject} to the bookmarks database.
- *
- * @param ctx The current context
- * @param fso The file system object
- */
- public static void addToBookmarks(final Context ctx, final FileSystemObject fso) {
- try {
- // Create the bookmark
- Bookmark bookmark =
- new Bookmark(BOOKMARK_TYPE.USER_DEFINED, fso.getName(), fso.getFullPath());
- bookmark = Bookmarks.addBookmark(ctx, bookmark);
- if (bookmark == null) {
- // The operation fails
- Toast.makeText(
- ctx,
- R.string.msgs_operation_failure,
- Toast.LENGTH_SHORT).show();
- } else {
- // Success
- Toast.makeText(
- ctx,
- R.string.bookmarks_msgs_add_success,
- Toast.LENGTH_SHORT).show();
- }
-
- } catch (Exception e) {
- ExceptionUtil.translateException(ctx, e);
- }
- }
-
- /**
- * Method that executes a {@link FileSystemObject} and show the output in the console
- * dialog.
- *
- * @param ctx The current context
- * @param fso The file system object
- */
- public static void execute(
- final Context ctx, final FileSystemObject fso) {
- try {
- // Create a console dialog for display the script output
- final ExecutionDialog dialog = new ExecutionDialog(ctx, fso);
- dialog.show();
-
- Thread t = new Thread() {
- @Override
- public void run() {
- final ExecutionListener listener = new ExecutionListener(dialog);
- try {
- Thread.sleep(250L);
-
- // Execute the script
- ExecExecutable cmd =
- CommandHelper.exec(
- ctx, fso.getFullPath(), listener, null);
- dialog.setCmd(cmd);
- } catch (Exception e) {
- listener.onException(e);
- }
- }
- };
- t.start();
-
- } catch (Exception e) {
- ExceptionUtil.translateException(ctx, e);
- }
- }
-
- /**
- * Method that create the a new file system object.
- *
- * @param ctx The current context
- * @param name The name of the file to be created
- * @param onSelectionListener The selection listener (required)
- * @param onRequestRefreshListener The listener for request a refresh after the new
- * file was created (option)
- */
- public static void createNewFile(
- final Context ctx, final String name,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
- createNewFileSystemObject(ctx, name, false, onSelectionListener, onRequestRefreshListener);
- }
-
- /**
- * Method that create the a new folder system object.
- *
- * @param ctx The current context
- * @param name The name of the file to be created
- * @param onSelectionListener The selection listener (required)
- * @param onRequestRefreshListener The listener for request a refresh after the new
- * folder was created (option)
- */
- public static void createNewDirectory(
- final Context ctx, final String name,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
- createNewFileSystemObject(ctx, name, true, onSelectionListener, onRequestRefreshListener);
- }
-
- /**
- * Method that create the a new file system object.
- *
- * @param ctx The current context
- * @param name The name of the file to be created
- * @param folder If the new {@link FileSystemObject} to create is a folder (true) or a
- * file (false).
- * @param onSelectionListener The selection listener (required)
- * @param onRequestRefreshListener The listener for request a refresh after the new
- * folder was created (option)
- */
- private static void createNewFileSystemObject(
- final Context ctx, final String name, final boolean folder,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- //Create the absolute file name
- File newFso = new File(
- onSelectionListener.onRequestCurrentDir(), name);
- final String newName = newFso.getAbsolutePath();
-
- try {
- if (folder) {
- if (DEBUG) {
- Log.d(TAG, String.format("Creating new directory: %s", newName)); //$NON-NLS-1$
- }
- CommandHelper.createDirectory(ctx, newName, null);
- } else {
- if (DEBUG) {
- Log.d(TAG, String.format("Creating new file: %s", newName)); //$NON-NLS-1$
- }
- CommandHelper.createFile(ctx, newName, null);
- }
-
- //Operation complete. Show refresh
- if (onRequestRefreshListener != null) {
- FileSystemObject fso = null;
- try {
- fso = CommandHelper.getFileInfo(ctx, newName, false, null);
- } catch (Throwable ex2) {
- /**NON BLOCK**/
- }
- onRequestRefreshListener.onRequestRefresh(fso);
- }
- showOperationSuccessMsg(ctx);
-
- } catch (Throwable ex) {
- //Capture the exception
- if (ex instanceof RelaunchableException) {
- ExceptionUtil.attachAsyncTask(ex, new AsyncTask<Object, Integer, Boolean>() {
- /**
- * {@inheritDoc}
- */
- @Override
- protected Boolean doInBackground(Object... params) {
- //Operation complete. Show refresh
- if (onRequestRefreshListener != null) {
- FileSystemObject fso = null;
- try {
- fso =
- CommandHelper.getFileInfo(ctx, newName, false, null);
- } catch (Throwable ex2) {
- /**NON BLOCK**/
- }
- onRequestRefreshListener.onRequestRefresh(fso);
- }
- return Boolean.TRUE;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onPostExecute(Boolean result) {
- if (result != null && result.booleanValue()) {
- showOperationSuccessMsg(ctx);
- }
- }
- });
- }
- ExceptionUtil.translateException(ctx, ex);
- }
- }
-
- /**
- * Method that remove an existing file system object.
- *
- * @param ctx The current context
- * @param src The source file system object
- * @param lnkName The new name of the link
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- public static void createSymlink(
- final Context ctx,
- final FileSystemObject src,
- final String lnkName,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- //Create the absolute file name
- File newFso = new File(
- onSelectionListener.onRequestCurrentDir(), lnkName);
- final String link = newFso.getAbsolutePath();
-
- try {
- if (DEBUG) {
- Log.d(TAG, String.format(
- "Creating new symlink: %s -> %s", src.getFullPath(), link)); //$NON-NLS-1$
- }
- CommandHelper.createLink(ctx, src.getFullPath(), link, null);
-
- //Operation complete. Show refresh
- if (onRequestRefreshListener != null) {
- FileSystemObject fso = null;
- try {
- fso = CommandHelper.getFileInfo(ctx, link, false, null);
- } catch (Throwable ex2) {
- /**NON BLOCK**/
- }
- onRequestRefreshListener.onRequestRefresh(fso);
- }
- showOperationSuccessMsg(ctx);
-
- } catch (Throwable ex) {
- //Capture the exception
- if (ex instanceof RelaunchableException) {
- ExceptionUtil.attachAsyncTask(ex, new AsyncTask<Object, Integer, Boolean>() {
- /**
- * {@inheritDoc}
- */
- @Override
- protected Boolean doInBackground(Object... params) {
- //Operation complete. Show refresh
- if (onRequestRefreshListener != null) {
- FileSystemObject fso = null;
- try {
- fso = CommandHelper.getFileInfo(ctx, link, false, null);
- } catch (Throwable ex2) {
- /**NON BLOCK**/
- }
- onRequestRefreshListener.onRequestRefresh(fso);
- }
- return Boolean.TRUE;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onPostExecute(Boolean result) {
- if (result != null && result.booleanValue()) {
- showOperationSuccessMsg(ctx);
- }
- }
-
- });
- }
- ExceptionUtil.translateException(ctx, ex);
- }
- }
-
- /**
- * Method that remove an existing file system object.
- *
- * @param ctx The current context
- * @param fso The file system object to remove
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- public static void removeFileSystemObject(
- final Context ctx, final FileSystemObject fso,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
- // Generate an array and invoke internal method
- List<FileSystemObject> files = new ArrayList<FileSystemObject>(1);
- files.add(fso);
- removeFileSystemObjects(ctx, files, onSelectionListener, onRequestRefreshListener);
- }
-
- /**
- * Method that remove an existing file system object.
- *
- * @param ctx The current context
- * @param files The list of files to remove
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- public static void removeFileSystemObjects(
- final Context ctx, final List<FileSystemObject> files,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- // Ask the user before remove
- AlertDialog dialog =DialogHelper.createYesNoDialog(
- ctx, R.string.actions_ask_undone_operation,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface alertDialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- // Remove the items
- removeFileSystemObjectsInBackground(
- ctx,
- files,
- onSelectionListener,
- onRequestRefreshListener);
- }
- }
- });
- dialog.show();
- }
-
- /**
- * Method that remove an existing file system object in background.
- *
- * @param ctx The current context
- * @param files The list of files to remove
- * @param onSelectionListener The listener for obtain selection information (optional)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- * @hide
- */
- static void removeFileSystemObjectsInBackground(
- final Context ctx, final List<FileSystemObject> files,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- // Some previous checks prior to execute
- // 1.- Check the operation consistency (only if it is viable)
- if (onSelectionListener != null) {
- final String currentDirectory = onSelectionListener.onRequestCurrentDir();
- if (!checkRemoveConsistency(ctx, files, currentDirectory)) {
- return;
- }
- }
- // 2.- Sort the items by path to avoid delete parents fso prior to child fso
- final List<FileSystemObject> sortedFsos = new ArrayList<FileSystemObject>(files);
- Collections.sort(sortedFsos, new Comparator<FileSystemObject>() {
- @Override
- public int compare(FileSystemObject lhs, FileSystemObject rhs) {
- return lhs.compareTo(rhs) * -1; //Reverse
- }
- });
-
- // The callable interface
- final BackgroundCallable callable = new BackgroundCallable() {
- // The current items
- private int mCurrent = 0;
- final Context mCtx = ctx;
- final List<FileSystemObject> mFiles = sortedFsos;
- final OnRequestRefreshListener mOnRequestRefreshListener = onRequestRefreshListener;
-
- final Object mSync = new Object();
- Throwable mCause;
-
- @Override
- public int getDialogTitle() {
- return R.string.waiting_dialog_deleting_title;
- }
- @Override
- public int getDialogIcon() {
- return R.drawable.ic_holo_light_operation;
- }
-
- @Override
- public Spanned requestProgress() {
- FileSystemObject fso = this.mFiles.get(this.mCurrent);
-
- // Return the current operation
- String progress =
- this.mCtx.getResources().
- getString(
- R.string.waiting_dialog_deleting_msg,
- fso.getFullPath());
- return Html.fromHtml(progress);
- }
-
- @Override
- public void onSuccess() {
- //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);
- }
-
- @Override
- public void doInBackground(Object... params) throws Throwable {
- this.mCause = null;
-
- // This method expect to receive
- // 1.- BackgroundAsyncTask
- BackgroundAsyncTask task = (BackgroundAsyncTask)params[0];
-
- for (int i = 0; i < this.mFiles.size(); i++) {
- FileSystemObject fso = this.mFiles.get(i);
-
- doOperation(this.mCtx, fso);
-
- // Next file
- this.mCurrent++;
- if (this.mCurrent < this.mFiles.size()) {
- task.onRequestProgress();
- }
- }
- }
-
- /**
- * Method that deletes the file or directory
- *
- * @param ctx The current context
- * @param fso The file or folder to be deleted
- */
- @SuppressWarnings("hiding")
- private void doOperation(
- final Context ctx, final FileSystemObject fso) throws Throwable {
- try {
- // Remove the item
- if (FileHelper.isDirectory(fso)) {
- CommandHelper.deleteDirectory(ctx, fso.getFullPath(), null);
- } else {
- CommandHelper.deleteFile(ctx, fso.getFullPath(), null);
- }
- } 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;
- }
- }
-
- // Check that the operation was completed retrieving the deleted fso
- boolean failed = false;
- try {
- CommandHelper.getFileInfo(ctx, fso.getFullPath(), false, null);
-
- // Failed. The file still exists
- failed = true;
-
- } catch (Throwable e) {
- // Operation complete successfully
- }
- if (failed) {
- throw new ExecutionException(
- String.format(
- "Failed to delete file: %s", fso.getFullPath())); //$NON-NLS-1$
- }
- }
- };
- final BackgroundAsyncTask task = new BackgroundAsyncTask(ctx, callable);
-
- // Execute background task
- task.execute(task);
- }
-
- /**
- * Method that remove an existing file system object.
- *
- * @param ctx The current context
- * @param fso The file system object
- * @param newName The new name of the object
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- public static void renameFileSystemObject(
- final Context ctx,
- final FileSystemObject fso,
- final String newName,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- // Create the destination filename
- File dst = new File(fso.getParent(), newName);
- File src = new File(fso.getFullPath());
-
- // Create arguments
- LinkedResource linkRes = new LinkedResource(src, dst);
- List<LinkedResource> files = new ArrayList<ActionsPolicy.LinkedResource>(1);
- files.add(linkRes);
-
- // Internal copy
- copyOrMoveFileSystemObjects(
- ctx,
- COPY_MOVE_OPERATION.RENAME,
- files,
- onSelectionListener,
- onRequestRefreshListener);
- }
-
- /**
- * Method that copy an existing file system object.
- *
- * @param ctx The current context
- * @param fso The file system object
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- public static void createCopyFileSystemObject(
- final Context ctx,
- final FileSystemObject fso,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- // Create a non-existing name
- List<FileSystemObject> curFiles = onSelectionListener.onRequestCurrentItems();
- String newName = FileHelper.createNonExistingName(ctx, curFiles, fso);
- final File dst = new File(fso.getParent(), newName);
- File src = new File(fso.getFullPath());
-
- // Create arguments
- LinkedResource linkRes = new LinkedResource(src, dst);
- List<LinkedResource> files = new ArrayList<ActionsPolicy.LinkedResource>(1);
- files.add(linkRes);
-
- // Internal copy
- copyOrMoveFileSystemObjects(
- ctx,
- COPY_MOVE_OPERATION.CREATE_COPY,
- files,
- onSelectionListener,
- onRequestRefreshListener);
- }
-
- /**
- * Method that copy an existing file system object.
- *
- * @param ctx The current context
- * @param files The list of files to copy
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- public static void copyFileSystemObjects(
- final Context ctx,
- final List<LinkedResource> files,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
- // Internal copy
- copyOrMoveFileSystemObjects(
- ctx,
- COPY_MOVE_OPERATION.COPY,
- files,
- onSelectionListener,
- onRequestRefreshListener);
- }
-
- /**
- * Method that copy an existing file system object.
- *
- * @param ctx The current context
- * @param files The list of files to move
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- public static void moveFileSystemObjects(
- final Context ctx,
- final List<LinkedResource> files,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
- // Internal move
- copyOrMoveFileSystemObjects(
- ctx,
- COPY_MOVE_OPERATION.MOVE,
- files,
- onSelectionListener,
- onRequestRefreshListener);
- }
-
- /**
- * Method that copy an existing file system object.
- *
- * @param ctx The current context
- * @param operation Indicates the operation to do
- * @param files The list of source/destination files to copy
- * @param onSelectionListener The listener for obtain selection information (required)
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- */
- private static void copyOrMoveFileSystemObjects(
- final Context ctx,
- final COPY_MOVE_OPERATION operation,
- final List<LinkedResource> files,
- final OnSelectionListener onSelectionListener,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- // Some previous checks prior to execute
- // 1.- Listener can't not be null
- if (onSelectionListener == null) {
- AlertDialog dialog =
- DialogHelper.createErrorDialog(ctx, R.string.msgs_illegal_argument);
- dialog.show();
- return;
- }
- // 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++) {
- LinkedResource linkedRes = files.get(i);
- if (linkedRes.mSrc == null || linkedRes.mDst == null) {
- AlertDialog dialog =
- DialogHelper.createErrorDialog(ctx, R.string.msgs_illegal_argument);
- dialog.show();
- return;
- }
- if (linkedRes.mDst.getParent() == null ||
- linkedRes.mDst.getParent().compareTo(currentDirectory) != 0) {
- AlertDialog dialog =
- DialogHelper.createErrorDialog(ctx, R.string.msgs_illegal_argument);
- dialog.show();
- return;
- }
- }
- // 3.- Check the operation consistency
- if (operation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0) {
- if (!checkMoveConsistency(ctx, files, currentDirectory)) {
- return;
- }
- }
-
- // The callable interface
- final BackgroundCallable callable = new BackgroundCallable() {
- // The current items
- private int mCurrent = 0;
- final Context mCtx = ctx;
- final COPY_MOVE_OPERATION mOperation = operation;
- final List<LinkedResource> mFiles = files;
- final OnRequestRefreshListener mOnRequestRefreshListener = onRequestRefreshListener;
-
- final Object mSync = new Object();
- Throwable mCause;
-
- @Override
- public int getDialogTitle() {
- return this.mOperation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
- this.mOperation.compareTo(COPY_MOVE_OPERATION.RENAME) == 0 ?
- R.string.waiting_dialog_moving_title :
- R.string.waiting_dialog_copying_title;
- }
- @Override
- public int getDialogIcon() {
- return R.drawable.ic_holo_light_operation;
- }
-
- @Override
- public Spanned requestProgress() {
- File src = this.mFiles.get(this.mCurrent).mSrc;
- File dst = this.mFiles.get(this.mCurrent).mDst;
-
- // Return the current operation
- String progress =
- this.mCtx.getResources().
- getString(
- this.mOperation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
- this.mOperation.compareTo(COPY_MOVE_OPERATION.RENAME) == 0 ?
- R.string.waiting_dialog_moving_msg :
- R.string.waiting_dialog_copying_msg,
- src.getAbsolutePath(),
- dst.getAbsolutePath());
- return Html.fromHtml(progress);
- }
-
- @Override
- public void onSuccess() {
- //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);
- }
-
- @Override
- public void doInBackground(Object... params) throws Throwable {
- this.mCause = null;
-
- // This method expect to receive
- // 1.- BackgroundAsyncTask
- BackgroundAsyncTask task = (BackgroundAsyncTask)params[0];
-
- for (int i = 0; i < this.mFiles.size(); i++) {
- File src = this.mFiles.get(i).mSrc;
- File dst = this.mFiles.get(i).mDst;
-
- doOperation(this.mCtx, src, dst, this.mOperation);
-
- // Next file
- this.mCurrent++;
- if (this.mCurrent < this.mFiles.size()) {
- task.onRequestProgress();
- }
- }
- }
-
- /**
- * Method that copy or move the file to another location
- *
- * @param ctx The current context
- * @param src The source file
- * @param dst The destination file
- * @param operation Indicates the operation to do
- */
- @SuppressWarnings("hiding")
- private void doOperation(
- Context ctx, File src, File dst, COPY_MOVE_OPERATION operation)
- throws Throwable {
- // If the source is the same as destiny then don't do the operation
- if (src.compareTo(dst) == 0) return;
-
- try {
- // Copy or move?
- if (operation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
- operation.compareTo(COPY_MOVE_OPERATION.RENAME) == 0) {
- CommandHelper.move(
- ctx,
- src.getAbsolutePath(),
- dst.getAbsolutePath(),
- null);
- } else {
- CommandHelper.copy(
- ctx,
- src.getAbsolutePath(),
- dst.getAbsolutePath(),
- null);
- }
- } 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;
- }
- }
-
- // Check that the operation was completed retrieving the fso modified
- CommandHelper.getFileInfo(ctx, dst.getAbsolutePath(), false, null);
- }
- };
- final BackgroundAsyncTask task = new BackgroundAsyncTask(ctx, callable);
-
- // Prior to execute, we need to check if some of the files will be overwritten
- List<FileSystemObject> curFiles = onSelectionListener.onRequestCurrentItems();
- if (curFiles != null) {
- // Is necessary to ask the user?
- if (isOverwriteNeeded(files, curFiles)) {
- //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();
- return;
- }
- }
-
- // Execute background task
- task.execute(task);
- }
-
- /**
- * Method that uncompress a compressed file.
- *
- * @param ctx The current context
- * @param fso The compressed file
- * @param onRequestRefreshListener The listener for request a refresh (optional)
- * @hide
- */
- public static void uncompress(
- final Context ctx, final FileSystemObject fso,
- final OnRequestRefreshListener onRequestRefreshListener) {
-
- // The callable interface
- final BackgroundCallable callable = new BackgroundCallable() {
- // The current items
- final Context mCtx = ctx;
- final FileSystemObject mFso = fso;
- final OnRequestRefreshListener mOnRequestRefreshListener = onRequestRefreshListener;
-
- final Object mSync = new Object();
- Throwable mCause;
-
- final CompressListener mListener =
- new CompressListener();
- private String mMsg;
- private boolean mStarted = false;
-
- @Override
- public int getDialogTitle() {
- return R.string.waiting_dialog_extracting_title;
- }
- @Override
- public int getDialogIcon() {
- return R.drawable.ic_holo_light_operation;
- }
-
- @Override
- public Spanned requestProgress() {
- // Initializing the dialog
- if (!this.mStarted) {
- String progress =
- this.mCtx.getResources().
- getString(
- R.string.waiting_dialog_extracting_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_extracting_msg,
- msg);
- return Html.fromHtml(progress);
- }
-
- @Override
- public void onSuccess() {
- //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);
- }
-
- @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 {
- UncompressExecutable cmd =
- CommandHelper.uncompress(
- ctx,
- this.mFso.getFullPath(),
- this.mListener, null);
- out = cmd.getOutUncompressedFile();
-
- // 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 extract file: %s", //$NON-NLS-1$
- this.mFso.getFullPath()));
- }
- }
- };
- final BackgroundAsyncTask task = new BackgroundAsyncTask(ctx, callable);
-
- // Check if the output exists
- boolean askUser = false;
- try {
- UncompressExecutable ucmd =
- ExplorerApplication.getBackgroundConsole().
- getExecutableFactory().newCreator().
- createUncompressExecutable(fso.getFullPath(), null);
- String dst = ucmd.getOutUncompressedFile();
- 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) {
- // Check if the necessary to display a warning because
- // security issues
- checkZipSecurityWarning(ctx, task, fso);
- }
- }
- });
- dialog.show();
- } else {
- // Execute background task
- task.execute(task);
- }
- }
-
- /**
- * Method that checks if it is necessary to display a warning dialog because
- * the privileged extraction of a zip file.
- *
- * @param ctx The current context
- * @param task The task
- * @param fso The zip file
- * @hide
- */
- static void checkZipSecurityWarning(
- final Context ctx, final BackgroundAsyncTask task, FileSystemObject fso) {
- // WARNING! Extracting a ZIP file with relatives or absolutes path could break
- // the system and is need a security alert that the user can confirm prior to
- // make the extraction
- String ext = FileHelper.getExtension(fso);
- if (ConsoleBuilder.isPrivileged() && ext.compareTo("zip") == 0) { //$NON-NLS-1$
- AlertDialog dialog =DialogHelper.createYesNoDialog(
- ctx, R.string.security_warning_extract,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface alertDialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- // Execute background task
- task.execute(task);
- }
- }
- });
- dialog.show();
- } else {
- // Execute background task
- task.execute(task);
- }
- }
-
- /**
- * Method that check if is needed to prompt the user for overwrite prior to do
- * the operation.
- *
- * @param files The list of source/destination files.
- * @param currentFiles The list of the current files in the destination directory.
- * @return boolean If is needed to prompt the user for overwrite
- */
- 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++) {
- FileSystemObject dst1 = currentFiles.get(i);
- File dst2 = files.get(j).mDst;
-
- // The file exists in the destination directory
- if (dst1.getFullPath().compareTo(dst2.getAbsolutePath()) == 0) {
- askUser = true;
- break;
- }
- }
- if (askUser) break;
- }
- return askUser;
- }
-
- /**
- * Method that check the consistency of move operations.<br/>
- * <br/>
- * The method checks the following rules:<br/>
- * <ul>
- * <li>Any of the files of the move operation can not include the
- * current directory.</li>
- * <li>Any of the files of the move operation can not include the
- * current directory.</li>
- * </ul>
- *
- * @param ctx The current context
- * @param files The list of source/destination files
- * @param currentDirectory The current directory
- * @return boolean If the consistency is validate successfully
- */
- private static boolean checkMoveConsistency(
- Context ctx, List<LinkedResource> files, String currentDirectory) {
- for (int i = 0; i < files.size(); i++) {
- LinkedResource linkRes = files.get(i);
- String src = linkRes.mSrc.getAbsolutePath();
- String dst = linkRes.mDst.getAbsolutePath();
-
- // 1.- Current directory can't be moved
- if (currentDirectory != null && currentDirectory.startsWith(src)) {
- // Operation not allowed
- AlertDialog dialog =
- DialogHelper.createErrorDialog(
- ctx, R.string.msgs_unresolved_inconsistencies);
- dialog.show();
- return false;
- }
-
- // 2.- Destination can't be a child of source
- if (dst.startsWith(src)) {
- // Operation not allowed
- AlertDialog dialog =
- DialogHelper.createErrorDialog(
- ctx, R.string.msgs_operation_not_allowed_in_current_directory);
- dialog.show();
- return false;
- }
- }
- return true;
- }
-
- /**
- * Method that check the consistency of delete operations.<br/>
- * <br/>
- * The method checks the following rules:<br/>
- * <ul>
- * <li>Any of the files of the move or delete operation can not include the
- * current directory.</li>
- * </ul>
- *
- * @param ctx The current context
- * @param files The list of source/destination files
- * @param currentDirectory The current directory
- * @return boolean If the consistency is validate successfully
- */
- private static boolean checkRemoveConsistency(
- Context ctx, List<FileSystemObject> files, String currentDirectory) {
- for (int i = 0; i < files.size(); i++) {
- FileSystemObject fso = files.get(i);
-
- // 1.- Current directory can't be deleted
- if (currentDirectory.startsWith(fso.getFullPath())) {
- // Operation not allowed
- AlertDialog dialog =
- DialogHelper.createErrorDialog(
- ctx, R.string.msgs_unresolved_inconsistencies);
- dialog.show();
- return false;
- }
- }
- return true;
- }
-
/**
* Method that shows a message when the operation is complete successfully
*
* @param ctx The current context
* @hide
*/
- static void showOperationSuccessMsg(Context ctx) {
+ protected static void showOperationSuccessMsg(Context ctx) {
Toast.makeText(ctx, R.string.msgs_success, Toast.LENGTH_SHORT).show();
}
} \ 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
new file mode 100644
index 0000000..6afe0df
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/BookmarksActionPolicy.java
@@ -0,0 +1,65 @@
+/*
+ * 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.ui.policy;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import com.cyanogenmod.explorer.R;
+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.ExceptionUtil;
+
+/**
+ * A class with the convenience methods for resolve bookmarks related actions
+ */
+public final class BookmarksActionPolicy extends ActionsPolicy {
+
+ /**
+ * Method that adds the {@link FileSystemObject} to the bookmarks database.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ */
+ public static void addToBookmarks(final Context ctx, final FileSystemObject fso) {
+ try {
+ // Create the bookmark
+ Bookmark bookmark =
+ new Bookmark(BOOKMARK_TYPE.USER_DEFINED, fso.getName(), fso.getFullPath());
+ bookmark = Bookmarks.addBookmark(ctx, bookmark);
+ if (bookmark == null) {
+ // The operation fails
+ Toast.makeText(
+ ctx,
+ R.string.msgs_operation_failure,
+ Toast.LENGTH_SHORT).show();
+ } else {
+ // Success
+ Toast.makeText(
+ ctx,
+ R.string.bookmarks_msgs_add_success,
+ Toast.LENGTH_SHORT).show();
+ }
+
+ } catch (Exception e) {
+ ExceptionUtil.translateException(ctx, e);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java
new file mode 100644
index 0000000..b41ed3d
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/CompressActionPolicy.java
@@ -0,0 +1,354 @@
+/*
+ * 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.ui.policy;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.text.Html;
+import android.text.Spanned;
+
+import com.cyanogenmod.explorer.ExplorerApplication;
+import com.cyanogenmod.explorer.R;
+import com.cyanogenmod.explorer.commands.AsyncResultListener;
+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.model.FileSystemObject;
+import com.cyanogenmod.explorer.util.CommandHelper;
+import com.cyanogenmod.explorer.util.DialogHelper;
+import com.cyanogenmod.explorer.util.ExceptionUtil;
+import com.cyanogenmod.explorer.util.ExceptionUtil.OnRelaunchCommandResult;
+import com.cyanogenmod.explorer.util.FileHelper;
+import com.cyanogenmod.explorer.util.FixedQueue;
+
+import java.util.List;
+
+/**
+ * A class with the convenience methods for resolve compress/uncompress related actions
+ */
+public final class CompressActionPolicy extends ActionsPolicy {
+
+ /**
+ * A class that holds a listener for compression/uncompression operations
+ */
+ private static class CompressListener implements AsyncResultListener {
+
+ Object mSync;
+ final FixedQueue<String> mQueue;
+ boolean mEnd;
+ Throwable mCause;
+
+ /**
+ * Constructor of <code>CompressListener</code>
+ */
+ 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);
+ }
+ }
+
+ @Override
+ public void onException(Exception cause) {
+ synchronized (this.mSync) {
+ this.mCause = cause;
+ }
+ }
+
+ @Override
+ public void onAsyncStart() {/**NON BLOCK**/}
+
+ @Override
+ public void onAsyncEnd(boolean canceled) {/**NON BLOCK**/}
+
+ @Override
+ public void onAsyncExitCode(int exitCode) {
+ synchronized (this.mSync) {
+ this.mEnd = true;
+ }
+ }
+ }
+
+ /**
+ * Method that uncompress a compressed file.
+ *
+ * @param ctx The current context
+ * @param fso The compressed file
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ * @hide
+ */
+ public static void uncompress(
+ final Context ctx, final FileSystemObject fso,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ // The callable interface
+ final BackgroundCallable callable = new BackgroundCallable() {
+ // The current items
+ final Context mCtx = ctx;
+ final FileSystemObject mFso = fso;
+ final OnRequestRefreshListener mOnRequestRefreshListener = onRequestRefreshListener;
+
+ final Object mSync = new Object();
+ Throwable mCause;
+
+ final CompressListener mListener =
+ new CompressListener();
+ private String mMsg;
+ private boolean mStarted = false;
+
+ @Override
+ public int getDialogTitle() {
+ return R.string.waiting_dialog_extracting_title;
+ }
+ @Override
+ public int getDialogIcon() {
+ return R.drawable.ic_holo_light_operation;
+ }
+
+ @Override
+ public Spanned requestProgress() {
+ // Initializing the dialog
+ if (!this.mStarted) {
+ String progress =
+ this.mCtx.getResources().
+ getString(
+ R.string.waiting_dialog_extracting_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_extracting_msg,
+ msg);
+ return Html.fromHtml(progress);
+ }
+
+ @Override
+ public void onSuccess() {
+ //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);
+ }
+
+ @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 {
+ UncompressExecutable cmd =
+ CommandHelper.uncompress(
+ ctx,
+ this.mFso.getFullPath(),
+ this.mListener, null);
+ out = cmd.getOutUncompressedFile();
+
+ // 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 extract file: %s", //$NON-NLS-1$
+ this.mFso.getFullPath()));
+ }
+ }
+ };
+ final BackgroundAsyncTask task = new BackgroundAsyncTask(ctx, callable);
+
+ // Check if the output exists
+ boolean askUser = false;
+ try {
+ UncompressExecutable ucmd =
+ ExplorerApplication.getBackgroundConsole().
+ getExecutableFactory().newCreator().
+ createUncompressExecutable(fso.getFullPath(), null);
+ String dst = ucmd.getOutUncompressedFile();
+ 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) {
+ // Check if the necessary to display a warning because
+ // security issues
+ checkZipSecurityWarning(ctx, task, fso);
+ }
+ }
+ });
+ dialog.show();
+ } else {
+ // Execute background task
+ task.execute(task);
+ }
+ }
+
+ /**
+ * Method that checks if it is necessary to display a warning dialog because
+ * the privileged extraction of a zip file.
+ *
+ * @param ctx The current context
+ * @param task The task
+ * @param fso The zip file
+ * @hide
+ */
+ static void checkZipSecurityWarning(
+ final Context ctx, final BackgroundAsyncTask task, FileSystemObject fso) {
+ // WARNING! Extracting a ZIP file with relatives or absolutes path could break
+ // the system and is need a security alert that the user can confirm prior to
+ // make the extraction
+ String ext = FileHelper.getExtension(fso);
+ if (ConsoleBuilder.isPrivileged() && ext.compareTo("zip") == 0) { //$NON-NLS-1$
+ AlertDialog dialog =DialogHelper.createYesNoDialog(
+ ctx, R.string.security_warning_extract,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface alertDialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ // Execute background task
+ task.execute(task);
+ }
+ }
+ });
+ dialog.show();
+ } else {
+ // Execute background task
+ task.execute(task);
+ }
+ }
+} \ 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
new file mode 100644
index 0000000..3a49c1f
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/CopyMoveActionPolicy.java
@@ -0,0 +1,509 @@
+/*
+ * 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.ui.policy;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.text.Html;
+import android.text.Spanned;
+
+import com.cyanogenmod.explorer.R;
+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.util.CommandHelper;
+import com.cyanogenmod.explorer.util.DialogHelper;
+import com.cyanogenmod.explorer.util.ExceptionUtil;
+import com.cyanogenmod.explorer.util.ExceptionUtil.OnRelaunchCommandResult;
+import com.cyanogenmod.explorer.util.FileHelper;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A class with the convenience methods for resolve copy/move related actions
+ */
+public final class CopyMoveActionPolicy extends ActionsPolicy {
+
+ /**
+ * @hide
+ */
+ private enum COPY_MOVE_OPERATION {
+ COPY,
+ MOVE,
+ RENAME,
+ CREATE_COPY,
+ }
+
+
+ /**
+ * A class that holds a relationship between a source {@link File} and
+ * his destination {@link File}
+ */
+ public static class LinkedResource implements Comparable<LinkedResource> {
+ final File mSrc;
+ final File mDst;
+
+ /**
+ * Constructor of <code>LinkedResource</code>
+ *
+ * @param src The source file system object
+ * @param dst The destination file system object
+ */
+ public LinkedResource(File src, File dst) {
+ super();
+ this.mSrc = src;
+ this.mDst = dst;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(LinkedResource another) {
+ return this.mSrc.compareTo(another.mSrc);
+ }
+ }
+
+ /**
+ * Method that remove an existing file system object.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ * @param newName The new name of the object
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ public static void renameFileSystemObject(
+ final Context ctx,
+ final FileSystemObject fso,
+ final String newName,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ // Create the destination filename
+ File dst = new File(fso.getParent(), newName);
+ File src = new File(fso.getFullPath());
+
+ // Create arguments
+ LinkedResource linkRes = new LinkedResource(src, dst);
+ List<LinkedResource> files = new ArrayList<LinkedResource>(1);
+ files.add(linkRes);
+
+ // Internal copy
+ copyOrMoveFileSystemObjects(
+ ctx,
+ COPY_MOVE_OPERATION.RENAME,
+ files,
+ onSelectionListener,
+ onRequestRefreshListener);
+ }
+
+ /**
+ * Method that copy an existing file system object.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ public static void createCopyFileSystemObject(
+ final Context ctx,
+ final FileSystemObject fso,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ // Create a non-existing name
+ List<FileSystemObject> curFiles = onSelectionListener.onRequestCurrentItems();
+ String newName = FileHelper.createNonExistingName(ctx, curFiles, fso);
+ final File dst = new File(fso.getParent(), newName);
+ File src = new File(fso.getFullPath());
+
+ // Create arguments
+ LinkedResource linkRes = new LinkedResource(src, dst);
+ List<LinkedResource> files = new ArrayList<LinkedResource>(1);
+ files.add(linkRes);
+
+ // Internal copy
+ copyOrMoveFileSystemObjects(
+ ctx,
+ COPY_MOVE_OPERATION.CREATE_COPY,
+ files,
+ onSelectionListener,
+ onRequestRefreshListener);
+ }
+
+ /**
+ * Method that copy an existing file system object.
+ *
+ * @param ctx The current context
+ * @param files The list of files to copy
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ public static void copyFileSystemObjects(
+ final Context ctx,
+ final List<LinkedResource> files,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+ // Internal copy
+ copyOrMoveFileSystemObjects(
+ ctx,
+ COPY_MOVE_OPERATION.COPY,
+ files,
+ onSelectionListener,
+ onRequestRefreshListener);
+ }
+
+ /**
+ * Method that copy an existing file system object.
+ *
+ * @param ctx The current context
+ * @param files The list of files to move
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ public static void moveFileSystemObjects(
+ final Context ctx,
+ final List<LinkedResource> files,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+ // Internal move
+ copyOrMoveFileSystemObjects(
+ ctx,
+ COPY_MOVE_OPERATION.MOVE,
+ files,
+ onSelectionListener,
+ onRequestRefreshListener);
+ }
+
+ /**
+ * Method that copy an existing file system object.
+ *
+ * @param ctx The current context
+ * @param operation Indicates the operation to do
+ * @param files The list of source/destination files to copy
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ private static void copyOrMoveFileSystemObjects(
+ final Context ctx,
+ final COPY_MOVE_OPERATION operation,
+ final List<LinkedResource> files,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ // Some previous checks prior to execute
+ // 1.- Listener can't not be null
+ if (onSelectionListener == null) {
+ AlertDialog dialog =
+ DialogHelper.createErrorDialog(ctx, R.string.msgs_illegal_argument);
+ dialog.show();
+ return;
+ }
+ // 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++) {
+ LinkedResource linkedRes = files.get(i);
+ if (linkedRes.mSrc == null || linkedRes.mDst == null) {
+ AlertDialog dialog =
+ DialogHelper.createErrorDialog(ctx, R.string.msgs_illegal_argument);
+ dialog.show();
+ return;
+ }
+ if (linkedRes.mDst.getParent() == null ||
+ linkedRes.mDst.getParent().compareTo(currentDirectory) != 0) {
+ AlertDialog dialog =
+ DialogHelper.createErrorDialog(ctx, R.string.msgs_illegal_argument);
+ dialog.show();
+ return;
+ }
+ }
+ // 3.- Check the operation consistency
+ if (operation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0) {
+ if (!checkMoveConsistency(ctx, files, currentDirectory)) {
+ return;
+ }
+ }
+
+ // The callable interface
+ final BackgroundCallable callable = new BackgroundCallable() {
+ // The current items
+ private int mCurrent = 0;
+ final Context mCtx = ctx;
+ final COPY_MOVE_OPERATION mOperation = operation;
+ final List<LinkedResource> mFiles = files;
+ final OnRequestRefreshListener mOnRequestRefreshListener = onRequestRefreshListener;
+
+ final Object mSync = new Object();
+ Throwable mCause;
+
+ @Override
+ public int getDialogTitle() {
+ return this.mOperation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
+ this.mOperation.compareTo(COPY_MOVE_OPERATION.RENAME) == 0 ?
+ R.string.waiting_dialog_moving_title :
+ R.string.waiting_dialog_copying_title;
+ }
+ @Override
+ public int getDialogIcon() {
+ return R.drawable.ic_holo_light_operation;
+ }
+
+ @Override
+ public Spanned requestProgress() {
+ File src = this.mFiles.get(this.mCurrent).mSrc;
+ File dst = this.mFiles.get(this.mCurrent).mDst;
+
+ // Return the current operation
+ String progress =
+ this.mCtx.getResources().
+ getString(
+ this.mOperation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
+ this.mOperation.compareTo(COPY_MOVE_OPERATION.RENAME) == 0 ?
+ R.string.waiting_dialog_moving_msg :
+ R.string.waiting_dialog_copying_msg,
+ src.getAbsolutePath(),
+ dst.getAbsolutePath());
+ return Html.fromHtml(progress);
+ }
+
+ @Override
+ public void onSuccess() {
+ //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);
+ }
+
+ @Override
+ public void doInBackground(Object... params) throws Throwable {
+ this.mCause = null;
+
+ // This method expect to receive
+ // 1.- BackgroundAsyncTask
+ BackgroundAsyncTask task = (BackgroundAsyncTask)params[0];
+
+ for (int i = 0; i < this.mFiles.size(); i++) {
+ File src = this.mFiles.get(i).mSrc;
+ File dst = this.mFiles.get(i).mDst;
+
+ doOperation(this.mCtx, src, dst, this.mOperation);
+
+ // Next file
+ this.mCurrent++;
+ if (this.mCurrent < this.mFiles.size()) {
+ task.onRequestProgress();
+ }
+ }
+ }
+
+ /**
+ * Method that copy or move the file to another location
+ *
+ * @param ctx The current context
+ * @param src The source file
+ * @param dst The destination file
+ * @param operation Indicates the operation to do
+ */
+ @SuppressWarnings("hiding")
+ private void doOperation(
+ Context ctx, File src, File dst, COPY_MOVE_OPERATION operation)
+ throws Throwable {
+ // If the source is the same as destiny then don't do the operation
+ if (src.compareTo(dst) == 0) return;
+
+ try {
+ // Copy or move?
+ if (operation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
+ operation.compareTo(COPY_MOVE_OPERATION.RENAME) == 0) {
+ CommandHelper.move(
+ ctx,
+ src.getAbsolutePath(),
+ dst.getAbsolutePath(),
+ null);
+ } else {
+ CommandHelper.copy(
+ ctx,
+ src.getAbsolutePath(),
+ dst.getAbsolutePath(),
+ null);
+ }
+ } 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;
+ }
+ }
+
+ // Check that the operation was completed retrieving the fso modified
+ CommandHelper.getFileInfo(ctx, dst.getAbsolutePath(), false, null);
+ }
+ };
+ final BackgroundAsyncTask task = new BackgroundAsyncTask(ctx, callable);
+
+ // Prior to execute, we need to check if some of the files will be overwritten
+ List<FileSystemObject> curFiles = onSelectionListener.onRequestCurrentItems();
+ if (curFiles != null) {
+ // Is necessary to ask the user?
+ if (isOverwriteNeeded(files, curFiles)) {
+ //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();
+ return;
+ }
+ }
+
+ // Execute background task
+ task.execute(task);
+ }
+
+ /**
+ * Method that check if is needed to prompt the user for overwrite prior to do
+ * the operation.
+ *
+ * @param files The list of source/destination files.
+ * @param currentFiles The list of the current files in the destination directory.
+ * @return boolean If is needed to prompt the user for overwrite
+ */
+ 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++) {
+ FileSystemObject dst1 = currentFiles.get(i);
+ File dst2 = files.get(j).mDst;
+
+ // The file exists in the destination directory
+ if (dst1.getFullPath().compareTo(dst2.getAbsolutePath()) == 0) {
+ askUser = true;
+ break;
+ }
+ }
+ if (askUser) break;
+ }
+ return askUser;
+ }
+
+
+ /**
+ * Method that check the consistency of move operations.<br/>
+ * <br/>
+ * The method checks the following rules:<br/>
+ * <ul>
+ * <li>Any of the files of the move operation can not include the
+ * current directory.</li>
+ * <li>Any of the files of the move operation can not include the
+ * current directory.</li>
+ * </ul>
+ *
+ * @param ctx The current context
+ * @param files The list of source/destination files
+ * @param currentDirectory The current directory
+ * @return boolean If the consistency is validate successfully
+ */
+ private static boolean checkMoveConsistency(
+ Context ctx, List<LinkedResource> files, String currentDirectory) {
+ for (int i = 0; i < files.size(); i++) {
+ LinkedResource linkRes = files.get(i);
+ String src = linkRes.mSrc.getAbsolutePath();
+ String dst = linkRes.mDst.getAbsolutePath();
+
+ // 1.- Current directory can't be moved
+ if (currentDirectory != null && currentDirectory.startsWith(src)) {
+ // Operation not allowed
+ AlertDialog dialog =
+ DialogHelper.createErrorDialog(
+ ctx, R.string.msgs_unresolved_inconsistencies);
+ dialog.show();
+ return false;
+ }
+
+ // 2.- Destination can't be a child of source
+ if (dst.startsWith(src)) {
+ // Operation not allowed
+ AlertDialog dialog =
+ DialogHelper.createErrorDialog(
+ ctx, R.string.msgs_operation_not_allowed_in_current_directory);
+ dialog.show();
+ return false;
+ }
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java
new file mode 100644
index 0000000..d66cb95
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/DeleteActionPolicy.java
@@ -0,0 +1,311 @@
+/*
+ * 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.ui.policy;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.text.Html;
+import android.text.Spanned;
+
+import com.cyanogenmod.explorer.R;
+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.util.CommandHelper;
+import com.cyanogenmod.explorer.util.DialogHelper;
+import com.cyanogenmod.explorer.util.ExceptionUtil;
+import com.cyanogenmod.explorer.util.ExceptionUtil.OnRelaunchCommandResult;
+import com.cyanogenmod.explorer.util.FileHelper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+
+/**
+ * A class with the convenience methods for resolve delete related actions
+ */
+public final class DeleteActionPolicy extends ActionsPolicy {
+
+ /**
+ * Method that remove an existing file system object.
+ *
+ * @param ctx The current context
+ * @param fso The file system object to remove
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ public static void removeFileSystemObject(
+ final Context ctx, final FileSystemObject fso,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+ // Generate an array and invoke internal method
+ List<FileSystemObject> files = new ArrayList<FileSystemObject>(1);
+ files.add(fso);
+ removeFileSystemObjects(ctx, files, onSelectionListener, onRequestRefreshListener);
+ }
+
+ /**
+ * Method that remove an existing file system object.
+ *
+ * @param ctx The current context
+ * @param files The list of files to remove
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ public static void removeFileSystemObjects(
+ final Context ctx, final List<FileSystemObject> files,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ // Ask the user before remove
+ AlertDialog dialog =DialogHelper.createYesNoDialog(
+ ctx, R.string.actions_ask_undone_operation,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface alertDialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ // Remove the items
+ removeFileSystemObjectsInBackground(
+ ctx,
+ files,
+ onSelectionListener,
+ onRequestRefreshListener);
+ }
+ }
+ });
+ dialog.show();
+ }
+
+ /**
+ * Method that remove an existing file system object in background.
+ *
+ * @param ctx The current context
+ * @param files The list of files to remove
+ * @param onSelectionListener The listener for obtain selection information (optional)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ * @hide
+ */
+ static void removeFileSystemObjectsInBackground(
+ final Context ctx, final List<FileSystemObject> files,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ // Some previous checks prior to execute
+ // 1.- Check the operation consistency (only if it is viable)
+ if (onSelectionListener != null) {
+ final String currentDirectory = onSelectionListener.onRequestCurrentDir();
+ if (!checkRemoveConsistency(ctx, files, currentDirectory)) {
+ return;
+ }
+ }
+ // 2.- Sort the items by path to avoid delete parents fso prior to child fso
+ final List<FileSystemObject> sortedFsos = new ArrayList<FileSystemObject>(files);
+ Collections.sort(sortedFsos, new Comparator<FileSystemObject>() {
+ @Override
+ public int compare(FileSystemObject lhs, FileSystemObject rhs) {
+ return lhs.compareTo(rhs) * -1; //Reverse
+ }
+ });
+
+ // The callable interface
+ final BackgroundCallable callable = new BackgroundCallable() {
+ // The current items
+ private int mCurrent = 0;
+ final Context mCtx = ctx;
+ final List<FileSystemObject> mFiles = sortedFsos;
+ final OnRequestRefreshListener mOnRequestRefreshListener = onRequestRefreshListener;
+
+ final Object mSync = new Object();
+ Throwable mCause;
+
+ @Override
+ public int getDialogTitle() {
+ return R.string.waiting_dialog_deleting_title;
+ }
+ @Override
+ public int getDialogIcon() {
+ return R.drawable.ic_holo_light_operation;
+ }
+
+ @Override
+ public Spanned requestProgress() {
+ FileSystemObject fso = this.mFiles.get(this.mCurrent);
+
+ // Return the current operation
+ String progress =
+ this.mCtx.getResources().
+ getString(
+ R.string.waiting_dialog_deleting_msg,
+ fso.getFullPath());
+ return Html.fromHtml(progress);
+ }
+
+ @Override
+ public void onSuccess() {
+ //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);
+ }
+
+ @Override
+ public void doInBackground(Object... params) throws Throwable {
+ this.mCause = null;
+
+ // This method expect to receive
+ // 1.- BackgroundAsyncTask
+ BackgroundAsyncTask task = (BackgroundAsyncTask)params[0];
+
+ for (int i = 0; i < this.mFiles.size(); i++) {
+ FileSystemObject fso = this.mFiles.get(i);
+
+ doOperation(this.mCtx, fso);
+
+ // Next file
+ this.mCurrent++;
+ if (this.mCurrent < this.mFiles.size()) {
+ task.onRequestProgress();
+ }
+ }
+ }
+
+ /**
+ * Method that deletes the file or directory
+ *
+ * @param ctx The current context
+ * @param fso The file or folder to be deleted
+ */
+ @SuppressWarnings("hiding")
+ private void doOperation(
+ final Context ctx, final FileSystemObject fso) throws Throwable {
+ try {
+ // Remove the item
+ if (FileHelper.isDirectory(fso)) {
+ CommandHelper.deleteDirectory(ctx, fso.getFullPath(), null);
+ } else {
+ CommandHelper.deleteFile(ctx, fso.getFullPath(), null);
+ }
+ } 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;
+ }
+ }
+
+ // Check that the operation was completed retrieving the deleted fso
+ boolean failed = false;
+ try {
+ CommandHelper.getFileInfo(ctx, fso.getFullPath(), false, null);
+
+ // Failed. The file still exists
+ failed = true;
+
+ } catch (Throwable e) {
+ // Operation complete successfully
+ }
+ if (failed) {
+ throw new ExecutionException(
+ String.format(
+ "Failed to delete file: %s", fso.getFullPath())); //$NON-NLS-1$
+ }
+ }
+ };
+ final BackgroundAsyncTask task = new BackgroundAsyncTask(ctx, callable);
+
+ // Execute background task
+ task.execute(task);
+ }
+
+ /**
+ * Method that check the consistency of delete operations.<br/>
+ * <br/>
+ * The method checks the following rules:<br/>
+ * <ul>
+ * <li>Any of the files of the move or delete operation can not include the
+ * current directory.</li>
+ * </ul>
+ *
+ * @param ctx The current context
+ * @param files The list of source/destination files
+ * @param currentDirectory The current directory
+ * @return boolean If the consistency is validate successfully
+ */
+ private static boolean checkRemoveConsistency(
+ Context ctx, List<FileSystemObject> files, String currentDirectory) {
+ for (int i = 0; i < files.size(); i++) {
+ FileSystemObject fso = files.get(i);
+
+ // 1.- Current directory can't be deleted
+ if (currentDirectory.startsWith(fso.getFullPath())) {
+ // Operation not allowed
+ AlertDialog dialog =
+ DialogHelper.createErrorDialog(
+ ctx, R.string.msgs_unresolved_inconsistencies);
+ dialog.show();
+ return false;
+ }
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/explorer/ui/policy/ExecutionActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/ExecutionActionPolicy.java
new file mode 100644
index 0000000..05f6ed3
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/ExecutionActionPolicy.java
@@ -0,0 +1,111 @@
+/*
+ * 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.ui.policy;
+
+import android.content.Context;
+
+import com.cyanogenmod.explorer.commands.AsyncResultListener;
+import com.cyanogenmod.explorer.commands.ExecExecutable;
+import com.cyanogenmod.explorer.model.FileSystemObject;
+import com.cyanogenmod.explorer.ui.dialogs.ExecutionDialog;
+import com.cyanogenmod.explorer.util.CommandHelper;
+import com.cyanogenmod.explorer.util.ExceptionUtil;
+
+/**
+ * A class with the convenience methods for resolve executions related actions
+ */
+public final class ExecutionActionPolicy extends ActionsPolicy {
+
+ /**
+ * A class that holds a listener of the execution of a program
+ */
+ private static class ExecutionListener implements AsyncResultListener {
+
+ private final ExecutionDialog mDialog;
+
+ /**
+ * Constructor of <code>ExecutionListener</code>
+ *
+ * @param dialog The console dialog
+ */
+ public ExecutionListener(ExecutionDialog dialog) {
+ super();
+ this.mDialog = dialog;
+ }
+
+ @Override
+ public void onPartialResult(Object result) {
+ this.mDialog.onAppendData((String)result);
+ }
+
+ @Override
+ public void onException(Exception cause) {
+ this.mDialog.onAppendData(ExceptionUtil.toStackTrace(cause));
+ }
+
+ @Override
+ public void onAsyncStart() {
+ this.mDialog.onStart();
+ }
+
+ @Override
+ public void onAsyncEnd(boolean canceled) {/**NON BLOCK**/}
+
+ @Override
+ public void onAsyncExitCode(int exitCode) {
+ this.mDialog.onEnd(exitCode);
+ }
+ }
+
+ /**
+ * Method that executes a {@link FileSystemObject} and show the output in the console
+ * dialog.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ */
+ public static void execute(
+ final Context ctx, final FileSystemObject fso) {
+ try {
+ // Create a console dialog for display the script output
+ final ExecutionDialog dialog = new ExecutionDialog(ctx, fso);
+ dialog.show();
+
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ final ExecutionListener listener = new ExecutionListener(dialog);
+ try {
+ Thread.sleep(250L);
+
+ // Execute the script
+ ExecExecutable cmd =
+ CommandHelper.exec(
+ ctx, fso.getFullPath(), listener, null);
+ dialog.setCmd(cmd);
+ } catch (Exception e) {
+ listener.onException(e);
+ }
+ }
+ };
+ t.start();
+
+ } catch (Exception e) {
+ ExceptionUtil.translateException(ctx, e);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java
new file mode 100644
index 0000000..8168015
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/InfoActionPolicy.java
@@ -0,0 +1,70 @@
+/*
+ * 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.ui.policy;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.widget.Toast;
+
+import com.cyanogenmod.explorer.listeners.OnRequestRefreshListener;
+import com.cyanogenmod.explorer.model.FileSystemObject;
+import com.cyanogenmod.explorer.ui.dialogs.FsoPropertiesDialog;
+
+/**
+ * A class with the convenience methods for resolve the display of info actions
+ */
+public final class InfoActionPolicy extends ActionsPolicy {
+
+ /**
+ * Method that show a {@link Toast} with the content description of a {@link FileSystemObject}.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ */
+ public static void showContentDescription(final Context ctx, final FileSystemObject fso) {
+ String contentDescription = fso.getFullPath();
+ Toast.makeText(ctx, contentDescription, Toast.LENGTH_SHORT).show();
+ }
+
+ /**
+ * Method that show a new dialog for show {@link FileSystemObject} properties.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ * @param onRequestRefreshListener The listener for request a refresh after properties
+ * of the {@link FileSystemObject} were changed (optional)
+ */
+ public static void showPropertiesDialog(
+ final Context ctx, final FileSystemObject fso,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+ //Show a the filesystem info dialog
+ final FsoPropertiesDialog dialog = new FsoPropertiesDialog(ctx, fso);
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dlg) {
+ // Any change?
+ if (dialog.isHasChanged()) {
+ if (onRequestRefreshListener != null) {
+ onRequestRefreshListener.onRequestRefresh(dialog.getFso());
+ }
+ }
+ }
+ });
+ dialog.show();
+ }
+
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java
new file mode 100644
index 0000000..1d43a8c
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/IntentsActionPolicy.java
@@ -0,0 +1,167 @@
+/*
+ * 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.ui.policy;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+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.ExceptionUtil;
+import com.cyanogenmod.explorer.util.MimeTypeHelper;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * A class with the convenience methods for resolve intents related actions
+ */
+public final class IntentsActionPolicy extends ActionsPolicy {
+
+ private static boolean DEBUG = false;
+
+ /**
+ * Method that opens a {@link FileSystemObject} with the default registered application
+ * by the system, or ask the user for select a registered application.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ * @param choose If allow the user to select the application to open with
+ */
+ public static void openFileSystemObject(
+ final Context ctx, final FileSystemObject fso, final boolean choose) {
+ try {
+ // Create the intent to
+ Intent intent = new Intent();
+ intent.setAction(android.content.Intent.ACTION_VIEW);
+
+ // Obtain the mime/type and passed it to intent
+ String mime = MimeTypeHelper.getMimeType(ctx, fso);
+ File file = new File(fso.getFullPath());
+ if (mime != null) {
+ intent.setDataAndType(Uri.fromFile(file), mime);
+ } else {
+ intent.setData(Uri.fromFile(file));
+ }
+
+ // Resolve the intent
+ resolveIntent(
+ ctx,
+ intent,
+ choose,
+ R.drawable.ic_holo_light_open,
+ R.string.associations_dialog_openwith_title,
+ R.string.associations_dialog_openwith_action,
+ true);
+
+ } catch (Exception e) {
+ ExceptionUtil.translateException(ctx, e);
+ }
+ }
+
+ /**
+ * Method that sends a {@link FileSystemObject} with the default registered application
+ * by the system, or ask the user for select a registered application.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ */
+ public static void sendFileSystemObject(
+ final Context ctx, final FileSystemObject fso) {
+ try {
+ // Create the intent to
+ Intent intent = new Intent();
+ intent.setAction(android.content.Intent.ACTION_SEND);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setType(MimeTypeHelper.getMimeType(ctx, fso));
+ Uri uri = Uri.fromFile(new File(fso.getFullPath()));
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+
+ // Resolve the intent
+ resolveIntent(
+ ctx,
+ intent,
+ false,
+ R.drawable.ic_holo_light_send,
+ R.string.associations_dialog_sendwith_title,
+ R.string.associations_dialog_sendwith_action,
+ false);
+
+ } catch (Exception e) {
+ ExceptionUtil.translateException(ctx, e);
+ }
+ }
+
+ /**
+ * Method that resolve
+ *
+ * @param ctx The current context
+ * @param intent The intent to resolve
+ * @param choose If allow the user to select the application to select the registered
+ * application. If no preferred app or more than one exists the dialog is shown.
+ * @param icon The icon of the dialog
+ * @param title The title of the dialog
+ * @param action The button title of the dialog
+ * @param allowPreferred If allow the user to mark the selected app as preferred
+ */
+ private static void resolveIntent(
+ Context ctx, Intent intent, boolean choose,
+ int icon, int title, int action, boolean allowPreferred) {
+ //Retrieve the activities that can handle the file
+ final PackageManager packageManager = ctx.getPackageManager();
+ if (DEBUG) {
+ intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
+ }
+ List<ResolveInfo> info =
+ packageManager.
+ queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ // Retrieve the preferred activity that can handle the file
+ final ResolveInfo mPreferredInfo = packageManager.resolveActivity(intent, 0);
+
+ // No registered application
+ if (info.size() == 0) {
+ Toast.makeText(ctx, R.string.msgs_not_registered_app, Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ // Is a simple open and we have an application that can handle the file?
+ if (!choose &&
+ ((mPreferredInfo != null && mPreferredInfo.match != 0) || info.size() == 1)) {
+ ctx.startActivity(intent);
+ return;
+ }
+
+ // Otherwise, we have to show the open with dialog
+ AssociationsDialog dialog =
+ new AssociationsDialog(
+ ctx,
+ icon,
+ ctx.getString(title),
+ ctx.getString(action),
+ intent,
+ info,
+ mPreferredInfo,
+ allowPreferred);
+ dialog.show();
+ }
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/explorer/ui/policy/NewActionPolicy.java b/src/com/cyanogenmod/explorer/ui/policy/NewActionPolicy.java
new file mode 100644
index 0000000..fd29fbe
--- /dev/null
+++ b/src/com/cyanogenmod/explorer/ui/policy/NewActionPolicy.java
@@ -0,0 +1,234 @@
+/*
+ * 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.ui.policy;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Log;
+
+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.util.CommandHelper;
+import com.cyanogenmod.explorer.util.ExceptionUtil;
+
+import java.io.File;
+
+/**
+ * A class with the convenience methods for resolve new related actions
+ */
+public final class NewActionPolicy extends ActionsPolicy {
+
+ private static final String TAG = "NewActionPolicy"; //$NON-NLS-1$
+
+ private static boolean DEBUG = false;
+
+ /**
+ * Method that create the a new file system object.
+ *
+ * @param ctx The current context
+ * @param name The name of the file to be created
+ * @param onSelectionListener The selection listener (required)
+ * @param onRequestRefreshListener The listener for request a refresh after the new
+ * file was created (option)
+ */
+ public static void createNewFile(
+ final Context ctx, final String name,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+ createNewFileSystemObject(ctx, name, false, onSelectionListener, onRequestRefreshListener);
+ }
+
+ /**
+ * Method that create the a new folder system object.
+ *
+ * @param ctx The current context
+ * @param name The name of the file to be created
+ * @param onSelectionListener The selection listener (required)
+ * @param onRequestRefreshListener The listener for request a refresh after the new
+ * folder was created (option)
+ */
+ public static void createNewDirectory(
+ final Context ctx, final String name,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+ createNewFileSystemObject(ctx, name, true, onSelectionListener, onRequestRefreshListener);
+ }
+
+ /**
+ * Method that create the a new file system object.
+ *
+ * @param ctx The current context
+ * @param name The name of the file to be created
+ * @param folder If the new {@link FileSystemObject} to create is a folder (true) or a
+ * file (false).
+ * @param onSelectionListener The selection listener (required)
+ * @param onRequestRefreshListener The listener for request a refresh after the new
+ * folder was created (option)
+ */
+ private static void createNewFileSystemObject(
+ final Context ctx, final String name, final boolean folder,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ //Create the absolute file name
+ File newFso = new File(
+ onSelectionListener.onRequestCurrentDir(), name);
+ final String newName = newFso.getAbsolutePath();
+
+ try {
+ if (folder) {
+ if (DEBUG) {
+ Log.d(TAG, String.format("Creating new directory: %s", newName)); //$NON-NLS-1$
+ }
+ CommandHelper.createDirectory(ctx, newName, null);
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, String.format("Creating new file: %s", newName)); //$NON-NLS-1$
+ }
+ CommandHelper.createFile(ctx, newName, null);
+ }
+
+ //Operation complete. Show refresh
+ if (onRequestRefreshListener != null) {
+ FileSystemObject fso = null;
+ try {
+ fso = CommandHelper.getFileInfo(ctx, newName, false, null);
+ } catch (Throwable ex2) {
+ /**NON BLOCK**/
+ }
+ onRequestRefreshListener.onRequestRefresh(fso);
+ }
+ showOperationSuccessMsg(ctx);
+
+ } catch (Throwable ex) {
+ //Capture the exception
+ if (ex instanceof RelaunchableException) {
+ ExceptionUtil.attachAsyncTask(ex, new AsyncTask<Object, Integer, Boolean>() {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Boolean doInBackground(Object... params) {
+ //Operation complete. Show refresh
+ if (onRequestRefreshListener != null) {
+ FileSystemObject fso = null;
+ try {
+ fso =
+ CommandHelper.getFileInfo(ctx, newName, false, null);
+ } catch (Throwable ex2) {
+ /**NON BLOCK**/
+ }
+ onRequestRefreshListener.onRequestRefresh(fso);
+ }
+ return Boolean.TRUE;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (result != null && result.booleanValue()) {
+ showOperationSuccessMsg(ctx);
+ }
+ }
+ });
+ }
+ ExceptionUtil.translateException(ctx, ex);
+ }
+ }
+
+ /**
+ * Method that remove an existing file system object.
+ *
+ * @param ctx The current context
+ * @param src The source file system object
+ * @param lnkName The new name of the link
+ * @param onSelectionListener The listener for obtain selection information (required)
+ * @param onRequestRefreshListener The listener for request a refresh (optional)
+ */
+ public static void createSymlink(
+ final Context ctx,
+ final FileSystemObject src,
+ final String lnkName,
+ final OnSelectionListener onSelectionListener,
+ final OnRequestRefreshListener onRequestRefreshListener) {
+
+ //Create the absolute file name
+ File newFso = new File(
+ onSelectionListener.onRequestCurrentDir(), lnkName);
+ final String link = newFso.getAbsolutePath();
+
+ try {
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "Creating new symlink: %s -> %s", src.getFullPath(), link)); //$NON-NLS-1$
+ }
+ CommandHelper.createLink(ctx, src.getFullPath(), link, null);
+
+ //Operation complete. Show refresh
+ if (onRequestRefreshListener != null) {
+ FileSystemObject fso = null;
+ try {
+ fso = CommandHelper.getFileInfo(ctx, link, false, null);
+ } catch (Throwable ex2) {
+ /**NON BLOCK**/
+ }
+ onRequestRefreshListener.onRequestRefresh(fso);
+ }
+ showOperationSuccessMsg(ctx);
+
+ } catch (Throwable ex) {
+ //Capture the exception
+ if (ex instanceof RelaunchableException) {
+ ExceptionUtil.attachAsyncTask(ex, new AsyncTask<Object, Integer, Boolean>() {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Boolean doInBackground(Object... params) {
+ //Operation complete. Show refresh
+ if (onRequestRefreshListener != null) {
+ FileSystemObject fso = null;
+ try {
+ fso = CommandHelper.getFileInfo(ctx, link, false, null);
+ } catch (Throwable ex2) {
+ /**NON BLOCK**/
+ }
+ onRequestRefreshListener.onRequestRefresh(fso);
+ }
+ return Boolean.TRUE;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (result != null && result.booleanValue()) {
+ showOperationSuccessMsg(ctx);
+ }
+ }
+
+ });
+ }
+ ExceptionUtil.translateException(ctx, ex);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/explorer/ui/widgets/NavigationView.java b/src/com/cyanogenmod/explorer/ui/widgets/NavigationView.java
index 66d0007..7ef697e 100644
--- a/src/com/cyanogenmod/explorer/ui/widgets/NavigationView.java
+++ b/src/com/cyanogenmod/explorer/ui/widgets/NavigationView.java
@@ -48,7 +48,8 @@ import com.cyanogenmod.explorer.preferences.NavigationLayoutMode;
import com.cyanogenmod.explorer.preferences.ObjectIdentifier;
import com.cyanogenmod.explorer.preferences.ObjectStringIdentifier;
import com.cyanogenmod.explorer.preferences.Preferences;
-import com.cyanogenmod.explorer.ui.policy.ActionsPolicy;
+import com.cyanogenmod.explorer.ui.policy.InfoActionPolicy;
+import com.cyanogenmod.explorer.ui.policy.IntentsActionPolicy;
import com.cyanogenmod.explorer.util.CommandHelper;
import com.cyanogenmod.explorer.util.DialogHelper;
import com.cyanogenmod.explorer.util.ExceptionUtil;
@@ -753,19 +754,19 @@ public class NavigationView extends RelativeLayout implements
// Show content description
else if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.SHOW_CONTENT_DESCRIPTION) == 0) {
- ActionsPolicy.showContentDescription(getContext(), fso);
+ InfoActionPolicy.showContentDescription(getContext(), fso);
}
// Open with
else if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.OPEN_WITH) == 0) {
- ActionsPolicy.openFileSystemObject(getContext(), fso, true);
+ IntentsActionPolicy.openFileSystemObject(getContext(), fso, true);
}
// Show properties
else if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.SHOW_PROPERTIES) == 0) {
- ActionsPolicy.showPropertiesDialog(getContext(), fso, this);
+ InfoActionPolicy.showPropertiesDialog(getContext(), fso, this);
}
// Show actions
@@ -798,7 +799,7 @@ public class NavigationView extends RelativeLayout implements
changeCurrentDir(fso.getFullPath(), searchInfo);
} else {
// Open the file with the preferred registered app
- ActionsPolicy.openFileSystemObject(getContext(), fso, false);
+ IntentsActionPolicy.openFileSystemObject(getContext(), fso, false);
}
}
@@ -821,7 +822,7 @@ public class NavigationView extends RelativeLayout implements
}
} else {
// Open the file with the preferred registered app
- ActionsPolicy.openFileSystemObject(getContext(), fso, false);
+ IntentsActionPolicy.openFileSystemObject(getContext(), fso, false);
}
} catch (Throwable ex) {
ExceptionUtil.translateException(getContext(), ex);