OSDN Git Service

CMFM: Fix typo
[android-x86/packages-apps-CMFileManager.git] / src / com / cyanogenmod / filemanager / activities / NavigationActivity.java
1 /*
2  * Copyright (C) 2012 The CyanogenMod Project
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 package com.cyanogenmod.filemanager.activities;
18
19 import android.app.ActionBar;
20 import android.app.Activity;
21 import android.app.AlertDialog;
22 import android.app.SearchManager;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.res.Configuration;
29 import android.net.Uri;
30 import android.nfc.NfcAdapter;
31 import android.nfc.NfcEvent;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.os.Parcelable;
35 import android.os.storage.StorageVolume;
36 import android.util.Log;
37 import android.view.KeyEvent;
38 import android.view.Menu;
39 import android.view.MenuItem;
40 import android.view.View;
41 import android.view.ViewGroup;
42 import android.widget.AdapterView;
43 import android.widget.AdapterView.OnItemClickListener;
44 import android.widget.ImageView;
45 import android.widget.LinearLayout;
46 import android.widget.ListPopupWindow;
47 import android.widget.PopupWindow;
48 import android.widget.TextView;
49 import android.widget.Toast;
50
51 import com.cyanogenmod.filemanager.FileManagerApplication;
52 import com.cyanogenmod.filemanager.R;
53 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
54 import com.cyanogenmod.filemanager.adapters.HighlightedSimpleMenuListAdapter;
55 import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter;
56 import com.cyanogenmod.filemanager.adapters.SimpleMenuListAdapter;
57 import com.cyanogenmod.filemanager.console.Console;
58 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
59 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
60 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
61 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
62 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
63 import com.cyanogenmod.filemanager.model.DiskUsage;
64 import com.cyanogenmod.filemanager.model.FileSystemObject;
65 import com.cyanogenmod.filemanager.model.History;
66 import com.cyanogenmod.filemanager.model.MountPoint;
67 import com.cyanogenmod.filemanager.parcelables.HistoryNavigable;
68 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
69 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
70 import com.cyanogenmod.filemanager.preferences.AccessMode;
71 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
72 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
73 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
74 import com.cyanogenmod.filemanager.preferences.Preferences;
75 import com.cyanogenmod.filemanager.ui.ThemeManager;
76 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
77 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
78 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog;
79 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener;
80 import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb;
81 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
82 import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView;
83 import com.cyanogenmod.filemanager.ui.widgets.NavigationView;
84 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener;
85 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener;
86 import com.cyanogenmod.filemanager.ui.widgets.SelectionView;
87 import com.cyanogenmod.filemanager.util.AndroidHelper;
88 import com.cyanogenmod.filemanager.util.CommandHelper;
89 import com.cyanogenmod.filemanager.util.DialogHelper;
90 import com.cyanogenmod.filemanager.util.ExceptionUtil;
91 import com.cyanogenmod.filemanager.util.FileHelper;
92 import com.cyanogenmod.filemanager.util.StorageHelper;
93
94 import java.io.File;
95 import java.io.FileNotFoundException;
96 import java.io.Serializable;
97 import java.util.ArrayList;
98 import java.util.Arrays;
99 import java.util.List;
100
101 /**
102  * The main navigation activity. This activity is the center of the application.
103  * From this the user can navigate, search, make actions.<br/>
104  * This activity is singleTop, so when it is displayed no other activities exists in
105  * the stack.<br/>
106  * This cause an issue with the saved instance of this class, because if another activity
107  * is displayed, and the process is killed, NavigationActivity is started and the saved
108  * instance gets corrupted.<br/>
109  * For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and
110  * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time
111  * the app is killed, is restarted from his initial state.
112  */
113 public class NavigationActivity extends Activity
114     implements OnHistoryListener, OnRequestRefreshListener,
115     OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener {
116
117     private static final String TAG = "NavigationActivity"; //$NON-NLS-1$
118
119     private static boolean DEBUG = false;
120
121     /**
122      * Intent code for request a bookmark selection.
123      */
124     public static final int INTENT_REQUEST_BOOKMARK = 10001;
125
126     /**
127      * Intent code for request a history selection.
128      */
129     public static final int INTENT_REQUEST_HISTORY = 20001;
130
131     /**
132      * Intent code for request a search.
133      */
134     public static final int INTENT_REQUEST_SEARCH = 30001;
135
136
137     /**
138      * Constant for extra information about selected bookmark.
139      */
140     public static final String EXTRA_BOOKMARK_SELECTION =
141             "extra_bookmark_selection"; //$NON-NLS-1$
142
143     /**
144      * Constant for extra information about selected history entry.
145      */
146     public static final String EXTRA_HISTORY_ENTRY_SELECTION =
147             "extra_history_entry_selection"; //$NON-NLS-1$
148
149     /**
150      * Constant for extra information about clear selection action.
151      */
152     public static final String EXTRA_HISTORY_CLEAR =
153             "extra_history_clear_history"; //$NON-NLS-1$
154
155     /**
156      * Constant for extra information about selected search entry.
157      */
158     public static final String EXTRA_SEARCH_ENTRY_SELECTION =
159             "extra_search_entry_selection"; //$NON-NLS-1$
160
161     /**
162      * Constant for extra information about last search data.
163      */
164     public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
165             "extra_search_last_search_data"; //$NON-NLS-1$
166
167     /**
168      * Constant for extra information for request a navigation to the passed path.
169      */
170     public static final String EXTRA_NAVIGATE_TO =
171             "extra_navigate_to"; //$NON-NLS-1$
172
173     // The timeout needed to reset the exit status for back button
174     // After this time user need to tap 2 times the back button to
175     // exit, and the toast is shown again after the first tap.
176     private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500;
177
178     private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
179         @Override
180         public void onReceive(Context context, Intent intent) {
181             if (intent != null) {
182                 if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
183                     // The settings has changed
184                     String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
185                     if (key != null) {
186                         // Disk usage warning level
187                         if (key.compareTo(FileManagerSettings.
188                                 SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) {
189
190                             // Set the free disk space warning level of the breadcrumb widget
191                             Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
192                             String fds = Preferences.getSharedPreferences().getString(
193                                     FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
194                                     (String)FileManagerSettings.
195                                         SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
196                             breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
197                             breadcrumb.updateMountPointInfo();
198                             return;
199                         }
200
201                         // Case sensitive sort
202                         if (key.compareTo(FileManagerSettings.
203                                 SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) {
204                             getCurrentNavigationView().refresh();
205                             return;
206                         }
207
208                         // Use flinger
209                         if (key.compareTo(FileManagerSettings.
210                                 SETTINGS_USE_FLINGER.getId()) == 0) {
211                             boolean useFlinger =
212                                     Preferences.getSharedPreferences().getBoolean(
213                                             FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
214                                                 ((Boolean)FileManagerSettings.
215                                                         SETTINGS_USE_FLINGER.
216                                                             getDefaultValue()).booleanValue());
217                             getCurrentNavigationView().setUseFlinger(useFlinger);
218                             return;
219                         }
220
221                         // Access mode
222                         if (key.compareTo(FileManagerSettings.
223                                 SETTINGS_ACCESS_MODE.getId()) == 0) {
224                             // Is it necessary to create or exit of the ChRooted?
225                             boolean chRooted =
226                                     FileManagerApplication.
227                                         getAccessMode().compareTo(AccessMode.SAFE) == 0;
228                             if (chRooted != NavigationActivity.this.mChRooted) {
229                                 if (chRooted) {
230                                     createChRooted();
231                                 } else {
232                                     exitChRooted();
233                                 }
234                             }
235                         }
236                     }
237
238                 } else if (intent.getAction().compareTo(
239                         FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
240                     // Retrieve the file that was changed
241                     String file =
242                             intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
243                     try {
244                         FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
245                         if (fso != null) {
246                             getCurrentNavigationView().refresh(fso);
247                         }
248                     } catch (Exception e) {
249                         ExceptionUtil.translateException(context, e, true, false);
250                     }
251                 } else if (intent.getAction().compareTo(
252                         FileManagerSettings.INTENT_THEME_CHANGED) == 0) {
253                     applyTheme();
254                 }
255             }
256         }
257     };
258
259     /**
260      * @hide
261      */
262     NavigationView[] mNavigationViews;
263     private List<History> mHistory;
264
265     private int mCurrentNavigationView;
266
267     private ViewGroup mActionBar;
268     private SelectionView mSelectionBar;
269
270     private boolean mExitFlag = false;
271     private long mExitBackTimeout = -1;
272
273     private View mOptionsAnchorView;
274
275     private int mOrientation;
276
277     /**
278      * @hide
279      */
280     boolean mChRooted;
281
282     /**
283      * @hide
284      */
285     Handler mHandler;
286
287     /**
288      * {@inheritDoc}
289      */
290     @Override
291     protected void onCreate(Bundle state) {
292
293         if (DEBUG) {
294             Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
295         }
296
297         // Register the broadcast receiver
298         IntentFilter filter = new IntentFilter();
299         filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
300         filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED);
301         filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED);
302         registerReceiver(this.mNotificationReceiver, filter);
303
304         //Set the main layout of the activity
305         setContentView(R.layout.navigation);
306
307         //Initialize nfc adapter
308         NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
309         if (mNfcAdapter != null) {
310             mNfcAdapter.setBeamPushUrisCallback(new NfcAdapter.CreateBeamUrisCallback() {
311                 @Override
312                 public Uri[] createBeamUris(NfcEvent event) {
313                     List<FileSystemObject> selectedFiles =
314                             getCurrentNavigationView().getSelectedFiles();
315                     if (selectedFiles.size() > 0) {
316                         List<Uri> fileUri = new ArrayList<Uri>();
317                         for (FileSystemObject f : selectedFiles) {
318                             //Beam ignores folders and system files
319                             if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) {
320                                 fileUri.add(Uri.fromFile(new File(f.getFullPath())));
321                             }
322                         }
323                         if (fileUri.size() > 0) {
324                             return fileUri.toArray(new Uri[fileUri.size()]);
325                         }
326                     }
327                     return null;
328                 }
329             }, this);
330         }
331
332         //Initialize activity
333         init();
334
335         //Navigation views
336         initNavigationViews();
337
338         //Initialize action bars
339         initTitleActionBar();
340         initStatusActionBar();
341         initSelectionBar();
342
343         // Adjust layout (only when start on landscape mode)
344         int orientation = getResources().getConfiguration().orientation;
345         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
346             onLayoutChanged();
347         }
348         this.mOrientation = orientation;
349
350         // Apply the theme
351         applyTheme();
352
353         // Show welcome message
354         showWelcomeMsg();
355
356         this.mHandler = new Handler();
357         this.mHandler.post(new Runnable() {
358             @Override
359             public void run() {
360                 //Initialize navigation
361                 int cc = NavigationActivity.this.mNavigationViews.length;
362                 for (int i = 0; i < cc; i++) {
363                     initNavigation(i, false);
364                 }
365
366                 //Check the intent action
367                 checkIntent(getIntent());
368             }
369         });
370
371         //Save state
372         super.onCreate(state);
373     }
374
375     /**
376      * {@inheritDoc}
377      */
378     @Override
379     protected void onNewIntent(Intent intent) {
380         //Initialize navigation
381         initNavigation(this.mCurrentNavigationView, true);
382
383         //Check the intent action
384         checkIntent(intent);
385     }
386
387     /**
388      * {@inheritDoc}
389      */
390     @Override
391     public void onConfigurationChanged(Configuration newConfig) {
392         super.onConfigurationChanged(newConfig);
393         onLayoutChanged();
394     }
395
396     /**
397      * {@inheritDoc}
398      */
399     @Override
400     protected void onDestroy() {
401         if (DEBUG) {
402             Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$
403         }
404
405         // Unregister the receiver
406         try {
407             unregisterReceiver(this.mNotificationReceiver);
408         } catch (Throwable ex) {
409             /**NON BLOCK**/
410         }
411
412         //All destroy. Continue
413         super.onDestroy();
414     }
415
416     /**
417      * Method that returns the current navigation view.
418      *
419      * @return NavigationView The current navigation view
420      */
421     public NavigationView getCurrentNavigationView() {
422         return getNavigationView(this.mCurrentNavigationView);
423     }
424
425     /**
426      * Method that returns the current navigation view.
427      *
428      * @param viewId The view to return
429      * @return NavigationView The current navigation view
430      */
431     public NavigationView getNavigationView(int viewId) {
432         if (this.mNavigationViews == null) return null;
433         return this.mNavigationViews[viewId];
434     }
435
436     /**
437      * Method that initializes the activity.
438      */
439     private void init() {
440         this.mHistory = new ArrayList<History>();
441         this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
442     }
443
444     /**
445      * Method that displays a welcome message the first time the user
446      * access the application
447      */
448     private void showWelcomeMsg() {
449         boolean firstUse = Preferences.getSharedPreferences().getBoolean(
450                 FileManagerSettings.SETTINGS_FIRST_USE.getId(),
451                 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
452
453         //Display the welcome message?
454         if (firstUse) {
455             AlertDialog dialog = DialogHelper.createAlertDialog(
456                 this, R.drawable.ic_launcher,
457                 R.string.welcome_title, getString(R.string.welcome_msg), false);
458             DialogHelper.delegateDialogShow(this, dialog);
459
460             // Don't display again this dialog
461             try {
462                 Preferences.savePreference(
463                         FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true);
464             } catch (Exception e) {/**NON BLOCK**/}
465         }
466     }
467
468     /**
469      * Method that initializes the titlebar of the activity.
470      */
471     private void initTitleActionBar() {
472         //Inflate the view and associate breadcrumb
473         View titleLayout = getLayoutInflater().inflate(
474                 R.layout.navigation_view_customtitle, null, false);
475         NavigationCustomTitleView title =
476                 (NavigationCustomTitleView)titleLayout.findViewById(R.id.navigation_title_flipper);
477         title.setOnHistoryListener(this);
478         Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view);
479         int cc = this.mNavigationViews.length;
480         for (int i = 0; i < cc; i++) {
481             this.mNavigationViews[i].setBreadcrumb(breadcrumb);
482             this.mNavigationViews[i].setOnHistoryListener(this);
483             this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this);
484             this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this);
485             this.mNavigationViews[i].setCustomTitle(title);
486         }
487
488         // Set the free disk space warning level of the breadcrumb widget
489         String fds = Preferences.getSharedPreferences().getString(
490                 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
491                 (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
492         breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
493
494         //Configure the action bar options
495         getActionBar().setBackgroundDrawable(
496                 getResources().getDrawable(R.drawable.bg_holo_titlebar));
497         getActionBar().setDisplayOptions(
498                 ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
499         getActionBar().setCustomView(titleLayout);
500     }
501
502     /**
503      * Method that initializes the statusbar of the activity.
504      */
505     private void initStatusActionBar() {
506         //Performs a width calculation of buttons. Buttons exceeds the width
507         //of the action bar should be hidden
508         //This application not use android ActionBar because the application
509         //make uses of the title and bottom areas, and wants to force to show
510         //the overflow button (without care of physical buttons)
511         this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar);
512         this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
513             @Override
514             public void onLayoutChange(
515                     View v, int left, int top, int right, int bottom, int oldLeft,
516                     int oldTop, int oldRight, int oldBottom) {
517                 //Get the width of the action bar
518                 int w = v.getMeasuredWidth();
519
520                 //Wake through children calculation his dimensions
521                 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
522                 int cw = 0;
523                 final ViewGroup abView = ((ViewGroup)v);
524                 int cc = abView.getChildCount();
525                 for (int i = 0; i < cc; i++) {
526                     View child = abView.getChildAt(i);
527                     child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE);
528                     cw += bw;
529                 }
530             }
531         });
532
533         // Have overflow menu?
534         View overflow = findViewById(R.id.ab_overflow);
535         boolean showOptionsMenu = AndroidHelper.showOptionsMenu(getApplicationContext());
536         overflow.setVisibility(showOptionsMenu ? View.VISIBLE : View.GONE);
537         this.mOptionsAnchorView = showOptionsMenu ? overflow : this.mActionBar;
538
539         // Show the status bar
540         View statusBar = findViewById(R.id.navigation_statusbar_portrait_holder);
541         statusBar.setVisibility(View.VISIBLE);
542     }
543
544     /**
545      * Method that initializes the selectionbar of the activity.
546      */
547     private void initSelectionBar() {
548         this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar);
549     }
550
551     /**
552      * Method that initializes the navigation views of the activity
553      */
554     private void initNavigationViews() {
555         //Get the navigation views (wishlist: multiple view; for now only one view)
556         this.mNavigationViews = new NavigationView[1];
557         this.mCurrentNavigationView = 0;
558         //- 0
559         this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view);
560         this.mNavigationViews[0].setId(0);
561     }
562
563     /**
564      * Method that initializes the navigation.
565      *
566      * @param viewId The navigation view identifier where apply the navigation
567      * @param restore Initialize from a restore info
568      * @hide
569      */
570     void initNavigation(final int viewId, final boolean restore) {
571         final NavigationView navigationView = getNavigationView(viewId);
572         this.mHandler.post(new Runnable() {
573             @Override
574             public void run() {
575                 //Create the default console (from the preferences)
576                 try {
577                     Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
578                     if (console == null) {
579                         throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
580                     }
581                 } catch (Throwable ex) {
582                     if (!NavigationActivity.this.mChRooted) {
583                         //Show exception and exit
584                         Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
585                         // We don't have any console
586                         // Show exception and exit
587                         DialogHelper.showToast(
588                                 NavigationActivity.this,
589                                 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
590                         exit();
591                         return;
592                     }
593
594                     // We are in a trouble (something is not allowing creating the console)
595                     // Ask the user to return to prompt or root access mode mode with a
596                     // non-privileged console, prior to make crash the application
597                     askOrExit();
598                     return;
599                 }
600
601                 //Is necessary navigate?
602                 if (!restore) {
603                     //Load the preference initial directory
604                     String initialDir =
605                             Preferences.getSharedPreferences().getString(
606                                 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
607                                 (String)FileManagerSettings.
608                                     SETTINGS_INITIAL_DIR.getDefaultValue());
609                     if (NavigationActivity.this.mChRooted) {
610                         // Initial directory is the first external sdcard (sdcard, emmc, usb, ...)
611                         StorageVolume[] volumes =
612                                 StorageHelper.getStorageVolumes(NavigationActivity.this);
613                         if (volumes != null && volumes.length > 0) {
614                             initialDir = volumes[0].getPath();
615                         } else {
616                             // Show exception and exit
617                             DialogHelper.showToast(
618                                     NavigationActivity.this,
619                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
620                             exit();
621                             return;
622                         }
623                     }
624
625                     //Ensure initial is an absolute directory
626                     try {
627                         initialDir = new File(initialDir).getAbsolutePath();
628                     } catch (Throwable e) {
629                         Log.e(TAG, "Resolve of initital directory fails", e); //$NON-NLS-1$
630                         String msg =
631                                 getString(
632                                         R.string.msgs_settings_invalid_initial_directory,
633                                         initialDir);
634                         DialogHelper.showToast(NavigationActivity.this, msg, Toast.LENGTH_SHORT);
635                         initialDir = FileHelper.ROOT_DIRECTORY;
636                     }
637
638                     // Change the current directory to the preference initial directory or the
639                     // request if exists
640                     String navigateTo = getIntent().getStringExtra(EXTRA_NAVIGATE_TO);
641                     if (navigateTo != null && navigateTo.length() > 0) {
642                         navigationView.changeCurrentDir(navigateTo);
643                     } else {
644                         navigationView.changeCurrentDir(initialDir);
645                     }
646                 }
647             }
648         });
649     }
650
651     /**
652      * Method that verifies the intent passed to the activity, and checks
653      * if a request is made like Search.
654      *
655      * @param intent The intent to check
656      * @hide
657      */
658     void checkIntent(Intent intent) {
659         //Search action
660         if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
661             Intent searchIntent = new Intent(this, SearchActivity.class);
662             searchIntent.setAction(Intent.ACTION_SEARCH);
663             //- SearchActivity.EXTRA_SEARCH_DIRECTORY
664             searchIntent.putExtra(
665                     SearchActivity.EXTRA_SEARCH_DIRECTORY,
666                     getCurrentNavigationView().getCurrentDir());
667             //- SearchManager.APP_DATA
668             if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
669                 Bundle bundle = new Bundle();
670                 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
671                 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
672             }
673             //-- SearchManager.QUERY
674             String query = intent.getStringExtra(SearchManager.QUERY);
675             if (query != null) {
676                 searchIntent.putExtra(SearchManager.QUERY, query);
677             }
678             //- android.speech.RecognizerIntent.EXTRA_RESULTS
679             ArrayList<String> extraResults =
680                     intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
681             if (extraResults != null) {
682                 searchIntent.putStringArrayListExtra(
683                         android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
684             }
685             startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
686             return;
687         }
688
689         // Navigate to the requested path
690         String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
691         if (navigateTo != null && navigateTo.length() >= 0) {
692             getCurrentNavigationView().changeCurrentDir(navigateTo);
693         }
694     }
695
696     /**
697      * {@inheritDoc}
698      */
699     @Override
700     public boolean onKeyUp(int keyCode, KeyEvent event) {
701         if (keyCode == KeyEvent.KEYCODE_MENU) {
702             showOverflowPopUp(this.mOptionsAnchorView);
703             return true;
704         }
705         if (keyCode == KeyEvent.KEYCODE_BACK) {
706             if (checkBackAction()) {
707                 return true;
708             }
709
710             // An exit event has occurred, force the destroy the consoles
711             exit();
712         }
713         return super.onKeyUp(keyCode, event);
714     }
715
716     /**
717      * {@inheritDoc}
718      */
719     @Override
720     public boolean onOptionsItemSelected(MenuItem item) {
721        switch (item.getItemId()) {
722           case android.R.id.home:
723               if ((getActionBar().getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP)
724                       == ActionBar.DISPLAY_HOME_AS_UP) {
725                   checkBackAction();
726               }
727               return true;
728           default:
729              return super.onOptionsItemSelected(item);
730        }
731     }
732
733     /**
734      * Method invoked when an action item is clicked.
735      *
736      * @param view The button pushed
737      */
738     public void onActionBarItemClick(View view) {
739         switch (view.getId()) {
740             //######################
741             //Navigation Custom Title
742             //######################
743             case R.id.ab_configuration:
744                 //Show navigation view configuration toolbar
745                 getCurrentNavigationView().getCustomTitle().showConfigurationView();
746                 getActionBar().setDisplayHomeAsUpEnabled(true);
747                 getActionBar().setHomeButtonEnabled(true);
748                 break;
749             case R.id.ab_close:
750                 //Hide navigation view configuration toolbar
751                 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
752                 break;
753
754             //######################
755             //Breadcrumb Actions
756             //######################
757             case R.id.ab_filesystem_info:
758                 //Show information of the filesystem
759                 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
760                 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
761                 showMountPointInfo(mp, du);
762                 break;
763
764             //######################
765             //Navigation view options
766             //######################
767             case R.id.ab_sort_mode:
768                 showSettingsPopUp(view,
769                         Arrays.asList(
770                                 new FileManagerSettings[]{
771                                         FileManagerSettings.SETTINGS_SORT_MODE}));
772                 break;
773             case R.id.ab_layout_mode:
774                 showSettingsPopUp(view,
775                         Arrays.asList(
776                                 new FileManagerSettings[]{
777                                         FileManagerSettings.SETTINGS_LAYOUT_MODE}));
778                 break;
779             case R.id.ab_view_options:
780                 // If we are in ChRooted mode, then don't show non-secure items
781                 if (this.mChRooted) {
782                     showSettingsPopUp(view,
783                             Arrays.asList(new FileManagerSettings[]{
784                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
785                 } else {
786                     showSettingsPopUp(view,
787                             Arrays.asList(new FileManagerSettings[]{
788                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
789                                     FileManagerSettings.SETTINGS_SHOW_HIDDEN,
790                                     FileManagerSettings.SETTINGS_SHOW_SYSTEM,
791                                     FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
792                 }
793
794                 break;
795
796             //######################
797             //Selection Actions
798             //######################
799             case R.id.ab_selection_done:
800                 //Show information of the filesystem
801                 getCurrentNavigationView().onDeselectAll();
802                 break;
803
804             //######################
805             //Action Bar buttons
806             //######################
807             case R.id.ab_actions:
808                 openActionsDialog(getCurrentNavigationView().getCurrentDir(), true);
809                 break;
810
811             case R.id.ab_bookmarks:
812                 openBookmarks();
813                 break;
814
815             case R.id.ab_history:
816                 openHistory();
817                 break;
818
819             case R.id.ab_search:
820                 openSearch();
821                 break;
822
823             case R.id.ab_overflow:
824                 showOverflowPopUp(view);
825                 break;
826
827             default:
828                 break;
829         }
830     }
831
832     /**
833      * {@inheritDoc}
834      */
835     @Override
836     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
837         if (data != null) {
838             switch (requestCode) {
839                 case INTENT_REQUEST_BOOKMARK:
840                     if (resultCode == RESULT_OK) {
841                         FileSystemObject fso =
842                                 (FileSystemObject)data.
843                                     getSerializableExtra(EXTRA_BOOKMARK_SELECTION);
844                         if (fso != null) {
845                             //Open the fso
846                             getCurrentNavigationView().open(fso);
847                         }
848                     }
849                     break;
850
851                 case INTENT_REQUEST_HISTORY:
852                     if (resultCode == RESULT_OK) {
853                         //Change current directory
854                         History history =
855                                 (History)data.getSerializableExtra(EXTRA_HISTORY_ENTRY_SELECTION);
856                         navigateToHistory(history);
857                     } else if (resultCode == RESULT_CANCELED) {
858                         boolean clear = data.getBooleanExtra(EXTRA_HISTORY_CLEAR, false);
859                         if (clear) {
860                             clearHistory();
861                         }
862                     }
863                     break;
864
865                 case INTENT_REQUEST_SEARCH:
866                     if (resultCode == RESULT_OK) {
867                         //Change directory?
868                         FileSystemObject fso =
869                                 (FileSystemObject)data.
870                                     getSerializableExtra(EXTRA_SEARCH_ENTRY_SELECTION);
871                         SearchInfoParcelable searchInfo =
872                                 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
873                         if (fso != null) {
874                             //Goto to new directory
875                             getCurrentNavigationView().open(fso, searchInfo);
876                         }
877                     } else if (resultCode == RESULT_CANCELED) {
878                         SearchInfoParcelable searchInfo =
879                                 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
880                         if (searchInfo != null && searchInfo.isSuccessNavigation()) {
881                             //Navigate to previous history
882                             back();
883                         } else {
884                             // I don't know is the search view was changed, so try to do a refresh
885                             // of the navigation view
886                             getCurrentNavigationView().refresh(true);
887                         }
888                     }
889                     break;
890
891                 default:
892                     break;
893             }
894         }
895     }
896
897     /**
898      * {@inheritDoc}
899      */
900     @Override
901     public void onNewHistory(HistoryNavigable navigable) {
902         //Recollect information about current status
903         History history = new History(this.mHistory.size(), navigable);
904         this.mHistory.add(history);
905         getActionBar().setDisplayHomeAsUpEnabled(true);
906         getActionBar().setHomeButtonEnabled(true);
907     }
908
909     /**
910      * {@inheritDoc}
911      */
912     @Override
913     public void onCheckHistory() {
914         //Need to show HomeUp Button
915         boolean enabled = this.mHistory != null && this.mHistory.size() > 0;
916         getActionBar().setDisplayHomeAsUpEnabled(enabled);
917         getActionBar().setHomeButtonEnabled(enabled);
918     }
919
920     /**
921      * {@inheritDoc}
922      */
923     @Override
924     public void onRequestRefresh(Object o, boolean clearSelection) {
925         if (o instanceof FileSystemObject) {
926             // Refresh only the item
927             this.getCurrentNavigationView().refresh((FileSystemObject)o);
928         } else if (o == null) {
929             // Refresh all
930             getCurrentNavigationView().refresh();
931         }
932         if (clearSelection) {
933             this.getCurrentNavigationView().onDeselectAll();
934         }
935     }
936
937     /**
938      * {@inheritDoc}
939      */
940     @Override
941     public void onRequestRemove(Object o, boolean clearSelection) {
942         if (o instanceof FileSystemObject) {
943             // Remove from view
944             this.getCurrentNavigationView().removeItem((FileSystemObject)o);
945
946             //Remove from history
947             removeFromHistory((FileSystemObject)o);
948         } else {
949             onRequestRefresh(null, clearSelection);
950         }
951         if (clearSelection) {
952             this.getCurrentNavigationView().onDeselectAll();
953         }
954     }
955
956     /**
957      * {@inheritDoc}
958      */
959     @Override
960     public void onNavigateTo(Object o) {
961         // Ignored
962     }
963
964     /**
965      * {@inheritDoc}
966      */
967     @Override
968     public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
969         this.mSelectionBar.setSelection(selectedItems);
970     }
971
972     /**
973      * {@inheritDoc}
974      */
975     @Override
976     public void onRequestMenu(NavigationView navView, FileSystemObject item) {
977         // Show the actions dialog
978         openActionsDialog(item, false);
979     }
980
981     /**
982      * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
983      *
984      * @param anchor The action button that was pressed
985      * @param settings The array of settings associated with the action button
986      */
987     private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
988         //Create the adapter
989         final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
990
991         //Create a show the popup menu
992         final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
993         popup.setOnItemClickListener(new OnItemClickListener() {
994             @Override
995             public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
996                 FileManagerSettings setting =
997                         ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
998                 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
999                 popup.dismiss();
1000                 try {
1001                     if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
1002                         //Need to change the layout
1003                         getCurrentNavigationView().changeViewMode(
1004                                 NavigationLayoutMode.fromId(value));
1005                     } else {
1006                         //Save and refresh
1007                         if (setting.getDefaultValue() instanceof Enum<?>) {
1008                             //Enumeration
1009                             Preferences.savePreference(setting, new ObjectIdentifier() {
1010                                 @Override
1011                                 public int getId() {
1012                                     return value;
1013                                 }
1014                             }, false);
1015                         } else {
1016                             //Boolean
1017                             boolean newval =
1018                                     Preferences.getSharedPreferences().
1019                                         getBoolean(
1020                                             setting.getId(),
1021                                             ((Boolean)setting.getDefaultValue()).booleanValue());
1022                             Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
1023                         }
1024                         getCurrentNavigationView().refresh();
1025                     }
1026                 } catch (Exception e) {
1027                     Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
1028                     NavigationActivity.this.mHandler.post(new Runnable() {
1029                         @Override
1030                         public void run() {
1031                             DialogHelper.showToast(
1032                                     NavigationActivity.this,
1033                                     R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
1034                         }
1035                     });
1036
1037                 } finally {
1038                     adapter.dispose();
1039                     getCurrentNavigationView().getCustomTitle().restoreView();
1040                 }
1041
1042             }
1043         });
1044         popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
1045             @Override
1046             public void onDismiss() {
1047                 adapter.dispose();
1048             }
1049         });
1050         popup.show();
1051     }
1052
1053     /**
1054      * Method that shows a popup with the activity main menu.
1055      *
1056      * @param anchor The action button that was pressed
1057      */
1058     private void showOverflowPopUp(View anchor) {
1059         SimpleMenuListAdapter adapter =
1060                 new HighlightedSimpleMenuListAdapter(this, R.menu.navigation);
1061         Menu menu = adapter.getMenu();
1062         int cc = this.mActionBar.getChildCount();
1063         for (int i = 0, j = this.mActionBar.getChildCount() - 1; i < cc; i++, j--) {
1064             View child = this.mActionBar.getChildAt(i);
1065             boolean visible = child.getVisibility() == View.VISIBLE;
1066             if (visible) {
1067                 menu.removeItem(menu.getItem(j).getItemId());
1068             }
1069         }
1070
1071         final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
1072         popup.setOnItemClickListener(new OnItemClickListener() {
1073             @Override
1074             public void onItemClick(
1075                     final AdapterView<?> parent, final View v, final int position, final long id) {
1076
1077                 final int itemId = (int)id;
1078                 NavigationActivity.this.mHandler.post(new Runnable() {
1079                     @Override
1080                     public void run() {
1081                         popup.dismiss();
1082                         switch (itemId) {
1083                             case R.id.mnu_settings:
1084                                 //Settings
1085                                 Intent settings = new Intent(
1086                                         NavigationActivity.this, SettingsPreferences.class);
1087                                 startActivity(settings);
1088                                 break;
1089
1090                             case R.id.mnu_history:
1091                                 //History
1092                                 openHistory();
1093                                 popup.dismiss();
1094                                 break;
1095
1096                             case R.id.mnu_bookmarks:
1097                                 //Bookmarks
1098                                 openBookmarks();
1099                                 popup.dismiss();
1100                                 break;
1101
1102                             case R.id.mnu_search:
1103                                 //Search
1104                                 openSearch();
1105                                 popup.dismiss();
1106                                 break;
1107                             default:
1108                                 break;
1109                         }
1110                     }
1111                 });
1112             }
1113         });
1114         popup.show();
1115     }
1116
1117     /**
1118      * Method that show the information of a filesystem mount point.
1119      *
1120      * @param mp The mount point info
1121      * @param du The disk usage of the mount point
1122      */
1123     private void showMountPointInfo(MountPoint mp, DiskUsage du) {
1124         //Has mount point info?
1125         if (mp == null) {
1126             //There is no information
1127             AlertDialog alert =
1128                     DialogHelper.createWarningDialog(
1129                             this,
1130                             R.string.filesystem_info_warning_title,
1131                             R.string.filesystem_info_warning_msg);
1132             DialogHelper.delegateDialogShow(this, alert);
1133             return;
1134         }
1135
1136         //Show a the filesystem info dialog
1137         FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
1138         dialog.setOnMountListener(new OnMountListener() {
1139             @Override
1140             public void onRemount(MountPoint mountPoint) {
1141                 //Update the statistics of breadcrumb, only if mount point is the same
1142                 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
1143                 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
1144                     breadcrumb.updateMountPointInfo();
1145                 }
1146             }
1147         });
1148         dialog.show();
1149     }
1150
1151     /**
1152      * Method that checks the action that must be realized when the
1153      * back button is pushed.
1154      *
1155      * @return boolean Indicates if the action must be intercepted
1156      */
1157     private boolean checkBackAction() {
1158         // We need a basic structure to check this
1159         if (getCurrentNavigationView() == null) return false;
1160
1161         //Check if the configuration view is showing. In this case back
1162         //action must be "close configuration"
1163         if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
1164             getCurrentNavigationView().getCustomTitle().restoreView();
1165             return true;
1166         }
1167
1168         //Do back operation over the navigation history
1169         boolean flag = this.mExitFlag;
1170
1171         this.mExitFlag = !back();
1172
1173         // Retrieve if the exit status timeout has expired
1174         long now = System.currentTimeMillis();
1175         boolean timeout = (this.mExitBackTimeout == -1 ||
1176                             (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
1177
1178         //Check if there no history and if the user was advised in the last back action
1179         if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
1180             //Communicate the user that the next time the application will be closed
1181             this.mExitBackTimeout = System.currentTimeMillis();
1182             DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
1183             return true;
1184         }
1185
1186         //Back action not applied
1187         return !this.mExitFlag;
1188     }
1189
1190     /**
1191      * {@inheritDoc}
1192      */
1193     @Override
1194     public boolean onSearchRequested() {
1195         Bundle bundle = new Bundle();
1196         bundle.putString(
1197                 SearchActivity.EXTRA_SEARCH_DIRECTORY,
1198                 getCurrentNavigationView().getCurrentDir());
1199         startSearch(Preferences.getLastSearch(), true, bundle, false);
1200         return true;
1201     }
1202
1203     /**
1204      * Method that returns the history size.
1205      */
1206     private void clearHistory() {
1207         this.mHistory.clear();
1208         onCheckHistory();
1209     }
1210
1211     /**
1212      * Method that navigates to the passed history reference.
1213      *
1214      * @param history The history reference
1215      * @return boolean A problem occurs while navigate
1216      */
1217     public boolean navigateToHistory(History history) {
1218         try {
1219             //Gets the history
1220             History realHistory = this.mHistory.get(history.getPosition());
1221
1222             //Navigate to item. Check what kind of history is
1223             if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
1224                 //Navigation
1225                 NavigationViewInfoParcelable info =
1226                         (NavigationViewInfoParcelable)realHistory.getItem();
1227                 int viewId = info.getId();
1228                 NavigationView view = getNavigationView(viewId);
1229                 // Selected items must not be restored from on history navigation
1230                 info.setSelectedFiles(view.getSelectedFiles());
1231                 view.onRestoreState(info);
1232
1233             } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
1234                 //Search (open search with the search results)
1235                 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
1236                 Intent searchIntent = new Intent(this, SearchActivity.class);
1237                 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
1238                 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
1239                 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1240             } else {
1241                 //The type is unknown
1242                 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
1243             }
1244
1245             //Remove the old history
1246             int cc = realHistory.getPosition();
1247             for (int i = this.mHistory.size() - 1; i >= cc; i--) {
1248                 this.mHistory.remove(i);
1249             }
1250             if (this.mHistory.size() == 0) {
1251                 getActionBar().setDisplayHomeAsUpEnabled(false);
1252                 getActionBar().setHomeButtonEnabled(false);
1253             }
1254
1255             //Navigate
1256             return true;
1257
1258         } catch (Throwable ex) {
1259             if (history != null) {
1260                 Log.e(TAG,
1261                         String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
1262                                 Integer.valueOf(history.getPosition()),
1263                                 history.getItem().getTitle()), ex);
1264             } else {
1265                 Log.e(TAG,
1266                         String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
1267             }
1268             this.mHandler.post(new Runnable() {
1269                 @Override
1270                 public void run() {
1271                     DialogHelper.showToast(
1272                             NavigationActivity.this,
1273                             R.string.msgs_history_unknown, Toast.LENGTH_LONG);
1274                 }
1275             });
1276
1277             //Not change directory
1278             return false;
1279         }
1280     }
1281
1282     /**
1283      * Method that request a back action over the navigation history.
1284      *
1285      * @return boolean If a back action was applied
1286      */
1287     public boolean back() {
1288         // Check that has valid history
1289         while (this.mHistory.size() > 0) {
1290             History h = this.mHistory.get(this.mHistory.size() - 1);
1291             if (h.getItem() instanceof NavigationViewInfoParcelable) {
1292                 // Verify that the path exists
1293                 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
1294
1295                 try {
1296                     FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
1297                     if (info != null) {
1298                         break;
1299                     }
1300                     this.mHistory.remove(this.mHistory.size() - 1);
1301                 } catch (Exception e) {
1302                     ExceptionUtil.translateException(this, e, true, false);
1303                     this.mHistory.remove(this.mHistory.size() - 1);
1304                 }
1305             } else {
1306                 break;
1307             }
1308         }
1309
1310         //Extract a history from the
1311         if (this.mHistory.size() > 0) {
1312             //Navigate to history
1313             return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
1314         }
1315
1316         //Nothing to apply
1317         return false;
1318     }
1319
1320     /**
1321      * Method that opens the actions dialog
1322      *
1323      * @param item The path or the {@link FileSystemObject}
1324      * @param global If the menu to display is the one with global actions
1325      */
1326     private void openActionsDialog(Object item, boolean global) {
1327         // Resolve the full path
1328         String path = String.valueOf(item);
1329         if (item instanceof FileSystemObject) {
1330             path = ((FileSystemObject)item).getFullPath();
1331         }
1332
1333         // Prior to show the dialog, refresh the item reference
1334         FileSystemObject fso = null;
1335         try {
1336             fso = CommandHelper.getFileInfo(this, path, false, null);
1337             if (fso == null) {
1338                 throw new NoSuchFileOrDirectory(path);
1339             }
1340
1341         } catch (Exception e) {
1342             // Notify the user
1343             ExceptionUtil.translateException(this, e);
1344
1345             // Remove the object
1346             if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
1347                 // If have a FileSystemObject reference then there is no need to search
1348                 // the path (less resources used)
1349                 if (item instanceof FileSystemObject) {
1350                     getCurrentNavigationView().removeItem((FileSystemObject)item);
1351                 } else {
1352                     getCurrentNavigationView().removeItem((String)item);
1353                 }
1354             }
1355             return;
1356         }
1357
1358         // Show the dialog
1359         ActionsDialog dialog = new ActionsDialog(this, fso, global, false);
1360         dialog.setOnRequestRefreshListener(this);
1361         dialog.setOnSelectionListener(getCurrentNavigationView());
1362         dialog.show();
1363     }
1364
1365     /**
1366      * Method that opens the bookmarks activity.
1367      * @hide
1368      */
1369     void openBookmarks() {
1370         Intent bookmarksIntent = new Intent(this, BookmarksActivity.class);
1371         bookmarksIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1372         startActivityForResult(bookmarksIntent, INTENT_REQUEST_BOOKMARK);
1373     }
1374
1375     /**
1376      * Method that opens the history activity.
1377      * @hide
1378      */
1379     void openHistory() {
1380         Intent historyIntent = new Intent(this, HistoryActivity.class);
1381         historyIntent.putExtra(HistoryActivity.EXTRA_HISTORY_LIST, (Serializable)this.mHistory);
1382         historyIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1383         startActivityForResult(historyIntent, INTENT_REQUEST_HISTORY);
1384     }
1385
1386     /**
1387      * Method that opens the search activity.
1388      * @hide
1389      */
1390     void openSearch() {
1391         onSearchRequested();
1392     }
1393
1394     /**
1395      * Method that remove the {@link FileSystemObject} from the history
1396      */
1397     private void removeFromHistory(FileSystemObject fso) {
1398         if (this.mHistory != null) {
1399             int cc = this.mHistory.size();
1400             for (int i = cc-1; i >= 0 ; i--) {
1401                 History history = this.mHistory.get(i);
1402                 if (history.getItem() instanceof NavigationViewInfoParcelable) {
1403                     String p0 = fso.getFullPath();
1404                     String p1 =
1405                             ((NavigationViewInfoParcelable)history.getItem()).getCurrentDir();
1406                     if (p0.compareTo(p1) == 0) {
1407                         this.mHistory.remove(i);
1408                     }
1409                 }
1410             }
1411         }
1412     }
1413
1414     /**
1415      * Method that ask the user to change the access mode prior to crash.
1416      * @hide
1417      */
1418     void askOrExit() {
1419         //Show a dialog asking the user
1420         AlertDialog dialog =
1421             DialogHelper.createYesNoDialog(
1422                 this,
1423                 R.string.msgs_change_to_prompt_access_mode_title,
1424                 R.string.msgs_change_to_prompt_access_mode_msg,
1425                 new DialogInterface.OnClickListener() {
1426                     @Override
1427                     public void onClick(DialogInterface alertDialog, int which) {
1428                         if (which == DialogInterface.BUTTON_NEGATIVE) {
1429                             // We don't have any console
1430                             // Show exception and exit
1431                             DialogHelper.showToast(
1432                                     NavigationActivity.this,
1433                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1434                             exit();
1435                             return;
1436                         }
1437
1438                         // Ok. Now try to change to prompt mode. Any crash
1439                         // here is a fatal error. We won't have any console to operate.
1440                         try {
1441                             // Change console
1442                             ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
1443
1444                             // Save preferences
1445                             Preferences.savePreference(
1446                                     FileManagerSettings.SETTINGS_ACCESS_MODE,
1447                                     AccessMode.PROMPT, true);
1448
1449                         } catch (Exception e) {
1450                             // Displays an exception and exit
1451                             Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
1452                             DialogHelper.showToast(
1453                                     NavigationActivity.this,
1454                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1455                             exit();
1456                         }
1457                     }
1458                });
1459         DialogHelper.delegateDialogShow(this, dialog);
1460     }
1461
1462     /**
1463      * Method that creates a ChRooted environment, protecting the user to break anything in
1464      * the device
1465      * @hide
1466      */
1467     void createChRooted() {
1468         // If we are in a ChRooted mode, then do nothing
1469         if (this.mChRooted) return;
1470         this.mChRooted = true;
1471
1472         int cc = this.mNavigationViews.length;
1473         for (int i = 0; i < cc; i++) {
1474             this.mNavigationViews[i].createChRooted();
1475         }
1476
1477         // Remove the selection
1478         cc = this.mNavigationViews.length;
1479         for (int i = 0; i < cc; i++) {
1480             getCurrentNavigationView().onDeselectAll();
1481         }
1482
1483         // Remove the history (don't allow to access to previous data)
1484         clearHistory();
1485     }
1486
1487     /**
1488      * Method that exits from a ChRooted
1489      * @hide
1490      */
1491     void exitChRooted() {
1492         // If we aren't in a ChRooted mode, then do nothing
1493         if (!this.mChRooted) return;
1494         this.mChRooted = false;
1495
1496         int cc = this.mNavigationViews.length;
1497         for (int i = 0; i < cc; i++) {
1498             this.mNavigationViews[i].exitChRooted();
1499         }
1500     }
1501
1502     /**
1503      * Method called when a controlled exit is required
1504      * @hide
1505      */
1506     void exit() {
1507         try {
1508             FileManagerApplication.destroyBackgroundConsole();
1509         } catch (Throwable ex) {
1510             /**NON BLOCK**/
1511         }
1512         try {
1513             ConsoleBuilder.destroyConsole();
1514         } catch (Throwable ex) {
1515             /**NON BLOCK**/
1516         }
1517         finish();
1518     }
1519
1520     /**
1521      * Method that reconfigures the layout for better fit in portrait and landscape modes
1522      */
1523     private void onLayoutChanged() {
1524         Theme theme = ThemeManager.getCurrentTheme(this);
1525
1526         // Apply only when the orientation was changed
1527         int orientation = getResources().getConfiguration().orientation;
1528         if (this.mOrientation == orientation) return;
1529         this.mOrientation = orientation;
1530
1531         if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
1532             // Landscape mode
1533             ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
1534             if (statusBar.getParent() != null) {
1535                 ViewGroup parent = (ViewGroup) statusBar.getParent();
1536                 parent.removeView(statusBar);
1537             }
1538
1539             // Calculate the action button size (all the buttons must fit in the title bar)
1540             int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
1541             int abw = this.mActionBar.getChildCount() * bw;
1542             int rbw = 0;
1543             int cc = statusBar.getChildCount();
1544             for (int i = 0; i < cc; i++) {
1545                 View child = statusBar.getChildAt(i);
1546                 if (child instanceof ButtonItem) {
1547                     rbw += bw;
1548                 }
1549             }
1550             int w = abw + rbw;
1551             boolean showOptionsMenu = AndroidHelper.showOptionsMenu(getApplicationContext());
1552             if (!showOptionsMenu) {
1553                 w -= bw;
1554             }
1555
1556             // Add to the new location
1557             ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder);
1558             LinearLayout.LayoutParams params =
1559                     new LinearLayout.LayoutParams(
1560                             w,
1561                             ViewGroup.LayoutParams.MATCH_PARENT);
1562             statusBar.setLayoutParams(params);
1563             newParent.addView(statusBar);
1564
1565             // Apply theme
1566             theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$
1567
1568             // Hide holder
1569             View holder = findViewById(R.id.navigation_statusbar_portrait_holder);
1570             holder.setVisibility(View.GONE);
1571
1572         } else {
1573             // Portrait mode
1574             ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
1575             if (statusBar.getParent() != null) {
1576                 ViewGroup parent = (ViewGroup) statusBar.getParent();
1577                 parent.removeView(statusBar);
1578             }
1579
1580             // Add to the new location
1581             ViewGroup newParent = (ViewGroup)findViewById(
1582                     R.id.navigation_statusbar_portrait_holder);
1583             LinearLayout.LayoutParams params =
1584                     new LinearLayout.LayoutParams(
1585                             ViewGroup.LayoutParams.MATCH_PARENT,
1586                             ViewGroup.LayoutParams.MATCH_PARENT);
1587             statusBar.setLayoutParams(params);
1588             newParent.addView(statusBar);
1589
1590             // Apply theme
1591             theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$
1592
1593             // Show holder
1594             newParent.setVisibility(View.VISIBLE);
1595         }
1596     }
1597
1598     /**
1599      * Method that applies the current theme to the activity
1600      * @hide
1601      */
1602     void applyTheme() {
1603         int orientation = getResources().getConfiguration().orientation;
1604         Theme theme = ThemeManager.getCurrentTheme(this);
1605         theme.setBaseTheme(this, false);
1606
1607         //- Layout
1608         View v = findViewById(R.id.navigation_layout);
1609         theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
1610         //- ActionBar
1611         theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$
1612         //- StatusBar
1613         v = findViewById(R.id.navigation_statusbar);
1614         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1615             theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$
1616         } else {
1617             theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$
1618         }
1619         v = findViewById(R.id.ab_overflow);
1620         theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$
1621         v = findViewById(R.id.ab_actions);
1622         theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$
1623         v = findViewById(R.id.ab_search);
1624         theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$
1625         v = findViewById(R.id.ab_bookmarks);
1626         theme.setImageDrawable(this, (ImageView)v, "ab_bookmarks_drawable"); //$NON-NLS-1$
1627         v = findViewById(R.id.ab_history);
1628         theme.setImageDrawable(this, (ImageView)v, "ab_history_drawable"); //$NON-NLS-1$
1629         //- Expanders
1630         v = findViewById(R.id.ab_configuration);
1631         theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$
1632         v = findViewById(R.id.ab_close);
1633         theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$
1634         v = findViewById(R.id.ab_sort_mode);
1635         theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$
1636         v = findViewById(R.id.ab_layout_mode);
1637         theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$
1638         v = findViewById(R.id.ab_view_options);
1639         theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$
1640         //- SelectionBar
1641         v = findViewById(R.id.navigation_selectionbar);
1642         theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$
1643         v = findViewById(R.id.ab_selection_done);
1644         theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$
1645         v = findViewById(R.id.navigation_status_selection_label);
1646         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
1647         //- NavigationView
1648         int cc = this.mNavigationViews.length;
1649         for (int i = 0; i < cc; i++) {
1650             getNavigationView(i).applyTheme();
1651         }
1652     }
1653
1654 }