2 * Copyright (C) 2012 The CyanogenMod Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.cyanogenmod.filemanager.activities;
19 import android.app.ActionBar;
20 import android.app.Activity;
21 import android.app.AlertDialog;
22 import android.app.SearchManager;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.pm.ActivityInfo;
29 import android.content.res.Configuration;
30 import android.os.Bundle;
31 import android.os.Parcelable;
32 import android.preference.PreferenceActivity;
33 import android.provider.SearchRecentSuggestions;
34 import android.text.Html;
35 import android.text.TextUtils;
36 import android.util.Log;
37 import android.view.KeyEvent;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.widget.AdapterView;
41 import android.widget.AdapterView.OnItemClickListener;
42 import android.widget.AdapterView.OnItemLongClickListener;
43 import android.widget.ListAdapter;
44 import android.widget.ListView;
45 import android.widget.ProgressBar;
46 import android.widget.TextView;
47 import android.widget.Toast;
49 import com.cyanogenmod.filemanager.FileManagerApplication;
50 import com.cyanogenmod.filemanager.R;
51 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
52 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences.SearchPreferenceFragment;
53 import com.cyanogenmod.filemanager.adapters.SearchResultAdapter;
54 import com.cyanogenmod.filemanager.commands.AsyncResultExecutable;
55 import com.cyanogenmod.filemanager.commands.AsyncResultListener;
56 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
57 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
58 import com.cyanogenmod.filemanager.model.Directory;
59 import com.cyanogenmod.filemanager.model.FileSystemObject;
60 import com.cyanogenmod.filemanager.model.ParentDirectory;
61 import com.cyanogenmod.filemanager.model.Query;
62 import com.cyanogenmod.filemanager.model.SearchResult;
63 import com.cyanogenmod.filemanager.model.Symlink;
64 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
65 import com.cyanogenmod.filemanager.preferences.AccessMode;
66 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
67 import com.cyanogenmod.filemanager.preferences.Preferences;
68 import com.cyanogenmod.filemanager.providers.RecentSearchesContentProvider;
69 import com.cyanogenmod.filemanager.tasks.SearchResultDrawingAsyncTask;
70 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
71 import com.cyanogenmod.filemanager.ui.dialogs.MessageProgressDialog;
72 import com.cyanogenmod.filemanager.ui.policy.DeleteActionPolicy;
73 import com.cyanogenmod.filemanager.ui.policy.IntentsActionPolicy;
74 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
75 import com.cyanogenmod.filemanager.ui.widgets.FlingerListView;
76 import com.cyanogenmod.filemanager.ui.widgets.FlingerListView.OnItemFlingerListener;
77 import com.cyanogenmod.filemanager.ui.widgets.FlingerListView.OnItemFlingerResponder;
78 import com.cyanogenmod.filemanager.util.AndroidHelper;
79 import com.cyanogenmod.filemanager.util.CommandHelper;
80 import com.cyanogenmod.filemanager.util.DialogHelper;
81 import com.cyanogenmod.filemanager.util.ExceptionUtil;
82 import com.cyanogenmod.filemanager.util.FileHelper;
83 import com.cyanogenmod.filemanager.util.StorageHelper;
85 import java.io.FileNotFoundException;
86 import java.util.ArrayList;
87 import java.util.List;
90 * An activity for search files and folders.
92 public class SearchActivity extends Activity
93 implements AsyncResultListener, OnItemClickListener,
94 OnItemLongClickListener, OnRequestRefreshListener {
96 private static final String TAG = "SearchActivity"; //$NON-NLS-1$
98 private static boolean DEBUG = false;
101 * An {@link Intent} action for restore view information.
103 public static final String ACTION_RESTORE =
104 "com.cyanogenmod.filemanager.activities.SearchActivity#Restore"; //$NON-NLS-1$
107 * Intent extra parameter for search in the selected directory on enter.
109 public static final String EXTRA_SEARCH_DIRECTORY = "extra_search_directory"; //$NON-NLS-1$
112 * Intent extra parameter for pass the restore information.
114 public static final String EXTRA_SEARCH_RESTORE = "extra_search_restore"; //$NON-NLS-1$
117 //Minimum characters to allow query
118 private static final int MIN_CHARS_SEARCH = 3;
120 private final BroadcastReceiver mOnSettingChangeReceiver = new BroadcastReceiver() {
122 public void onReceive(Context context, Intent intent) {
123 if (intent != null &&
124 intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
126 // The settings has changed
127 String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
129 if (SearchActivity.this.mSearchListView.getAdapter() != null &&
131 FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.getId()) == 0 ||
133 FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.getId()) == 0 ||
135 FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.getId()) == 0)) {
137 // Recreate the adapter
138 int pos = SearchActivity.this.mSearchListView.getFirstVisiblePosition();
140 SearchActivity.this.mSearchListView.setSelection(pos);
149 * A listener for flinging events from {@link FlingerListView}
151 private final OnItemFlingerListener mOnItemFlingerListener = new OnItemFlingerListener() {
154 public boolean onItemFlingerStart(
155 AdapterView<?> parent, View view, int position, long id) {
157 // Response if the item can be removed
158 SearchResultAdapter adapter = (SearchResultAdapter)parent.getAdapter();
159 SearchResult result = adapter.getItem(position);
160 if (result != null && result.getFso() != null) {
161 if (result.getFso() instanceof ParentDirectory) {
162 // This is not possible ...
167 } catch (Exception e) {
168 ExceptionUtil.translateException(SearchActivity.this, e, true, false);
174 public void onItemFlingerEnd(OnItemFlingerResponder responder,
175 AdapterView<?> parent, View view, int position, long id) {
178 // Response if the item can be removed
179 SearchResultAdapter adapter = (SearchResultAdapter)parent.getAdapter();
180 SearchResult result = adapter.getItem(position);
181 if (result != null && result.getFso() != null) {
182 DeleteActionPolicy.removeFileSystemObject(
191 // Cancels the flinger operation
194 } catch (Exception e) {
195 ExceptionUtil.translateException(SearchActivity.this, e, true, false);
204 MessageProgressDialog mDialog = null;
208 AsyncResultExecutable mExecutable = null;
213 ListView mSearchListView;
217 ProgressBar mSearchWaiting;
221 TextView mSearchFoundItems;
225 TextView mSearchTerms;
226 private View mEmptyListMsg;
228 private String mSearchDirectory;
232 List<FileSystemObject> mResultList;
241 SearchInfoParcelable mRestoreState;
243 private SearchResultDrawingAsyncTask mDrawingSearchResultTask;
255 protected void onCreate(Bundle state) {
257 Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
260 // Check if app is running in chrooted mode
261 this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
263 // Register the broadcast receiver
264 IntentFilter filter = new IntentFilter();
265 filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
266 registerReceiver(this.mOnSettingChangeReceiver, filter);
269 overridePendingTransition(R.anim.translate_to_right_in, R.anim.hold_out);
271 //Set the main layout of the activity
272 setContentView(R.layout.search);
279 //Initialize action bars and search
280 initTitleActionBar();
282 if (this.mRestoreState != null) {
283 //Restore activity from cached data
287 if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
289 } else if (ACTION_RESTORE.equals(getIntent().getAction())) {
290 restoreState(getIntent().getExtras());
296 super.onCreate(state);
303 public void onConfigurationChanged(Configuration newConfig) {
304 super.onConfigurationChanged(newConfig);
311 protected void onNewIntent(Intent intent) {
313 if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
322 protected void onPause() {
324 overridePendingTransition(R.anim.hold_in, R.anim.translate_to_left_out);
332 protected void onDestroy() {
335 unregisterReceiver(this.mOnSettingChangeReceiver);
336 } catch (Throwable ex) {/**NON BLOCK**/}
343 protected void onSaveInstanceState(Bundle outState) {
345 Log.d(TAG, "SearchActivity.onSaveInstanceState"); //$NON-NLS-1$
348 super.onSaveInstanceState(outState);
352 * Method that save the instance of the activity.
354 * @param state The current state of the activity
356 private void saveState(Bundle state) {
358 if (this.mSearchListView.getAdapter() != null) {
359 state.putParcelable(EXTRA_SEARCH_RESTORE, createSearchInfo());
361 } catch (Throwable ex) {
362 Log.w(TAG, "The state can't be saved", ex); //$NON-NLS-1$
367 * Method that restore the instance of the activity.
369 * @param state The previous state of the activity
371 private void restoreState(Bundle state) {
373 if (state.containsKey(EXTRA_SEARCH_RESTORE)) {
374 this.mRestoreState = state.getParcelable(EXTRA_SEARCH_RESTORE);
376 } catch (Throwable ex) {
377 Log.w(TAG, "The state can't be restored", ex); //$NON-NLS-1$
382 * Method that initializes the titlebar of the activity.
384 private void initTitleActionBar() {
385 //Configure the action bar options
386 getActionBar().setBackgroundDrawable(
387 getResources().getDrawable(R.drawable.bg_holo_titlebar));
388 getActionBar().setDisplayOptions(
389 ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
390 getActionBar().setDisplayHomeAsUpEnabled(true);
391 View customTitle = getLayoutInflater().inflate(R.layout.simple_customtitle, null, false);
393 TextView title = (TextView)customTitle.findViewById(R.id.customtitle_title);
394 title.setText(R.string.search);
395 title.setContentDescription(getString(R.string.search));
396 ButtonItem configuration = (ButtonItem)customTitle.findViewById(R.id.ab_button1);
397 configuration.setImageResource(R.drawable.ic_holo_light_config);
398 configuration.setVisibility(View.VISIBLE);
400 getActionBar().setCustomView(customTitle);
404 * Method that initializes the component of the activity.
406 private void initComponents() {
408 this.mEmptyListMsg = findViewById(R.id.search_empty_msg);
410 this.mSearchListView = (ListView)findViewById(R.id.search_listview);
411 this.mSearchListView.setOnItemClickListener(this);
412 this.mSearchListView.setOnItemLongClickListener(this);
414 // If we should set the listview to response to flinger gesture detection
416 Preferences.getSharedPreferences().getBoolean(
417 FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
418 ((Boolean)FileManagerSettings.
419 SETTINGS_USE_FLINGER.
420 getDefaultValue()).booleanValue());
422 ((FlingerListView)this.mSearchListView).
423 setOnItemFlingerListener(this.mOnItemFlingerListener);
427 this.mSearchWaiting = (ProgressBar)findViewById(R.id.search_waiting);
428 this.mSearchFoundItems = (TextView)findViewById(R.id.search_status_found_items);
429 setFoundItems(0, ""); //$NON-NLS-1$
430 this.mSearchTerms = (TextView)findViewById(R.id.search_status_query_terms);
431 this.mSearchTerms.setText(
432 Html.fromHtml(getString(R.string.search_terms, ""))); //$NON-NLS-1$
436 * Method invoked when an action item is clicked.
438 * @param view The button pushed
440 public void onActionBarItemClick(View view) {
441 switch (view.getId()) {
442 case R.id.ab_button1:
444 Intent settings = new Intent(this, SettingsPreferences.class);
446 PreferenceActivity.EXTRA_SHOW_FRAGMENT,
447 SearchPreferenceFragment.class.getName());
448 startActivity(settings);
457 * Method that initializes the titlebar of the activity.
459 private void initSearch() {
460 //Stop any pending action
462 if (SearchActivity.this.mDrawingSearchResultTask != null
463 && SearchActivity.this.mDrawingSearchResultTask.isRunning()) {
464 SearchActivity.this.mDrawingSearchResultTask.cancel(true);
466 } catch (Throwable ex2) {
470 if (SearchActivity.this.mDialog != null) {
471 SearchActivity.this.mDialog.dismiss();
473 } catch (Throwable ex2) {
477 //Recovery the search directory
478 Bundle bundle = getIntent().getBundleExtra(SearchManager.APP_DATA);
479 //If data is not present, use root directory to do the search
480 this.mSearchDirectory = FileHelper.ROOT_DIRECTORY;
481 if (bundle != null) {
482 this.mSearchDirectory =
483 bundle.getString(EXTRA_SEARCH_DIRECTORY, FileHelper.ROOT_DIRECTORY);
486 //Retrieve the query ¿from voice recognizer?
487 boolean voiceQuery = true;
488 List<String> userQueries =
489 getIntent().getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
490 if (userQueries == null || userQueries.size() == 0) {
492 userQueries = new ArrayList<String>();
493 //Recovers and save the last term search in the memory
494 Preferences.setLastSearch(getIntent().getStringExtra(SearchManager.QUERY));
495 userQueries.add(Preferences.getLastSearch());
499 //Filter the queries? Needed if queries come from voice recognition
500 final List<String> filteredUserQueries =
501 (voiceQuery) ? filterQuery(userQueries) : userQueries;
504 this.mQuery = new Query().fillSlots(filteredUserQueries);
505 List<String> queries = this.mQuery.getQueries();
507 //Check if some queries has lower than allowed, in this case
508 //request the user for stop the search
510 int cc = queries.size();
511 for (int i = 0; i < cc; i++) {
512 if (queries.get(i).trim().length() < MIN_CHARS_SEARCH) {
518 askUserBeforeSearch(voiceQuery, this.mQuery, this.mSearchDirectory);
520 doSearch(voiceQuery, this.mQuery, this.mSearchDirectory);
526 * Method that ask the user before do the search.
528 * @param voiceQuery Indicates if the query is from voice recognition
529 * @param query The terms of the search
530 * @param searchDirectory The directory of the search
532 private void askUserBeforeSearch(
533 final boolean voiceQuery, final Query query, final String searchDirectory) {
534 //Show a dialog asking the user
536 DialogHelper.createYesNoDialog(
538 R.string.search_few_characters_title,
539 R.string.search_few_characters_msg,
540 new DialogInterface.OnClickListener() {
542 public void onClick(DialogInterface alertDialog, int which) {
543 if (which == DialogInterface.BUTTON_POSITIVE) {
544 doSearch(voiceQuery, query, searchDirectory);
548 //Close search activity
549 back(true, null, false);
556 * Method that do the search.
558 * @param voiceQuery Indicates if the query is from voice recognition
559 * @param query The terms of the search
560 * @param searchDirectory The directory of the search
564 final boolean voiceQuery, final Query query, final String searchDirectory) {
566 // Recovers the user preferences about save suggestions
567 boolean saveSuggestions = Preferences.getSharedPreferences().getBoolean(
568 FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.getId(),
569 ((Boolean)FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.
570 getDefaultValue()).booleanValue());
571 if (saveSuggestions) {
572 //Save every query for use as recent suggestions
573 SearchRecentSuggestions suggestions =
574 new SearchRecentSuggestions(this,
575 RecentSearchesContentProvider.AUTHORITY,
576 RecentSearchesContentProvider.MODE);
578 List<String> queries = query.getQueries();
579 int cc = queries.size();
580 for (int i = 0; i < cc; i++) {
581 suggestions.saveRecentQuery(queries.get(i), null);
587 this.mResultList = new ArrayList<FileSystemObject>();
588 SearchResultAdapter adapter =
589 new SearchResultAdapter(this,
590 new ArrayList<SearchResult>(), R.layout.search_item, this.mQuery);
591 this.mSearchListView.setAdapter(adapter);
594 this.mSearchTerms.setText(
595 Html.fromHtml(getString(R.string.search_terms, query.getTerms())));
597 //Now, do the search in background
598 this.mSearchListView.post(new Runnable() {
602 //Retrieve the terms of the search
603 String label = getString(R.string.searching_action_label);
605 //Show a dialog for the progress
606 SearchActivity.this.mDialog =
607 new MessageProgressDialog(
610 R.string.searching, label, true);
614 // Set the cancel listener
615 SearchActivity.this.mDialog.setOnCancelListener(
616 new MessageProgressDialog.OnCancelListener() {
618 public boolean onCancel() {
619 //User has requested the cancellation of the search
620 //Broadcast the cancellation
621 if (!SearchActivity.this.mExecutable.isCancelled()) {
622 if (SearchActivity.this.mExecutable.cancel()) {
623 ListAdapter listAdapter =
625 this.mSearchListView.getAdapter();
626 if (listAdapter != null) {
627 SearchActivity.this.toggleResults(
628 listAdapter.getCount() > 0, true);
637 SearchActivity.this.mDialog.show();
639 //Execute the query (search are process in background)
640 SearchActivity.this.mExecutable =
641 CommandHelper.findFiles(
644 SearchActivity.this.mQuery,
648 } catch (Throwable ex) {
649 //Remove all elements
651 SearchActivity.this.removeAll();
652 } catch (Throwable ex2) {
656 if (SearchActivity.this.mDialog != null) {
657 SearchActivity.this.mDialog.dismiss();
659 } catch (Throwable ex2) {
663 //Capture the exception
664 Log.e(TAG, "Search failed", ex); //$NON-NLS-1$
665 DialogHelper.showToast(
667 R.string.search_error_msg, Toast.LENGTH_SHORT);
668 SearchActivity.this.mSearchListView.setVisibility(View.GONE);
675 * Method that restore the activity from the cached data.
677 private void loadFromCacheData() {
678 this.mSearchListView.post(new Runnable() {
682 List<SearchResult> list = SearchActivity.this.mRestoreState.getSearchResultList();
683 String directory = SearchActivity.this.mRestoreState.getSearchDirectory();
684 SearchActivity.this.toggleResults(list.size() > 0, true);
685 setFoundItems(list.size(), directory);
688 Query query = SearchActivity.this.mRestoreState.getSearchQuery();
690 TextUtils.join(" | ", //$NON-NLS-1$;
691 query.getQueries().toArray(new String[]{}));
692 if (terms.endsWith(" | ")) { //$NON-NLS-1$;
693 terms = ""; //$NON-NLS-1$;
695 SearchActivity.this.mSearchTerms.setText(
696 Html.fromHtml(getString(R.string.search_terms, terms)));
699 if (SearchActivity.this.mSearchWaiting != null) {
700 SearchActivity.this.mSearchWaiting.setVisibility(View.VISIBLE);
703 //Add list to the listview
704 if (SearchActivity.this.mSearchListView.getAdapter() != null) {
705 ((SearchResultAdapter)SearchActivity.this.
706 mSearchListView.getAdapter()).clear();
708 SearchResultAdapter adapter =
709 new SearchResultAdapter(
710 SearchActivity.this.mSearchListView.getContext(),
712 R.layout.search_item,
714 SearchActivity.this.mSearchListView.setAdapter(adapter);
715 SearchActivity.this.mSearchListView.setSelection(0);
717 } catch (Throwable ex) {
718 //Capture the exception
719 ExceptionUtil.translateException(SearchActivity.this, ex);
723 if (SearchActivity.this.mSearchWaiting != null) {
724 SearchActivity.this.mSearchWaiting.setVisibility(View.GONE);
732 * Method that filter the user queries for valid queries only.<br/>
734 * Only allow query strings with more that 3 characters
736 * @param original The original user queries
737 * @return List<String> The list of queries filtered
739 @SuppressWarnings("static-method")
740 private List<String> filterQuery(List<String> original) {
741 List<String> dst = new ArrayList<String>(original);
743 for (int i = cc - 1; i >= 0; i--) {
744 String query = dst.get(i);
745 if (query == null || query.trim().length() < MIN_CHARS_SEARCH) {
753 * Method that removes all items and display a message.
757 SearchResultAdapter adapter = (SearchResultAdapter)this.mSearchListView.getAdapter();
759 adapter.notifyDataSetChanged();
760 this.mSearchListView.setSelection(0);
761 toggleResults(false, true);
765 * Method that toggle the views when there are results.
767 * @param hasResults Indicates if there are results
768 * @param showEmpty Show the empty list message
771 void toggleResults(boolean hasResults, boolean showEmpty) {
772 this.mSearchListView.setVisibility(hasResults ? View.VISIBLE : View.INVISIBLE);
773 this.mEmptyListMsg.setVisibility(!hasResults && showEmpty ? View.VISIBLE : View.INVISIBLE);
777 * Method that display the number of found items.
779 * @param items The number of items
780 * @param searchDirectory The search directory path
783 void setFoundItems(final int items, final String searchDirectory) {
784 if (this.mSearchFoundItems != null) {
785 this.mSearchFoundItems.post(new Runnable() {
788 String directory = searchDirectory;
789 if (SearchActivity.this.mChRooted &&
790 directory != null && directory.length() > 0) {
791 directory = StorageHelper.getChrootedPath(directory);
797 R.plurals.search_found_items, items, Integer.valueOf(items));
798 SearchActivity.this.mSearchFoundItems.setText(
800 R.string.search_found_items_in_directory,
812 public boolean onKeyUp(int keyCode, KeyEvent event) {
814 case KeyEvent.KEYCODE_BACK:
815 back(true, null, false);
818 return super.onKeyUp(keyCode, event);
826 public boolean onOptionsItemSelected(MenuItem item) {
827 switch (item.getItemId()) {
828 case android.R.id.home:
829 back(true, null, false);
832 return super.onOptionsItemSelected(item);
840 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
842 SearchResult result = ((SearchResultAdapter)parent.getAdapter()).getItem(position);
843 FileSystemObject fso = result.getFso();
844 if (fso instanceof Directory) {
845 back(false, fso, false);
846 } else if (fso instanceof Symlink) {
847 Symlink symlink = (Symlink)fso;
848 if (symlink.getLinkRef() != null && symlink.getLinkRef() instanceof Directory) {
849 back(false, symlink.getLinkRef(), false);
852 // Open the file with the preferred registered app
853 back(false, fso, false);
855 } catch (Throwable ex) {
856 ExceptionUtil.translateException(this.mSearchListView.getContext(), ex);
864 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
865 // Different actions depending on user preference
867 // Get the adapter, the search result and the fso
868 SearchResultAdapter adapter = ((SearchResultAdapter)parent.getAdapter());
869 SearchResult searchResult = adapter.getItem(position);
870 FileSystemObject fso = searchResult.getFso();
872 // Open the actions menu
874 return true; //Always consume the event
878 * Method invoked when a request to show the menu associated
879 * with an item is started.
881 * @param item The item for which the request was started
883 public void onRequestMenu(FileSystemObject item) {
884 // Prior to show the dialog, refresh the item reference
885 FileSystemObject fso = null;
887 fso = CommandHelper.getFileInfo(this, item.getFullPath(), false, null);
889 throw new NoSuchFileOrDirectory(item.getFullPath());
892 } catch (Exception e) {
894 ExceptionUtil.translateException(this, e);
897 if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
903 ActionsDialog dialog = new ActionsDialog(this, fso, false, true);
904 dialog.setOnRequestRefreshListener(this);
909 * Method that removes the {@link FileSystemObject} reference
911 * @param fso The file system object
913 private void removeItem(FileSystemObject fso) {
914 SearchResultAdapter adapter =
915 (SearchResultAdapter)this.mSearchListView.getAdapter();
916 if (adapter != null) {
917 int pos = adapter.getPosition(fso);
919 SearchResult sr = adapter.getItem(pos);
924 toggleResults(adapter.getCount() > 0, true);
925 setFoundItems(adapter.getCount(), this.mSearchDirectory);
933 public void onRequestRefresh(Object o) {
934 // Refresh only the item
935 SearchResultAdapter adapter =
936 (SearchResultAdapter)this.mSearchListView.getAdapter();
937 if (adapter != null) {
938 if (o instanceof FileSystemObject) {
940 FileSystemObject fso = (FileSystemObject)o;
941 int pos = adapter.getPosition(fso);
943 SearchResult sr = adapter.getItem(pos);
946 } else if (o == null) {
948 List<SearchResult> results = adapter.getData();
949 this.mResultList = new ArrayList<FileSystemObject>(results.size());
950 int cc = results.size();
951 for (int i = 0; i < cc; i++) {
952 this.mResultList.add(results.get(i).getFso());
963 public void onRequestRemove(Object o) {
964 if (o instanceof FileSystemObject) {
965 removeItem((FileSystemObject)o);
973 public void onNavigateTo(Object o) {
974 if (o instanceof FileSystemObject) {
975 back(false, (FileSystemObject)o, true);
980 * Method that returns to previous activity.
982 * @param cancelled Indicates if the activity was cancelled
983 * @param item The fso
986 void back(final boolean cancelled, FileSystemObject item, boolean isChecked) {
987 Intent intent = new Intent();
989 if (SearchActivity.this.mDrawingSearchResultTask != null
990 && SearchActivity.this.mDrawingSearchResultTask.isRunning()) {
991 SearchActivity.this.mDrawingSearchResultTask.cancel(true);
993 if (this.mRestoreState != null) {
995 NavigationActivity.EXTRA_SEARCH_LAST_SEARCH_DATA,
996 (Parcelable)this.mRestoreState);
998 setResult(RESULT_CANCELED, intent);
1000 // Check that the bookmark exists
1002 FileSystemObject fso = item;
1004 fso = CommandHelper.getFileInfo(this, item.getFullPath(), null);
1007 if (FileHelper.isDirectory(fso)) {
1008 intent.putExtra(NavigationActivity.EXTRA_SEARCH_ENTRY_SELECTION, fso);
1010 NavigationActivity.EXTRA_SEARCH_LAST_SEARCH_DATA,
1011 (Parcelable)createSearchInfo());
1012 setResult(RESULT_OK, intent);
1014 // Open the file here, so when focus back to the app, the search activity
1015 // its in top of the stack
1016 IntentsActionPolicy.openFileSystemObject(this, fso, false, null, null);
1020 // The fso not exists, delete the fso from the search
1023 } catch (Exception ex) {/**NON BLOCK**/}
1026 } catch (Exception e) {
1027 // Capture the exception
1028 ExceptionUtil.translateException(this, e);
1029 if (e instanceof NoSuchFileOrDirectory || e instanceof FileNotFoundException) {
1030 // The fso not exists, delete the fso from the search
1033 } catch (Exception ex) {/**NON BLOCK**/}
1045 public void onAsyncStart() {
1046 runOnUiThread(new Runnable() {
1049 SearchActivity.this.toggleResults(false, false);
1058 public void onAsyncEnd(boolean cancelled) {
1059 this.mSearchListView.post(new Runnable() {
1063 //Dismiss the dialog
1064 if (SearchActivity.this.mDialog != null) {
1065 SearchActivity.this.mDialog.dismiss();
1068 // Resolve the symlinks
1069 FileHelper.resolveSymlinks(
1070 SearchActivity.this, SearchActivity.this.mResultList);
1075 } catch (Throwable ex) {
1076 Log.e(TAG, "onAsyncEnd method fails", ex); //$NON-NLS-1$
1086 @SuppressWarnings("unchecked")
1087 public void onPartialResult(final Object partialResults) {
1088 //Saved in the global result list, for save at the end
1089 if (partialResults instanceof FileSystemObject) {
1090 SearchActivity.this.mResultList.add((FileSystemObject)partialResults);
1092 SearchActivity.this.mResultList.addAll((List<FileSystemObject>)partialResults);
1096 this.mSearchListView.post(new Runnable() {
1099 if (SearchActivity.this.mDialog != null) {
1100 int progress = SearchActivity.this.mResultList.size();
1101 setProgressMsg(progress);
1111 public void onAsyncExitCode(int exitCode) {/**NON BLOCK**/}
1117 public void onException(Exception cause) {
1118 //Capture the exception
1119 ExceptionUtil.translateException(this, cause);
1123 * Method that draw the results in the listview
1126 void drawResults() {
1128 this.toggleResults(this.mResultList.size() > 0, true);
1129 setFoundItems(this.mResultList.size(), this.mSearchDirectory);
1131 //Create the task for drawing the data
1132 this.mDrawingSearchResultTask =
1133 new SearchResultDrawingAsyncTask(
1134 this.mSearchListView,
1135 this.mSearchWaiting,
1138 this.mDrawingSearchResultTask.execute();
1142 * Method that creates a {@link SearchInfoParcelable} reference from
1145 * @return SearchInfoParcelable The search info reference
1147 private SearchInfoParcelable createSearchInfo() {
1148 SearchInfoParcelable parcel = new SearchInfoParcelable();
1149 parcel.setSearchDirectory(this.mSearchDirectory);
1150 parcel.setSearchResultList(
1151 ((SearchResultAdapter)this.mSearchListView.getAdapter()).getData());
1152 parcel.setSearchQuery(this.mQuery);
1157 * Method that set the progress of the search
1159 * @param progress The progress
1162 void setProgressMsg(int progress) {
1164 getResources().getQuantityString(
1165 R.plurals.search_found_items,
1167 Integer.valueOf(progress));
1168 SearchActivity.this.mDialog.setProgress(Html.fromHtml(msg));