package gem.kevin.widget;
import gem.kevin.provider.ClipSourceProvider;
import gem.kevin.task.FileOperationTask;
import gem.kevin.task.FileOperationTask.ClipOpTaskListener;
import gem.kevin.util.DataUtil;
import gem.kevin.util.FileUtil;
import gem.kevin.util.FileUtil.SimpleRenameCallback;
import gem.kevin.util.StorageUtil;
import java.io.File;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import com.sparseboolean.ifexplorer.FileItem;
import com.sparseboolean.ifexplorer.R;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class ClipItemAdapter extends MutualAdapter implements
ClipOpTaskListener {
public interface ClipItemManager {
public String getClipPasteDir();
public DeleteDelegate getDeleteDelegate();
public PasteDelegate getPasteDelegate();
public void onClipItemFinished(ClipItemAdapter adapter);
public void onClipItemRemoved(ClipItemAdapter adapter);
}
public interface DeleteDelegate {
public void cancelDelete(ClipItemAdapter assignor, boolean rollback);
public void doDelete(HashSet<FileClip> toDelete,
ClipItemAdapter assignor);
public void showDeleteUi();
}
public interface PasteDelegate {
public void cancelPaste(ClipItemAdapter assignor, boolean rollback);
public void doPaste(HashSet<FileClip> toPaste, String pasteDir,
ClipItemAdapter assignor);
public void showPasteUi();
}
private static class ClipItemViewHolder {
TextView nameTextView;
ImageView iconImageView;
}
private static final String TAG = "ClipItemAdapter";
private static final boolean KLOG = false;
public static final int MSG_FILE_TASKS_READY = 1;
public static final int MSG_FILE_TASKS_FINISHED = 2;
public static final int MSG_FILE_TASKS_EXECUTING = 3;
public static final int MSG_FILE_TASKS_CANCELING = 4;
public static final int MSG_FILE_TASKS_CANCELED = 5;
public static final int MSG_FILE_TASKS_STOPPED = 6;
public static final int MSG_FILE_TASKS_UNVAILABLE = 7;
public static final int MSG_FILE_TASKS_EVALUATING = 8;
public static final int MSG_FILE_TASKS_ROLLBACKED = 9;
public static final int MSG_FILE_TASKS_PENDING_COPY = 10;
public static final int MSG_FILE_TASKS_PENDING_DELETE = 11;
public static final int MSG_FILE_TASKS_PENDING_RENAME = 12;
public static final int STATUS_NO_CLIP = -1;
public static final int STATUS_NO_VALID_CLIP = -2;
public static final int STATUS_CANNOT_HANDLE = -3;
public static final int STATUS_SHOULD_WAIT = 1;
public static final int STATUS_SHOULD_SHOW_PROGRESS = 2;
public static final int STATUS_NO_NEED_PROGRESS = 3;
public static final long SIZE_THRESHOLD_SHOW_COPY_PROGRESS = 10 * 1024 * 1024; // in
// size/Bytes
public static final long COUNT_THRESHOLD_SHOW_DELETE_PROGRESS = 100; // in
// counts
public static final long NOT_SET = -1;
public static void renameSingleFile(Context context, String srcFilePath,
String targetFilePath) {
int ret = FileUtil
.renameFile(
srcFilePath,
targetFilePath,
(context instanceof SimpleRenameCallback) ? (SimpleRenameCallback) context
: null);
Resources resources = context.getResources();
String errStr;
if (ret == FileUtil.OP_SUCCESS) {
Toast.makeText(
context,
resources.getString(R.string.rename_succeed,
FileUtil.getFileName(srcFilePath),
FileUtil.getFileName(targetFilePath)),
Toast.LENGTH_SHORT).show();
} else {
errStr = FileUtil.getDefaultFileOpErrStr(resources, ret);
Toast.makeText(
context,
resources.getString(R.string.rename_failed,
FileUtil.getFileName(srcFilePath), errStr),
Toast.LENGTH_LONG).show();
}
}
private ClipItemManager mManager;
private HashSet<FileOperationTask> mOneshotFileOpTasks = null;
private boolean mClipExecuting = false;
// private long mTotalBytes = NOT_SET;
// private long mTotalFileCount = NOT_SET;
private int mTotalSubTaskNum = 0;
private int mSucceedSubTaskNum = 0;
private int mProcessedSubTaskNum = 0;
private int mSucceedPercentage = 0;
private int mProcessedPercentage = 0;
private String mProcessingFilePath = null;
private String mPendingSrcFilePath = null;
private String mPendingTargetFilePath = null;
private int mPendingReason;
private View mBoundClipContentView;
private View mBoundOneshotTaskView;
private TextView mBoundOneshotTaskStatus;
private ProgressBar mBoundOneshotProgress;
private String mId;
private Handler mUiHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_FILE_TASKS_UNVAILABLE:
confirmOnUnavailabeTask((FileOperationTask) msg.obj,
mPendingReason);
break;
case MSG_FILE_TASKS_EVALUATING:
updateInterativeClipUi(true, false, false, false,
mSucceedSubTaskNum, mSucceedPercentage,
mProcessedSubTaskNum, mProcessedPercentage, false,
false);
break;
case MSG_FILE_TASKS_EXECUTING:
updateInterativeClipUi(false, true, false, false,
mSucceedSubTaskNum, mSucceedPercentage,
mProcessedSubTaskNum, mProcessedPercentage, false,
false);
break;
case MSG_FILE_TASKS_CANCELING:
updateInterativeClipUi(false, false, true, false,
mSucceedSubTaskNum, mSucceedPercentage,
mProcessedSubTaskNum, mProcessedPercentage,
(mSucceedSubTaskNum == mTotalSubTaskNum), false);
break;
case MSG_FILE_TASKS_STOPPED:
updateInterativeClipUi(false, false, false, true,
mSucceedSubTaskNum, mSucceedPercentage,
mProcessedSubTaskNum, mProcessedPercentage,
(mSucceedSubTaskNum == mTotalSubTaskNum), false);
break;
case MSG_FILE_TASKS_CANCELED:
// Copy clip can be reused
if (getClipType() == ClipSourceProvider.CLIP_TYPE_COPY_SOURCE) {
switchBoundViewMode(false);
} else {
// treat as stopped state
updateInterativeClipUi(false, false, false, true,
mSucceedSubTaskNum, mSucceedPercentage,
mProcessedSubTaskNum, mProcessedPercentage,
(mSucceedSubTaskNum == mTotalSubTaskNum), false);
}
break;
case MSG_FILE_TASKS_ROLLBACKED:
updateInterativeClipUi(false, false, false, false,
mSucceedSubTaskNum, mSucceedPercentage,
mProcessedSubTaskNum, mProcessedPercentage, false, true);
break;
case MSG_FILE_TASKS_FINISHED:
updateInterativeClipUi(false, false, false, false,
mSucceedSubTaskNum, mSucceedPercentage,
mProcessedSubTaskNum, mProcessedPercentage,
(mSucceedSubTaskNum == mTotalSubTaskNum), false);
break;
case MSG_FILE_TASKS_READY:
FileOperationTask task = (FileOperationTask) msg.obj;
showClipUiIfNecessary(task);
break;
case MSG_FILE_TASKS_PENDING_COPY:
confirmOnPendingCopyTask((FileOperationTask) msg.obj,
mPendingReason);
break;
case MSG_FILE_TASKS_PENDING_DELETE:
confirmOnPendingDeleteTask((FileOperationTask) msg.obj,
mPendingReason);
break;
case MSG_FILE_TASKS_PENDING_RENAME:
confirmOnPendingRenameTask((FileOperationTask) msg.obj,
mPendingReason);
break;
default:
super.handleMessage(msg);
}
}
};
public static final float CLIP_TYPE_UNBOUND = -1.0f;
public static final String CLIP_DATA_FIELD_FILE_PATH = "file_path";
public static final String CLIP_DATA_FIELD_FILE_NAME = "file_name";
public static final String CLIP_DATA_FIELD_FILE_ICON = "file_icon";
private int mDisplayItemNum = -1;
public ClipItemAdapter(Context context,
List<? extends Map<String, ?>> data, int resource, String[] from,
int[] to) {
super(context, null, resource, from, to);
}
public void applyOnCopyErrorPolicy(FileOperationTask fileOpTask,
boolean skip) {
if (skip) {
fileOpTask.getOptions().skipAllCopyError = true;
} else {
fileOpTask.getOptions().skipAllCopyError = false;
}
}
public void applyOnDeleteErrorPolicy(FileOperationTask fileOpTask,
boolean skip) {
if (skip) {
fileOpTask.getOptions().skipAllDeleteError = true;
} else {
fileOpTask.getOptions().skipAllDeleteError = false;
}
}
public void applyOnRenameErrorPolicy(FileOperationTask fileOpTask,
boolean skip) {
if (skip) {
fileOpTask.getOptions().skipAllRenameError = true;
} else {
fileOpTask.getOptions().skipAllRenameError = false;
}
}
public void applyOverwritePolicy(FileOperationTask fileOpTask,
boolean overwrite) {
if (overwrite) {
fileOpTask.getOptions().overwriteAllExist = true;
fileOpTask.getOptions().skipAllExist = false;
} else {
fileOpTask.getOptions().skipAllExist = true;
fileOpTask.getOptions().overwriteAllExist = false;
}
}
public void bindInterativeClipUi(View clipContentView,
View oneshotTaskView, TextView oneshotStatus,
ProgressBar oneshotProgress, AbsListView repeatableTaskList) {
mBoundClipContentView = clipContentView;
mBoundOneshotTaskView = oneshotTaskView;
mBoundOneshotTaskStatus = oneshotStatus;
mBoundOneshotProgress = oneshotProgress;
}
public void cancelFileClip() {
if (mManager == null) {
return;
} else {
float clipType = getClipType();
if (clipType == ClipSourceProvider.CLIP_TYPE_COPY_SOURCE
|| clipType == ClipSourceProvider.CLIP_TYPE_CUT_SOURCE) {
PasteDelegate delegate = mManager.getPasteDelegate();
if (delegate != null) {
delegate.cancelPaste(this, false);
}
} else if (clipType == ClipSourceProvider.CLIP_TYPE_DELETE_SOURCE) {
DeleteDelegate delegate = mManager.getDeleteDelegate();
if (delegate != null) {
delegate.cancelDelete(this, false);
}
} else {
return;
}
}
}
public void deleteFileClip(HashSet<FileClip> toDelete) {
if (mManager == null) {
return;
} else {
if (toDelete.size() != 0) {
DeleteDelegate delegate = mManager.getDeleteDelegate();
if (delegate != null) {
delegate.doDelete(toDelete, this);
}
}
}
}
public void executeFileClip(HashSet<FileClip> toExecute) {
float clipType = getClipType();
if (clipType == ClipSourceProvider.CLIP_TYPE_COPY_SOURCE
|| clipType == ClipSourceProvider.CLIP_TYPE_CUT_SOURCE) {
pasteFileClip(toExecute);
} else if (clipType == ClipSourceProvider.CLIP_TYPE_DELETE_SOURCE) {
deleteFileClip(toExecute);
}
}
public int fetchFileClips(HashSet<FileClip> result) {
if (!isBound()) {
return STATUS_NO_CLIP;
}
ClipSourceProvider provider = (ClipSourceProvider) getBoundMutualSourceProvider();
float clipType = provider.getClipType();
HashSet<Object> rawData = provider.getMutualSources();
int total = rawData.size();
int fetched = 0;
for (Object item : rawData) {
if (item instanceof FileItem
&& FileUtil.isExistingFilePath(((FileItem) item).getPath())) {
result.add(new FileClip(clipType, ((FileItem) item).getPath()));
fetched++;
}
}
return total - fetched;
}
public float getClipType() {
return (isBound()) ? ((ClipSourceProvider) getBoundMutualSourceProvider())
.getClipType() : CLIP_TYPE_UNBOUND;
}
public int getDisplayItemNum() {
return mDisplayItemNum;
}
public String getId() {
return mId;
}
public HashSet<FileOperationTask> getOneShotClipTask() {
return mOneshotFileOpTasks;
}
public int getPendingReason() {
return mPendingReason;
}
public String getPendingSrcFilePath() {
return mPendingSrcFilePath;
}
public String getPendingTargetFilePath() {
return mPendingTargetFilePath;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ClipItemViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(mResource,
null);
viewHolder = new ClipItemViewHolder();
viewHolder.nameTextView = (TextView) convertView
.findViewById(R.id.item_name);
viewHolder.iconImageView = (ImageView) convertView
.findViewById(R.id.item_icon);
convertView.setTag(viewHolder);
} else {
viewHolder = (ClipItemViewHolder) convertView.getTag();
}
if (position == (mDisplayItemNum - 1) && getCount() > mDisplayItemNum) {
viewHolder.iconImageView.setImageResource(R.drawable.file_stack);
viewHolder.nameTextView.setText(R.string.otherClips);
return convertView;
}
@SuppressWarnings("rawtypes")
final Map clipItemData = (Map) getItem(position);
final String path = (String) clipItemData
.get(CLIP_DATA_FIELD_FILE_PATH);
final File file = new File(path);
if (file != null && file.isFile()) {
String ext = file.toString();
String sub_ext = ext.substring(ext.lastIndexOf(".") + 1);
// if (sub_ext.equalsIgnoreCase("apk")) {
// Drawable icon = DataUtil.getNonInstalledAppIcon(getContext(),
// path);
// viewHolder.iconImageView.setImageDrawable(icon);
// } else {
viewHolder.iconImageView.setImageResource(DataUtil
.getFileIconResId(sub_ext));
// }
}
if (file != null && file.isDirectory()) {
viewHolder.iconImageView.setImageResource(R.drawable.folder);
}
String fullName = file.getName();
String displayName;
if (fullName.length() > 18) {
displayName = String
.format("%s...%s",
fullName.substring(0, 6),
fullName.substring(fullName.length() - 7,
fullName.length()));
} else {
displayName = fullName;
}
viewHolder.nameTextView.setText(displayName);
return convertView;
}
public boolean isClipExecuting() {
return mClipExecuting;
}
@Override
public String localeSensitiveCopyName(String srcName,
int existDuplicateCount) {
Log.i(TAG, "srcName is: " + srcName);
String countStr = (existDuplicateCount > 1) ? String.format(" %d",
existDuplicateCount) : "";
return getContext().getResources().getString(R.string.copy_file_name,
srcName, countStr);
}
@Override
public void onClipOpTaskCanceled(FileOperationTask canceledTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(canceledTask)) {
Message cancelingMsg = mUiHandler
.obtainMessage(MSG_FILE_TASKS_CANCELING);
mUiHandler.sendMessage(cancelingMsg);
// unlock correspond mutual sources when all tasks idle
Log.i(TAG, "unlock mutual sources due to task canceled.");
unlockMutualSourcesIfAvailable();
Message canceledMsg = mUiHandler
.obtainMessage(MSG_FILE_TASKS_CANCELED);
mUiHandler.sendMessageDelayed(canceledMsg, 500);
}
}
@Override
public void onClipOpTaskEvaluating(FileOperationTask evaluatingTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(evaluatingTask)) {
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_EVALUATING);
msg.obj = evaluatingTask;
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskFinished(FileOperationTask finishedTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(finishedTask)) {
// on last processing
onClipOpTaskProgressing(finishedTask);
mProcessingFilePath = null;
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_FINISHED);
mUiHandler.sendMessage(msg);
// unlock correspond mutual sources when all tasks idle
Log.i(TAG, "unlock mutual sources due to task finished.");
unlockMutualSourcesIfAvailable();
}
}
@Override
public void onClipOpTaskPendingOnCopyError(FileOperationTask pendingTask,
String srcPath, String targetPath, int errorCode) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(pendingTask)) {
// on last processing
// onFileOpTaskProgressing(pendingTask);
mProcessingFilePath = null;
mPendingSrcFilePath = srcPath;
mPendingTargetFilePath = targetPath;
mPendingReason = errorCode;
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_PENDING_COPY);
msg.obj = pendingTask;
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskPendingOnDeleteError(FileOperationTask pendingTask,
String srcPath, int errorCode) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(pendingTask)) {
// on last processing
// onFileOpTaskProgressing(pendingTask);
mProcessingFilePath = null;
mPendingSrcFilePath = srcPath;
mPendingTargetFilePath = null;
mPendingReason = errorCode;
Message msg = mUiHandler
.obtainMessage(MSG_FILE_TASKS_PENDING_DELETE);
msg.obj = pendingTask;
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskPendingOnExists(FileOperationTask pendingTask,
String srcPath, String existFilePath) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(pendingTask)) {
// on last processing
// onFileOpTaskProgressing(pendingTask);
mProcessingFilePath = null;
mPendingSrcFilePath = srcPath;
mPendingTargetFilePath = existFilePath;
mPendingReason = FileUtil.ERROR_FILE_EXISTS;
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_PENDING_COPY);
msg.obj = pendingTask;
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskPendingOnRenameError(FileOperationTask pendingTask,
String srcPath, String targetPath, int errorCode) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(pendingTask)) {
// on last processing
// onFileOpTaskProgressing(pendingTask);
mProcessingFilePath = null;
mPendingSrcFilePath = srcPath;
mPendingTargetFilePath = targetPath;
mPendingReason = errorCode;
Message msg = mUiHandler
.obtainMessage(MSG_FILE_TASKS_PENDING_RENAME);
msg.obj = pendingTask;
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskProgressing(FileOperationTask processingTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(processingTask)) {
syncFileOperationTaskStatus();
mProcessingFilePath = processingTask.getCurrentProcessingFilePath();
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_EXECUTING);
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskReady(FileOperationTask readyTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(readyTask)) {
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_READY);
msg.obj = readyTask;
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskRollbacked(FileOperationTask newTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(newTask)) {
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_ROLLBACKED);
msg.obj = newTask;
mUiHandler.sendMessage(msg);
}
}
@Override
public void onClipOpTaskStarted(FileOperationTask startedTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(startedTask)) {
// lock correspond mutual sources when any task started
lockMutualSources();
}
}
@Override
public void onClipOpTaskStopped(FileOperationTask stoppedTask) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(stoppedTask)) {
onClipOpTaskProgressing(stoppedTask);
mProcessingFilePath = null;
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_STOPPED);
mUiHandler.sendMessage(msg);
// unlock correspond mutual sources when all tasks idle
Log.i(TAG, "unlock mutual sources due to task stopped.");
unlockMutualSourcesIfAvailable();
}
}
@Override
public void onClipOpTaskUnavailable(FileOperationTask unavailableTask,
int reason) {
if (mOneshotFileOpTasks != null
&& mOneshotFileOpTasks.contains(unavailableTask)) {
mPendingReason = reason;
Message msg = mUiHandler.obtainMessage(MSG_FILE_TASKS_UNVAILABLE);
msg.obj = unavailableTask;
mUiHandler.sendMessage(msg);
}
}
public void pasteFileClip(HashSet<FileClip> toPaste) {
if (mManager == null) {
return;
} else {
String defaultPasteDir = mManager.getClipPasteDir();
if (defaultPasteDir != null) {
pasteFileClip(toPaste, defaultPasteDir);
} else {
confirmOnInvalidPasteDir();
}
}
}
public void pasteFileClip(HashSet<FileClip> toPaste, String pasteDir) {
if (toPaste == null || pasteDir == null) {
return;
}
if (toPaste.size() != 0) {
PasteDelegate delegate = mManager.getPasteDelegate();
if (delegate != null) {
delegate.doPaste(toPaste, pasteDir, this);
}
}
}
public HashSet<FileClip> prepare() {
HashSet<FileClip> toHandle = new HashSet<FileClip>();
int invalid = fetchFileClips(toHandle);
if (invalid > 0) {
Context context = getContext();
Resources resources = context.getResources();
Toast.makeText(
context,
resources.getString(R.string.invalid_clip_removed, invalid),
Toast.LENGTH_SHORT).show();
} else if (invalid == ClipItemAdapter.STATUS_NO_CLIP) {
Context context = getContext();
Resources resources = context.getResources();
Toast.makeText(context,
resources.getString(R.string.no_available_clip),
Toast.LENGTH_SHORT).show();
}
return toHandle;
}
public void setClipItemManager(ClipItemManager manager) {
mManager = manager;
}
public void setDisplayItemNum(int num) {
mDisplayItemNum = num;
}
public void setId(String id) {
mId = id;
}
public void setOneShotClipTask(HashSet<FileOperationTask> fileOpTasks) {
mOneshotFileOpTasks = fileOpTasks;
}
private void confirmOnCopyPermissionDeny(
final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
String message = resources.getString(R.string.no_permission_read_file,
getPendingSrcFilePath());
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.error_permission_deny)
.setPositiveButton(R.string.skip,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.setSkipCopyErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNeutralButton(R.string.skip_all,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
applyOnCopyErrorPolicy(taskNeedConfirm, true);
taskNeedConfirm.setSkipCopyErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNegativeButton(R.string.stop_task,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.cancel();
}
}).setMessage(message).create();
dialog.show();
}
private void confirmOnDeletePermissionDeny(
final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
String message = resources.getString(
R.string.no_permission_delete_file, getPendingSrcFilePath());
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.error_permission_deny)
.setPositiveButton(R.string.skip,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.setSkipDeleteErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNeutralButton(R.string.skip_all,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
applyOnDeleteErrorPolicy(taskNeedConfirm, true);
taskNeedConfirm.setSkipDeleteErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNegativeButton(R.string.stop_task,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.cancel();
}
}).setMessage(message).create();
dialog.show();
}
private void confirmOnFileExists(final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
View contentRootView = LayoutInflater.from(context).inflate(
R.layout.overwrite_confirm_dialog, null);
final CheckBox applyToAll = (CheckBox) contentRootView
.findViewById(R.id.applyToAll);
final TextView srcPathText = (TextView) contentRootView
.findViewById(R.id.srcPath);
final TextView srcSizeText = (TextView) contentRootView
.findViewById(R.id.srcSize);
final TextView srcModTimeText = (TextView) contentRootView
.findViewById(R.id.srcModTime);
final TextView targetPathText = (TextView) contentRootView
.findViewById(R.id.targetPath);
final TextView targetSizeText = (TextView) contentRootView
.findViewById(R.id.targetSize);
final TextView targetModTimeText = (TextView) contentRootView
.findViewById(R.id.targetModTime);
String srcPath = getPendingSrcFilePath();
String srcPathStr = resources.getString(R.string.source_file) + ":"
+ srcPath;
String srcSizeStr = resources.getString(R.string.size) + ":"
+ FileUtil.formattedSizeStr(FileUtil.getFileSize(srcPath));
long srcLastMod = FileUtil.getLastModifyTime(srcPath);
String srcModTimeStr = resources.getString(R.string.modified)
+ ":"
+ (new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(
srcLastMod)));
String targetPath = getPendingTargetFilePath();
String targetPathStr = resources.getString(R.string.dest_file) + ":"
+ targetPath;
String targetSizeStr = resources.getString(R.string.size) + ":"
+ FileUtil.formattedSizeStr(FileUtil.getFileSize(targetPath));
long targetLastMod = FileUtil.getLastModifyTime(targetPath);
String targetModTimeStr = resources.getString(R.string.modified)
+ ":"
+ (new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(
targetLastMod)));
if (targetLastMod > srcLastMod) {
targetModTimeStr = targetModTimeStr + " "
+ resources.getString(R.string.newer);
} else {
srcModTimeStr = srcModTimeStr + " "
+ resources.getString(R.string.newer);
}
srcPathText.setText(srcPathStr);
srcSizeText.setText(srcSizeStr);
srcModTimeText.setText(srcModTimeStr);
targetPathText.setText(targetPathStr);
targetSizeText.setText(targetSizeStr);
targetModTimeText.setText(targetModTimeStr);
String message = resources.getString(R.string.overwrite_prompt) + "\n"
+ FileUtil.getFileName(srcPath);
AlertDialog dialog = new AlertDialog.Builder(getContext())
.setTitle(R.string.overwrite)
.setView(contentRootView)
.setPositiveButton(R.string.overwrite,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
if (applyToAll.isChecked()) {
applyOverwritePolicy(taskNeedConfirm, true);
}
taskNeedConfirm.setSkipExistOnce(false);
taskNeedConfirm.resume();
}
})
.setNegativeButton(R.string.skip,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
if (applyToAll.isChecked()) {
applyOverwritePolicy(taskNeedConfirm, false);
}
taskNeedConfirm.setSkipExistOnce(true);
taskNeedConfirm.resume();
}
}).setMessage(message).create();
dialog.show();
}
private void confirmOnInvalidPasteDir() {
Context context = getContext();
Resources resources = context.getResources();
Toast.makeText(context,
resources.getString(R.string.invalid_paste_dir),
Toast.LENGTH_SHORT).show();
}
private void confirmOnMovePermissionDeny(
final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
String message = resources.getString(R.string.no_permission_move_file,
getPendingSrcFilePath());
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.error_permission_deny)
.setPositiveButton(R.string.skip,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.setSkipCopyErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNeutralButton(R.string.skip_all,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
applyOnCopyErrorPolicy(taskNeedConfirm, true);
taskNeedConfirm.setSkipCopyErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNegativeButton(R.string.stop_task,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.cancel();
}
}).setMessage(message).create();
dialog.show();
}
private void confirmOnNoEnoughSpace(final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
String requiredSpaceStr = resources.getString(
R.string.required_space,
Formatter.formatFileSize(context,
taskNeedConfirm.getRequiredSpace()));
String availableSpaceStr = resources.getString(
R.string.available_space,
Formatter.formatFileSize(context,
taskNeedConfirm.getAvailableSpace()));
String message = requiredSpaceStr + "\n\n" + availableSpaceStr;
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.error_space_insufficient)
.setPositiveButton(R.string.dlg_ok, null).setMessage(message)
.create();
dialog.show();
}
private void confirmOnNoSpace(final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
String defaultStorageName = resources.getString(R.string.dest_storage);
String storageName = getStorageName(getPendingTargetFilePath());
String message = resources.getString(R.string.storage_insufficient,
storageName != null ? storageName : defaultStorageName);
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.error_space_insufficient)
.setPositiveButton(R.string.dlg_ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.cancel();
}
}).setMessage(message).create();
dialog.show();
}
private void confirmOnPendingCopyTask(
final FileOperationTask taskNeedConfirm, int errorCode) {
switch (errorCode) {
case FileUtil.ERROR_FILE_EXISTS:
confirmOnFileExists(taskNeedConfirm);
break;
case FileUtil.ERROR_SOURCE_READ_DENY:
confirmOnCopyPermissionDeny(taskNeedConfirm);
break;
case FileUtil.ERROR_SOURCE_WRITE_DENY:
confirmOnMovePermissionDeny(taskNeedConfirm);
break;
case FileUtil.ERROR_TARGET_PERMISSION_DENY:
confirmOnWritePermissionDeny(taskNeedConfirm);
break;
case FileUtil.ERROR_NO_SPACE:
confirmOnNoSpace(taskNeedConfirm);
break;
// TOTO: handle more errors
}
}
private void confirmOnPendingDeleteTask(
final FileOperationTask taskNeedConfirm, int errorCode) {
switch (errorCode) {
case FileUtil.ERROR_SOURCE_WRITE_DENY:
confirmOnDeletePermissionDeny(taskNeedConfirm);
break;
}
}
private void confirmOnPendingRenameTask(
final FileOperationTask taskNeedConfirm, int errorCode) {
switch (errorCode) {
case FileUtil.ERROR_SOURCE_WRITE_DENY:
confirmOnRenamePermissionDeny(taskNeedConfirm);
break;
}
}
private void confirmOnRenamePermissionDeny(
final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
String message = resources.getString(R.string.no_permission_move_file,
getPendingSrcFilePath());
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.error_permission_deny)
.setPositiveButton(R.string.skip,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.setSkipRenameErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNeutralButton(R.string.skip_all,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
applyOnRenameErrorPolicy(taskNeedConfirm, true);
taskNeedConfirm.setSkipRenameErrorOnce(true);
taskNeedConfirm.resume();
}
})
.setNegativeButton(R.string.stop_task,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.cancel();
}
}).setMessage(message).create();
dialog.show();
}
private void confirmOnUnavailabeTask(
final FileOperationTask taskUnavailable, int reason) {
switch (reason) {
case FileOperationTask.OP_UNAVAILABLE_SRC_NULL:
// TODO
break;
case FileOperationTask.OP_UNAVAILABLE_SRC_EMPTY:
break;
case FileOperationTask.OP_UNAVAILABLE_DEST_NULL:
break;
case FileOperationTask.OP_UNAVAILABLE_DEST_NOSPACE:
confirmOnNoEnoughSpace(taskUnavailable);
break;
}
}
private void confirmOnWritePermissionDeny(
final FileOperationTask taskNeedConfirm) {
Context context = getContext();
Resources resources = context.getResources();
String message = resources.getString(R.string.no_permission_write_file,
getPendingTargetFilePath());
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.error_permission_deny)
.setPositiveButton(R.string.dlg_ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
taskNeedConfirm.cancel();
}
}).setMessage(message).create();
dialog.show();
}
private String getStorageName(String filePath) {
if (filePath == null) {
return null;
}
StorageUtil util = StorageUtil.getSingleton(getContext());
if (util != null) {
String mountPoint = util.getMountpoint(filePath);
if (mountPoint != null) {
return util
.getCachedId(mountPoint, StorageUtil.VOLID_TAG_LABEL);
} else {
return null;
}
} else {
return null;
}
}
private boolean isAllFileOpTaskIdle() {
for (FileOperationTask task : mOneshotFileOpTasks) {
if (!task.isIdle()) {
return false;
}
}
return true;
}
private void lockMutualSources() {
ClipSourceProvider provider = (ClipSourceProvider) getBoundMutualSourceProvider();
if (provider != null) {
Log.i(TAG, "Lock mutual sources due to purpose: " + getClipType());
provider.lockMutualSources(getClipType());
}
mClipExecuting = true;
}
private void showClipUiIfNecessary(final FileOperationTask task) {
long evalCopyBytes = task.getSouceCopySize();
long evalDeleteCount = task.getSourceFileCount();
if (evalCopyBytes > SIZE_THRESHOLD_SHOW_COPY_PROGRESS) {
PasteDelegate delegate = mManager.getPasteDelegate();
if (delegate != null) {
delegate.showPasteUi();
}
}
if (evalDeleteCount > COUNT_THRESHOLD_SHOW_DELETE_PROGRESS) {
DeleteDelegate delegate = mManager.getDeleteDelegate();
if (delegate != null) {
delegate.showDeleteUi();
}
}
}
private void switchBoundViewMode(boolean showTaskView) {
if (mBoundClipContentView != null) {
mBoundClipContentView.setVisibility(showTaskView ? View.GONE
: View.VISIBLE);
}
if (mBoundOneshotTaskView != null) {
mBoundOneshotTaskView.setVisibility(showTaskView ? View.VISIBLE
: View.GONE);
}
}
private void syncFileOperationTaskStatus() {
if (mOneshotFileOpTasks == null) {
return;
}
synchronized (mOneshotFileOpTasks) {
mTotalSubTaskNum = 0;
mSucceedSubTaskNum = 0;
mProcessedSubTaskNum = 0;
mSucceedPercentage = 0;
mProcessedPercentage = 0;
for (FileOperationTask task : mOneshotFileOpTasks) {
mTotalSubTaskNum += task.getSubTaskNum();
mSucceedSubTaskNum += task.getSucceedSubTaskNum();
mProcessedSubTaskNum += task.getProcessedSubTaskNum();
mSucceedPercentage += task.getSucceedPecentage();
mProcessedPercentage += task.getProcessedPecentage();
}
}
if (KLOG) {
Log.i(TAG, "syncFileOperationTaskStatus --- totalSubTaskNum:"
+ mTotalSubTaskNum + " succeedSubTaskNum: "
+ mSucceedSubTaskNum + " succeedPercentage: "
+ mSucceedPercentage + " processedSubTaskNum: "
+ mProcessedSubTaskNum + " processedPercentage: "
+ mProcessedPercentage);
}
}
private void unlockMutualSourcesIfAvailable() {
if (isAllFileOpTaskIdle()) {
ClipSourceProvider provider = (ClipSourceProvider) getBoundMutualSourceProvider();
if (provider != null) {
Log.i(TAG, "Unock mutual sources");
provider.unLockMutualSources();
}
mClipExecuting = false;
}
}
private void updateInterativeClipUi(boolean clipEvaluating,
boolean clipExecuting, boolean clipCanceling, boolean clipStopped,
int succeedCount, int succeedPercentage, int processedCount,
int processedPercentage, boolean clipFinished,
boolean clipRollbacked) {
if (clipFinished || clipStopped) {
switchBoundViewMode(false);
if (mManager != null) {
mManager.onClipItemFinished(this);
}
return;
} else {
if (clipRollbacked) {
switchBoundViewMode(false);
return;
}
}
switchBoundViewMode(clipEvaluating || clipExecuting || clipCanceling);
if (mBoundOneshotTaskStatus != null) {
String info = "";
Context context = getContext();
Resources resources = context.getResources();
String extraInfo = (this.getClipType() == ClipSourceProvider.CLIP_TYPE_COPY_SOURCE) ? resources
.getString(R.string.copying_) : resources
.getString(R.string.moving_);
if (clipCanceling) {
info = resources.getString(R.string.canceling);
} else if (clipExecuting) {
if (mProcessingFilePath != null) {
String filePath;
try {
filePath = new String(mProcessingFilePath);
} catch (NullPointerException e) {
filePath = "";
}
int pathLength = filePath.length();
if (pathLength < 48) {
extraInfo = extraInfo + filePath;
} else {
extraInfo = extraInfo
+ filePath.substring(0, 36)
+ "...."
+ filePath
.substring(pathLength - 8, pathLength);
}
info = String.format("%d/%d - %d%% %s",
(succeedPercentage < 100) ? succeedCount + 1
: succeedCount, ClipItemAdapter.this
.getCount(), succeedPercentage, extraInfo);
} else {
info = String.format("%d/%d - %d%%",
(succeedPercentage < 100) ? succeedCount + 1
: succeedCount, ClipItemAdapter.this
.getCount(), succeedPercentage);
}
} else if (clipEvaluating) {
info = resources.getString(R.string.calculating);
}
mBoundOneshotTaskStatus.setText(info);
}
if (mBoundOneshotProgress != null) {
mBoundOneshotProgress.setProgress(succeedPercentage);
// mBoundOneshotProgress.setSecondaryProgress(succeedPercentage +
// 10);
}
}
}