OSDN Git Service

cmfm: fix edit home bookmark icon
[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.Activity;
20 import android.app.AlertDialog;
21 import android.app.SearchManager;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.res.Configuration;
28 import android.content.res.XmlResourceParser;
29 import android.database.Cursor;
30 import android.graphics.Color;
31 import android.graphics.drawable.Drawable;
32 import android.net.Uri;
33 import android.nfc.NfcAdapter;
34 import android.nfc.NfcEvent;
35 import android.os.AsyncTask;
36 import android.os.Bundle;
37 import android.os.Environment;
38 import android.os.Handler;
39 import android.os.Parcelable;
40 import android.os.storage.StorageVolume;
41 import android.support.v4.app.ActionBarDrawerToggle;
42 import android.support.v4.widget.DrawerLayout;
43 import android.text.TextUtils;
44 import android.util.Log;
45 import android.view.Gravity;
46 import android.view.KeyEvent;
47 import android.view.MenuItem;
48 import android.view.View;
49 import android.view.View.OnClickListener;
50 import android.view.ViewGroup;
51 import android.widget.AdapterView;
52 import android.widget.AdapterView.OnItemClickListener;
53 import android.widget.ImageButton;
54 import android.widget.ImageView;
55 import android.widget.LinearLayout;
56 import android.widget.ListPopupWindow;
57 import android.widget.ListView;
58 import android.widget.PopupWindow;
59 import android.widget.SearchView;
60 import android.widget.TextView;
61 import android.widget.Toast;
62 import android.widget.Toolbar;
63 import android.widget.ArrayAdapter;
64
65 import com.android.internal.util.XmlUtils;
66 import com.cyanogenmod.filemanager.FileManagerApplication;
67 import com.cyanogenmod.filemanager.R;
68 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
69 import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter;
70 import com.cyanogenmod.filemanager.console.Console;
71 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
72 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
73 import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
74 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
75 import com.cyanogenmod.filemanager.console.VirtualConsole;
76 import com.cyanogenmod.filemanager.console.VirtualMountPointConsole;
77 import com.cyanogenmod.filemanager.console.secure.SecureConsole;
78 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
79 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
80 import com.cyanogenmod.filemanager.model.Bookmark;
81 import com.cyanogenmod.filemanager.model.DiskUsage;
82 import com.cyanogenmod.filemanager.model.FileSystemObject;
83 import com.cyanogenmod.filemanager.model.History;
84 import com.cyanogenmod.filemanager.model.MountPoint;
85 import com.cyanogenmod.filemanager.model.Bookmark.BOOKMARK_TYPE;
86 import com.cyanogenmod.filemanager.parcelables.HistoryNavigable;
87 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
88 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
89 import com.cyanogenmod.filemanager.preferences.AccessMode;
90 import com.cyanogenmod.filemanager.preferences.Bookmarks;
91 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
92 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
93 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
94 import com.cyanogenmod.filemanager.preferences.Preferences;
95 import com.cyanogenmod.filemanager.ui.IconHolder;
96 import com.cyanogenmod.filemanager.ui.ThemeManager;
97 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
98 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
99 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog;
100 import com.cyanogenmod.filemanager.ui.dialogs.InitialDirectoryDialog;
101 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener;
102 import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb;
103 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
104 import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView;
105 import com.cyanogenmod.filemanager.ui.widgets.NavigationView;
106 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener;
107 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener;
108 import com.cyanogenmod.filemanager.ui.widgets.SelectionView;
109 import com.cyanogenmod.filemanager.util.AndroidHelper;
110 import com.cyanogenmod.filemanager.util.BookmarksHelper;
111 import com.cyanogenmod.filemanager.util.CommandHelper;
112 import com.cyanogenmod.filemanager.util.DialogHelper;
113 import com.cyanogenmod.filemanager.util.ExceptionUtil;
114 import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
115 import com.cyanogenmod.filemanager.util.FileHelper;
116 import com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory;
117 import com.cyanogenmod.filemanager.util.StorageHelper;
118
119 import java.io.File;
120 import java.io.FileNotFoundException;
121 import java.util.ArrayList;
122 import java.util.Arrays;
123 import java.util.HashMap;
124 import java.util.List;
125 import java.util.Locale;
126 import java.util.Map;
127
128 import static com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory.*;
129
130 /**
131  * The main navigation activity. This activity is the center of the application.
132  * From this the user can navigate, search, make actions.<br/>
133  * This activity is singleTop, so when it is displayed no other activities exists in
134  * the stack.<br/>
135  * This cause an issue with the saved instance of this class, because if another activity
136  * is displayed, and the process is killed, NavigationActivity is started and the saved
137  * instance gets corrupted.<br/>
138  * For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and
139  * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time
140  * the app is killed, is restarted from his initial state.
141  */
142 public class NavigationActivity extends Activity
143     implements OnHistoryListener, OnRequestRefreshListener,
144     OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener {
145
146     private static final String TAG = "NavigationActivity"; //$NON-NLS-1$
147
148     private static boolean DEBUG = false;
149
150     // Bookmark list XML tags
151     private static final String TAG_BOOKMARKS = "Bookmarks"; //$NON-NLS-1$
152     private static final String TAG_BOOKMARK = "bookmark"; //$NON-NLS-1$
153
154     private static final String STR_USB = "usb"; // $NON-NLS-1$
155
156     /**
157      * Intent code for request a search.
158      */
159     public static final int INTENT_REQUEST_SEARCH = 10001;
160
161     /**
162      * Intent code for request a search.
163      */
164     public static final int INTENT_REQUEST_SETTINGS = 20001;
165
166     /**
167      * Constant for extra information about selected search entry.
168      */
169     public static final String EXTRA_SEARCH_ENTRY_SELECTION =
170             "extra_search_entry_selection"; //$NON-NLS-1$
171
172     /**
173      * Constant for extra information about last search data.
174      */
175     public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
176             "extra_search_last_search_data"; //$NON-NLS-1$
177
178     /**
179      * Constant for extra information for request a navigation to the passed path.
180      */
181     public static final String EXTRA_NAVIGATE_TO =
182             "extra_navigate_to"; //$NON-NLS-1$
183
184     /**
185      * Constant for extra information for request to add navigation to the history
186      */
187     public static final String EXTRA_ADD_TO_HISTORY =
188             "extra_add_to_history"; //$NON-NLS-1$
189
190     // The timeout needed to reset the exit status for back button
191     // After this time user need to tap 2 times the back button to
192     // exit, and the toast is shown again after the first tap.
193     private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500;
194
195
196     private Toolbar mToolBar;
197     private SearchView mSearchView;
198     private NavigationCustomTitleView mCustomTitleView;
199
200     private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
201         @Override
202         public void onReceive(Context context, Intent intent) {
203             if (intent != null) {
204                 if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
205                     // The settings has changed
206                     String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
207                     if (key != null) {
208                         // Disk usage warning level
209                         if (key.compareTo(FileManagerSettings.
210                                 SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) {
211
212                             // Set the free disk space warning level of the breadcrumb widget
213                             Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
214                             String fds = Preferences.getSharedPreferences().getString(
215                                     FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
216                                     (String)FileManagerSettings.
217                                         SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
218                             breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
219                             breadcrumb.updateMountPointInfo();
220                             return;
221                         }
222
223                         // Case sensitive sort
224                         if (key.compareTo(FileManagerSettings.
225                                 SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) {
226                             getCurrentNavigationView().refresh();
227                             return;
228                         }
229
230                         // Display thumbs
231                         if (key.compareTo(FileManagerSettings.
232                                 SETTINGS_DISPLAY_THUMBS.getId()) == 0) {
233                             // Clean the icon cache applying the current theme
234                             applyTheme();
235                             return;
236                         }
237
238                         // Use flinger
239                         if (key.compareTo(FileManagerSettings.
240                                 SETTINGS_USE_FLINGER.getId()) == 0) {
241                             boolean useFlinger =
242                                     Preferences.getSharedPreferences().getBoolean(
243                                             FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
244                                                 ((Boolean)FileManagerSettings.
245                                                         SETTINGS_USE_FLINGER.
246                                                             getDefaultValue()).booleanValue());
247                             getCurrentNavigationView().setUseFlinger(useFlinger);
248                             return;
249                         }
250
251                         // Access mode
252                         if (key.compareTo(FileManagerSettings.
253                                 SETTINGS_ACCESS_MODE.getId()) == 0) {
254                             // Is it necessary to create or exit of the ChRooted?
255                             boolean chRooted =
256                                     FileManagerApplication.
257                                         getAccessMode().compareTo(AccessMode.SAFE) == 0;
258                             if (chRooted != NavigationActivity.this.mChRooted) {
259                                 if (chRooted) {
260                                     createChRooted();
261                                 } else {
262                                     exitChRooted();
263                                 }
264                             }
265                         }
266
267                         // Restricted access
268                         if (key.compareTo(FileManagerSettings.
269                                 SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()) == 0) {
270                             if (AndroidHelper.isSecondaryUser(context)) {
271                                 try {
272                                     Preferences.savePreference(
273                                             FileManagerSettings.SETTINGS_ACCESS_MODE,
274                                             AccessMode.SAFE, true);
275                                 } catch (Throwable ex) {
276                                     Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$
277                                 }
278                                 ConsoleBuilder.changeToNonPrivilegedConsole(context);
279                                 createChRooted();
280                             }
281                         }
282
283                         // Filetime format mode
284                         if (key.compareTo(FileManagerSettings.
285                                 SETTINGS_FILETIME_FORMAT_MODE.getId()) == 0) {
286                             // Refresh the data
287                             synchronized (FileHelper.DATETIME_SYNC) {
288                                 FileHelper.sReloadDateTimeFormats = true;
289                                 NavigationActivity.this.getCurrentNavigationView().refresh();
290                             }
291                         }
292                     }
293
294                 } else if (intent.getAction().compareTo(
295                         FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
296                     // Retrieve the file that was changed
297                     String file =
298                             intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
299                     try {
300                         FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
301                         if (fso != null) {
302                             getCurrentNavigationView().refresh(fso);
303                         }
304                     } catch (Exception e) {
305                         ExceptionUtil.translateException(context, e, true, false);
306                     }
307
308                 } else if (intent.getAction().compareTo(
309                         FileManagerSettings.INTENT_THEME_CHANGED) == 0) {
310                     applyTheme();
311
312                 } else if (intent.getAction().compareTo(Intent.ACTION_TIME_CHANGED) == 0 ||
313                            intent.getAction().compareTo(Intent.ACTION_DATE_CHANGED) == 0 ||
314                            intent.getAction().compareTo(Intent.ACTION_TIMEZONE_CHANGED) == 0) {
315                     // Refresh the data
316                     synchronized (FileHelper.DATETIME_SYNC) {
317                         FileHelper.sReloadDateTimeFormats = true;
318                         NavigationActivity.this.getCurrentNavigationView().refresh();
319                     }
320                 } else if (intent.getAction().compareTo(
321                         FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED) == 0) {
322                     onRequestBookmarksRefresh();
323                     removeUnmountedHistory();
324                     removeUnmountedSelection();
325                 } else if(intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)) {
326                     onRequestBookmarksRefresh();
327                     removeUnmountedHistory();
328                     removeUnmountedSelection();
329                 }
330             }
331         }
332     };
333
334     private OnClickListener mOnClickDrawerTabListener = new OnClickListener() {
335         @Override
336         public void onClick(View v) {
337             switch (v.getId()) {
338                 case R.id.drawer_bookmarks_tab:
339                     if (!mBookmarksTab.isSelected()) {
340                         mBookmarksTab.setSelected(true);
341                         mHistoryTab.setSelected(false);
342                         mBookmarksTab.setTextAppearance(
343                                 NavigationActivity.this, R.style.primary_text_appearance);
344                         mHistoryTab.setTextAppearance(
345                                 NavigationActivity.this, R.style.secondary_text_appearance);
346                         mHistoryLayout.setVisibility(View.GONE);
347                         mBookmarksLayout.setVisibility(View.VISIBLE);
348                         applyTabTheme();
349
350                         try {
351                             Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
352                                     Integer.valueOf(0), true);
353                         } catch (Exception ex) {
354                             Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
355                         }
356
357                         mClearHistory.setVisibility(View.GONE);
358                     }
359                     break;
360                 case R.id.drawer_history_tab:
361                     if (!mHistoryTab.isSelected()) {
362                         mHistoryTab.setSelected(true);
363                         mBookmarksTab.setSelected(false);
364                         mHistoryTab.setTextAppearance(
365                                 NavigationActivity.this, R.style.primary_text_appearance);
366                         mBookmarksTab.setTextAppearance(
367                                 NavigationActivity.this, R.style.secondary_text_appearance);
368                         mBookmarksLayout.setVisibility(View.GONE);
369                         mHistoryLayout.setVisibility(View.VISIBLE);
370                         applyTabTheme();
371
372                         try {
373                             Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
374                                     Integer.valueOf(1), true);
375                         } catch (Exception ex) {
376                             Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
377                         }
378
379                         mClearHistory.setVisibility(mHistory.size() > 0 ? View.VISIBLE : View.GONE);
380                     }
381                     break;
382                 default:
383                     break;
384             }
385         }
386     };
387
388     private OnClickListener mOnClickDrawerActionBarListener = new OnClickListener() {
389         @Override
390         public void onClick(View v) {
391             switch (v.getId()) {
392                 case R.id.ab_settings:
393                     mDrawerLayout.closeDrawer(Gravity.START);
394                     openSettings();
395                     break;
396                 case R.id.ab_clear_history:
397                     clearHistory();
398                     mClearHistory.setVisibility(View.GONE);
399                     break;
400                 default:
401                     break;
402             }
403         }
404     };
405
406     static String MIME_TYPE_LOCALIZED_NAMES[];
407     /**
408      * @hide
409      */
410     static Map<MimeTypeCategory, Drawable> EASY_MODE_ICONS = new
411             HashMap<MimeTypeCategory, Drawable>();
412
413     /**
414      * @hide
415      */
416     NavigationView[] mNavigationViews;
417     /**
418      * @hide
419      */
420     ListView mEasyModeListView;
421     private List<History> mHistory;
422
423     private static final List<MimeTypeCategory> EASY_MODE_LIST = new ArrayList<MimeTypeCategory>() {
424         {
425             add(NONE);
426             add(IMAGE);
427             add(VIDEO);
428             add(AUDIO);
429             add(DOCUMENT);
430             add(APP);
431         }
432     };
433
434     private ArrayAdapter<MimeTypeCategory> mEasyModeAdapter;
435     private View.OnClickListener mEasyModeItemClickListener = new View.OnClickListener() {
436         @Override
437         public void onClick(View view) {
438             Integer position = (Integer) view.getTag();
439             onClicked(position);
440         }
441     };
442
443     private int mCurrentNavigationView;
444
445     private ViewGroup mActionBar;
446     private SelectionView mSelectionBar;
447
448     private DrawerLayout mDrawerLayout;
449     private ViewGroup mDrawer;
450     private ActionBarDrawerToggle mDrawerToggle;
451     private LinearLayout mDrawerHistory;
452     private TextView mDrawerHistoryEmpty;
453
454     private TextView mBookmarksTab;
455     private TextView mHistoryTab;
456     private View mBookmarksLayout;
457     private View mHistoryLayout;
458
459     private ButtonItem mSettings;
460     private ButtonItem mClearHistory;
461
462     private List<Bookmark> mBookmarks;
463     private List<Bookmark> mSdBookmarks;
464     private LinearLayout mDrawerBookmarks;
465
466     private boolean mExitFlag = false;
467     private long mExitBackTimeout = -1;
468
469     private int mOrientation;
470
471     /**
472      * @hide
473      */
474     boolean mChRooted;
475
476     /**
477      * @hide
478      */
479     Handler mHandler;
480
481     private AsyncTask<Void, Void, Boolean> mBookmarksTask;
482
483     /**
484      * {@inheritDoc}
485      */
486     @Override
487     protected void onCreate(Bundle state) {
488
489         if (DEBUG) {
490             Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
491         }
492
493         // Register the broadcast receiver
494         IntentFilter filter = new IntentFilter();
495         filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
496         filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED);
497         filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED);
498         filter.addAction(Intent.ACTION_DATE_CHANGED);
499         filter.addAction(Intent.ACTION_TIME_CHANGED);
500         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
501         filter.addAction(FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED);
502         filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
503         registerReceiver(this.mNotificationReceiver, filter);
504
505         // Set the theme before setContentView
506         Theme theme = ThemeManager.getCurrentTheme(this);
507         theme.setBaseThemeNoActionBar(this);
508
509         //Set the main layout of the activity
510         setContentView(R.layout.navigation);
511
512         //Initialize nfc adapter
513         NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
514         if (mNfcAdapter != null) {
515             mNfcAdapter.setBeamPushUrisCallback(new NfcAdapter.CreateBeamUrisCallback() {
516                 @Override
517                 public Uri[] createBeamUris(NfcEvent event) {
518                     List<FileSystemObject> selectedFiles =
519                             getCurrentNavigationView().getSelectedFiles();
520                     if (selectedFiles.size() > 0) {
521                         List<Uri> fileUri = new ArrayList<Uri>();
522                         for (FileSystemObject f : selectedFiles) {
523                             //Beam ignores folders and system files
524                             if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) {
525                                 fileUri.add(Uri.fromFile(new File(f.getFullPath())));
526                             }
527                         }
528                         if (fileUri.size() > 0) {
529                             return fileUri.toArray(new Uri[fileUri.size()]);
530                         }
531                     }
532                     return null;
533                 }
534             }, this);
535         }
536
537         //Initialize activity
538         init();
539
540         //Navigation views
541         initNavigationViews();
542
543         // As we're using a Toolbar, we should retrieve it and set it
544         // to be our ActionBar
545         mToolBar = (Toolbar) findViewById(R.id.material_toolbar);
546         setActionBar(mToolBar);
547
548         //Initialize action bars
549         initTitleActionBar();
550         initStatusActionBar();
551         initSelectionBar();
552
553         // Initialize navigation drawer
554         initDrawer();
555         initBookmarks();
556
557         // Adjust layout (only when start on landscape mode)
558         int orientation = getResources().getConfiguration().orientation;
559         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
560             onLayoutChanged();
561         }
562         this.mOrientation = orientation;
563
564         // Apply the theme
565         applyTheme();
566
567         // Show welcome message
568         showWelcomeMsg();
569
570         this.mHandler = new Handler();
571         this.mHandler.post(new Runnable() {
572             @Override
573             public void run() {
574                 // Initialize console
575                 initConsole();
576
577                 //Initialize navigation
578                 int cc = NavigationActivity.this.mNavigationViews.length;
579                 for (int i = 0; i < cc; i++) {
580                     initNavigation(i, false, getIntent());
581                 }
582
583                 //Check the intent action
584                 checkIntent(getIntent());
585             }
586         });
587
588         MIME_TYPE_LOCALIZED_NAMES = MimeTypeCategory.getFriendlyLocalizedNames(NavigationActivity
589             .this);
590
591         EASY_MODE_ICONS.put(MimeTypeCategory.NONE, getResources().getDrawable(R.drawable
592                 .ic_em_all));
593         EASY_MODE_ICONS.put(MimeTypeCategory.IMAGE, getResources().getDrawable(R.drawable
594                 .ic_em_image));
595         EASY_MODE_ICONS.put(MimeTypeCategory.VIDEO, getResources().getDrawable(R.drawable
596                 .ic_em_video));
597         EASY_MODE_ICONS.put(MimeTypeCategory.AUDIO, getResources().getDrawable(R.drawable
598                 .ic_em_music));
599         EASY_MODE_ICONS.put(MimeTypeCategory.DOCUMENT, getResources().getDrawable(R.drawable
600                 .ic_em_document));
601         EASY_MODE_ICONS.put(MimeTypeCategory.APP, getResources().getDrawable(R.drawable
602                 .ic_em_application));
603
604         //Save state
605         super.onCreate(state);
606     }
607
608     @Override
609     protected void onResume() {
610         super.onResume();
611
612         if (mSearchView.getVisibility() == View.VISIBLE) {
613             closeSearch();
614         }
615
616         // Check restrictions
617         if (!FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) {
618             return;
619         }
620
621         // Check that the current dir is mounted (for virtual filesystems)
622         String curDir = mNavigationViews[mCurrentNavigationView].getCurrentDir();
623         if (curDir != null) {
624             VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(
625                     mNavigationViews[mCurrentNavigationView].getCurrentDir());
626             if (vc != null && !vc.isMounted()) {
627                 onRequestBookmarksRefresh();
628                 removeUnmountedHistory();
629                 removeUnmountedSelection();
630
631                 Intent intent = new Intent();
632                 intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
633                 initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
634             }
635         }
636     }
637
638     @Override
639     protected void onPostCreate(Bundle savedInstanceState) {
640         super.onPostCreate(savedInstanceState);
641         // Sync the toggle state after onRestoreInstanceState has occurred.
642         mDrawerToggle.syncState();
643     }
644
645     /**
646      * {@inheritDoc}
647      */
648     @Override
649     protected void onNewIntent(Intent intent) {
650         //Initialize navigation
651         initNavigation(this.mCurrentNavigationView, true, intent);
652
653         //Check the intent action
654         checkIntent(intent);
655     }
656
657     /**
658      * {@inheritDoc}
659      */
660     @Override
661     public void onConfigurationChanged(Configuration newConfig) {
662         super.onConfigurationChanged(newConfig);
663         onLayoutChanged();
664         mDrawerToggle.onConfigurationChanged(newConfig);
665     }
666
667     /**
668      * {@inheritDoc}
669      */
670     @Override
671     public boolean onOptionsItemSelected(MenuItem item) {
672         if (mDrawerToggle.onOptionsItemSelected(item)) {
673           return true;
674         }
675         return super.onOptionsItemSelected(item);
676     }
677
678     /**
679      * {@inheritDoc}
680      */
681     @Override
682     protected void onDestroy() {
683         if (DEBUG) {
684             Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$
685         }
686
687         // Unregister the receiver
688         try {
689             unregisterReceiver(this.mNotificationReceiver);
690         } catch (Throwable ex) {
691             /**NON BLOCK**/
692         }
693
694         //All destroy. Continue
695         super.onDestroy();
696     }
697
698     /**
699      * Method that returns the current navigation view.
700      *
701      * @return NavigationView The current navigation view
702      */
703     public NavigationView getCurrentNavigationView() {
704         return getNavigationView(this.mCurrentNavigationView);
705     }
706
707     /**
708      * Method that returns the current navigation view.
709      *
710      * @param viewId The view to return
711      * @return NavigationView The current navigation view
712      */
713     public NavigationView getNavigationView(int viewId) {
714         if (this.mNavigationViews == null) return null;
715         return this.mNavigationViews[viewId];
716     }
717
718     /**
719      * Method that initializes the activity.
720      */
721     private void init() {
722         this.mHistory = new ArrayList<History>();
723         this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
724     }
725
726     /**
727      * Method that displays a welcome message the first time the user
728      * access the application
729      */
730     private void showWelcomeMsg() {
731         boolean firstUse = Preferences.getSharedPreferences().getBoolean(
732                 FileManagerSettings.SETTINGS_FIRST_USE.getId(),
733                 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
734
735         //Display the welcome message?
736         if (firstUse && FileManagerApplication.hasShellCommands()) {
737             // open navigation drawer to show user that it exists
738             mDrawerLayout.openDrawer(Gravity.START);
739
740             AlertDialog dialog = DialogHelper.createAlertDialog(this,
741                     R.mipmap.ic_launcher_filemanager, R.string.welcome_title,
742                     getString(R.string.welcome_msg), false);
743             DialogHelper.delegateDialogShow(this, dialog);
744
745             // Don't display again this dialog
746             try {
747                 Preferences.savePreference(
748                         FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true);
749             } catch (Exception e) {/**NON BLOCK**/}
750         }
751     }
752
753     /**
754      * Method that initializes the titlebar of the activity.
755      */
756     private void initTitleActionBar() {
757         //Inflate the view and associate breadcrumb
758         View titleLayout = getLayoutInflater().inflate(
759                 R.layout.navigation_view_customtitle, null, false);
760         NavigationCustomTitleView title =
761                 (NavigationCustomTitleView)titleLayout.findViewById(R.id.navigation_title_flipper);
762         title.setOnHistoryListener(this);
763         Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view);
764         int cc = this.mNavigationViews.length;
765         for (int i = 0; i < cc; i++) {
766             this.mNavigationViews[i].setBreadcrumb(breadcrumb);
767             this.mNavigationViews[i].setOnHistoryListener(this);
768             this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this);
769             this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this);
770             this.mNavigationViews[i].setCustomTitle(title);
771         }
772
773         // Set the free disk space warning level of the breadcrumb widget
774         String fds = Preferences.getSharedPreferences().getString(
775                 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
776                 (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
777         breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
778
779         //Configure the action bar options
780         getActionBar().setBackgroundDrawable(
781                 getResources().getDrawable(R.drawable.bg_material_titlebar));
782         mToolBar.addView(titleLayout);
783     }
784
785     /**
786      * Method that initializes the statusbar of the activity.
787      */
788     private void initStatusActionBar() {
789         //Performs a width calculation of buttons. Buttons exceeds the width
790         //of the action bar should be hidden
791         //This application not use android ActionBar because the application
792         //make uses of the title and bottom areas, and wants to force to show
793         //the overflow button (without care of physical buttons)
794         this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar);
795         this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
796             @Override
797             public void onLayoutChange(
798                     View v, int left, int top, int right, int bottom, int oldLeft,
799                     int oldTop, int oldRight, int oldBottom) {
800                 //Get the width of the action bar
801                 int w = v.getMeasuredWidth();
802
803                 //Wake through children calculation his dimensions
804                 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
805                 int cw = 0;
806                 final ViewGroup abView = ((ViewGroup)v);
807                 int cc = abView.getChildCount();
808                 for (int i = 0; i < cc; i++) {
809                     View child = abView.getChildAt(i);
810                     child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE);
811                     cw += bw;
812                 }
813             }
814         });
815
816         // Have overflow menu? Actually no. There is only a search action, so just hide
817         // the overflow
818         View overflow = findViewById(R.id.ab_overflow);
819         overflow.setVisibility(View.GONE);
820
821         // Show the status bar
822         View statusBar = findViewById(R.id.navigation_statusbar_portrait_holder);
823         statusBar.setVisibility(View.VISIBLE);
824     }
825
826     /**
827      * Method that initializes the selectionbar of the activity.
828      */
829     private void initSelectionBar() {
830         this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar);
831     }
832
833     /**
834      * Method that initializes the navigation drawer of the activity.
835      */
836     private void initDrawer() {
837         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
838         //Set our status bar color
839         mDrawerLayout.setStatusBarBackgroundColor(R.color.material_palette_blue_primary_dark);
840         mDrawer = (ViewGroup) findViewById(R.id.drawer);
841         mDrawerBookmarks = (LinearLayout) findViewById(R.id.bookmarks_list);
842         mDrawerHistory = (LinearLayout) findViewById(R.id.history_list);
843         mDrawerHistoryEmpty = (TextView) findViewById(R.id.history_empty);
844
845         mBookmarksLayout = findViewById(R.id.drawer_bookmarks);
846         mHistoryLayout = findViewById(R.id.drawer_history);
847         mBookmarksTab = (TextView) findViewById(R.id.drawer_bookmarks_tab);
848         mHistoryTab = (TextView) findViewById(R.id.drawer_history_tab);
849         mBookmarksTab.setOnClickListener(mOnClickDrawerTabListener);
850         mHistoryTab.setOnClickListener(mOnClickDrawerTabListener);
851
852         mSettings = (ButtonItem) findViewById(R.id.ab_settings);
853         mSettings.setOnClickListener(mOnClickDrawerActionBarListener);
854         mClearHistory = (ButtonItem) findViewById(R.id.ab_clear_history);
855         mClearHistory.setOnClickListener(mOnClickDrawerActionBarListener);
856
857         // Restore the last tab pressed
858         Integer lastTab = Preferences.getSharedPreferences().getInt(
859                 FileManagerSettings.USER_PREF_LAST_DRAWER_TAB.getId(),
860                 (Integer) FileManagerSettings.USER_PREF_LAST_DRAWER_TAB
861                         .getDefaultValue());
862         mOnClickDrawerTabListener.onClick(lastTab == 0 ? mBookmarksTab : mHistoryTab);
863
864         // Set the navigation drawer "hamburger" icon
865         mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
866                 R.drawable.ic_material_light_navigation_drawer,
867                 R.string.drawer_open, R.string.drawer_close) {
868
869             /** Called when a drawer has settled in a completely closed state. */
870             public void onDrawerClosed(View view) {
871                 super.onDrawerClosed(view);
872             }
873
874             /** Called when a drawer has settled in a completely open state. */
875             public void onDrawerOpened(View drawerView) {
876                 super.onDrawerOpened(drawerView);
877             }
878         };
879
880         // Set the drawer toggle as the DrawerListener
881         mDrawerLayout.setDrawerListener(mDrawerToggle);
882     }
883
884     /**
885      * Method that adds a history entry to the history list in the drawer
886      */
887     private void addHistoryToDrawer(int index, HistoryNavigable navigable) {
888         // hide empty message
889         mDrawerHistoryEmpty.setVisibility(View.GONE);
890
891         Theme theme = ThemeManager.getCurrentTheme(this);
892         IconHolder iconholder = new IconHolder(this, false);
893
894         // inflate single bookmark layout item and fill it
895         LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
896                 R.layout.history_item, null);
897
898         ImageView iconView = (ImageView) view
899                 .findViewById(R.id.history_item_icon);
900         TextView name = (TextView) view.findViewById(R.id.history_item_name);
901         TextView directory = (TextView) view
902                 .findViewById(R.id.history_item_directory);
903
904         Drawable icon = iconholder.getDrawable("ic_fso_folder_drawable"); //$NON-NLS-1$
905         if (navigable instanceof SearchInfoParcelable) {
906             icon = iconholder.getDrawable("ic_history_search_drawable"); //$NON-NLS-1$
907         }
908         iconView.setImageDrawable(icon);
909
910         String title = navigable.getTitle();
911         if (title == null || title.trim().length() == 0) {
912             title = getString(R.string.root_directory_name);
913         }
914
915         name.setText(title);
916         directory.setText(navigable.getDescription());
917
918         theme.setTextColor(this, name, "text_color");
919         theme.setTextColor(this, directory, "text_color");
920
921         // handle item click
922         view.setOnClickListener(new OnClickListener() {
923             @Override
924             public void onClick(View v) {
925                 final int index = mDrawerHistory.indexOfChild(v);
926                 final int count = mDrawerHistory.getChildCount();
927                 final History history = mHistory.get(count - index - 1);
928
929                 navigateToHistory(history);
930                 mDrawerLayout.closeDrawer(Gravity.START);
931             }
932         });
933
934         // add as first child
935         mDrawerHistory.addView(view, 0);
936
937         // Show clear button if history tab is selected
938         mClearHistory.setVisibility(mHistoryTab.isSelected() ? View.VISIBLE : View.GONE);
939     }
940
941     /**
942      * Method takes a bookmark as argument and adds it to mBookmarks and the
943      * list in the drawer
944      */
945     public void addBookmark(Bookmark bookmark) {
946         mBookmarks.add(bookmark);
947         addBookmarkToDrawer(bookmark);
948     }
949
950     /**
951      * Show the easy mode view
952      */
953     private void performShowEasyMode() {
954         mEasyModeListView.setVisibility(View.VISIBLE);
955         getCurrentNavigationView().setVisibility(View.GONE);
956     }
957
958     /**
959      * Hide the easy mode view
960      */
961     private void performHideEasyMode() {
962         mEasyModeListView.setVisibility(View.GONE);
963         getCurrentNavigationView().setVisibility(View.VISIBLE);
964     }
965
966     /**
967      * Method takes a bookmark as argument and adds it to the bookmark list in
968      * the drawer
969      */
970     private void addBookmarkToDrawer(Bookmark bookmark) {
971         Theme theme = ThemeManager.getCurrentTheme(this);
972         IconHolder iconholder = new IconHolder(this, false);
973
974         // inflate single bookmark layout item and fill it
975         LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
976                 R.layout.bookmarks_item, null);
977
978         ImageView icon = (ImageView) view
979                 .findViewById(R.id.bookmarks_item_icon);
980         TextView name = (TextView) view.findViewById(R.id.bookmarks_item_name);
981         TextView path = (TextView) view.findViewById(R.id.bookmarks_item_path);
982         ImageButton actionButton = (ImageButton) view
983                 .findViewById(R.id.bookmarks_item_action);
984
985         name.setText(bookmark.mName);
986         path.setText(bookmark.mPath);
987
988         theme.setTextColor(this, name, "text_color");
989         theme.setTextColor(this, path, "text_color");
990
991         icon.setImageDrawable(iconholder.getDrawable(BookmarksHelper
992                 .getIcon(bookmark)));
993
994         Drawable action = null;
995         String actionCd = null;
996         if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
997             action = iconholder.getDrawable("ic_edit_home_bookmark_drawable"); //$NON-NLS-1$
998             actionCd = getApplicationContext().getString(
999                     R.string.bookmarks_button_config_cd);
1000         }
1001         else if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1002             action = iconholder.getDrawable("ic_close_drawable"); //$NON-NLS-1$
1003             actionCd = getApplicationContext().getString(
1004                     R.string.bookmarks_button_remove_bookmark_cd);
1005         }
1006
1007         actionButton.setImageDrawable(action);
1008         actionButton.setVisibility(action != null ? View.VISIBLE : View.GONE);
1009         actionButton.setOnClickListener(new OnClickListener() {
1010             @Override
1011             public void onClick(View view) {
1012                 final View v = (View) view.getParent();
1013                 final int index = mDrawerBookmarks.indexOfChild(v);
1014                 final Bookmark bookmark = mBookmarks.get(index);
1015
1016                 // Configure home
1017                 if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
1018                     // Show a dialog for configure initial directory
1019                     InitialDirectoryDialog dialog = new InitialDirectoryDialog(
1020                             NavigationActivity.this);
1021                     dialog.setOnValueChangedListener(new InitialDirectoryDialog.OnValueChangedListener() {
1022                         @Override
1023                         public void onValueChanged(String newInitialDir) {
1024                             bookmark.mPath = newInitialDir;
1025
1026                             // reset drawer bookmarks list
1027                             initBookmarks();
1028                         }
1029                     });
1030                     dialog.show();
1031                     return;
1032                 }
1033
1034                 // Remove bookmark
1035                 if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1036                     boolean result = Bookmarks.removeBookmark(
1037                             getApplicationContext(), bookmark);
1038                     if (!result) { // Show warning
1039                         DialogHelper.showToast(getApplicationContext(),
1040                                 R.string.msgs_operation_failure,
1041                                 Toast.LENGTH_SHORT);
1042                         return;
1043                     }
1044                     mBookmarks.remove(bookmark);
1045                     mDrawerBookmarks.removeView(v);
1046                     return;
1047                 }
1048             }
1049         });
1050         actionButton.setContentDescription(actionCd);
1051
1052         // handle item click
1053         view.setOnClickListener(new OnClickListener() {
1054             @Override
1055             public void onClick(View v) {
1056                 final int index = mDrawerBookmarks.indexOfChild(v);
1057                 final Bookmark bookmark = mBookmarks.get(index);
1058
1059                 boolean showEasyMode = (mSdBookmarks.contains(bookmark)) &&
1060                         getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1061
1062                 // try to navigate to the bookmark path
1063                 try {
1064                     FileSystemObject fso = CommandHelper.getFileInfo(
1065                             getApplicationContext(), bookmark.mPath, null);
1066                     if (fso != null) {
1067                         if (showEasyMode) {
1068                             performShowEasyMode();
1069                         } else {
1070                             performHideEasyMode();
1071                         }
1072                         getCurrentNavigationView().open(fso);
1073                         mDrawerLayout.closeDrawer(Gravity.START);
1074                     }
1075                     else {
1076                         // The bookmark does not exist, delete the user-defined
1077                         // bookmark
1078                         try {
1079                             Bookmarks.removeBookmark(getApplicationContext(),
1080                                     bookmark);
1081
1082                             // reset bookmarks list to default
1083                             initBookmarks();
1084                         }
1085                         catch (Exception ex) {
1086                         }
1087                     }
1088                 }
1089                 catch (Exception e) { // Capture the exception
1090                     ExceptionUtil
1091                             .translateException(NavigationActivity.this, e);
1092                     if (e instanceof NoSuchFileOrDirectory
1093                             || e instanceof FileNotFoundException) {
1094                         // The bookmark does not exist, delete the user-defined
1095                         // bookmark
1096                         try {
1097                             Bookmarks.removeBookmark(getApplicationContext(),
1098                                     bookmark);
1099
1100                             // reset bookmarks list to default
1101                             initBookmarks();
1102                         }
1103                         catch (Exception ex) {
1104                         }
1105                     }
1106                     return;
1107                 }
1108             }
1109         });
1110
1111         mDrawerBookmarks.addView(view);
1112     }
1113
1114     /**
1115      * Method that initializes the bookmarks.
1116      */
1117     private synchronized void initBookmarks() {
1118         if (mBookmarksTask != null &&
1119                 !mBookmarksTask.getStatus().equals(AsyncTask.Status.FINISHED)) {
1120             return;
1121         }
1122
1123         // Retrieve the loading view
1124         final View waiting = findViewById(R.id.bookmarks_loading);
1125
1126         // Load bookmarks in background
1127         mBookmarksTask = new AsyncTask<Void, Void, Boolean>() {
1128             Exception mCause;
1129
1130             @Override
1131             protected Boolean doInBackground(Void... params) {
1132                 try {
1133                     mBookmarks = loadBookmarks();
1134                     return Boolean.TRUE;
1135
1136                 }
1137                 catch (Exception e) {
1138                     this.mCause = e;
1139                     return Boolean.FALSE;
1140                 }
1141             }
1142
1143             @Override
1144             protected void onPreExecute() {
1145                 waiting.setVisibility(View.VISIBLE);
1146                 mDrawerBookmarks.removeAllViews();
1147             }
1148
1149             @Override
1150             protected void onPostExecute(Boolean result) {
1151                 waiting.setVisibility(View.GONE);
1152                 if (result.booleanValue()) {
1153                     for (Bookmark bookmark : mBookmarks) {
1154                         addBookmarkToDrawer(bookmark);
1155                     }
1156                 }
1157                 else {
1158                     if (this.mCause != null) {
1159                         ExceptionUtil.translateException(
1160                                 NavigationActivity.this, this.mCause);
1161                     }
1162                 }
1163                 mBookmarksTask = null;
1164             }
1165
1166             @Override
1167             protected void onCancelled() {
1168                 waiting.setVisibility(View.GONE);
1169                 mBookmarksTask = null;
1170             }
1171         };
1172         mBookmarksTask.execute();
1173     }
1174
1175     /**
1176      * Method that loads all kind of bookmarks and join in an array to be used
1177      * in the listview adapter.
1178      *
1179      * @return List<Bookmark>
1180      * @hide
1181      */
1182     List<Bookmark> loadBookmarks() {
1183         // Bookmarks = HOME + FILESYSTEM + SD STORAGES + USER DEFINED
1184         // In ChRooted mode = SD STORAGES + USER DEFINED (from SD STORAGES)
1185         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1186         if (!this.mChRooted) {
1187             bookmarks.add(loadHomeBookmarks());
1188             bookmarks.addAll(loadFilesystemBookmarks());
1189         }
1190         mSdBookmarks = loadSdStorageBookmarks();
1191         bookmarks.addAll(mSdBookmarks);
1192         bookmarks.addAll(loadVirtualBookmarks());
1193         bookmarks.addAll(loadUserBookmarks());
1194         return bookmarks;
1195     }
1196
1197     /**
1198      * Method that loads the home bookmark from the user preference.
1199      *
1200      * @return Bookmark The bookmark loaded
1201      */
1202     private Bookmark loadHomeBookmarks() {
1203         String initialDir = Preferences.getSharedPreferences().getString(
1204                 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1205                 (String) FileManagerSettings.SETTINGS_INITIAL_DIR
1206                         .getDefaultValue());
1207         return new Bookmark(BOOKMARK_TYPE.HOME,
1208                 getString(R.string.bookmarks_home), initialDir);
1209     }
1210
1211     /**
1212      * Method that loads the filesystem bookmarks from the internal xml file.
1213      * (defined by this application)
1214      *
1215      * @return List<Bookmark> The bookmarks loaded
1216      */
1217     private List<Bookmark> loadFilesystemBookmarks() {
1218         try {
1219             // Initialize the bookmarks
1220             List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1221
1222             // Read the command list xml file
1223             XmlResourceParser parser = getResources().getXml(
1224                     R.xml.filesystem_bookmarks);
1225
1226             try {
1227                 // Find the root element
1228                 XmlUtils.beginDocument(parser, TAG_BOOKMARKS);
1229                 while (true) {
1230                     XmlUtils.nextElement(parser);
1231                     String element = parser.getName();
1232                     if (element == null) {
1233                         break;
1234                     }
1235
1236                     if (TAG_BOOKMARK.equals(element)) {
1237                         CharSequence name = null;
1238                         CharSequence directory = null;
1239
1240                         try {
1241                             name = getString(parser.getAttributeResourceValue(
1242                                     R.styleable.Bookmark_name, 0));
1243                         }
1244                         catch (Exception e) {
1245                             /** NON BLOCK **/
1246                         }
1247                         try {
1248                             directory = getString(parser
1249                                     .getAttributeResourceValue(
1250                                             R.styleable.Bookmark_directory, 0));
1251                         }
1252                         catch (Exception e) {
1253                             /** NON BLOCK **/
1254                         }
1255                         if (directory == null) {
1256                             directory = parser
1257                                     .getAttributeValue(R.styleable.Bookmark_directory);
1258                         }
1259                         if (name != null && directory != null) {
1260                             bookmarks.add(new Bookmark(
1261                                     BOOKMARK_TYPE.FILESYSTEM, name.toString(),
1262                                     directory.toString()));
1263                         }
1264                     }
1265                 }
1266
1267                 // Return the bookmarks
1268                 return bookmarks;
1269
1270             }
1271             finally {
1272                 parser.close();
1273             }
1274         }
1275         catch (Throwable ex) {
1276             Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1277         }
1278
1279         // No data
1280         return new ArrayList<Bookmark>();
1281     }
1282
1283     /**
1284      * Method that loads the secure digital card storage bookmarks from the
1285      * system.
1286      *
1287      * @return List<Bookmark> The bookmarks loaded
1288      */
1289     private List<Bookmark> loadSdStorageBookmarks() {
1290         // Initialize the bookmarks
1291         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1292
1293         try {
1294             // Recovery sdcards from storage manager
1295             StorageVolume[] volumes = StorageHelper
1296                     .getStorageVolumes(getApplication());
1297             for (StorageVolume volume: volumes) {
1298                 if (volume != null) {
1299                     String mountedState = volume.getState();
1300                     String path = volume.getPath();
1301                     if (!Environment.MEDIA_MOUNTED.equalsIgnoreCase(mountedState) &&
1302                             !Environment.MEDIA_MOUNTED_READ_ONLY.equalsIgnoreCase(mountedState)) {
1303                         Log.w(TAG, "Ignoring '" + path + "' with state of '"+ mountedState + "'");
1304                         continue;
1305                     }
1306                     if (!TextUtils.isEmpty(path)) {
1307                         String lowerPath = path.toLowerCase(Locale.ROOT);
1308                         Bookmark bookmark;
1309                         if (lowerPath.contains(STR_USB)) {
1310                             bookmark = new Bookmark(BOOKMARK_TYPE.USB, StorageHelper
1311                                     .getStorageVolumeDescription(getApplication(), volume), path);
1312                         } else {
1313                             bookmark = new Bookmark(BOOKMARK_TYPE.SDCARD, StorageHelper
1314                                     .getStorageVolumeDescription(getApplication(), volume), path);
1315                         }
1316                         bookmarks.add(bookmark);
1317                     }
1318                 }
1319             }
1320
1321             // Return the bookmarks
1322             return bookmarks;
1323         }
1324         catch (Throwable ex) {
1325             Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1326         }
1327
1328         // No data
1329         return new ArrayList<Bookmark>();
1330     }
1331
1332     /**
1333      * Method that loads all virtual mount points.
1334      *
1335      * @return List<Bookmark> The bookmarks loaded
1336      */
1337     private List<Bookmark> loadVirtualBookmarks() {
1338         // Initialize the bookmarks
1339         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1340         List<MountPoint> mps = VirtualMountPointConsole.getVirtualMountPoints();
1341         for (MountPoint mp : mps) {
1342             BOOKMARK_TYPE type = null;
1343             String name = null;
1344             if (mp.isSecure()) {
1345                 type = BOOKMARK_TYPE.SECURE;
1346                 name = getString(R.string.bookmarks_secure);
1347             } else if (mp.isRemote()) {
1348                 type = BOOKMARK_TYPE.REMOTE;
1349                 name = getString(R.string.bookmarks_remote);
1350             } else {
1351                 continue;
1352             }
1353             bookmarks.add(new Bookmark(type, name, mp.getMountPoint()));
1354         }
1355         return bookmarks;
1356     }
1357
1358     /**
1359      * Method that loads the user bookmarks (added by the user).
1360      *
1361      * @return List<Bookmark> The bookmarks loaded
1362      */
1363     private List<Bookmark> loadUserBookmarks() {
1364         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1365         Cursor cursor = Bookmarks.getAllBookmarks(this.getContentResolver());
1366         try {
1367             if (cursor != null && cursor.moveToFirst()) {
1368                 do {
1369                     Bookmark bm = new Bookmark(cursor);
1370                     if (this.mChRooted
1371                             && !StorageHelper.isPathInStorageVolume(bm.mPath)) {
1372                         continue;
1373                     }
1374                     bookmarks.add(bm);
1375                 }
1376                 while (cursor.moveToNext());
1377             }
1378         }
1379         finally {
1380             try {
1381                 if (cursor != null) {
1382                     cursor.close();
1383                 }
1384             }
1385             catch (Exception e) {
1386                 /** NON BLOCK **/
1387             }
1388         }
1389
1390         // Remove bookmarks from virtual storage if the filesystem is not mount
1391         int c = bookmarks.size() - 1;
1392         for (int i = c; i >= 0; i--) {
1393             VirtualMountPointConsole vc =
1394                     VirtualMountPointConsole.getVirtualConsoleForPath(bookmarks.get(i).mPath);
1395             if (vc != null && !vc.isMounted()) {
1396                 bookmarks.remove(i);
1397             }
1398         }
1399
1400         return bookmarks;
1401     }
1402
1403     /**
1404      * Method that initializes the navigation views of the activity
1405      */
1406     private void initNavigationViews() {
1407         //Get the navigation views (wishlist: multiple view; for now only one view)
1408         this.mNavigationViews = new NavigationView[1];
1409         this.mCurrentNavigationView = 0;
1410         //- 0
1411         this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view);
1412         this.mNavigationViews[0].setId(0);
1413         this.mEasyModeListView = (ListView) findViewById(R.id.lv_easy_mode);
1414         mEasyModeAdapter = new ArrayAdapter<MimeTypeCategory>(this, R.layout
1415                 .navigation_view_simple_item) {
1416             @Override
1417             public View getView(int position, View convertView, ViewGroup parent) {
1418                 convertView = (convertView == null) ?getLayoutInflater().inflate(R.layout
1419                         .navigation_view_simple_item, parent, false) : convertView;
1420                 MimeTypeCategory item = getItem(position);
1421                 String typeTitle = MIME_TYPE_LOCALIZED_NAMES[item.ordinal()];
1422                 TextView typeTitleTV = (TextView) convertView
1423                         .findViewById(R.id.navigation_view_item_name);
1424                 ImageView typeIconIV = (ImageView) convertView
1425                         .findViewById(R.id.navigation_view_item_icon);
1426                 View checkBoxView = convertView.findViewById(R.id.navigation_view_item_check);
1427                 checkBoxView.setVisibility(View.GONE);
1428                 typeTitleTV.setText(typeTitle);
1429                 typeIconIV.setImageDrawable(EASY_MODE_ICONS.get(item));
1430                 convertView.setOnClickListener(mEasyModeItemClickListener);
1431                 convertView.setTag(position);
1432                 return convertView;
1433             }
1434         };
1435         mEasyModeAdapter.addAll(EASY_MODE_LIST);
1436         mEasyModeListView.setAdapter(mEasyModeAdapter);
1437     }
1438
1439     private void onClicked(int position) {
1440         Intent intent = new Intent(this, SearchActivity.class);
1441         intent.setAction(Intent.ACTION_SEARCH);
1442         intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
1443                 getCurrentNavigationView().getCurrentDir());
1444         intent.putExtra(SearchManager.QUERY, "*"); // Use wild-card '*'
1445
1446         if (position == 0) {
1447             performHideEasyMode();
1448             return;
1449
1450         } else {
1451             ArrayList<MimeTypeCategory> searchCategories = new ArrayList<MimeTypeCategory>();
1452             MimeTypeCategory selectedCategory = EASY_MODE_LIST.get(position);
1453             searchCategories.add(selectedCategory);
1454             // a one off case where we implicitly want to also search for TEXT mimetypes when the
1455             // DOCUMENTS category is selected
1456             if (selectedCategory == MimeTypeCategory.DOCUMENT) {
1457                 searchCategories.add(MimeTypeCategory.TEXT);
1458             }
1459             intent.putExtra(SearchActivity.EXTRA_SEARCH_MIMETYPE, searchCategories);
1460         }
1461
1462         startActivity(intent);
1463     }
1464
1465     /**
1466      * Method that initialize the console
1467      * @hide
1468      */
1469     void initConsole() {
1470         //Create the default console (from the preferences)
1471         try {
1472             Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
1473             if (console == null) {
1474                 throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
1475             }
1476         } catch (Throwable ex) {
1477             if (!NavigationActivity.this.mChRooted) {
1478                 //Show exception and exit
1479                 Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
1480                 // We don't have any console
1481                 // Show exception and exit
1482                 DialogHelper.showToast(
1483                         NavigationActivity.this,
1484                         R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1485                 exit();
1486                 return;
1487             }
1488
1489             // We are in a trouble (something is not allowing creating the console)
1490             // Ask the user to return to prompt or root access mode mode with a
1491             // non-privileged console, prior to make crash the application
1492             askOrExit();
1493             return;
1494         }
1495     }
1496
1497     /**
1498      * Method that initializes the navigation.
1499      *
1500      * @param viewId The navigation view identifier where apply the navigation
1501      * @param restore Initialize from a restore info
1502      * @param intent The current intent
1503      * @hide
1504      */
1505     void initNavigation(final int viewId, final boolean restore, final Intent intent) {
1506         final NavigationView navigationView = getNavigationView(viewId);
1507         this.mHandler.post(new Runnable() {
1508             @Override
1509             public void run() {
1510                 //Is necessary navigate?
1511                 if (!restore) {
1512                     applyInitialDir(navigationView, intent);
1513                 }
1514             }
1515         });
1516     }
1517
1518     /**
1519      * Method that applies the user-defined initial directory
1520      *
1521      * @param navigationView The navigation view
1522      * @param intent The current intent
1523      * @hide
1524      */
1525     void applyInitialDir(final NavigationView navigationView, final Intent intent) {
1526         //Load the user-defined initial directory
1527         String initialDir =
1528                 Preferences.getSharedPreferences().getString(
1529                     FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1530                     (String)FileManagerSettings.
1531                         SETTINGS_INITIAL_DIR.getDefaultValue());
1532
1533         // Check if request navigation to directory (use as default), and
1534         // ensure chrooted and absolute path
1535         String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
1536         if (navigateTo != null && navigateTo.length() > 0) {
1537             initialDir = navigateTo;
1538         } else if (intent.getAction().equals(Intent.ACTION_VIEW)) {
1539             Uri data = intent.getData();
1540             if (data != null && (FileHelper.FILE_URI_SCHEME.equals(data.getScheme())
1541                     || FileHelper.FOLDER_URI_SCHEME.equals(data.getScheme())
1542                     || FileHelper.DIRECTORY_URI_SCHEME.equals(data.getScheme()))) {
1543                 File path = new File(data.getPath());
1544                 if (path.isDirectory()) {
1545                     initialDir = path.getAbsolutePath();
1546                 }
1547             }
1548         }
1549
1550         // Add to history
1551         final boolean addToHistory = intent.getBooleanExtra(EXTRA_ADD_TO_HISTORY, true);
1552
1553         // We cannot navigate to a secure console if is unmount, go to root in that case
1554         VirtualConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(initialDir);
1555         if (vc != null && vc instanceof SecureConsole && !((SecureConsole) vc).isMounted()) {
1556             initialDir = FileHelper.ROOT_DIRECTORY;
1557         }
1558
1559         if (this.mChRooted) {
1560             // Initial directory is the first external sdcard (sdcard, emmc, usb, ...)
1561             if (!StorageHelper.isPathInStorageVolume(initialDir)) {
1562                 StorageVolume[] volumes =
1563                         StorageHelper.getStorageVolumes(this);
1564                 if (volumes != null && volumes.length > 0) {
1565                     initialDir = volumes[0].getPath();
1566                     //Ensure that initial directory is an absolute directory
1567                     initialDir = FileHelper.getAbsPath(initialDir);
1568                 } else {
1569                     // Show exception and exit
1570                     DialogHelper.showToast(
1571                             this,
1572                             R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1573                     exit();
1574                     return;
1575                 }
1576             }
1577         } else {
1578             //Ensure that initial directory is an absolute directory
1579             final String userInitialDir = initialDir;
1580             initialDir = FileHelper.getAbsPath(initialDir);
1581             final String absInitialDir = initialDir;
1582             File f = new File(initialDir);
1583             boolean exists = f.exists();
1584             if (!exists) {
1585                 // Fix for /data/media/0. Libcore doesn't detect it correctly.
1586                 try {
1587                     exists = CommandHelper.getFileInfo(this, initialDir, false, null) != null;
1588                 } catch (InsufficientPermissionsException ipex) {
1589                     ExceptionUtil.translateException(
1590                             this, ipex, false, true, new OnRelaunchCommandResult() {
1591                         @Override
1592                         public void onSuccess() {
1593                             navigationView.changeCurrentDir(absInitialDir, addToHistory);
1594                         }
1595                         @Override
1596                         public void onFailed(Throwable cause) {
1597                             showInitialInvalidDirectoryMsg(userInitialDir);
1598                             navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1599                                     addToHistory);
1600                         }
1601                         @Override
1602                         public void onCancelled() {
1603                             showInitialInvalidDirectoryMsg(userInitialDir);
1604                             navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1605                                     addToHistory);
1606                         }
1607                     });
1608
1609                     // Asynchronous mode
1610                     return;
1611                 } catch (Exception ex) {
1612                     // We are not interested in other exceptions
1613                     ExceptionUtil.translateException(this, ex, true, false);
1614                 }
1615
1616                 // Check again the initial directory
1617                 if (!exists) {
1618                     showInitialInvalidDirectoryMsg(userInitialDir);
1619                     initialDir = FileHelper.ROOT_DIRECTORY;
1620                 }
1621
1622                 // Weird, but we have a valid initial directory
1623             }
1624         }
1625
1626         boolean needsEasyMode = false;
1627         if (mSdBookmarks != null ) {
1628             for (Bookmark bookmark :mSdBookmarks) {
1629                 if (bookmark.mPath.equalsIgnoreCase(initialDir)) {
1630                     needsEasyMode = true;
1631                     break;
1632                 }
1633             }
1634         }
1635
1636         needsEasyMode = needsEasyMode
1637                 && getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1638         if (needsEasyMode) {
1639             performShowEasyMode();
1640         } else {
1641             performHideEasyMode();
1642         }
1643         // Change the current directory to the user-defined initial directory
1644         navigationView.changeCurrentDir(initialDir, addToHistory);
1645     }
1646
1647     /**
1648      * Displays a message reporting invalid directory
1649      *
1650      * @param initialDir The initial directory
1651      * @hide
1652      */
1653     void showInitialInvalidDirectoryMsg(String initialDir) {
1654         // Change to root directory
1655         DialogHelper.showToast(
1656                 this,
1657                 getString(
1658                         R.string.msgs_settings_invalid_initial_directory,
1659                         initialDir),
1660                 Toast.LENGTH_SHORT);
1661     }
1662
1663     /**
1664      * Method that verifies the intent passed to the activity, and checks
1665      * if a request is made like Search.
1666      *
1667      * @param intent The intent to check
1668      * @hide
1669      */
1670     void checkIntent(Intent intent) {
1671         //Search action
1672         if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
1673             Intent searchIntent = new Intent(this, SearchActivity.class);
1674             searchIntent.setAction(Intent.ACTION_SEARCH);
1675             //- SearchActivity.EXTRA_SEARCH_DIRECTORY
1676             searchIntent.putExtra(
1677                     SearchActivity.EXTRA_SEARCH_DIRECTORY,
1678                     getCurrentNavigationView().getCurrentDir());
1679             //- SearchManager.APP_DATA
1680             if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
1681                 Bundle bundle = new Bundle();
1682                 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
1683                 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
1684             }
1685             //-- SearchManager.QUERY
1686             String query = intent.getStringExtra(SearchManager.QUERY);
1687             if (query != null) {
1688                 searchIntent.putExtra(SearchManager.QUERY, query);
1689             }
1690             //- android.speech.RecognizerIntent.EXTRA_RESULTS
1691             ArrayList<String> extraResults =
1692                     intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
1693             if (extraResults != null) {
1694                 searchIntent.putStringArrayListExtra(
1695                         android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
1696             }
1697             startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1698             return;
1699         }
1700     }
1701
1702     /**
1703      * {@inheritDoc}
1704      */
1705     @Override
1706     public boolean onKeyUp(int keyCode, KeyEvent event) {
1707         if (keyCode == KeyEvent.KEYCODE_MENU) {
1708             if (mDrawerLayout.isDrawerOpen(mDrawer)) {
1709                 mDrawerLayout.closeDrawer(Gravity.START);
1710             } else {
1711                 mDrawerLayout.openDrawer(Gravity.START);
1712             }
1713             return true;
1714         }
1715         return super.onKeyUp(keyCode, event);
1716     }
1717
1718     @Override
1719     public void onBackPressed() {
1720         if (checkBackAction()) {
1721             performHideEasyMode();
1722             return;
1723         }
1724
1725         // An exit event has occurred, force the destroy the consoles
1726         exit();
1727     }
1728
1729     /**
1730      * Method invoked when an action item is clicked.
1731      *
1732      * @param view The button pushed
1733      */
1734     public void onActionBarItemClick(View view) {
1735         switch (view.getId()) {
1736             //######################
1737             //Navigation Custom Title
1738             //######################
1739             case R.id.ab_configuration:
1740                 //Show navigation view configuration toolbar
1741                 getCurrentNavigationView().getCustomTitle().showConfigurationView();
1742                 break;
1743             case R.id.ab_close:
1744                 //Hide navigation view configuration toolbar
1745                 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
1746                 break;
1747
1748             //######################
1749             //Breadcrumb Actions
1750             //######################
1751             case R.id.ab_filesystem_info:
1752                 //Show information of the filesystem
1753                 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
1754                 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
1755                 showMountPointInfo(mp, du);
1756                 break;
1757
1758             //######################
1759             //Navigation view options
1760             //######################
1761             case R.id.ab_sort_mode:
1762                 showSettingsPopUp(view,
1763                         Arrays.asList(
1764                                 new FileManagerSettings[]{
1765                                         FileManagerSettings.SETTINGS_SORT_MODE}));
1766                 break;
1767             case R.id.ab_layout_mode:
1768                 showSettingsPopUp(view,
1769                         Arrays.asList(
1770                                 new FileManagerSettings[]{
1771                                         FileManagerSettings.SETTINGS_LAYOUT_MODE}));
1772                 break;
1773             case R.id.ab_view_options:
1774                 // If we are in ChRooted mode, then don't show non-secure items
1775                 if (this.mChRooted) {
1776                     showSettingsPopUp(view,
1777                             Arrays.asList(new FileManagerSettings[]{
1778                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
1779                 } else {
1780                     showSettingsPopUp(view,
1781                             Arrays.asList(new FileManagerSettings[]{
1782                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
1783                                     FileManagerSettings.SETTINGS_SHOW_HIDDEN,
1784                                     FileManagerSettings.SETTINGS_SHOW_SYSTEM,
1785                                     FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
1786                 }
1787
1788                 break;
1789
1790             //######################
1791             //Selection Actions
1792             //######################
1793             case R.id.ab_selection_done:
1794                 //Show information of the filesystem
1795                 getCurrentNavigationView().onDeselectAll();
1796                 break;
1797
1798             //######################
1799             //Action Bar buttons
1800             //######################
1801             case R.id.ab_actions:
1802                 openActionsDialog(getCurrentNavigationView().getCurrentDir(),
1803                         true);
1804                 break;
1805
1806             case R.id.ab_search:
1807
1808                 openSearch();
1809                 break;
1810
1811             default:
1812                 break;
1813         }
1814     }
1815
1816     /**
1817      * {@inheritDoc}
1818      */
1819     @Override
1820     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1821         if (requestCode == INTENT_REQUEST_SETTINGS) {
1822             // reset bookmarks list to default as the user could changed the
1823             // root mode which changes the system bookmarks
1824             initBookmarks();
1825             return;
1826         }
1827
1828         if (data != null) {
1829             switch (requestCode) {
1830                 case INTENT_REQUEST_SEARCH:
1831                     if (resultCode == RESULT_OK) {
1832                         //Change directory?
1833                         Bundle bundle = data.getExtras();
1834                         if (bundle != null) {
1835                             FileSystemObject fso = (FileSystemObject) bundle.getSerializable(
1836                                     EXTRA_SEARCH_ENTRY_SELECTION);
1837                             SearchInfoParcelable searchInfo =
1838                                     bundle.getParcelable(EXTRA_SEARCH_LAST_SEARCH_DATA);
1839                             if (fso != null) {
1840                                 //Goto to new directory
1841                                 getCurrentNavigationView().open(fso, searchInfo);
1842                                 performHideEasyMode();
1843                             }
1844                         }
1845                     } else if (resultCode == RESULT_CANCELED) {
1846                         SearchInfoParcelable searchInfo =
1847                                 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
1848                         if (searchInfo != null && searchInfo.isSuccessNavigation()) {
1849                             //Navigate to previous history
1850                             back();
1851                         } else {
1852                             // I don't know is the search view was changed, so try to do a refresh
1853                             // of the navigation view
1854                             getCurrentNavigationView().refresh(true);
1855                         }
1856                     }
1857                     // reset bookmarks list to default as the user could have set a
1858                     // new bookmark in the search activity
1859                     initBookmarks();
1860                     break;
1861
1862                 default:
1863                     break;
1864             }
1865         }
1866     }
1867
1868     /**
1869      * {@inheritDoc}
1870      */
1871     @Override
1872     public void onNewHistory(HistoryNavigable navigable) {
1873         addHistoryToDrawer(this.mHistory.size(), navigable);
1874         //Recollect information about current status
1875         History history = new History(this.mHistory.size(), navigable);
1876         this.mHistory.add(history);
1877     }
1878
1879     /**
1880      * {@inheritDoc}
1881      */
1882     @Override
1883     public void onCheckHistory() {
1884     }
1885
1886     /**
1887      * {@inheritDoc}
1888      */
1889     @Override
1890     public void onRequestRefresh(Object o, boolean clearSelection) {
1891         if (o instanceof FileSystemObject) {
1892             // Refresh only the item
1893             this.getCurrentNavigationView().refresh((FileSystemObject)o);
1894         } else if (o == null) {
1895             // Refresh all
1896             getCurrentNavigationView().refresh();
1897         }
1898         if (clearSelection) {
1899             this.getCurrentNavigationView().onDeselectAll();
1900         }
1901     }
1902
1903     /**
1904      * {@inheritDoc}
1905      */
1906     @Override
1907     public void onRequestBookmarksRefresh() {
1908         initBookmarks();
1909     }
1910
1911     /**
1912      * {@inheritDoc}
1913      */
1914     @Override
1915     public void onRequestRemove(Object o, boolean clearSelection) {
1916         if (o instanceof FileSystemObject) {
1917             // Remove from view
1918             this.getCurrentNavigationView().removeItem((FileSystemObject)o);
1919
1920             //Remove from history
1921             removeFromHistory((FileSystemObject)o);
1922         } else {
1923             onRequestRefresh(null, clearSelection);
1924         }
1925         if (clearSelection) {
1926             this.getCurrentNavigationView().onDeselectAll();
1927         }
1928     }
1929
1930     /**
1931      * {@inheritDoc}
1932      */
1933     @Override
1934     public void onNavigateTo(Object o) {
1935         // Ignored
1936     }
1937
1938     /**
1939      * {@inheritDoc}
1940      */
1941     @Override
1942     public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
1943         this.mSelectionBar.setSelection(selectedItems);
1944     }
1945
1946     /**
1947      * {@inheritDoc}
1948      */
1949     @Override
1950     public void onRequestMenu(NavigationView navView, FileSystemObject item) {
1951         // Show the actions dialog
1952         openActionsDialog(item, false);
1953     }
1954
1955     /**
1956      * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
1957      *
1958      * @param anchor The action button that was pressed
1959      * @param settings The array of settings associated with the action button
1960      */
1961     private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
1962         //Create the adapter
1963         final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
1964
1965         //Create a show the popup menu
1966         final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
1967         popup.setOnItemClickListener(new OnItemClickListener() {
1968             @Override
1969             public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
1970                 FileManagerSettings setting =
1971                         ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
1972                 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
1973                 popup.dismiss();
1974                 try {
1975                     if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
1976                         //Need to change the layout
1977                         getCurrentNavigationView().changeViewMode(
1978                                 NavigationLayoutMode.fromId(value));
1979                     } else {
1980                         //Save and refresh
1981                         if (setting.getDefaultValue() instanceof Enum<?>) {
1982                             //Enumeration
1983                             Preferences.savePreference(setting, new ObjectIdentifier() {
1984                                 @Override
1985                                 public int getId() {
1986                                     return value;
1987                                 }
1988                             }, false);
1989                         } else {
1990                             //Boolean
1991                             boolean newval =
1992                                     Preferences.getSharedPreferences().
1993                                         getBoolean(
1994                                             setting.getId(),
1995                                             ((Boolean)setting.getDefaultValue()).booleanValue());
1996                             Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
1997                         }
1998                         getCurrentNavigationView().refresh();
1999                     }
2000                 } catch (Exception e) {
2001                     Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
2002                     NavigationActivity.this.mHandler.post(new Runnable() {
2003                         @Override
2004                         public void run() {
2005                             DialogHelper.showToast(
2006                                     NavigationActivity.this,
2007                                     R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
2008                         }
2009                     });
2010
2011                 } finally {
2012                     adapter.dispose();
2013                     getCurrentNavigationView().getCustomTitle().restoreView();
2014                 }
2015
2016             }
2017         });
2018         popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
2019             @Override
2020             public void onDismiss() {
2021                 adapter.dispose();
2022             }
2023         });
2024         popup.show();
2025     }
2026
2027     /**
2028      * Method that show the information of a filesystem mount point.
2029      *
2030      * @param mp The mount point info
2031      * @param du The disk usage of the mount point
2032      */
2033     private void showMountPointInfo(MountPoint mp, DiskUsage du) {
2034         //Has mount point info?
2035         if (mp == null) {
2036             //There is no information
2037             AlertDialog alert =
2038                     DialogHelper.createWarningDialog(
2039                             this,
2040                             R.string.filesystem_info_warning_title,
2041                             R.string.filesystem_info_warning_msg);
2042             DialogHelper.delegateDialogShow(this, alert);
2043             return;
2044         }
2045
2046         //Show a the filesystem info dialog
2047         FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
2048         dialog.setOnMountListener(new OnMountListener() {
2049             @Override
2050             public void onRemount(MountPoint mountPoint) {
2051                 //Update the statistics of breadcrumb, only if mount point is the same
2052                 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
2053                 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
2054                     breadcrumb.updateMountPointInfo();
2055                 }
2056                 if (mountPoint.isSecure()) {
2057                     // Secure mountpoints only can be unmount, so we need to move the navigation
2058                     // to a secure storage (do not add to history)
2059                     Intent intent = new Intent();
2060                     intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
2061                     initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
2062                 }
2063             }
2064         });
2065         dialog.show();
2066     }
2067
2068     /**
2069      * Method that checks the action that must be realized when the
2070      * back button is pushed.
2071      *
2072      * @return boolean Indicates if the action must be intercepted
2073      */
2074     private boolean checkBackAction() {
2075         // We need a basic structure to check this
2076         if (getCurrentNavigationView() == null) return false;
2077
2078         if (mSearchView.getVisibility() == View.VISIBLE) {
2079             closeSearch();
2080         }
2081
2082         //Check if the configuration view is showing. In this case back
2083         //action must be "close configuration"
2084         if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
2085             getCurrentNavigationView().getCustomTitle().restoreView();
2086             return true;
2087         }
2088
2089         //Do back operation over the navigation history
2090         boolean flag = this.mExitFlag;
2091
2092         this.mExitFlag = !back();
2093
2094         // Retrieve if the exit status timeout has expired
2095         long now = System.currentTimeMillis();
2096         boolean timeout = (this.mExitBackTimeout == -1 ||
2097                             (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
2098
2099         //Check if there no history and if the user was advised in the last back action
2100         if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
2101             //Communicate the user that the next time the application will be closed
2102             this.mExitBackTimeout = System.currentTimeMillis();
2103             DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
2104             return true;
2105         }
2106
2107         //Back action not applied
2108         return !this.mExitFlag;
2109     }
2110
2111     @Override
2112     public void startActivity(Intent intent) {
2113         // check if search intent
2114         if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
2115             intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
2116                     getCurrentNavigationView().getCurrentDir());
2117         }
2118
2119         super.startActivity(intent);
2120     }
2121
2122     /**
2123      * Method that returns the history size.
2124      */
2125     private void clearHistory() {
2126         this.mHistory.clear();
2127         mDrawerHistory.removeAllViews();
2128         mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2129     }
2130
2131     /**
2132      * Method that navigates to the passed history reference.
2133      *
2134      * @param history The history reference
2135      * @return boolean A problem occurs while navigate
2136      */
2137     public synchronized boolean navigateToHistory(History history) {
2138         try {
2139             //Gets the history
2140             History realHistory = this.mHistory.get(history.getPosition());
2141
2142             //Navigate to item. Check what kind of history is
2143             if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
2144                 //Navigation
2145                 NavigationViewInfoParcelable info =
2146                         (NavigationViewInfoParcelable)realHistory.getItem();
2147                 int viewId = info.getId();
2148                 NavigationView view = getNavigationView(viewId);
2149                 // Selected items must not be restored from on history navigation
2150                 info.setSelectedFiles(view.getSelectedFiles());
2151                 if (!view.onRestoreState(info)) {
2152                     return true;
2153                 }
2154
2155             } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
2156                 //Search (open search with the search results)
2157                 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
2158                 Intent searchIntent = new Intent(this, SearchActivity.class);
2159                 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
2160                 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
2161                 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
2162             } else {
2163                 //The type is unknown
2164                 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
2165             }
2166
2167             //Remove the old history
2168             int cc = realHistory.getPosition();
2169             for (int i = this.mHistory.size() - 1; i >= cc; i--) {
2170                 this.mHistory.remove(i);
2171                 mDrawerHistory.removeViewAt(0);
2172             }
2173
2174             if (mDrawerHistory.getChildCount() == 0) {
2175                 mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2176             }
2177
2178             //Navigate
2179             boolean clearHistory = mHistoryTab.isSelected() && mHistory.size() > 0;
2180             mClearHistory.setVisibility(clearHistory ? View.VISIBLE : View.GONE);
2181             return true;
2182
2183         } catch (Throwable ex) {
2184             if (history != null) {
2185                 Log.e(TAG,
2186                         String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
2187                                 Integer.valueOf(history.getPosition()),
2188                                 history.getItem().getTitle()), ex);
2189             } else {
2190                 Log.e(TAG,
2191                         String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
2192             }
2193             this.mHandler.post(new Runnable() {
2194                 @Override
2195                 public void run() {
2196                     DialogHelper.showToast(
2197                             NavigationActivity.this,
2198                             R.string.msgs_history_unknown, Toast.LENGTH_LONG);
2199                 }
2200             });
2201
2202             //Not change directory
2203             return false;
2204         }
2205     }
2206
2207     /**
2208      * Method that request a back action over the navigation history.
2209      *
2210      * @return boolean If a back action was applied
2211      */
2212     public boolean back() {
2213         // Check that has valid history
2214         while (this.mHistory.size() > 0) {
2215             History h = this.mHistory.get(this.mHistory.size() - 1);
2216             if (h.getItem() instanceof NavigationViewInfoParcelable) {
2217                 // Verify that the path exists
2218                 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
2219
2220                 try {
2221                     FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
2222                     if (info != null) {
2223                         break;
2224                     }
2225                     this.mHistory.remove(this.mHistory.size() - 1);
2226                 } catch (Exception e) {
2227                     ExceptionUtil.translateException(this, e, true, false);
2228                     this.mHistory.remove(this.mHistory.size() - 1);
2229                 }
2230             } else {
2231                 break;
2232             }
2233         }
2234
2235         //Navigate to history
2236         if (this.mHistory.size() > 0) {
2237             return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
2238         }
2239
2240         //Nothing to apply
2241         mClearHistory.setVisibility(View.GONE);
2242         return false;
2243     }
2244
2245     /**
2246      * Method that opens the actions dialog
2247      *
2248      * @param item The path or the {@link FileSystemObject}
2249      * @param global If the menu to display is the one with global actions
2250      */
2251     private void openActionsDialog(Object item, boolean global) {
2252         // Resolve the full path
2253         String path = String.valueOf(item);
2254         if (item instanceof FileSystemObject) {
2255             path = ((FileSystemObject)item).getFullPath();
2256         }
2257
2258         // Prior to show the dialog, refresh the item reference
2259         FileSystemObject fso = null;
2260         try {
2261             fso = CommandHelper.getFileInfo(this, path, false, null);
2262             if (fso == null) {
2263                 throw new NoSuchFileOrDirectory(path);
2264             }
2265
2266         } catch (Exception e) {
2267             // Notify the user
2268             ExceptionUtil.translateException(this, e);
2269
2270             // Remove the object
2271             if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
2272                 // If have a FileSystemObject reference then there is no need to search
2273                 // the path (less resources used)
2274                 if (item instanceof FileSystemObject) {
2275                     getCurrentNavigationView().removeItem((FileSystemObject)item);
2276                 } else {
2277                     getCurrentNavigationView().removeItem((String)item);
2278                 }
2279             }
2280             return;
2281         }
2282
2283         // Show the dialog
2284         ActionsDialog dialog = new ActionsDialog(this, this, fso, global, false);
2285         dialog.setOnRequestRefreshListener(this);
2286         dialog.setOnSelectionListener(getCurrentNavigationView());
2287         dialog.show();
2288     }
2289
2290     /**
2291      * Method that opens the search view.
2292      *
2293      * @hide
2294      */
2295     void openSearch() {
2296         mSearchView.setVisibility(View.VISIBLE);
2297         mSearchView.onActionViewExpanded();
2298         mCustomTitleView.setVisibility(View.GONE);
2299     }
2300
2301     void closeSearch() {
2302         mSearchView.setVisibility(View.GONE);
2303         mSearchView.onActionViewCollapsed();
2304         mCustomTitleView.setVisibility(View.VISIBLE);
2305     }
2306
2307     /**
2308      * Method that opens the settings activity.
2309      *
2310      * @hide
2311      */
2312     void openSettings() {
2313         Intent settingsIntent = new Intent(NavigationActivity.this,
2314                 SettingsPreferences.class);
2315         startActivityForResult(settingsIntent, INTENT_REQUEST_SETTINGS);
2316     }
2317
2318     /**
2319      * Method that remove the {@link FileSystemObject} from the history
2320      */
2321     private void removeFromHistory(FileSystemObject fso) {
2322         if (this.mHistory != null) {
2323             int cc = this.mHistory.size() - 1;
2324             for (int i = cc; i >= 0 ; i--) {
2325                 History history = this.mHistory.get(i);
2326                 if (history.getItem() instanceof NavigationViewInfoParcelable) {
2327                     String p0 = fso.getFullPath();
2328                     String p1 = ((NavigationViewInfoParcelable) history.getItem()).getCurrentDir();
2329                     if (p0.compareTo(p1) == 0) {
2330                         this.mHistory.remove(i);
2331                         mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2332                         mDrawerHistoryEmpty.setVisibility(
2333                                 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2334                         updateHistoryPositions();
2335                     }
2336                 }
2337             }
2338         }
2339     }
2340
2341     /**
2342      * Update the history positions after one of the history is removed from drawer
2343      */
2344     private void updateHistoryPositions() {
2345         int cc = this.mHistory.size() - 1;
2346         for (int i = 0; i <= cc ; i++) {
2347             History history = this.mHistory.get(i);
2348             history.setPosition(i + 1);
2349         }
2350     }
2351
2352     /**
2353      * Method that ask the user to change the access mode prior to crash.
2354      * @hide
2355      */
2356     void askOrExit() {
2357         //Show a dialog asking the user
2358         AlertDialog dialog =
2359             DialogHelper.createYesNoDialog(
2360                 this,
2361                 R.string.msgs_change_to_prompt_access_mode_title,
2362                 R.string.msgs_change_to_prompt_access_mode_msg,
2363                 new DialogInterface.OnClickListener() {
2364                     @Override
2365                     public void onClick(DialogInterface alertDialog, int which) {
2366                         if (which == DialogInterface.BUTTON_NEGATIVE) {
2367                             // We don't have any console
2368                             // Show exception and exit
2369                             DialogHelper.showToast(
2370                                     NavigationActivity.this,
2371                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2372                             exit();
2373                             return;
2374                         }
2375
2376                         // Ok. Now try to change to prompt mode. Any crash
2377                         // here is a fatal error. We won't have any console to operate.
2378                         try {
2379                             // Change console
2380                             ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
2381
2382                             // Save preferences
2383                             Preferences.savePreference(
2384                                     FileManagerSettings.SETTINGS_ACCESS_MODE,
2385                                     AccessMode.PROMPT, true);
2386
2387                         } catch (Exception e) {
2388                             // Displays an exception and exit
2389                             Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
2390                             DialogHelper.showToast(
2391                                     NavigationActivity.this,
2392                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2393                             exit();
2394                         }
2395                     }
2396                });
2397         DialogHelper.delegateDialogShow(this, dialog);
2398     }
2399
2400     /**
2401      * Method that creates a ChRooted environment, protecting the user to break anything in
2402      * the device
2403      * @hide
2404      */
2405     void createChRooted() {
2406         // If we are in a ChRooted mode, then do nothing
2407         if (this.mChRooted) return;
2408         this.mChRooted = true;
2409
2410         int cc = this.mNavigationViews.length;
2411         for (int i = 0; i < cc; i++) {
2412             this.mNavigationViews[i].createChRooted();
2413         }
2414
2415         // Remove the selection
2416         cc = this.mNavigationViews.length;
2417         for (int i = 0; i < cc; i++) {
2418             getCurrentNavigationView().onDeselectAll();
2419         }
2420
2421         // Remove the history (don't allow to access to previous data)
2422         clearHistory();
2423     }
2424
2425     /**
2426      * Method that exits from a ChRooted
2427      * @hide
2428      */
2429     void exitChRooted() {
2430         // If we aren't in a ChRooted mode, then do nothing
2431         if (!this.mChRooted) return;
2432         this.mChRooted = false;
2433
2434         int cc = this.mNavigationViews.length;
2435         for (int i = 0; i < cc; i++) {
2436             this.mNavigationViews[i].exitChRooted();
2437         }
2438     }
2439
2440     /**
2441      * Method called when a controlled exit is required
2442      * @hide
2443      */
2444     void exit() {
2445         // Recycle the navigation views
2446         int cc = this.mNavigationViews.length;
2447         for (int i = 0; i < cc; i++) {
2448             this.mNavigationViews[i].recycle();
2449         }
2450         try {
2451             FileManagerApplication.destroyBackgroundConsole();
2452         } catch (Throwable ex) {
2453             /**NON BLOCK**/
2454         }
2455         try {
2456             ConsoleBuilder.destroyConsole();
2457         } catch (Throwable ex) {
2458             /**NON BLOCK**/
2459         }
2460         finish();
2461     }
2462
2463     /**
2464      * Method that reconfigures the layout for better fit in portrait and landscape modes
2465      */
2466     private void onLayoutChanged() {
2467         Theme theme = ThemeManager.getCurrentTheme(this);
2468         boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2469
2470         // Apply only when the orientation was changed
2471         int orientation = getResources().getConfiguration().orientation;
2472         if (this.mOrientation == orientation) return;
2473         this.mOrientation = orientation;
2474
2475         // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2476         if (drawerOpen) {
2477             mDrawerLayout.closeDrawer(Gravity.START);
2478         }
2479
2480         if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
2481             // Landscape mode
2482             ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2483             if (statusBar.getParent() != null) {
2484                 ViewGroup parent = (ViewGroup) statusBar.getParent();
2485                 parent.removeView(statusBar);
2486             }
2487
2488             // Calculate the action button size (all the buttons must fit in the title bar)
2489             int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
2490             int abw = this.mActionBar.getChildCount() * bw;
2491             int rbw = 0;
2492             int cc = statusBar.getChildCount();
2493             for (int i = 0; i < cc; i++) {
2494                 View child = statusBar.getChildAt(i);
2495                 if (child instanceof ButtonItem) {
2496                     rbw += bw;
2497                 }
2498             }
2499             // Currently there isn't overflow menu
2500             int w = abw + rbw - bw;
2501
2502             // Add to the new location
2503             ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder);
2504             LinearLayout.LayoutParams params =
2505                     new LinearLayout.LayoutParams(
2506                             w,
2507                             ViewGroup.LayoutParams.MATCH_PARENT);
2508             statusBar.setLayoutParams(params);
2509             newParent.addView(statusBar);
2510
2511             // Apply theme
2512             theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$
2513
2514             // Hide holder
2515             View holder = findViewById(R.id.navigation_statusbar_portrait_holder);
2516             holder.setVisibility(View.GONE);
2517
2518         } else {
2519             // Portrait mode
2520             ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2521             if (statusBar.getParent() != null) {
2522                 ViewGroup parent = (ViewGroup) statusBar.getParent();
2523                 parent.removeView(statusBar);
2524             }
2525
2526             // Add to the new location
2527             ViewGroup newParent = (ViewGroup)findViewById(
2528                     R.id.navigation_statusbar_portrait_holder);
2529             LinearLayout.LayoutParams params =
2530                     new LinearLayout.LayoutParams(
2531                             ViewGroup.LayoutParams.MATCH_PARENT,
2532                             ViewGroup.LayoutParams.MATCH_PARENT);
2533             statusBar.setLayoutParams(params);
2534             newParent.addView(statusBar);
2535
2536             // Apply theme
2537             theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$
2538
2539             // Show holder
2540             newParent.setVisibility(View.VISIBLE);
2541         }
2542
2543         // if drawer was open, imitate reopening
2544         if (drawerOpen) {
2545             mDrawerToggle.onDrawerOpened(mDrawer);
2546         }
2547     }
2548
2549     /**
2550      * Method that removes all the history items that refers to virtual unmounted filesystems
2551      */
2552     private void removeUnmountedHistory() {
2553         int cc = mHistory.size() - 1;
2554         for (int i = cc; i >= 0; i--) {
2555             History history = mHistory.get(i);
2556             if (history.getItem() instanceof NavigationViewInfoParcelable) {
2557                 NavigationViewInfoParcelable navigableInfo =
2558                         ((NavigationViewInfoParcelable) history.getItem());
2559                 VirtualMountPointConsole vc =
2560                         VirtualMountPointConsole.getVirtualConsoleForPath(
2561                                 navigableInfo.getCurrentDir());
2562                 if (vc != null && !vc.isMounted()) {
2563                     mHistory.remove(i);
2564                     mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2565                 }
2566             }
2567         }
2568         mDrawerHistoryEmpty.setVisibility(
2569                 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2570         updateHistoryPositions();
2571     }
2572
2573     /**
2574      * Method that removes all the selection items that refers to virtual unmounted filesystems
2575      */
2576     private void removeUnmountedSelection() {
2577         for (NavigationView view : mNavigationViews) {
2578             view.removeUnmountedSelection();
2579         }
2580         mSelectionBar.setSelection(getNavigationView(mCurrentNavigationView).getSelectedFiles());
2581     }
2582
2583     /**
2584      * Method that applies the current theme to the activity
2585      * @hide
2586      */
2587     void applyTheme() {
2588         int orientation = getResources().getConfiguration().orientation;
2589         Theme theme = ThemeManager.getCurrentTheme(this);
2590         theme.setBaseThemeNoActionBar(this);
2591         applyTabTheme();
2592
2593         // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2594         boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2595         if (drawerOpen) {
2596             mDrawerLayout.closeDrawer(Gravity.START);
2597         }
2598
2599         //- Layout
2600         View v = findViewById(R.id.navigation_layout);
2601         theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2602
2603         //- ActionBar
2604         theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$
2605
2606         // Hackery to theme search view
2607         mSearchView = (SearchView) findViewById(R.id.navigation_search_bar);
2608         int searchPlateId = mSearchView.getContext().getResources()
2609                 .getIdentifier("android:id/search_plate", null, null);
2610         View searchPlate = mSearchView.findViewById(searchPlateId);
2611         if (searchPlate != null) {
2612             int searchTextId = searchPlate.getContext().getResources()
2613                     .getIdentifier("android:id/search_src_text", null, null);
2614             TextView searchText = (TextView) searchPlate.findViewById(searchTextId);
2615             if (searchText != null) {
2616                 searchText.setTextColor(Color.WHITE);
2617                 searchText.setHintTextColor(Color.WHITE);
2618             }
2619
2620             int magId = getResources().getIdentifier("android:id/search_mag_icon", null, null);
2621             ImageView magImage = (ImageView) mSearchView.findViewById(magId);
2622             if (magImage != null) {
2623                 magImage.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
2624             }
2625         }
2626
2627         SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
2628         mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
2629         mSearchView.setIconifiedByDefault(false);
2630
2631         mCustomTitleView = (NavigationCustomTitleView) findViewById(R.id.navigation_title_flipper);
2632         mCustomTitleView.setVisibility(View.VISIBLE);
2633
2634         //- StatusBar
2635         v = findViewById(R.id.navigation_statusbar);
2636         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
2637             theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$
2638         } else {
2639             theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$
2640         }
2641         v = findViewById(R.id.ab_overflow);
2642         theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$
2643         v = findViewById(R.id.ab_actions);
2644         theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$
2645         v = findViewById(R.id.ab_search);
2646         theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$
2647
2648         //- Expanders
2649         v = findViewById(R.id.ab_configuration);
2650         theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$
2651         v = findViewById(R.id.ab_close);
2652         theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$
2653         v = findViewById(R.id.ab_sort_mode);
2654         theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$
2655         v = findViewById(R.id.ab_layout_mode);
2656         theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$
2657         v = findViewById(R.id.ab_view_options);
2658         theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$
2659
2660         //- SelectionBar
2661         v = findViewById(R.id.navigation_selectionbar);
2662         theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$
2663         v = findViewById(R.id.ab_selection_done);
2664         theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$
2665         v = findViewById(R.id.navigation_status_selection_label);
2666         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2667
2668         // - Navigation drawer
2669         v = findViewById(R.id.history_empty);
2670         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2671
2672         for (int i=0; i<mDrawerHistory.getChildCount(); i++) {
2673             View item = mDrawerHistory.getChildAt(i);
2674
2675             v = item.findViewById(R.id.history_item_name);
2676             theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2677             v = item.findViewById(R.id.history_item_directory);
2678             theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2679         }
2680
2681         //- NavigationView
2682         int cc = this.mNavigationViews.length;
2683         for (int i = 0; i < cc; i++) {
2684             getNavigationView(i).applyTheme();
2685         }
2686
2687         // if drawer was open, imitate reopening
2688         if (drawerOpen) {
2689             mDrawerToggle.onDrawerOpened(mDrawer);
2690         }
2691     }
2692
2693     /**
2694      * Method that applies the current theme to the tab host
2695      */
2696     private void applyTabTheme() {
2697         // Apply the theme
2698         Theme theme = ThemeManager.getCurrentTheme(this);
2699
2700         View v = findViewById(R.id.drawer);
2701         theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2702
2703         v = findViewById(R.id.drawer_bookmarks_tab);
2704         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2705         v = findViewById(R.id.drawer_history_tab);
2706         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2707
2708         v = findViewById(R.id.ab_settings);
2709         theme.setImageDrawable(this, (ButtonItem) v, "ab_settings_drawable"); //$NON-NLS-1$
2710         v = findViewById(R.id.ab_clear_history);
2711         theme.setImageDrawable(this, (ButtonItem) v, "ab_delete_drawable"); //$NON-NLS-1$
2712     }
2713
2714 }