merge in OI distribution
[android_pandora.git] / apps / oi-filemanager / FileManager / src / org / openintents / filemanager / FileManagerActivity.java
1 /* 
2  * Copyright (C) 2008 OpenIntents.org
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Based on AndDev.org's file browser V 2.0.
19  */
20
21 package org.openintents.filemanager;
22
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.LinkedList;
29 import java.util.List;
30
31 import org.openintents.filemanager.DistributionLibraryListActivity;
32 import org.openintents.filemanager.util.CompressManager;
33 import org.openintents.filemanager.util.ExtractManager;
34 import org.openintents.filemanager.util.FileUtils;
35 import org.openintents.filemanager.util.MimeTypeParser;
36 import org.openintents.filemanager.util.MimeTypes;
37 import org.openintents.intents.FileManagerIntents;
38 import org.openintents.util.MenuIntentOptionsWithIcons;
39 import org.xmlpull.v1.XmlPullParserException;
40
41 import android.app.AlertDialog;
42 import android.app.Dialog;
43 import android.content.ActivityNotFoundException;
44 import android.content.ComponentName;
45 import android.content.ContentValues;
46 import android.content.Context;
47 import android.content.DialogInterface;
48 import android.content.DialogInterface.OnCancelListener;
49 import android.content.DialogInterface.OnClickListener;
50 import android.content.Intent;
51 import android.content.SharedPreferences;
52 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
53 import android.content.pm.ActivityInfo;
54 import android.content.pm.PackageManager;
55 import android.content.pm.PackageManager.NameNotFoundException;
56 import android.content.pm.ResolveInfo;
57 import android.content.res.XmlResourceParser;
58 import android.database.Cursor;
59 import android.graphics.drawable.Drawable;
60 import android.net.Uri;
61 import android.os.AsyncTask;
62 import android.os.Bundle;
63 import android.os.Handler;
64 import android.os.IBinder;
65 import android.os.Message;
66 import android.os.Parcelable;
67 import android.preference.PreferenceManager;
68 import android.support.v2.os.Build;
69 import android.support.v2.view.MenuCompat;
70 import android.text.TextUtils;
71 import android.util.Log;
72 import android.view.ContextMenu;
73 import android.view.ContextMenu.ContextMenuInfo;
74 import android.view.inputmethod.EditorInfo;
75 import android.view.KeyEvent;
76 import android.view.LayoutInflater;
77 import android.view.Menu;
78 import android.view.MenuItem;
79 import android.view.View;
80 import android.view.View.OnKeyListener;
81 import android.view.Window;
82 import android.widget.AbsListView;
83 import android.widget.AbsListView.OnScrollListener;
84 import android.widget.AdapterView;
85 import android.widget.AdapterView.AdapterContextMenuInfo;
86 import android.widget.BaseAdapter;
87 import android.widget.Button;
88 import android.widget.CheckBox;
89 import android.widget.EditText;
90 import android.widget.ImageButton;
91 import android.widget.ImageView;
92 import android.widget.LinearLayout;
93 import android.widget.ListView;
94 import android.widget.ProgressBar;
95 import android.widget.TextView;
96 import android.widget.Toast;
97
98 public class FileManagerActivity extends DistributionLibraryListActivity implements OnSharedPreferenceChangeListener { 
99         private static final String TAG = "FileManagerActivity";
100
101         private static final String NOMEDIA_FILE = ".nomedia";
102
103     private static final String DIALOG_EXISTS_ACTION_RENAME = "action_rename";
104     private static final String DIALOG_EXISTS_ACTION_MULTI_COMPRESS_ZIP = "action_multi_compress_zip";
105
106     /**
107          * @since 2011-03-23
108          */
109         private static final Character FILE_EXTENSION_SEPARATOR = '.';
110         
111         private int mState;
112         
113         private static final int STATE_BROWSE = 1;
114         private static final int STATE_PICK_FILE = 2;
115         private static final int STATE_PICK_DIRECTORY = 3;
116         private static final int STATE_MULTI_SELECT = 4;
117     
118         protected static final int REQUEST_CODE_MOVE = 1;
119         protected static final int REQUEST_CODE_COPY = 2;
120     protected static final int REQUEST_CODE_EXTRACT = 4;
121
122     /**
123      * @since 2011-02-11
124      */
125     private static final int REQUEST_CODE_MULTI_SELECT = 3;
126
127         private static final int MENU_PREFERENCES = Menu.FIRST + 3;
128         private static final int MENU_NEW_FOLDER = Menu.FIRST + 4;
129         private static final int MENU_DELETE = Menu.FIRST + 5;
130         private static final int MENU_RENAME = Menu.FIRST + 6;
131         private static final int MENU_SEND = Menu.FIRST + 7;
132         private static final int MENU_OPEN = Menu.FIRST + 8;
133         private static final int MENU_MOVE = Menu.FIRST + 9;
134         private static final int MENU_COPY = Menu.FIRST + 10;
135         /**
136      * @since 2011-09-29
137      */
138     private static final int MENU_MORE = Menu.FIRST + 11;
139         private static final int MENU_INCLUDE_IN_MEDIA_SCAN = Menu.FIRST + 12;
140         private static final int MENU_EXCLUDE_FROM_MEDIA_SCAN = Menu.FIRST + 13;
141         private static final int MENU_SETTINGS = Menu.FIRST + 14;
142         private static final int MENU_MULTI_SELECT = Menu.FIRST + 15;
143         private static final int MENU_FILTER = Menu.FIRST + 16;
144         private static final int MENU_DETAILS = Menu.FIRST + 17;
145         private static final int MENU_BOOKMARKS = Menu.FIRST + 18;
146         private static final int MENU_BOOKMARK = Menu.FIRST + 19;
147         private static final int MENU_COMPRESS = Menu.FIRST + 20;
148         private static final int MENU_EXTRACT = Menu.FIRST + 21;
149         private static final int MENU_REFRESH = Menu.FIRST + 22;
150         private static final int MENU_DISTRIBUTION_START = Menu.FIRST + 100; // MUST BE LAST
151         
152         private static final int DIALOG_NEW_FOLDER = 1;
153         private static final int DIALOG_DELETE = 2;
154         private static final int DIALOG_RENAME = 3;
155
156         /**
157      * @since 2011-02-12
158      */
159         private static final int DIALOG_MULTI_DELETE = 4;
160         private static final int DIALOG_FILTER = 5;
161         private static final int DIALOG_DETAILS = 6;
162         
163         private static final int DIALOG_BOOKMARKS = 7;
164     private static final int DIALOG_COMPRESSING = 8;
165     private static final int DIALOG_WARNING_EXISTS = 9;
166     private static final int DIALOG_CHANGE_FILE_EXTENSION = 10;
167     private static final int DIALOG_MULTI_COMPRESS_ZIP = 11;
168
169         private static final int DIALOG_DISTRIBUTION_START = 100; // MUST BE LAST
170
171         private static final int COPY_BUFFER_SIZE = 32 * 1024;
172         
173         private static final String BUNDLE_CURRENT_DIRECTORY = "current_directory";
174         private static final String BUNDLE_CONTEXT_FILE = "context_file";
175         private static final String BUNDLE_CONTEXT_TEXT = "context_text";
176         private static final String BUNDLE_SHOW_DIRECTORY_INPUT = "show_directory_input";
177         private static final String BUNDLE_STEPS_BACK = "steps_back";
178         private static final String BUNDLE_DIRECTORY_ENTRIES = "directory_entries";
179         
180         private static boolean mSoftKeyboardAvailable;
181         /** Shows whether activity state has been restored (e.g. from a rotation). */
182         private static boolean mRestored = false;
183         
184         static {
185                 try {
186                         org.openintents.filemanager.compatibility.SoftKeyboard.checkAvailable();
187                         mSoftKeyboardAvailable = true;
188                 } catch (Throwable t) {
189                         mSoftKeyboardAvailable = false;
190                 }
191         }
192         
193         
194         /** Contains directories and files together */
195      private ArrayList<IconifiedText> directoryEntries = new ArrayList<IconifiedText>();
196
197      /** Dir separate for sorting */
198      List<IconifiedText> mListDir = new ArrayList<IconifiedText>();
199      
200      /** Files separate for sorting */
201      List<IconifiedText> mListFile = new ArrayList<IconifiedText>();
202      
203      /** SD card separate for sorting */
204      List<IconifiedText> mListSdCard = new ArrayList<IconifiedText>();
205      
206      // There's a ".nomedia" file here
207      private boolean mNoMedia;
208      
209      private File currentDirectory = new File(""); 
210      
211      private String mSdCardPath = "";
212      
213      private MimeTypes mMimeTypes;
214      /** Files shown are filtered using this extension */
215      private String mFilterFiletype = "";
216      /** Files shown are filtered using this mimetype */
217      private String mFilterMimetype = null;
218
219      private String mContextText;
220      private File mContextFile = new File("");
221      private Drawable mContextIcon;
222      
223      /** How many steps one can make back using the back key. */
224      private int mStepsBack;
225      
226      private EditText mEditFilename;
227      private Button mButtonPick;
228      private LinearLayout mDirectoryButtons;
229      
230      /**
231       * @since 2011-02-11
232       */
233      private Button mButtonMove;
234
235      /**
236       * @since 2011-02-11
237       */
238      private Button mButtonCopy;
239
240      /**
241       * @since 2011-02-11
242       */
243      private Button mButtonDelete;
244
245     private Button mButtonCompress;
246      
247      private boolean fileDeleted = false;
248      private int positionAtDelete;
249      private boolean deletedFileIsDirectory = false;
250
251      private LinearLayout mDirectoryInput;
252      private EditText mEditDirectory;
253      private ImageButton mButtonDirectoryPick;
254      
255      /**
256       * @since 2011-02-11
257       */
258      private LinearLayout mActionNormal;
259
260      /**
261       * @since 2011-02-11
262       */
263      private LinearLayout mActionMultiselect;
264
265      private TextView mEmptyText;
266      private ProgressBar mProgressBar;
267      
268      private DirectoryScanner mDirectoryScanner;
269      private File mPreviousDirectory;
270      
271      private MenuItem mExcludeMediaScanMenuItem;
272      private MenuItem mIncludeMediaScanMenuItem;
273      
274      private Handler currentHandler;
275
276         private boolean mWritableOnly;
277
278     private IconifiedText[] mDirectoryEntries;
279
280          static final public int MESSAGE_SHOW_DIRECTORY_CONTENTS = 500; // List of contents is ready, obj = DirectoryContents
281      static final public int MESSAGE_SET_PROGRESS = 501;        // Set progress bar, arg1 = current value, arg2 = max value
282      static final public int MESSAGE_ICON_CHANGED = 502;        // View needs to be redrawn, obj = IconifiedText
283
284      private ImageView mCheckIconSelect;
285      private boolean mSelected = false;
286
287     /**
288      * use it field to pass params to onCreateDialog method
289      */
290     private String mDialogArgument;
291
292     /**
293      * to show warning dialog to user if he want to change file extension
294      */
295     private String mOldFileName;
296     private String mNewFileName;
297
298     /**
299      * use this filed to set behaviour in DIALOG_WARNING_EXISTS
300      */
301     private String mDialogExistsAction = "";
302
303      private Drawable mIconChecked;
304      private Drawable mIconUnchecked;
305      
306      private ThumbnailLoader mThumbnailLoader;
307      
308      /** Called when the activity is first created. */ 
309      @Override 
310      public void onCreate(Bundle icicle) { 
311           super.onCreate(icicle); 
312
313           mDistribution.setFirst(MENU_DISTRIBUTION_START, DIALOG_DISTRIBUTION_START);
314           
315           // Check whether EULA has been accepted
316           // or information about new version can be presented.
317           if (mDistribution.showEulaOrNewVersion()) {
318               return;
319           }
320
321           currentHandler = new Handler() {
322                         public void handleMessage(Message msg) {
323                                 FileManagerActivity.this.handleMessage(msg);
324                         }
325                 };
326
327                   requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
328           setContentView(R.layout.filelist);
329           
330           
331           SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
332           prefs.registerOnSharedPreferenceChangeListener(this);
333
334           
335           mEmptyText = (TextView) findViewById(R.id.empty_text);
336           mProgressBar = (ProgressBar) findViewById(R.id.scan_progress);
337
338                   getListView().setOnCreateContextMenuListener(this);
339                   getListView().setEmptyView(findViewById(R.id.empty));
340               getListView().setTextFilterEnabled(true);
341               getListView().requestFocus();
342               getListView().requestFocusFromTouch();
343               
344           mDirectoryButtons = (LinearLayout) findViewById(R.id.directory_buttons);
345           mActionNormal = (LinearLayout) findViewById(R.id.action_normal);
346           mActionMultiselect = (LinearLayout) findViewById(R.id.action_multiselect);
347           mEditFilename = (EditText) findViewById(R.id.filename);
348           
349
350           mButtonPick = (Button) findViewById(R.id.button_pick);
351           
352           mButtonPick.setOnClickListener(new View.OnClickListener() {
353                                 
354                                 public void onClick(View arg0) {
355                                         pickFileOrDirectory();
356                                 }
357           });
358           
359           // Initialize only when necessary:
360           mDirectoryInput = null;
361           
362           // Create map of extensions:
363           getMimeTypes();
364           
365           getSdCardPath();
366           
367           mState = STATE_BROWSE;
368           
369           Intent intent = getIntent();
370           String action = intent.getAction();
371           
372           File browseto = new File("/");
373           
374           if (!TextUtils.isEmpty(mSdCardPath)) {
375                   browseto = new File(mSdCardPath);
376           }
377           
378           // Default state
379           mState = STATE_BROWSE;
380           mWritableOnly = false;
381           
382           if (action != null) {
383                   
384                   if (action.equals(FileManagerIntents.ACTION_PICK_FILE)) {
385                           mState = STATE_PICK_FILE;                     
386                           mFilterFiletype = intent.getStringExtra("FILE_EXTENSION");
387                           if(mFilterFiletype == null)
388                                   mFilterFiletype = "";
389                           mFilterMimetype = intent.getType();
390                           if(mFilterMimetype == null)
391                                   mFilterMimetype = "";
392                   } else if (action.equals(FileManagerIntents.ACTION_PICK_DIRECTORY)) {
393                           mState = STATE_PICK_DIRECTORY;                                                          
394                           mWritableOnly = intent.getBooleanExtra(FileManagerIntents.EXTRA_WRITEABLE_ONLY, false);
395                           
396                           // Remove edit text and make button fill whole line
397                           mEditFilename.setVisibility(View.GONE);
398                           mButtonPick.setLayoutParams(new LinearLayout.LayoutParams(
399                                           LinearLayout.LayoutParams.FILL_PARENT,
400                                           LinearLayout.LayoutParams.WRAP_CONTENT));
401                   } else if (action.equals(FileManagerIntents.ACTION_MULTI_SELECT)) {
402                           mState = STATE_MULTI_SELECT;                                                    
403                           
404                           // Remove buttons
405                   mDirectoryButtons.setVisibility(View.GONE);
406                   mActionNormal.setVisibility(View.GONE);
407
408                   // Multi select action: move
409                       mButtonMove = (Button) findViewById(R.id.button_move);
410                       mButtonMove.setOnClickListener(new View.OnClickListener() {
411                             
412                             public void onClick(View arg0) {
413                                 if (checkSelection()) {
414                                     promptDestinationAndMoveFile();
415                                 }
416                             }
417                       });
418                       
419                       // Multi select action: copy
420                       mButtonCopy = (Button) findViewById(R.id.button_copy);
421                       mButtonCopy.setOnClickListener(new View.OnClickListener() {
422                             
423                             public void onClick(View arg0) {
424                             if (checkSelection()) {
425                                 promptDestinationAndCopyFile();
426                             }
427                             }
428                       });
429                     
430                       // Multi select action: delete
431                       mButtonDelete = (Button) findViewById(R.id.button_delete);
432                       mButtonDelete.setOnClickListener(new View.OnClickListener() {
433                             
434                             public void onClick(View arg0) {
435                             if (checkSelection()) {
436                                 showDialog(DIALOG_MULTI_DELETE);
437                             }
438                             }
439                       });
440
441                   // Multi select action: delete
442                   mButtonCompress = (Button) findViewById(R.id.button_compress_zip);
443                   mButtonCompress.setOnClickListener(new View.OnClickListener() {
444
445                       public void onClick(View arg0) {
446                           if (checkSelection()) {
447                               showDialog(DIALOG_MULTI_COMPRESS_ZIP);
448                           }
449                       }
450                   });
451
452                       // Cache the checked and unchecked icons
453                       mIconChecked = getResources().getDrawable(R.drawable.ic_button_checked);
454                       mIconUnchecked = getResources().getDrawable(R.drawable.ic_button_unchecked);
455                       
456                       mCheckIconSelect = (ImageView) findViewById(R.id.check_icon_select);
457                       mCheckIconSelect.setOnClickListener(new View.OnClickListener() {
458                                         
459                           @Override
460                           public void onClick(View v) {
461                                   mSelected = !mSelected;
462                                   
463                                   if(mSelected){
464                                           mCheckIconSelect.setImageDrawable(mIconChecked);
465                                   } else {
466                                           mCheckIconSelect.setImageDrawable(mIconUnchecked);
467                                   }
468                                   
469                                   toggleSelection(mSelected);
470                           }
471                       });
472                     
473                   } 
474           
475           } 
476           
477           if (mState == STATE_BROWSE) {
478                   // Remove edit text and button.
479                   mEditFilename.setVisibility(View.GONE);
480                   mButtonPick.setVisibility(View.GONE);
481           }
482
483           if (mState != STATE_MULTI_SELECT) {
484                   // Remove multiselect action buttons
485                   mActionMultiselect.setVisibility(View.GONE);
486           }
487
488           // Set current directory and file based on intent data.
489           File file = FileUtils.getFile(intent.getData());
490           if (file != null) {
491                   File dir = FileUtils.getPathWithoutFilename(file);
492                   if (dir.isDirectory()) {
493                           browseto = dir;
494                   }
495                   if (!file.isDirectory()) {
496                           mEditFilename.setText(file.getName());
497                   }
498           } else{
499                   if(mState == STATE_PICK_FILE || mState == STATE_PICK_DIRECTORY
500                                   || action.equals(Intent.ACTION_GET_CONTENT)){
501                           String path = PreferenceActivity.getDefaultPickFilePath(this);
502                           if(path != null){
503                                   File dir = new File(path);
504                                   if(dir.exists() && dir.isDirectory()){
505                                           browseto = dir;
506                                   }
507                           }
508                   }
509           }
510           
511           String title = intent.getStringExtra(FileManagerIntents.EXTRA_TITLE);
512           if (title != null) {
513                   setTitle(title);
514           }
515
516           String buttontext = intent.getStringExtra(FileManagerIntents.EXTRA_BUTTON_TEXT);
517           if (buttontext != null) {
518                   mButtonPick.setText(buttontext);
519           }
520           
521           mStepsBack = 0;
522           
523           // Reset mRestored flag.
524           mRestored = false;
525           if (icicle != null) {
526                   browseto = new File(icicle.getString(BUNDLE_CURRENT_DIRECTORY));
527                   mContextFile = new File(icicle.getString(BUNDLE_CONTEXT_FILE));
528                   mContextText = icicle.getString(BUNDLE_CONTEXT_TEXT);
529                   
530                   boolean show = icicle.getBoolean(BUNDLE_SHOW_DIRECTORY_INPUT);
531                   showDirectoryInput(show);
532                   
533                   mStepsBack = icicle.getInt(BUNDLE_STEPS_BACK);
534                   // had to bypass direct casting as it was causing a rather unexplainable crash
535                   Parcelable tmpDirectoryEntries[] = icicle.getParcelableArray(BUNDLE_DIRECTORY_ENTRIES);
536                   mDirectoryEntries = new IconifiedText[tmpDirectoryEntries.length];
537                   for(int i=0; i<tmpDirectoryEntries.length; i++){
538                           mDirectoryEntries[i] = (IconifiedText) tmpDirectoryEntries[i];
539                   }
540                   mRestored = true;
541           }
542           
543           getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
544                         
545                         @Override
546                         public void onScrollStateChanged(AbsListView view, int scrollState) {
547                                 IconifiedTextListAdapter adapter = (IconifiedTextListAdapter) getListAdapter();
548                                 if(adapter != null){
549                                         switch (scrollState) {
550                                 case OnScrollListener.SCROLL_STATE_IDLE:
551                                         adapter.toggleScrolling(false);
552                                         adapter.notifyDataSetChanged();
553                                     break;
554                                 case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
555                                         adapter.toggleScrolling(true);
556                                     break;
557                                 case OnScrollListener.SCROLL_STATE_FLING:
558                                         adapter.toggleScrolling(true);
559                                     break;
560                                 }
561                                 }
562                         }
563                         
564                         @Override
565                         public void onScroll(AbsListView view, int firstVisibleItem,
566                                         int visibleItemCount, int totalItemCount) {
567                                 // Not used
568                         }
569                 });
570           
571           browseTo(browseto);
572      }
573      
574      public void onDestroy() {
575          super.onDestroy();
576          
577          // Stop the scanner.
578          DirectoryScanner scanner = mDirectoryScanner;
579          
580          if (scanner != null) {
581                  scanner.cancel = true;
582          }
583          
584          mDirectoryScanner = null;
585          
586          ThumbnailLoader loader = mThumbnailLoader;
587          
588          if (loader != null) {
589                  loader.cancel();
590                  mThumbnailLoader = null;
591          }
592          
593          ListView lv;
594          if((lv = getListView()) != null){
595                  lv.setAdapter(null);
596          }
597      }
598      
599      private void handleMessage(Message message) {
600 //       Log.v(TAG, "Received message " + message.what);
601          
602          switch (message.what) {
603          case MESSAGE_SHOW_DIRECTORY_CONTENTS:
604                  showDirectoryContents((DirectoryContents) message.obj);
605                  break;
606                  
607          case MESSAGE_SET_PROGRESS:
608                  setProgress(message.arg1, message.arg2);
609                  break;
610          }
611      }
612      
613      private void setProgress(int progress, int maxProgress) {
614          mProgressBar.setMax(maxProgress);
615          mProgressBar.setProgress(progress);
616          mProgressBar.setVisibility(View.VISIBLE);
617      }
618      
619      private void showDirectoryContents(DirectoryContents contents) {
620          mDirectoryScanner = null;
621          
622          mListSdCard = contents.listSdCard;
623          mListDir = contents.listDir;
624          mListFile = contents.listFile;
625          mNoMedia = contents.noMedia;
626
627          if(!mRestored){
628                  directoryEntries.ensureCapacity(mListSdCard.size() + mListDir.size() + mListFile.size());
629
630                  addAllElements(directoryEntries, mListSdCard);
631                  addAllElements(directoryEntries, mListDir);
632                  addAllElements(directoryEntries, mListFile);
633
634                  mDirectoryEntries = directoryEntries.toArray(new IconifiedText[0]);
635          }
636          else {
637                  directoryEntries.clear();
638                  directoryEntries.ensureCapacity(mDirectoryEntries.length);
639                  for(int i = 0; i < mDirectoryEntries.length; i++){
640                          directoryEntries.add(mDirectoryEntries[i]);
641                  }
642                  
643                  // Once mRestore flag has been used, we should toggle it so that further refreshes don't take it into account
644                  mRestored = false;
645          }
646
647          IconifiedTextListAdapter itla = new IconifiedTextListAdapter(this); 
648          itla.setListItems(directoryEntries, getListView().hasTextFilter(), currentDirectory, mMimeTypes);          
649          setListAdapter(itla); 
650              getListView().setTextFilterEnabled(true);
651              
652              ThumbnailLoader mThumbnailLoader = ((IconifiedTextListAdapter) getListAdapter()).getThumbnailLoader();
653              
654              if(fileDeleted){
655                  getListView().setSelection(positionAtDelete);
656              }
657
658          selectInList(mPreviousDirectory);
659          refreshDirectoryPanel();
660          setProgressBarIndeterminateVisibility(false);
661
662          mProgressBar.setVisibility(View.GONE);
663          mEmptyText.setVisibility(View.VISIBLE);
664          
665          toggleCheckBoxVisibility(mState == STATE_MULTI_SELECT);
666      }
667
668      private void onCreateDirectoryInput() {
669          mDirectoryInput = (LinearLayout) findViewById(R.id.directory_input);
670          mEditDirectory = (EditText) findViewById(R.id.directory_text);
671
672
673                  mEditDirectory.setOnKeyListener(new OnKeyListener() {
674                          public boolean onKey(View v, int keyCode, KeyEvent event) {
675                                  // If the event is a key-down event on the "enter" button
676                                  if ((event.getAction() == KeyEvent.ACTION_DOWN)
677                                                 && (keyCode == KeyEvent.KEYCODE_ENTER)){
678                                          
679                                          goToDirectoryInEditText();
680                                          
681                                          return true;
682                                  }
683                                  return false;
684                          }
685                  });
686
687          mButtonDirectoryPick = (ImageButton) findViewById(R.id.button_directory_pick);
688          
689          mButtonDirectoryPick.setOnClickListener(new View.OnClickListener() {
690                                 
691                                 public void onClick(View arg0) {
692                                         goToDirectoryInEditText();
693                                 }
694          });
695      }
696      
697      //private boolean mHaveShownErrorMessage;
698      private File mHaveShownErrorMessageForFile = null;
699      
700      private void hideKeyboard(IBinder windowToken, int flags){
701          if(mSoftKeyboardAvailable){
702                  (new org.openintents.filemanager.compatibility.SoftKeyboard(this))
703                         .hideSoftInputFromWindow(windowToken, flags);
704          }
705      }
706      
707      private void goToDirectoryInEditText() {
708          File browseto = new File(mEditDirectory.getText().toString());
709          
710                  /*
711                   *  After calling showDirectoryInput(false); the keyboard stays displayed.
712                   *  Hide it by calling hideKeyboard(windowToken, 0);
713                   *  Might be a bit problematic - it hides the keyboard even if id didn't
714                   *  appear after focusing the editText (user had it displayed before).
715                   *  But I think letting it displayed when user doesn't want to
716                   *  is much worse (and much more common) than hiding it although
717                   *  the user wants it displayed
718                   */
719
720          IBinder windowToken = mEditDirectory.getWindowToken();
721          
722          if (browseto.equals(currentDirectory)) {
723                  showDirectoryInput(false);
724                  hideKeyboard(windowToken, 0);
725          } else {
726                  if (mHaveShownErrorMessageForFile != null 
727                                  && mHaveShownErrorMessageForFile.equals(browseto)) {
728                          // Don't let user get stuck in wrong directory.
729                          mHaveShownErrorMessageForFile = null;
730                          showDirectoryInput(false);
731                          hideKeyboard(windowToken, 0);
732                  } else {
733                          if (!browseto.exists()) {
734                                  // browseTo() below will show an error message,
735                                  // because file does not exist.
736                                  // It is ok to show this the first time.
737                                  mHaveShownErrorMessageForFile = browseto;
738                          }else{
739                                  showDirectoryInput(false);
740                                  hideKeyboard(windowToken, 0);
741                          }
742                                  browseTo(browseto);
743                  }
744          }
745      }
746      
747      /**
748       * Show the directory line as input box instead of button row.
749       * If Directory input does not exist yet, it is created.
750       * Since the default is show == false, nothing is created if
751       * it is not necessary (like after icicle).
752       * @param show
753       */
754      private void showDirectoryInput(boolean show) {
755          if (show) {
756                  if (mDirectoryInput == null) {
757                          onCreateDirectoryInput();
758                  }
759          }
760          if (mDirectoryInput != null) {
761                  mDirectoryInput.setVisibility(show ? View.VISIBLE : View.GONE);
762                  mDirectoryButtons.setVisibility(show ? View.GONE : View.VISIBLE);
763          }
764          
765          refreshDirectoryPanel();
766      }
767
768         /**
769          * 
770          */
771         private void refreshDirectoryPanel() {
772                 if (isDirectoryInputVisible()) {
773                         // Set directory path
774                         String path = currentDirectory.getAbsolutePath();
775                         mEditDirectory.setText(path);
776                         
777                         // Set selection to last position so user can continue to type:
778                         mEditDirectory.setSelection(path.length());
779                 } else {
780                         setDirectoryButtons();
781                 }
782         } 
783      /*
784      @Override
785         protected void onResume() {
786                 // TODO Auto-generated method stub
787                 super.onResume();
788         }
789 */
790      
791
792         @Override
793         protected void onSaveInstanceState(Bundle outState) {
794                 // TODO Auto-generated method stub
795                 super.onSaveInstanceState(outState);
796                 
797                 // remember file name
798                 outState.putString(BUNDLE_CURRENT_DIRECTORY, currentDirectory.getAbsolutePath());
799                 outState.putString(BUNDLE_CONTEXT_FILE, mContextFile.getAbsolutePath());
800                 outState.putString(BUNDLE_CONTEXT_TEXT, mContextText);
801                 boolean show = isDirectoryInputVisible();
802                 outState.putBoolean(BUNDLE_SHOW_DIRECTORY_INPUT, show);
803                 outState.putInt(BUNDLE_STEPS_BACK, mStepsBack);
804                 outState.putParcelableArray(BUNDLE_DIRECTORY_ENTRIES, mDirectoryEntries);
805         }
806
807         /**
808          * @return
809          */
810         private boolean isDirectoryInputVisible() {
811                 return ((mDirectoryInput != null) && (mDirectoryInput.getVisibility() == View.VISIBLE));
812         }
813
814         private void pickFileOrDirectory() {
815                 File file = null;
816                 if (mState == STATE_PICK_FILE) {
817                         String filename = mEditFilename.getText().toString();
818                         file = FileUtils.getFile(currentDirectory.getAbsolutePath(), filename);
819                 } else if (mState == STATE_PICK_DIRECTORY) {
820                         file = currentDirectory;
821                 }
822                 
823                 PreferenceActivity.setDefaultPickFilePath(this, currentDirectory.getAbsolutePath());
824          
825         Intent intent = getIntent();
826         intent.setData(FileUtils.getUri(file));
827         setResult(RESULT_OK, intent);
828         finish();
829      }
830      
831         /**
832          * 
833          */
834      private void getMimeTypes() {
835          MimeTypeParser mtp = null;
836                 try {
837                         mtp = new MimeTypeParser(this, this.getPackageName());
838                 } catch (NameNotFoundException e) {
839                         //Should never happen
840                 }
841
842          XmlResourceParser in = getResources().getXml(R.xml.mimetypes);
843
844          try {
845                  mMimeTypes = mtp.fromXmlResource(in);
846          } catch (XmlPullParserException e) {
847                  Log
848                  .e(
849                                  TAG,
850                                  "PreselectedChannelsActivity: XmlPullParserException",
851                                  e);
852                  throw new RuntimeException(
853                  "PreselectedChannelsActivity: XmlPullParserException");
854          } catch (IOException e) {
855                  Log.e(TAG, "PreselectedChannelsActivity: IOException", e);
856                  throw new RuntimeException(
857                  "PreselectedChannelsActivity: IOException");
858          }
859      } 
860       
861      /** 
862       * This function browses up one level 
863       * according to the field: currentDirectory 
864       */ 
865      private void upOneLevel(){
866          if (mStepsBack > 0) {
867                  mStepsBack--;
868          }
869          if(currentDirectory.getParent() != null) 
870                browseTo(currentDirectory.getParentFile()); 
871      } 
872       
873      /**
874       * Jump to some location by clicking on a 
875       * directory button.
876       * 
877       * This resets the counter for "back" actions.
878       * 
879       * @param aDirectory
880       */
881      private void jumpTo(final File aDirectory) {
882          mStepsBack = 0;
883          browseTo(aDirectory);
884      }
885      
886      /**
887       * Browse to some location by clicking on a list item.
888       * @param aDirectory
889       */
890      private void browseTo(final File aDirectory){ 
891           // setTitle(aDirectory.getAbsolutePath());
892           
893           if (aDirectory.isDirectory()){
894                   if (aDirectory.equals(currentDirectory)) {
895                           // Switch from button to directory input
896                           showDirectoryInput(true);
897                   } else {
898                            mPreviousDirectory = currentDirectory;
899                        currentDirectory = aDirectory;
900                        refreshList();
901 //                     selectInList(previousDirectory);
902         //               refreshDirectoryPanel();
903                   }
904           }else{ 
905                   if (mState == STATE_BROWSE || mState == STATE_PICK_DIRECTORY) {
906                       // Lets start an intent to View the file, that was clicked... 
907                           openFile(aDirectory); 
908                   } else if (mState == STATE_PICK_FILE) {
909                           // Pick the file
910                           mEditFilename.setText(aDirectory.getName());
911                   }
912           } 
913      }
914
915       
916      private void openFile(File aFile) { 
917          if (!aFile.exists()) {
918                  Toast.makeText(this, R.string.error_file_does_not_exists, Toast.LENGTH_SHORT).show();
919                  return;
920          }
921          
922           Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
923
924           Uri data = FileUtils.getUri(aFile);
925           String type = mMimeTypes.getMimeType(aFile.getName());
926           intent.setDataAndType(data, type);
927
928          // Were we in GET_CONTENT mode?
929          Intent originalIntent = getIntent();
930          
931          if (originalIntent != null && originalIntent.getAction() != null && originalIntent.getAction().equals(Intent.ACTION_GET_CONTENT)) {
932                  // In that case, we should probably just return the requested data.
933                  PreferenceActivity.setDefaultPickFilePath(this,
934                                  FileUtils.getPathWithoutFilename(aFile).getAbsolutePath());
935                  intent.setData(Uri.parse(FileManagerProvider.FILE_PROVIDER_PREFIX + aFile));
936                  setResult(RESULT_OK, intent);
937                  finish();
938                  return;
939          }
940          
941
942           
943           try {
944                   startActivity(intent); 
945           } catch (ActivityNotFoundException e) {
946                   Toast.makeText(this, R.string.application_not_available, Toast.LENGTH_SHORT).show();
947           };
948      } 
949
950      public void refreshList() {
951                  
952          boolean directoriesOnly = mState == STATE_PICK_DIRECTORY;
953          
954           // Cancel an existing scanner, if applicable.
955           DirectoryScanner scanner = mDirectoryScanner;
956           
957           if (scanner != null) {
958                   scanner.cancel = true;
959           }
960           
961           ThumbnailLoader loader = mThumbnailLoader;
962           
963           if (loader != null) {
964                   loader.cancel();
965                   mThumbnailLoader = null;
966           }
967           
968           directoryEntries.clear(); 
969           mListDir.clear();
970           mListFile.clear();
971           mListSdCard.clear();
972           
973           setProgressBarIndeterminateVisibility(true);
974           
975           // Don't show the "folder empty" text since we're scanning.
976           mEmptyText.setVisibility(View.GONE);
977           
978           // Also DON'T show the progress bar - it's kind of lame to show that
979           // for less than a second.
980           mProgressBar.setVisibility(View.GONE);
981           setListAdapter(null); 
982           
983                   mDirectoryScanner = new DirectoryScanner(currentDirectory, this, currentHandler, mMimeTypes, mFilterFiletype, mFilterMimetype, mSdCardPath, mWritableOnly, directoriesOnly);
984                   mDirectoryScanner.start();
985                   
986                   
987            
988           // Add the "." == "current directory" 
989           /*directoryEntries.add(new IconifiedText( 
990                     getString(R.string.current_dir), 
991                     getResources().getDrawable(R.drawable.ic_launcher_folder)));        */
992           // and the ".." == 'Up one level' 
993           /*
994           if(currentDirectory.getParent() != null) 
995                directoryEntries.add(new IconifiedText( 
996                          getString(R.string.up_one_level), 
997                          getResources().getDrawable(R.drawable.ic_launcher_folder_open))); 
998           */
999      } 
1000      
1001      private void selectInList(File selectFile) {
1002          String filename = selectFile.getName();
1003          IconifiedTextListAdapter la = (IconifiedTextListAdapter) getListAdapter();
1004          int count = la.getCount();
1005          for (int i = 0; i < count; i++) {
1006                  IconifiedText it = (IconifiedText) la.getItem(i);
1007                  if (it.getText().equals(filename)) {
1008                          getListView().setSelection(i);
1009                          break;
1010                  }
1011          }
1012      }
1013      
1014      private void addAllElements(List<IconifiedText> addTo, List<IconifiedText> addFrom) {
1015          int size = addFrom.size();
1016          for (int i = 0; i < size; i++) {
1017                  addTo.add(addFrom.get(i));
1018          }
1019      }
1020      
1021      private void setDirectoryButtons() {
1022          String[] parts = currentDirectory.getAbsolutePath().split("/");
1023          
1024          mDirectoryButtons.removeAllViews();
1025          
1026          int WRAP_CONTENT = LinearLayout.LayoutParams.WRAP_CONTENT;
1027          
1028          // Add home button separately
1029          ImageButton ib = new ImageButton(this);
1030          ib.setImageResource(R.drawable.ic_launcher_home_small);
1031                  ib.setLayoutParams(new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
1032                  ib.setOnClickListener(new View.OnClickListener() {
1033                         public void onClick(View view) {
1034                                 jumpTo(new File("/"));
1035                         }
1036                  });
1037                  mDirectoryButtons.addView(ib);
1038                  
1039          // Add other buttons
1040          
1041          String dir = "";
1042          
1043          for (int i = 1; i < parts.length; i++) {
1044                  dir += "/" + parts[i];
1045                  if (dir.equals(mSdCardPath)) {
1046                          // Add SD card button
1047                          ib = new ImageButton(this);
1048                  ib.setImageResource(R.drawable.ic_launcher_sdcard_small);
1049                          ib.setLayoutParams(new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
1050                          ib.setOnClickListener(new View.OnClickListener() {
1051                                         public void onClick(View view) {
1052                                                 jumpTo(new File(mSdCardPath));
1053                                         }
1054                          });
1055                          mDirectoryButtons.addView(ib);
1056                  } else {
1057                          Button b = new Button(this);
1058                          b.setLayoutParams(new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
1059                          b.setText(parts[i]);
1060                          b.setTag(dir);
1061                          b.setOnClickListener(new View.OnClickListener() {
1062                                         public void onClick(View view) {
1063                                                 String dir = (String) view.getTag();
1064                                                 jumpTo(new File(dir));
1065                                         }
1066                          });
1067                          mDirectoryButtons.addView(b);
1068                  }
1069          }
1070          
1071          checkButtonLayout();
1072      }
1073
1074      private void checkButtonLayout() {
1075          
1076          // Let's measure how much space we need:
1077          int spec = View.MeasureSpec.UNSPECIFIED;
1078          mDirectoryButtons.measure(spec, spec);
1079          int count = mDirectoryButtons.getChildCount();
1080          
1081          int requiredwidth = mDirectoryButtons.getMeasuredWidth();
1082          int width = getWindowManager().getDefaultDisplay().getWidth();
1083          
1084          if (requiredwidth > width) {
1085                  int WRAP_CONTENT = LinearLayout.LayoutParams.WRAP_CONTENT;
1086                  
1087                  // Create a new button that shows that there is more to the left:
1088                  ImageButton ib = new ImageButton(this);
1089                  ib.setImageResource(R.drawable.ic_menu_back_small);
1090                  ib.setLayoutParams(new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
1091                  // 
1092                  ib.setOnClickListener(new View.OnClickListener() {
1093                                 public void onClick(View view) {
1094                                         // Up one directory.
1095                                         upOneLevel();
1096                                 }
1097                  });
1098                  mDirectoryButtons.addView(ib, 0);
1099                  
1100                  // New button needs even more space
1101                  ib.measure(spec, spec);
1102                  requiredwidth += ib.getMeasuredWidth();
1103
1104                  // Need to take away some buttons
1105                  // but leave at least "back" button and one directory button.
1106                  while (requiredwidth > width && mDirectoryButtons.getChildCount() > 2) {
1107                          View view = mDirectoryButtons.getChildAt(1);
1108                          requiredwidth -= view.getMeasuredWidth();
1109                          
1110                          mDirectoryButtons.removeViewAt(1);
1111                  }
1112          }
1113      }
1114      
1115      @Override 
1116      protected void onListItemClick(ListView l, View v, int position, long id) { 
1117           super.onListItemClick(l, v, position, id); 
1118           
1119           IconifiedTextListAdapter adapter = (IconifiedTextListAdapter) getListAdapter();
1120           
1121           if (adapter == null) {
1122                   return;
1123           }
1124           
1125           IconifiedText text = (IconifiedText) adapter.getItem(position);
1126
1127           if (mState == STATE_MULTI_SELECT) {
1128                   text.setSelected(!text.isSelected());
1129                   adapter.notifyDataSetChanged();
1130                   return;
1131           }
1132                         
1133           String file = text.getText(); 
1134           /*
1135           if (selectedFileString.equals(getString(R.string.up_one_level))) { 
1136                upOneLevel(); 
1137           } else { 
1138           */
1139                   String curdir = currentDirectory 
1140               .getAbsolutePath() ;
1141                   File clickedFile = FileUtils.getFile(curdir, file);
1142                if (clickedFile != null) {
1143                    if (clickedFile.isDirectory()) {
1144                            // If we click on folders, we can return later by the "back" key.
1145                            mStepsBack++;
1146                    }
1147                     browseTo(clickedFile);
1148                }
1149           /*
1150           } 
1151           */
1152      }
1153
1154      private void getSdCardPath() {
1155          mSdCardPath = android.os.Environment
1156                         .getExternalStorageDirectory().getAbsolutePath();
1157      }
1158      
1159
1160         @Override
1161         public boolean onCreateOptionsMenu(Menu menu) {
1162                 super.onCreateOptionsMenu(menu);
1163
1164                 int icon = android.R.drawable.ic_menu_add;
1165                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
1166                         icon = R.drawable.ic_menu_add_folder;
1167                 }
1168                 MenuItem item = menu.add(0, MENU_NEW_FOLDER, 0, R.string.menu_new_folder).setIcon(
1169                                 icon).setShortcut('0', 'f');
1170                 MenuCompat.setShowAsAction(item, 0/*MenuItem.SHOW_AS_ACTION_IF_ROOM*/);
1171  
1172                 if (mState == STATE_BROWSE) {
1173                 // Multi select option menu.
1174                 menu.add(0, MENU_MULTI_SELECT, 0, R.string.menu_multi_select).setIcon(
1175                         R.drawable.ic_menu_multiselect).setShortcut('1', 'm');
1176         }
1177                         
1178                 mIncludeMediaScanMenuItem = menu.add(0, MENU_INCLUDE_IN_MEDIA_SCAN, 0, R.string.menu_include_in_media_scan).setShortcut('2', 's')
1179                                 .setIcon(android.R.drawable.ic_menu_gallery);
1180                 mExcludeMediaScanMenuItem = menu.add(0, MENU_EXCLUDE_FROM_MEDIA_SCAN, 0, R.string.menu_exclude_from_media_scan).setShortcut('2', 's')
1181                                 .setIcon(android.R.drawable.ic_menu_gallery);
1182                 
1183                 menu.add(0, MENU_BOOKMARKS, 0, R.string.bookmarks).setIcon(
1184                                 R.drawable.ic_menu_star);
1185                 
1186
1187                 menu.add(0, MENU_SETTINGS, 0, R.string.settings).setIcon(
1188                                 android.R.drawable.ic_menu_preferences).setShortcut('9', 'p');
1189                 
1190                 /* We don't want to allow the user to override a filter set
1191                  * by an application.
1192                  */
1193                 if(mState != STATE_PICK_FILE) {
1194                         menu.add(0, MENU_FILTER, 0, R.string.menu_filter).setIcon(
1195                                         android.R.drawable.ic_menu_search);
1196                 }
1197                 
1198                 menu.add(0, MENU_REFRESH, 0, R.string.menu_refresh).setIcon(
1199                                 android.R.drawable.ic_menu_rotate);
1200
1201                 mDistribution.onCreateOptionsMenu(menu);
1202                 return true;
1203         }
1204
1205
1206         @Override
1207         public boolean onPrepareOptionsMenu(Menu menu) {
1208                 super.onPrepareOptionsMenu(menu);
1209
1210                 mIncludeMediaScanMenuItem.setVisible(false);
1211                 mExcludeMediaScanMenuItem.setVisible(false);
1212                 
1213                 boolean showMediaScanMenuItem = PreferenceActivity.getMediaScanFromPreference(this);
1214                 
1215                 // We only know about ".nomedia" once we have the results list back.
1216                 if (showMediaScanMenuItem && mListDir != null) {
1217                         if (mNoMedia) {
1218                                 mIncludeMediaScanMenuItem.setVisible(true);
1219                         } else {
1220                                 mExcludeMediaScanMenuItem.setVisible(true);
1221                         }
1222                 }
1223
1224                 // Generate any additional actions that can be performed on the
1225                 // overall list. This allows other applications to extend
1226                 // our menu with their own actions.
1227                 Intent intent = new Intent(null, getIntent().getData());
1228                 intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
1229                 // menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
1230                 // new ComponentName(this, NoteEditor.class), null, intent, 0, null);
1231
1232                 // Workaround to add icons:
1233                 MenuIntentOptionsWithIcons menu2 = new MenuIntentOptionsWithIcons(this,
1234                                 menu);
1235                 menu2.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
1236                                 new ComponentName(this, FileManagerActivity.class), null, intent,
1237                                 0, null);
1238
1239                 return true;
1240         }
1241
1242         @Override
1243         public boolean onOptionsItemSelected(MenuItem item) {
1244                 switch (item.getItemId()) {
1245                 case MENU_NEW_FOLDER:
1246                         showDialog(DIALOG_NEW_FOLDER);
1247                         return true;
1248                         
1249                 case MENU_MULTI_SELECT:
1250             promptMultiSelect();
1251                         return true;
1252                         
1253                 case MENU_INCLUDE_IN_MEDIA_SCAN:
1254                         includeInMediaScan();
1255                         return true;
1256
1257                 case MENU_EXCLUDE_FROM_MEDIA_SCAN:
1258                         excludeFromMediaScan();
1259                         return true;
1260                         
1261                 case MENU_SETTINGS:
1262                         showSettings();
1263                         return true;
1264                         
1265                 case MENU_FILTER:
1266                         showDialog(DIALOG_FILTER);
1267                         return true;
1268                 
1269                 case MENU_BOOKMARKS:
1270                         showDialog(DIALOG_BOOKMARKS);
1271                         return true;
1272                         
1273                 case MENU_REFRESH:
1274                         refreshList();
1275                         return true;
1276                 }
1277                 return super.onOptionsItemSelected(item);
1278
1279         }
1280
1281     private void showSettings() {
1282                 Intent intent = new Intent(this, PreferenceActivity.class);
1283                 startActivity(intent);
1284         }
1285         
1286         @Override
1287         public void onCreateContextMenu(ContextMenu menu, View view,
1288                         ContextMenuInfo menuInfo) {
1289                 AdapterView.AdapterContextMenuInfo info;
1290                 try {
1291                         info = (AdapterView.AdapterContextMenuInfo) menuInfo;
1292                 } catch (ClassCastException e) {
1293                         Log.e(TAG, "bad menuInfo", e);
1294                         return;
1295                 }
1296 /*
1297                 Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
1298                 if (cursor == null) {
1299                         // For some reason the requested item isn't available, do nothing
1300                         return;
1301                 }
1302 */
1303         IconifiedTextListAdapter adapter = (IconifiedTextListAdapter) getListAdapter();
1304         
1305         if (adapter == null) {
1306           return;
1307         }
1308         
1309         IconifiedText it = (IconifiedText) adapter.getItem(info.position);
1310                 menu.setHeaderTitle(it.getText());
1311                 menu.setHeaderIcon(it.getIcon());
1312                 File file = FileUtils.getFile(currentDirectory, it.getText());
1313
1314                 
1315                 if (!file.isDirectory()) {
1316                         if (mState == STATE_PICK_FILE) {
1317                                 // Show "open" menu
1318                                 menu.add(0, MENU_OPEN, 0, R.string.menu_open);
1319                         }
1320                         menu.add(0, MENU_SEND, 0, R.string.menu_send);
1321                 }
1322                 menu.add(0, MENU_MOVE, 0, R.string.menu_move);
1323                 
1324                 if (!file.isDirectory()) {
1325                         menu.add(0, MENU_COPY, 0, R.string.menu_copy);
1326                 }
1327                 
1328                 menu.add(0, MENU_RENAME, 0, R.string.menu_rename);
1329                 menu.add(0, MENU_DELETE, 0, R.string.menu_delete);
1330
1331                 //if (!file.isDirectory()) {
1332                 Uri data = Uri.fromFile(file);
1333                 Intent intent = new Intent(null, data);
1334                 String type = mMimeTypes.getMimeType(file.getName());
1335         
1336                 intent.setDataAndType(data, type);
1337                 intent.addCategory(Intent.CATEGORY_SELECTED_ALTERNATIVE);
1338                 //intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
1339         
1340                 Log.v(TAG, "Data=" + data);
1341                 Log.v(TAG, "Type=" + type);
1342                         
1343                 if (type != null) {
1344                         // Add additional options for the MIME type of the selected file.
1345                                 menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
1346                                                 new ComponentName(this, FileManagerActivity.class), null, intent, 0, null);
1347                 }
1348                 //}
1349
1350         if (FileUtils.checkIfZipArchive(file)){
1351             menu.add(0, MENU_EXTRACT, 0, R.string.menu_extract);
1352         } else {
1353             menu.add(0, MENU_COMPRESS, 0, R.string.menu_compress);
1354         }
1355             menu.add(0, MENU_DETAILS, 0, R.string.menu_details);
1356             menu.add(0, MENU_BOOKMARK, 0, R.string.menu_bookmark);
1357         menu.add(0, MENU_MORE, 0, R.string.menu_more);
1358         }
1359
1360         @Override
1361         public boolean onContextItemSelected(MenuItem item) {
1362                 super.onContextItemSelected(item);
1363                 AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item
1364                                 .getMenuInfo();
1365                 
1366                 // Remember current selection
1367         IconifiedTextListAdapter adapter = (IconifiedTextListAdapter) getListAdapter();
1368         
1369         if (adapter == null) {
1370           return false;
1371         }
1372         
1373         IconifiedText ic = (IconifiedText) adapter.getItem(menuInfo.position);
1374                 mContextText = ic.getText();
1375                 mContextIcon = ic.getIcon();
1376                 mContextFile = FileUtils.getFile(currentDirectory, ic.getText());
1377                 
1378                 switch (item.getItemId()) {
1379                 case MENU_OPEN:
1380             openFile(mContextFile); 
1381                         return true;
1382                         
1383                 case MENU_MOVE:
1384                         promptDestinationAndMoveFile();
1385                         return true;
1386                         
1387                 case MENU_COPY:
1388                         promptDestinationAndCopyFile();
1389                         return true;
1390                         
1391                 case MENU_DELETE:
1392                         showDialog(DIALOG_DELETE);
1393                         return true;
1394
1395                 case MENU_RENAME:
1396                         showDialog(DIALOG_RENAME);
1397                         return true;
1398                         
1399                 case MENU_SEND:
1400                         sendFile(mContextFile);
1401                         return true;
1402                 
1403                 case MENU_DETAILS:
1404                         showDialog(DIALOG_DETAILS);
1405                         return true;
1406
1407         case MENU_COMPRESS:
1408             showDialog(DIALOG_COMPRESSING);
1409             return true;
1410
1411         case MENU_EXTRACT:
1412             promptDestinationAndExtract();            
1413             return true;
1414                         
1415                 case MENU_BOOKMARK:
1416                         String path = mContextFile.getAbsolutePath();
1417                         Cursor query = managedQuery(BookmarksProvider.CONTENT_URI,
1418                                                                                 new String[]{BookmarksProvider._ID},
1419                                                                                 BookmarksProvider.PATH + "=?",
1420                                                                                 new String[]{path},
1421                                                                                 null);
1422                         if(!query.moveToFirst()){
1423                                 ContentValues values = new ContentValues();
1424                                 values.put(BookmarksProvider.NAME, mContextFile.getName());
1425                                 values.put(BookmarksProvider.PATH, path);
1426                                 getContentResolver().insert(BookmarksProvider.CONTENT_URI, values);
1427                                 Toast.makeText(this, R.string.bookmark_added, Toast.LENGTH_SHORT).show();
1428                         }
1429                         else{
1430                                 Toast.makeText(this, R.string.bookmark_already_exists, Toast.LENGTH_SHORT).show();
1431                         }
1432                         return true;
1433
1434                 case MENU_MORE:
1435                         if (!PreferenceActivity.getShowAllWarning(FileManagerActivity.this)) {
1436                                 showMoreCommandsDialog();
1437                                 return true;
1438                         }
1439
1440                         showWarningDialog();
1441
1442                         return true;
1443                 }
1444
1445                 return false;
1446         }
1447         
1448         @Override
1449         protected Dialog onCreateDialog(int id) {
1450
1451                 switch (id) {
1452                 case DIALOG_NEW_FOLDER:
1453                         LayoutInflater inflater = LayoutInflater.from(this);
1454                         View view = inflater.inflate(R.layout.dialog_new_folder, null);
1455                         final EditText et = (EditText) view
1456                                         .findViewById(R.id.foldername);
1457                         et.setText("");
1458                         //accept "return" key
1459                         TextView.OnEditorActionListener returnListener = new TextView.OnEditorActionListener(){
1460                                 public boolean onEditorAction(TextView exampleView, int actionId, KeyEvent event) {
1461                                            if (actionId == EditorInfo.IME_NULL  
1462                                               && event.getAction() == KeyEvent.ACTION_DOWN) { 
1463                                                    createNewFolder(et.getText().toString()); //match this behavior to your OK button
1464                                                    dismissDialog(DIALOG_NEW_FOLDER);
1465                                            }
1466                                            return true;
1467                                         }
1468
1469                         };
1470                         et.setOnEditorActionListener(returnListener);
1471                         //end of code regarding "return key"
1472
1473                         return new AlertDialog.Builder(this)
1474                 .setIcon(android.R.drawable.ic_dialog_alert)
1475                 .setTitle(R.string.create_new_folder).setView(view).setPositiveButton(
1476                                         android.R.string.ok, new OnClickListener() {
1477                                                 
1478                                                 public void onClick(DialogInterface dialog, int which) {
1479                                                         createNewFolder(et.getText().toString());
1480                                                 }
1481                                                 
1482                                         }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1483                                                 
1484                                                 public void onClick(DialogInterface dialog, int which) {
1485                                                         // Cancel should not do anything.
1486                                                 }
1487                                                 
1488                                         }).create();
1489                 
1490
1491                 case DIALOG_DELETE:
1492                         return new AlertDialog.Builder(this).setTitle(getString(R.string.really_delete, mContextText))
1493                 .setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(
1494                                         android.R.string.ok, new OnClickListener() {
1495                                                 
1496                                                 public void onClick(DialogInterface dialog, int which) {
1497                                                         deleteFileOrFolder(mContextFile);
1498                                                 }
1499                                                 
1500                                         }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1501                                                 
1502                                                 public void onClick(DialogInterface dialog, int which) {
1503                                                         // Cancel should not do anything.
1504                                                 }
1505                                                 
1506                                         }).create();
1507
1508                 case DIALOG_RENAME:
1509                         inflater = LayoutInflater.from(this);
1510                         view = inflater.inflate(R.layout.dialog_new_folder, null);
1511                         final EditText et2 = (EditText) view
1512                                 .findViewById(R.id.foldername);
1513                         //accept "return" key
1514                         TextView.OnEditorActionListener returnListener2 = new TextView.OnEditorActionListener(){
1515                                 public boolean onEditorAction(TextView exampleView, int actionId, KeyEvent event) {
1516                                            if (actionId == EditorInfo.IME_NULL  
1517                                               && event.getAction() == KeyEvent.ACTION_DOWN) { 
1518                                                    renameFileOrFolder(mContextFile, et2.getText().toString()); //match this behavior to your OK button
1519                                                    dismissDialog(DIALOG_RENAME);
1520                                            }
1521                                            return true;
1522                                         }
1523
1524                         };
1525                         et2.setOnEditorActionListener(returnListener2);
1526                         //end of code regarding "return key"
1527                         return new AlertDialog.Builder(this)
1528                 .setTitle(R.string.menu_rename).setView(view).setPositiveButton(
1529                                         android.R.string.ok, new OnClickListener() {
1530                                                 
1531                                                 public void onClick(DialogInterface dialog, int which) {
1532                                                         
1533                                                         renameFileOrFolder(mContextFile, et2.getText().toString());
1534                                                 }
1535                                                 
1536                                         }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1537                                                 
1538                                                 public void onClick(DialogInterface dialog, int which) {
1539                                                         // Cancel should not do anything.
1540                                                 }
1541                                                 
1542                                         }).create();
1543
1544         case DIALOG_MULTI_DELETE:
1545             String contentText = null;
1546             int count = 0;
1547             for (IconifiedText it : mDirectoryEntries) {
1548                 if (!it.isSelected()) {
1549                     continue;
1550                 }
1551
1552                 contentText = it.getText();
1553                 count++;
1554             }
1555             String string;
1556             if (count == 1) {
1557                  string = getString(R.string.really_delete, contentText);
1558             } else {
1559                 string = getString(R.string.really_delete_multiselect, count);
1560             }
1561             return new AlertDialog.Builder(this).setTitle(string)
1562                 .setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(
1563                     android.R.string.ok, new OnClickListener() {
1564                         
1565                         public void onClick(DialogInterface dialog, int which) {
1566                             deleteMultiFile();
1567     
1568                             Intent intent = getIntent();
1569                             setResult(RESULT_OK, intent);
1570                             finish();
1571                         }
1572                         
1573                     }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1574                         
1575                         public void onClick(DialogInterface dialog, int which) {
1576                             // Cancel should not do anything.
1577                         }
1578                     
1579                     }).create();
1580
1581         case DIALOG_FILTER:
1582                         inflater = LayoutInflater.from(this);
1583                         view = inflater.inflate(R.layout.dialog_new_folder, null);
1584                         ((TextView)view.findViewById(R.id.foldernametext)).setText(R.string.extension);
1585                         final EditText et3 = (EditText) view
1586                                         .findViewById(R.id.foldername);
1587                         et3.setText("");
1588                         return new AlertDialog.Builder(this)
1589                 .setIcon(android.R.drawable.ic_dialog_alert)
1590                 .setTitle(R.string.menu_filter).setView(view).setPositiveButton(
1591                                         android.R.string.ok, new OnClickListener() {
1592                                                 
1593                                                 public void onClick(DialogInterface dialog, int which) {
1594                                                         mFilterFiletype = et3.getText().toString().trim();
1595                                                         refreshList();
1596                                                 }
1597                                                 
1598                                         }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1599                                                 
1600                                                 public void onClick(DialogInterface dialog, int which) {
1601                                                         // Cancel should not do anything.
1602                                                 }
1603                                                 
1604                                         }).create();
1605                         
1606
1607         case DIALOG_DETAILS:
1608                 inflater = LayoutInflater.from(this);
1609                 view =  inflater.inflate(R.layout.dialog_details, null);
1610                                 
1611                 return new AlertDialog.Builder(this).setTitle(mContextText).
1612                                 setIcon(mContextIcon).setView(view).create();
1613                 
1614         case DIALOG_BOOKMARKS:
1615                 AlertDialog.Builder builder = new AlertDialog.Builder(this);
1616
1617                 final Cursor bookmarksCursor = getBookmarks();
1618                 
1619                 builder.setTitle(R.string.bookmarks);
1620                 
1621                 builder.setCursor(bookmarksCursor, new DialogInterface.OnClickListener() {
1622                             public void onClick(DialogInterface dialog, int item) {
1623                                 if (bookmarksCursor.moveToPosition(item)) {
1624                                         String path = bookmarksCursor.getString(
1625                                                         bookmarksCursor.getColumnIndex(BookmarksProvider.PATH));
1626                                         File file = new File(path);
1627                                         if (file != null) {
1628                                                 if (file.isDirectory()) {
1629                                                         mStepsBack++;
1630                                                 }
1631                                                 browseTo(file);
1632                                         }
1633                                 } else{
1634                                         Toast.makeText(FileManagerActivity.this, R.string.bookmark_not_found,
1635                                                         Toast.LENGTH_SHORT).show();
1636                                 }
1637                             }
1638                         }, BookmarksProvider.NAME);
1639                 
1640                 return builder.create();
1641
1642         case DIALOG_COMPRESSING:
1643             inflater = LayoutInflater.from(this);
1644             view = inflater.inflate(R.layout.dialog_new_folder, null);
1645             final EditText editText = (EditText) view.findViewById(R.id.foldername);
1646           //accept "return" key
1647                         TextView.OnEditorActionListener returnListener3 = new TextView.OnEditorActionListener(){
1648                                 public boolean onEditorAction(TextView exampleView, int actionId, KeyEvent event) {
1649                                            if (actionId == EditorInfo.IME_NULL  
1650                                               && event.getAction() == KeyEvent.ACTION_DOWN) { 
1651                                                    if (new File(mContextFile.getParent()+File.separator+editText.getText().toString()).exists()){
1652                                mDialogArgument = editText.getText().toString();
1653                                showDialog(DIALOG_WARNING_EXISTS);
1654                            } else {
1655                                new CompressManager(FileManagerActivity.this).compress(mContextFile, editText.getText().toString());
1656                            } //match this behavior to your OK button
1657                                                    dismissDialog(DIALOG_COMPRESSING);
1658                                            }
1659                                            return true;
1660                                         }
1661
1662                         };
1663                         editText.setOnEditorActionListener(returnListener3);
1664                         //end of code regarding "return key"
1665             return new AlertDialog.Builder(this)
1666                     .setTitle(R.string.menu_compress).setView(view).setPositiveButton(
1667                             android.R.string.ok, new OnClickListener() {
1668                         public void onClick(DialogInterface dialog, int which) {
1669                             if (new File(mContextFile.getParent()+File.separator+editText.getText().toString()).exists()){
1670                                 mDialogArgument = editText.getText().toString();
1671                                 showDialog(DIALOG_WARNING_EXISTS);
1672                             } else {
1673                                 new CompressManager(FileManagerActivity.this).compress(mContextFile, editText.getText().toString());
1674                             }
1675                         }
1676                     }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1677                         public void onClick(DialogInterface dialog, int which) {
1678                             // Cancel should not do anything.
1679                         }
1680                     }).create();
1681
1682         case DIALOG_MULTI_COMPRESS_ZIP:
1683             inflater = LayoutInflater.from(this);
1684             view = inflater.inflate(R.layout.dialog_new_folder, null);
1685             final EditText editText1 = (EditText) view.findViewById(R.id.foldername);
1686           //accept "return" key
1687                         TextView.OnEditorActionListener returnListener4 = new TextView.OnEditorActionListener(){
1688                                 public boolean onEditorAction(TextView exampleView, int actionId, KeyEvent event) {
1689                                            if (actionId == EditorInfo.IME_NULL  
1690                                               && event.getAction() == KeyEvent.ACTION_DOWN) { 
1691                                                    if (new File(currentDirectory+File.separator+editText1.getText().toString()).exists()){
1692                                mDialogArgument = editText1.getText().toString();
1693                                mDialogExistsAction = DIALOG_EXISTS_ACTION_MULTI_COMPRESS_ZIP;
1694                                showDialog(DIALOG_WARNING_EXISTS);
1695                            } else {
1696                                compressMultiFile(editText1.getText().toString());
1697                            } //match this behavior to your OK button
1698                                                    dismissDialog(DIALOG_MULTI_COMPRESS_ZIP);
1699                                            }
1700                                            return true;
1701                                         }
1702
1703                         };
1704                         editText1.setOnEditorActionListener(returnListener4);
1705                         //end of code regarding "return key"
1706             return new AlertDialog.Builder(this)
1707                     .setTitle(R.string.menu_compress).setView(view).setPositiveButton(
1708                             android.R.string.ok, new OnClickListener() {
1709                         public void onClick(DialogInterface dialog, int which) {
1710                             if (new File(currentDirectory+File.separator+editText1.getText().toString()).exists()){
1711                                 mDialogArgument = editText1.getText().toString();
1712                                 mDialogExistsAction = DIALOG_EXISTS_ACTION_MULTI_COMPRESS_ZIP;
1713                                 showDialog(DIALOG_WARNING_EXISTS);
1714                             } else {
1715                                 compressMultiFile(editText1.getText().toString());
1716                             }
1717                         }
1718                     }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1719                         public void onClick(DialogInterface dialog, int which) {
1720                             // Cancel should not do anything.
1721                         }
1722                     }).create();
1723         
1724         case DIALOG_WARNING_EXISTS:
1725             return new AlertDialog.Builder(this).setTitle(getString(R.string.warning_overwrite, mDialogArgument))
1726                     .setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(
1727                             android.R.string.ok, new OnClickListener() {
1728                         public void onClick(DialogInterface dialog, int which) {
1729                             if (mDialogExistsAction.equals(DIALOG_EXISTS_ACTION_MULTI_COMPRESS_ZIP)){
1730                                 compressMultiFile(mDialogArgument);
1731                             } else if (mDialogExistsAction.equals(DIALOG_EXISTS_ACTION_RENAME)){
1732                                 File newFile = FileUtils.getFile(currentDirectory, mNewFileName);
1733                                 rename(FileUtils.getFile(currentDirectory, mOldFileName), newFile);
1734                             } else {
1735                                 new File(mContextFile.getParent()+File.separator+mDialogArgument).delete();
1736                                 new CompressManager(FileManagerActivity.this).compress(mContextFile, mDialogArgument);
1737                             }
1738                             mDialogExistsAction = "";
1739                         }
1740                     }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1741                         public void onClick(DialogInterface dialog, int which) {
1742                             if (mDialogExistsAction.equals(DIALOG_EXISTS_ACTION_RENAME)){
1743                                 mContextText = mOldFileName;
1744                                 showDialog(DIALOG_RENAME);
1745                             } else if (mDialogExistsAction.equals(DIALOG_EXISTS_ACTION_MULTI_COMPRESS_ZIP)){
1746                                 showDialog(DIALOG_MULTI_COMPRESS_ZIP);
1747                             } else {
1748                                 showDialog(DIALOG_COMPRESSING);
1749                             }
1750                             mDialogExistsAction = "";
1751                         }
1752                     }).create();
1753
1754             case DIALOG_CHANGE_FILE_EXTENSION:
1755                 return new AlertDialog.Builder(this).setTitle(getString(R.string.change_file_extension))
1756                         .setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(
1757                                 android.R.string.ok, new OnClickListener() {
1758                             public void onClick(DialogInterface dialog, int which) {
1759                                 File newFile = FileUtils.getFile(currentDirectory, mNewFileName);
1760                                 if (newFile.exists()){
1761                                     mDialogExistsAction = DIALOG_EXISTS_ACTION_RENAME;
1762                                     showDialog(DIALOG_WARNING_EXISTS);
1763                                 } else {
1764                                     rename(FileUtils.getFile(currentDirectory, mOldFileName), newFile);
1765                                 }
1766                             }
1767                         }).setNegativeButton(android.R.string.cancel, new OnClickListener() {
1768                             public void onClick(DialogInterface dialog, int which) {
1769                                 mContextText = mOldFileName;
1770                                 showDialog(DIALOG_RENAME);
1771                             }
1772                         }).create();
1773                 }
1774                 return super.onCreateDialog(id);
1775                         
1776         }
1777         
1778         private Cursor getBookmarks(){
1779                 return managedQuery(BookmarksProvider.CONTENT_URI,
1780                                         new String[] {
1781                                                 BookmarksProvider._ID,
1782                                                 BookmarksProvider.NAME,
1783                                                 BookmarksProvider.PATH,
1784                                         }, null, null, null);
1785         }
1786
1787
1788         @Override
1789         protected void onPrepareDialog(int id, Dialog dialog) {
1790                 super.onPrepareDialog(id, dialog);
1791                 
1792                 switch (id) {
1793                 case DIALOG_NEW_FOLDER:
1794                         EditText et = (EditText) dialog.findViewById(R.id.foldername);
1795                         et.setText("");
1796                         break;
1797
1798                 case DIALOG_DELETE:
1799                         ((AlertDialog) dialog).setTitle(getString(R.string.really_delete, mContextText));
1800                         break;
1801                         
1802                 case DIALOG_RENAME:
1803                         et = (EditText) dialog.findViewById(R.id.foldername);
1804                         et.setText(mContextText);
1805                         TextView tv = (TextView) dialog.findViewById(R.id.foldernametext);
1806                         if (mContextFile.isDirectory()) {
1807                                 tv.setText(R.string.file_name);
1808                         } else {
1809                                 tv.setText(R.string.file_name);
1810                         }
1811             et.setSelection(0, mContextText.lastIndexOf(".") == -1 ? mContextText.length() : mContextText.lastIndexOf("."));
1812                         ((AlertDialog) dialog).setIcon(mContextIcon);
1813                         break;
1814
1815                 case DIALOG_MULTI_DELETE:
1816             break;
1817             
1818                 case DIALOG_DETAILS:
1819                         final TextView type = ((TextView)dialog.findViewById(R.id.details_type_value));
1820                 type.setText((mContextFile.isDirectory() ? R.string.details_type_folder :
1821                                         (mContextFile.isFile() ? R.string.details_type_file :
1822                                                 R.string.details_type_other)));
1823                 
1824                 final TextView size = ((TextView)dialog.findViewById(R.id.details_size_value));
1825                 size.setText(FileUtils.formatSize(this, mContextFile.length()));
1826                 
1827                 // Creates a background thread that obtains the size of a directory and updates
1828                 // the TextView accordingly.
1829                 if(mContextFile.isDirectory()){
1830                         final AsyncTask folderSizeTask = new AsyncTask<File, Long, Long>(){
1831                                 
1832                                 protected long totalSize = 0L;
1833                                 
1834                                 @Override
1835                                 protected Long doInBackground(File... file) {
1836                                         sizeOf(file[0]);
1837                                         return totalSize;
1838                                 }
1839                         
1840                                 @Override
1841                                 protected void onProgressUpdate(Long... updatedSize){
1842                                         size.setText(FileUtils.formatSize(size.getContext(), updatedSize[0]));
1843                                 }
1844                                 
1845                                 @Override
1846                                 protected void onPostExecute(Long result){
1847                                         size.setText(FileUtils.formatSize(size.getContext(), result));
1848                                 }
1849                                 
1850                                 private void sizeOf(File file){
1851                                         if(file.isFile()){
1852                                                 totalSize += file.length();
1853                                                 publishProgress(totalSize);
1854                                         } else {
1855                                                 File[] files = file.listFiles();
1856                                                 
1857                                                 if(files != null && files.length != 0){
1858                                                         for(File subFile : files){
1859                                                                 sizeOf(subFile);
1860                                                         }
1861                                                 }
1862                                         }
1863                                 }
1864                 }.execute(mContextFile);
1865                 
1866                 ((AlertDialog) dialog).setOnCancelListener(new OnCancelListener(){
1867                                 @Override
1868                                 public void onCancel(DialogInterface dialog) {
1869                                         folderSizeTask.cancel(true);
1870                                 }
1871                 });
1872                 }
1873                 
1874                 String perms = (mContextFile.canRead() ? "R" : "-") +
1875                                 (mContextFile.canWrite() ? "W" : "-") +
1876                                 (FileUtils.canExecute(mContextFile) ? "X" : "-");
1877                 
1878                 final TextView permissions = ((TextView)dialog.findViewById(R.id.details_permissions_value));
1879                 permissions.setText(perms);
1880                 
1881                 final TextView hidden = ((TextView)dialog.findViewById(R.id.details_hidden_value));
1882                 hidden.setText(mContextFile.isHidden() ? R.string.details_yes : R.string.details_no);
1883                 
1884                 final TextView lastmodified = ((TextView)dialog.findViewById(R.id.details_lastmodified_value));
1885                 lastmodified.setText(FileUtils.formatDate(this, mContextFile.lastModified()));
1886                 ((AlertDialog) dialog).setIcon(mContextIcon);
1887                 ((AlertDialog) dialog).setTitle(mContextText);
1888                         break;
1889
1890         case DIALOG_COMPRESSING:
1891             TextView textView = (TextView) dialog.findViewById(R.id.foldernametext);
1892             textView.setText(R.string.compress_into_archive);
1893             final EditText editText = (EditText) dialog.findViewById(R.id.foldername);
1894             String archiveName = "";
1895             if (mContextFile.isDirectory()){
1896                 archiveName = mContextFile.getName()+".zip";
1897             } else {
1898                 String extension = FileUtils.getExtension(mContextFile.getName());
1899                 archiveName = mContextFile.getName().replaceAll(extension, "")+".zip";
1900             }
1901             editText.setText(archiveName);
1902             editText.setSelection(0, archiveName.length()-4);
1903             break;
1904
1905         case DIALOG_MULTI_COMPRESS_ZIP:
1906             textView = (TextView) dialog.findViewById(R.id.foldernametext);
1907             textView.setText(R.string.compress_into_archive);
1908             final EditText editText1 = (EditText) dialog.findViewById(R.id.foldername);
1909             archiveName = currentDirectory.getName()+".zip";
1910             editText1.setText(archiveName);
1911             editText1.setSelection(0, archiveName.length()-4);
1912             break;
1913
1914         case DIALOG_WARNING_EXISTS:
1915             dialog.setTitle(getString(R.string.warning_overwrite, mDialogArgument));
1916         }
1917         }
1918         
1919         /**
1920          * @since 2011-09-30
1921          */
1922         private void showWarningDialog() {
1923                 LayoutInflater li = LayoutInflater.from(this);
1924                 View warningView = li.inflate(R.layout.dialog_warning, null);
1925                 final CheckBox showWarningAgain = (CheckBox)warningView.findViewById(R.id.showagaincheckbox);
1926                 
1927                 showWarningAgain.setChecked(PreferenceActivity.getShowAllWarning(FileManagerActivity.this));
1928                 
1929                 new AlertDialog.Builder(this).setView(warningView).setTitle(getString(R.string.title_warning_some_may_not_work))
1930                                 .setMessage(getString(R.string.warning_some_may_not_work, mContextText))
1931                         .setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(
1932                                         android.R.string.ok, new OnClickListener() {
1933                                                 
1934                                                 public void onClick(DialogInterface dialog, int which) {
1935                                                         PreferenceActivity.setShowAllWarning(FileManagerActivity.this, showWarningAgain.isChecked());
1936
1937                                                         showMoreCommandsDialog();
1938                                                 }
1939                                                 
1940                                         }).create()
1941                                 .show();
1942         }
1943
1944         /**
1945          * @since 2011-09-30
1946          */
1947         private void showMoreCommandsDialog() {
1948                 final Uri data = Uri.fromFile(mContextFile);
1949                 final Intent intent = new Intent(null, data);
1950                 String type = mMimeTypes.getMimeType(mContextFile.getName());
1951
1952                 intent.setDataAndType(data, type);
1953
1954                 Log.v(TAG, "Data=" + data);
1955                 Log.v(TAG, "Type=" + type);
1956
1957                 if (type != null) {
1958                         // Add additional options for the MIME type of the selected file.
1959                         PackageManager pm = getPackageManager();
1960                         final List<ResolveInfo> lri = pm.queryIntentActivityOptions(
1961                                         new ComponentName(this, FileManagerActivity.class),
1962                                         null, intent, 0);
1963                         final int N = lri != null ? lri.size() : 0;
1964
1965                         // Create name list for menu item.
1966                         final List<CharSequence> items = new ArrayList<CharSequence>();
1967                         /* Some of the options don't go to the list hence we have to remove them
1968                          * to keep the lri correspond with the menu items. In the addition, we have
1969                          * to remove them after the first iteration, otherwise the iteration breaks.
1970                          */
1971                         List<ResolveInfo> toRemove = new ArrayList<ResolveInfo>();
1972                         for (int i = 0; i < N; i++) {
1973                                 final ResolveInfo ri = lri.get(i);
1974                                 Intent rintent = new Intent(intent);
1975                                 rintent.setComponent(
1976                                                 new ComponentName(
1977                                                                 ri.activityInfo.applicationInfo.packageName,
1978                                                                 ri.activityInfo.name));
1979                                 ActivityInfo info = rintent.resolveActivityInfo(pm, 0);
1980                                 String permission = info.permission;
1981                                 if(info.exported && (permission == null 
1982                                                 || checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED))
1983                                         items.add(ri.loadLabel(pm));
1984                                 else
1985                                         toRemove.add(ri);
1986                         }
1987
1988                         for(ResolveInfo ri : toRemove){
1989                                 lri.remove(ri);
1990                         }
1991
1992                         new AlertDialog.Builder(this)
1993                                         .setTitle(mContextText)
1994                                         .setIcon(mContextIcon)
1995                                         .setItems(items.toArray(new CharSequence[0]),
1996                                                         new DialogInterface.OnClickListener() {
1997                                                                 public void onClick(DialogInterface dialog, int item) {
1998                                                                         final ResolveInfo ri = lri.get(item);
1999                                                                         Intent rintent = new Intent(intent)
2000                                                                                         .setComponent(new ComponentName(
2001                                                                                                         ri.activityInfo.applicationInfo.packageName,
2002                                                                                                         ri.activityInfo.name));
2003                                                                         startActivity(rintent);
2004                                                                 }
2005                                                         }).create()
2006                                                 .show();
2007                 }
2008         }
2009
2010         private void includeInMediaScan() {
2011                 // Delete the .nomedia file.
2012                 File file = FileUtils.getFile(currentDirectory, NOMEDIA_FILE);
2013                 if (file.delete()) {
2014                         Toast.makeText(this, getString(R.string.media_scan_included), Toast.LENGTH_LONG).show();
2015                         mNoMedia = false;
2016                 } else {
2017                         // That didn't work.
2018                         Toast.makeText(this, getString(R.string.error_generic), Toast.LENGTH_LONG).show();
2019                 }
2020         }
2021
2022         private void excludeFromMediaScan() {
2023                 // Create the .nomedia file.
2024                 File file = FileUtils.getFile(currentDirectory, NOMEDIA_FILE);
2025                 try {
2026                         if (file.createNewFile()) {
2027                                 mNoMedia = true;
2028                                 Toast.makeText(this, getString(R.string.media_scan_excluded), Toast.LENGTH_LONG).show();
2029                         } else {
2030                                 Toast.makeText(this, getString(R.string.error_media_scan), Toast.LENGTH_LONG).show();
2031                         }
2032                 } catch (IOException e) {
2033                         // That didn't work.
2034                         Toast.makeText(this, getString(R.string.error_generic) + e.getMessage(), Toast.LENGTH_LONG).show();
2035                 }
2036         }
2037         
2038         private boolean checkSelection() {
2039         for (IconifiedText it : mDirectoryEntries) {
2040             if (!it.isSelected()) {
2041                 continue;
2042             }
2043
2044             return true;
2045         }
2046
2047         Toast.makeText(this, R.string.error_selection, Toast.LENGTH_SHORT).show();
2048
2049         return false;
2050    }
2051         
2052    private void toggleSelection(boolean selected) {
2053            for(IconifiedText it : mDirectoryEntries){
2054                    it.setSelected(selected);
2055            }
2056            
2057            ((BaseAdapter) getListAdapter()).notifyDataSetChanged();
2058    }
2059
2060         private void toggleCheckBoxVisibility(boolean visible) {
2061                 for(IconifiedText it : mDirectoryEntries){
2062                         it.setCheckIconVisible(visible);
2063                 }
2064                 
2065                 ((BaseAdapter) getListAdapter()).notifyDataSetChanged();
2066         }
2067
2068    private void promptDestinationAndMoveFile() {
2069
2070                 Intent intent = new Intent(FileManagerIntents.ACTION_PICK_DIRECTORY);
2071
2072                 intent.setData(FileUtils.getUri(currentDirectory));
2073
2074                 intent.putExtra(FileManagerIntents.EXTRA_TITLE, getString(R.string.move_title));
2075                 intent.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, getString(R.string.move_button));
2076                 intent.putExtra(FileManagerIntents.EXTRA_WRITEABLE_ONLY, true);
2077
2078                 startActivityForResult(intent, REQUEST_CODE_MOVE);
2079         }
2080
2081     private void promptDestinationAndExtract() {
2082         Intent intent = new Intent(FileManagerIntents.ACTION_PICK_DIRECTORY);
2083         intent.setData(FileUtils.getUri(currentDirectory));
2084         intent.putExtra(FileManagerIntents.EXTRA_TITLE, getString(R.string.extract_title));
2085         intent.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, getString(R.string.extract_button));
2086         intent.putExtra(FileManagerIntents.EXTRA_WRITEABLE_ONLY, true);
2087         startActivityForResult(intent, REQUEST_CODE_EXTRACT);
2088     }
2089         
2090         private void promptDestinationAndCopyFile() {
2091
2092                 Intent intent = new Intent(FileManagerIntents.ACTION_PICK_DIRECTORY);
2093                 
2094                 intent.setData(FileUtils.getUri(currentDirectory));
2095                 
2096                 intent.putExtra(FileManagerIntents.EXTRA_TITLE, getString(R.string.copy_title));
2097                 intent.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, getString(R.string.copy_button));
2098                 intent.putExtra(FileManagerIntents.EXTRA_WRITEABLE_ONLY, true);
2099                 
2100                 startActivityForResult(intent, REQUEST_CODE_COPY);
2101         }
2102         
2103         /**
2104          * Starts activity for multi select.
2105          */
2106         private void promptMultiSelect() {
2107         Intent intent = new Intent(FileManagerIntents.ACTION_MULTI_SELECT);
2108         
2109         intent.setData(FileUtils.getUri(currentDirectory));
2110         
2111         intent.putExtra(FileManagerIntents.EXTRA_TITLE, getString(R.string.multiselect_title));
2112         //intent.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, getString(R.string.move_button));
2113
2114         startActivityForResult(intent, REQUEST_CODE_MULTI_SELECT);
2115     }
2116
2117     private void createNewFolder(String foldername) {
2118                 if (!TextUtils.isEmpty(foldername)) {
2119                         File file = FileUtils.getFile(currentDirectory, foldername);
2120                         if (file.mkdirs()) {
2121                                 
2122                                 // Change into new directory:
2123                                 browseTo(file);
2124                         } else {
2125                                 Toast.makeText(this, R.string.error_creating_new_folder, Toast.LENGTH_SHORT).show();
2126                         }
2127                 }
2128         }
2129
2130     private void compressMultiFile(String out) {
2131         List<File> files = new ArrayList<File>();
2132         for (IconifiedText it : mDirectoryEntries) {
2133             if (!it.isSelected()) {
2134                 continue;
2135             }
2136
2137             File file = FileUtils.getFile(currentDirectory, it.getText());
2138             files.add(file);
2139         }
2140         new CompressManager(FileManagerActivity.this).compress(files, out);
2141     }
2142
2143         /*! Recursively delete a directory and all of its children.
2144          *  @params toastOnError If set to true, this function will toast if an error occurs.
2145          *  @returns true if successful, false otherwise.
2146          */
2147         private boolean recursiveDelete(File file, boolean toastOnError) {
2148                 // Recursively delete all contents.
2149                 File[] files = file.listFiles();
2150                 
2151                 if (files == null) {
2152                         Toast.makeText(this, getString(R.string.error_deleting_folder, file.getAbsolutePath()), Toast.LENGTH_LONG);
2153                         return false;
2154                 }
2155                 
2156                 for (int x=0; x<files.length; x++) {
2157                         File childFile = files[x];
2158                         if (childFile.isDirectory()) {
2159                                 if (!recursiveDelete(childFile, toastOnError)) {
2160                                         return false;
2161                                 }
2162                         } else {
2163                                 if (!childFile.delete()) {
2164                                         Toast.makeText(this, getString(R.string.error_deleting_child_file, childFile.getAbsolutePath()), Toast.LENGTH_LONG);
2165                                         return false;
2166                                 }
2167                         }
2168                 }
2169                 
2170                 if (!file.delete()) {
2171                         Toast.makeText(this, getString(R.string.error_deleting_folder, file.getAbsolutePath()), Toast.LENGTH_LONG);
2172                         return false;
2173                 }
2174                 
2175                 return true;
2176         }
2177         
2178         private class RecursiveDeleteTask extends AsyncTask<Object, Void, Integer> {
2179
2180                 private FileManagerActivity activity = FileManagerActivity.this;
2181                 private static final int success = 0;
2182                 private static final int err_deleting_folder = 1;
2183                 private static final int err_deleting_child_file = 2;
2184                 private static final int err_deleting_file = 3;
2185
2186                 private File errorFile;
2187
2188                 /**
2189                  * Recursively delete a file or directory and all of its children.
2190                  * 
2191                  * @returns 0 if successful, error value otherwise.
2192                  */
2193                 private int recursiveDelete(File file) {
2194                         if (file.isDirectory() && file.listFiles() != null)
2195                                 for (File childFile : file.listFiles()) {
2196                                         if (childFile.isDirectory()) {
2197                                                 int result = recursiveDelete(childFile);
2198                                                 if (result > 0) {
2199                                                         return result;
2200                                                 }
2201                                         } else {
2202                                                 if (!childFile.delete()) {
2203                                                         errorFile = childFile;
2204                                                         return err_deleting_child_file;
2205                                                 }
2206                                         }
2207                                 }
2208
2209                         if (!file.delete()) {
2210                                 errorFile = file;
2211                                 return file.isFile() ? err_deleting_file : err_deleting_folder;
2212                         }
2213
2214                         return success;
2215                 }
2216
2217                 @Override
2218                 protected void onPreExecute() {
2219                         Toast.makeText(activity, R.string.deleting_files, Toast.LENGTH_SHORT).show();
2220                 }
2221                 
2222                 @SuppressWarnings("unchecked")
2223                 @Override
2224                 protected Integer doInBackground(Object... params) {
2225                         Object files = params[0];
2226                         
2227                         if (files instanceof List<?>) {
2228                                 for (File file: (List<File>)files) {
2229                                         int result = recursiveDelete(file);
2230                                         if (result != success) return result;
2231                                 }
2232                                 return success;
2233                         } else
2234                                 return recursiveDelete((File)files);
2235
2236                 }
2237
2238                 @Override
2239                 protected void onPostExecute(Integer result) {
2240                         switch (result) {
2241                         case success:
2242                                 activity.refreshList();
2243                                 if(deletedFileIsDirectory){
2244                                         Toast.makeText(activity, R.string.folder_deleted,Toast.LENGTH_SHORT).show();
2245                                 } else {
2246                                         Toast.makeText(activity, R.string.file_deleted,Toast.LENGTH_SHORT).show();
2247                                 }
2248                                 break;
2249                         case err_deleting_folder:
2250                                 Toast.makeText(activity,getString(R.string.error_deleting_folder,
2251                                                 errorFile.getAbsolutePath()), Toast.LENGTH_LONG).show();
2252                                 break;
2253                         case err_deleting_child_file:
2254                                 Toast.makeText(activity,getString(R.string.error_deleting_child_file,
2255                                                 errorFile.getAbsolutePath()),Toast.LENGTH_SHORT).show();
2256                                 break;
2257                         case err_deleting_file:
2258                                 Toast.makeText(activity,getString(R.string.error_deleting_file,
2259                                                 errorFile.getAbsolutePath()), Toast.LENGTH_LONG).show();
2260                                 break;
2261                         }
2262                 }
2263
2264         }
2265
2266         private void deleteFileOrFolder(File file) {
2267                 fileDeleted = true;
2268                 positionAtDelete = getListView().getFirstVisiblePosition();
2269                 deletedFileIsDirectory = file.isDirectory();
2270                 new RecursiveDeleteTask().execute(file);
2271 //              if (file.isDirectory()) {
2272 //                      if (recursiveDelete(file, true)) {
2273 //                              refreshList();
2274 //                              Toast.makeText(this, R.string.folder_deleted, Toast.LENGTH_SHORT).show();
2275 //                      }
2276 //              } else {
2277 //                      if (file.delete()) {
2278 //                              // Delete was successful.
2279 //                              refreshList();
2280 //                              Toast.makeText(this, R.string.file_deleted, Toast.LENGTH_SHORT).show();
2281 //                      } else {
2282 //                              Toast.makeText(this, R.string.error_deleting_file, Toast.LENGTH_SHORT).show();
2283 //                      }
2284 //              }
2285         }
2286         
2287     private void deleteMultiFile() {
2288 //        int toast = 0;
2289         LinkedList<File> files = new LinkedList<File>();
2290         for (IconifiedText it : mDirectoryEntries) {
2291             if (!it.isSelected()) {
2292                 continue;
2293             }
2294
2295             File file = FileUtils.getFile(currentDirectory, it.getText());
2296             files.add(file);
2297 //            if (file.isDirectory()) {
2298 //                if (!recursiveDelete(file, true)) {
2299 //                    break;
2300 //                }
2301 //            } else {
2302 //                if (!file.delete()) {
2303 //                    toast = R.string.error_deleting_file;
2304 //                    break;
2305 //                }
2306 //            }
2307         }
2308
2309         new RecursiveDeleteTask().execute(files);
2310         
2311 //        if (toast == 0) {
2312 //            // Delete was successful.
2313 //            refreshList();
2314 //            toast = R.string.file_deleted;
2315 //        }
2316 //
2317 //        Toast.makeText(FileManagerActivity.this, toast, Toast.LENGTH_SHORT).show();
2318     }
2319     
2320     private void renameFileOrFolder(File file, String newFileName) {
2321         mOldFileName = file.getName();
2322         mNewFileName = newFileName;
2323         mDialogArgument = mNewFileName;
2324                 if (newFileName != null && newFileName.length() > 0){
2325                         if (!file.isDirectory() && !FileUtils.getExtension(newFileName).equals(FileUtils.getExtension(file.getName()))){
2326                 showDialog(DIALOG_CHANGE_FILE_EXTENSION);
2327                 return;
2328                         }
2329                 }
2330                 File newFile = FileUtils.getFile(currentDirectory, newFileName);
2331         if (newFile.exists()){
2332             mDialogExistsAction = DIALOG_EXISTS_ACTION_RENAME;
2333             showDialog(DIALOG_WARNING_EXISTS);
2334         } else {
2335             rename(file, newFile);
2336         }
2337         }
2338
2339         /**
2340          * @param oldFile
2341          * @param newFile
2342          */
2343         private void rename(File oldFile, File newFile) {
2344                 int toast = 0;
2345                 if (oldFile.renameTo(newFile)) {
2346                         // Rename was successful.
2347                         refreshList();
2348                         if (newFile.isDirectory()) {
2349                                 toast = R.string.folder_renamed;
2350                         } else {
2351                                 toast = R.string.file_renamed;
2352                         }
2353                 } else {
2354                         if (newFile.isDirectory()) {
2355                                 toast = R.string.error_renaming_folder;
2356                         } else {
2357                                 toast = R.string.error_renaming_file;
2358                         }
2359                 }
2360                 Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
2361         }
2362
2363         /*@ RETURNS: A file name that is guaranteed to not exist yet.
2364          * 
2365          * PARAMS:
2366          *   context - Application context.
2367          *   path - The path that the file is supposed to be in.
2368          *   fileName - Desired file name. This name will be modified to
2369          *     create a unique file if necessary.
2370          * 
2371          */
2372         private File createUniqueCopyName(Context context, File path, String fileName) {
2373                 // Does that file exist?
2374                 File file = FileUtils.getFile(path, fileName);
2375                 
2376                 if (!file.exists()) {
2377                         // Nope - we can take that.
2378                         return file;
2379                 }
2380                 
2381                 // Split file's name and extension to fix internationalization issue #307
2382                 int fromIndex = fileName.lastIndexOf(FILE_EXTENSION_SEPARATOR);
2383                 String extension = "";
2384                 if (fromIndex > 0) {
2385                         extension = fileName.substring(fromIndex);
2386                         fileName = fileName.substring(0, fromIndex);
2387                 }
2388                 
2389                 // Try a simple "copy of".
2390                 file = FileUtils.getFile(path, context.getString(R.string.copied_file_name, fileName).concat(extension));
2391                 
2392                 if (!file.exists()) {
2393                         // Nope - we can take that.
2394                         return file;
2395                 }
2396                 
2397                 int copyIndex = 2;
2398                 
2399                 // Well, we gotta find a unique name at some point.
2400                 while (copyIndex < 500) {
2401                         file = FileUtils.getFile(path, context.getString(R.string.copied_file_name_2, copyIndex, fileName).concat(extension));
2402                         
2403                         if (!file.exists()) {
2404                                 // Nope - we can take that.
2405                                 return file;
2406                         }
2407
2408                         copyIndex++;
2409                 }
2410         
2411                 // I GIVE UP.
2412                 return null;
2413         }
2414         
2415         private boolean copy(File oldFile, File newFile) {
2416                 try {
2417                         FileInputStream input = new FileInputStream(oldFile);
2418                         FileOutputStream output = new FileOutputStream(newFile);
2419                 
2420                         byte[] buffer = new byte[COPY_BUFFER_SIZE];
2421                         
2422                         while (true) {
2423                                 int bytes = input.read(buffer);
2424                                 
2425                                 if (bytes <= 0) {
2426                                         break;
2427                                 }
2428                                 
2429                                 output.write(buffer, 0, bytes);
2430                         }
2431                         
2432                         output.close();
2433                         input.close();
2434                         
2435                 } catch (Exception e) {
2436                     return false;
2437                 }
2438                 return true;
2439         }
2440         
2441         private void sendFile(File file) {
2442
2443                 String filename = file.getName();
2444                 String content = "hh";
2445                 
2446                 Log.i(TAG, "Title to send: " + filename);
2447                 Log.i(TAG, "Content to send: " + content);
2448
2449                 Intent i = new Intent();
2450                 i.setAction(Intent.ACTION_SEND);
2451                 i.setType(mMimeTypes.getMimeType(file.getName()));
2452                 i.putExtra(Intent.EXTRA_SUBJECT, filename);
2453                 //i.putExtra(Intent.EXTRA_STREAM, FileUtils.getUri(file));
2454                 i.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + FileManagerProvider.AUTHORITY + file.getAbsolutePath()));
2455
2456                 i = Intent.createChooser(i, getString(R.string.menu_send));
2457                 
2458                 try {
2459                         startActivity(i);
2460                 } catch (ActivityNotFoundException e) {
2461                         Toast.makeText(this, R.string.send_not_available,
2462                                         Toast.LENGTH_SHORT).show();
2463                         Log.e(TAG, "Email client not installed");
2464                 }
2465         }
2466
2467         // This code seems to work for SDK 2.3 (target="9")
2468         @Override
2469         public boolean onKeyDown(int keyCode, KeyEvent event) {
2470                 
2471                 if (keyCode == KeyEvent.KEYCODE_BACK) {
2472                         if (mStepsBack > 0) {
2473                                 upOneLevel();
2474                                 return true;
2475                         }
2476                 }
2477                 
2478                 return super.onKeyDown(keyCode, event);
2479         }
2480         
2481         // For targetSdkVersion="5" or higher, one needs to use the following code instead of the one above:
2482         // (See http://android-developers.blogspot.com/2009/12/back-and-other-hard-keys-three-stories.html )
2483         
2484         /*
2485         //@Override
2486         public boolean onKeyDown(int keyCode, KeyEvent event)  {
2487             if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR
2488                     && keyCode == KeyEvent.KEYCODE_BACK
2489                     && event.getRepeatCount() == 0) {
2490                 // Take care of calling this method on earlier versions of
2491                 // the platform where it doesn't exist.
2492                 onBackPressed();
2493             }
2494
2495             return super.onKeyDown(keyCode, event);
2496         }
2497
2498         //@Override
2499         public void onBackPressed() {
2500             // This will be called either automatically for you on 2.0
2501             // or later, or by the code above on earlier versions of the
2502             // platform.
2503                 if (mStepsBack > 0) {
2504                         upOneLevel();
2505                 } else {
2506                         finish();
2507                 }
2508         }
2509         */
2510
2511     /**
2512      * This is called after the file manager finished.
2513      */
2514         @Override
2515         protected void onActivityResult(int requestCode, int resultCode, Intent data) {
2516                 super.onActivityResult(requestCode, resultCode, data);
2517
2518                 switch (requestCode) {
2519                 case REQUEST_CODE_MOVE:
2520                         if (resultCode == RESULT_OK && data != null) {
2521                                 // obtain the filename
2522                                 File movefrom = mContextFile;
2523                                 File moveto = FileUtils.getFile(data.getData());
2524                                 if (moveto != null) {
2525                                         if (mState != STATE_MULTI_SELECT) {
2526                                             // Move single file.
2527                         moveto = FileUtils.getFile(moveto, movefrom.getName());
2528                                                 int toast = 0;
2529                                                 if (movefrom.renameTo(moveto)) {
2530                                                         // Move was successful.
2531                                                     refreshList();
2532                                             if (moveto.isDirectory()) {
2533                                                                 toast = R.string.folder_moved;
2534                                                         } else {
2535                                                                 toast = R.string.file_moved;
2536                                                         }
2537                                                 } else {
2538                                                         if (moveto.isDirectory()) {
2539                                                                 toast = R.string.error_moving_folder;
2540                                                         } else {
2541                                                                 toast = R.string.error_moving_file;
2542                                                         }
2543                                                 }
2544                                                 Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
2545                                         } else {
2546                                         // Move multi file.
2547                         int toast = 0;
2548                         for (IconifiedText it : mDirectoryEntries) {
2549                             if (!it.isSelected()) {
2550                                 continue;
2551                             }
2552
2553                             movefrom = FileUtils.getFile(currentDirectory, it.getText());
2554                                                 File newPath = FileUtils.getFile(moveto, movefrom.getName());
2555                             if (!movefrom.renameTo(newPath)) {
2556                                 refreshList();
2557                                 if (moveto.isDirectory()) {
2558                                     toast = R.string.error_moving_folder;
2559                                 } else {
2560                                     toast = R.string.error_moving_file;
2561                                 }
2562                                 break;
2563                             }
2564                                             }
2565
2566                         if (toast == 0) {
2567                             // Move was successful.
2568                             refreshList();
2569                             toast = R.string.file_moved;
2570                         }
2571
2572                         Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
2573
2574                         Intent intent = getIntent();
2575                         setResult(RESULT_OK, intent);
2576                         finish();
2577                     }
2578                                                 
2579                                 }                               
2580                                 
2581                         }
2582                         break;
2583         
2584         case REQUEST_CODE_EXTRACT:
2585             if (resultCode == RESULT_OK && data != null) {
2586                 new ExtractManager(this).extract(mContextFile, data.getData().getPath());
2587             }
2588             break;
2589
2590                 case REQUEST_CODE_COPY:
2591                         if (resultCode == RESULT_OK && data != null) {
2592                                 // obtain the filename
2593                                 File copyfrom = mContextFile;
2594                                 File copyto = FileUtils.getFile(data.getData());
2595                                 if (copyto != null) {
2596                     if (mState != STATE_MULTI_SELECT) {
2597                         // Copy single file.
2598                         copyto = createUniqueCopyName(this, copyto, copyfrom.getName());
2599                         
2600                         if (copyto != null) {
2601                             int toast = 0;
2602                             if (copy(copyfrom, copyto)) {
2603                                 toast = R.string.file_copied;
2604                                 refreshList();
2605                             } else {
2606                                 toast = R.string.error_copying_file;
2607                             }
2608                             Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
2609                         }
2610                     } else {
2611                         // Copy multi file.
2612                         int toast = 0;
2613                         for (IconifiedText it : mDirectoryEntries) {
2614                             if (!it.isSelected()) {
2615                                 continue;
2616                             }
2617
2618                             copyfrom = FileUtils.getFile(currentDirectory, it.getText());
2619                             File newPath = createUniqueCopyName(this, copyto, copyfrom.getName());
2620                             if (copyto != null) {
2621                                 if (!copy(copyfrom, newPath)) {
2622                                     toast = R.string.error_copying_file;
2623                                     break;
2624                                 }
2625                             }
2626                         }
2627
2628                         if (toast == 0) {
2629                             // Copy was successful.
2630                             toast = R.string.file_copied;
2631                             refreshList();
2632                         }
2633
2634                         Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
2635
2636                         Intent intent = getIntent();
2637                         setResult(RESULT_OK, intent);
2638                         finish();
2639                     }
2640                                 }                               
2641                         }
2642                         break;
2643
2644         case REQUEST_CODE_MULTI_SELECT:
2645             if (resultCode == RESULT_OK && data != null) {
2646                 refreshList();
2647             }
2648             break;
2649         }
2650                 
2651         }
2652         
2653         public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
2654             if (//When the user chooses to show/hide hidden files, update the list
2655                 //to correspond with the user's choice
2656                 PreferenceActivity.PREFS_DISPLAYHIDDENFILES.equals(key)
2657                 //When the user changes the sortBy settings, update the list
2658                 || PreferenceActivity.PREFS_SORTBY.equals(key)
2659                 || PreferenceActivity.PREFS_ASCENDING.equals(key)){
2660                 
2661                 refreshList();
2662             }
2663         }
2664
2665
2666 }