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.os.Bundle;
30 import android.os.Parcelable;
31 import android.preference.PreferenceActivity;
32 import android.provider.SearchRecentSuggestions;
33 import android.text.Html;
34 import android.text.TextUtils;
35 import android.util.Log;
36 import android.view.KeyEvent;
37 import android.view.MenuItem;
38 import android.view.View;
39 import android.widget.AdapterView;
40 import android.widget.AdapterView.OnItemClickListener;
41 import android.widget.AdapterView.OnItemLongClickListener;
42 import android.widget.ListAdapter;
43 import android.widget.ListView;
44 import android.widget.ProgressBar;
45 import android.widget.TextView;
46 import android.widget.Toast;
48 import com.cyanogenmod.filemanager.FileManagerApplication;
49 import com.cyanogenmod.filemanager.R;
50 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
51 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences.SearchPreferenceFragment;
52 import com.cyanogenmod.filemanager.adapters.SearchResultAdapter;
53 import com.cyanogenmod.filemanager.commands.AsyncResultExecutable;
54 import com.cyanogenmod.filemanager.commands.AsyncResultListener;
55 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
56 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
57 import com.cyanogenmod.filemanager.model.Directory;
58 import com.cyanogenmod.filemanager.model.FileSystemObject;
59 import com.cyanogenmod.filemanager.model.ParentDirectory;
60 import com.cyanogenmod.filemanager.model.Query;
61 import com.cyanogenmod.filemanager.model.SearchResult;
62 import com.cyanogenmod.filemanager.model.Symlink;
63 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
64 import com.cyanogenmod.filemanager.preferences.AccessMode;
65 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
66 import com.cyanogenmod.filemanager.preferences.Preferences;
67 import com.cyanogenmod.filemanager.providers.RecentSearchesContentProvider;
68 import com.cyanogenmod.filemanager.tasks.SearchResultDrawingAsyncTask;
69 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
70 import com.cyanogenmod.filemanager.ui.dialogs.MessageProgressDialog;
71 import com.cyanogenmod.filemanager.ui.policy.DeleteActionPolicy;
72 import com.cyanogenmod.filemanager.ui.policy.IntentsActionPolicy;
73 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
74 import com.cyanogenmod.filemanager.ui.widgets.FlingerListView;
75 import com.cyanogenmod.filemanager.ui.widgets.FlingerListView.OnItemFlingerListener;
76 import com.cyanogenmod.filemanager.ui.widgets.FlingerListView.OnItemFlingerResponder;
77 import com.cyanogenmod.filemanager.util.AndroidHelper;
78 import com.cyanogenmod.filemanager.util.CommandHelper;
79 import com.cyanogenmod.filemanager.util.DialogHelper;
80 import com.cyanogenmod.filemanager.util.ExceptionUtil;
81 import com.cyanogenmod.filemanager.util.FileHelper;
82 import com.cyanogenmod.filemanager.util.StorageHelper;
84 import java.io.FileNotFoundException;
85 import java.util.ArrayList;
86 import java.util.List;
89 * An activity for search files and folders.
91 public class SearchActivity extends Activity
92 implements AsyncResultListener, OnItemClickListener,
93 OnItemLongClickListener, OnRequestRefreshListener {
95 private static final String TAG = "SearchActivity"; //$NON-NLS-1$
97 private static boolean DEBUG = false;
100 * An {@link Intent} action for restore view information.
102 public static final String ACTION_RESTORE =
103 "com.cyanogenmod.filemanager.activities.SearchActivity#Restore"; //$NON-NLS-1$
106 * Intent extra parameter for search in the selected directory on enter.
108 public static final String EXTRA_SEARCH_DIRECTORY = "extra_search_directory"; //$NON-NLS-1$
111 * Intent extra parameter for pass the restore information.
113 public static final String EXTRA_SEARCH_RESTORE = "extra_search_restore"; //$NON-NLS-1$
116 //Minimum characters to allow query
117 private static final int MIN_CHARS_SEARCH = 3;
119 private final BroadcastReceiver mOnSettingChangeReceiver = new BroadcastReceiver() {
121 public void onReceive(Context context, Intent intent) {
122 if (intent != null &&
123 intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
125 // The settings has changed
126 String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
128 if (SearchActivity.this.mSearchListView.getAdapter() != null &&
130 FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.getId()) == 0 ||
132 FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.getId()) == 0 ||
134 FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.getId()) == 0)) {
136 // Recreate the adapter
137 int pos = SearchActivity.this.mSearchListView.getFirstVisiblePosition();
139 SearchActivity.this.mSearchListView.setSelection(pos);
148 * A listener for flinging events from {@link FlingerListView}
150 private final OnItemFlingerListener mOnItemFlingerListener = new OnItemFlingerListener() {
153 public boolean onItemFlingerStart(
154 AdapterView<?> parent, View view, int position, long id) {
156 // Response if the item can be removed
157 SearchResultAdapter adapter = (SearchResultAdapter)parent.getAdapter();
158 SearchResult result = adapter.getItem(position);
159 if (result != null && result.getFso() != null) {
160 if (result.getFso() instanceof ParentDirectory) {
161 // This is not possible ...
166 } catch (Exception e) {
167 ExceptionUtil.translateException(SearchActivity.this, e, true, false);
173 public void onItemFlingerEnd(OnItemFlingerResponder responder,
174 AdapterView<?> parent, View view, int position, long id) {
177 // Response if the item can be removed
178 SearchResultAdapter adapter = (SearchResultAdapter)parent.getAdapter();
179 SearchResult result = adapter.getItem(position);
180 if (result != null && result.getFso() != null) {
181 DeleteActionPolicy.removeFileSystemObject(
190 // Cancels the flinger operation
193 } catch (Exception e) {
194 ExceptionUtil.translateException(SearchActivity.this, e, true, false);
203 MessageProgressDialog mDialog = null;
207 AsyncResultExecutable mExecutable = null;
212 ListView mSearchListView;
216 ProgressBar mSearchWaiting;
220 TextView mSearchFoundItems;
224 TextView mSearchTerms;
225 private View mEmptyListMsg;
227 private String mSearchDirectory;
231 List<FileSystemObject> mResultList;
240 SearchInfoParcelable mRestoreState;
242 private SearchResultDrawingAsyncTask mDrawingSearchResultTask;
254 protected void onCreate(Bundle state) {
256 Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
259 // Check if app is running in chrooted mode
260 this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
262 // Register the broadcast receiver
263 IntentFilter filter = new IntentFilter();
264 filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
265 registerReceiver(this.mOnSettingChangeReceiver, filter);
268 if (!AndroidHelper.isTablet(this)) {
269 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
271 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
275 overridePendingTransition(R.anim.translate_to_right_in, R.anim.hold_out);
277 //Set the main layout of the activity
278 setContentView(R.layout.search);
285 //Initialize action bars and search
286 initTitleActionBar();
288 if (this.mRestoreState != null) {
289 //Restore activity from cached data
293 if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
295 } else if (ACTION_RESTORE.equals(getIntent().getAction())) {
296 restoreState(getIntent().getExtras());
302 super.onCreate(state);
309 protected void onNewIntent(Intent intent) {
311 if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
320 protected void onPause() {
322 overridePendingTransition(R.anim.hold_in, R.anim.translate_to_left_out);
330 protected void onDestroy() {
333 unregisterReceiver(this.mOnSettingChangeReceiver);
334 } catch (Throwable ex) {/**NON BLOCK**/}
341 protected void onSaveInstanceState(Bundle outState) {
343 Log.d(TAG, "SearchActivity.onSaveInstanceState"); //$NON-NLS-1$
346 super.onSaveInstanceState(outState);
350 * Method that save the instance of the activity.
352 * @param state The current state of the activity
354 private void saveState(Bundle state) {
356 if (this.mSearchListView.getAdapter() != null) {
357 state.putParcelable(EXTRA_SEARCH_RESTORE, createSearchInfo());
359 } catch (Throwable ex) {
360 Log.w(TAG, "The state can't be saved", ex); //$NON-NLS-1$
365 * Method that restore the instance of the activity.
367 * @param state The previous state of the activity
369 private void restoreState(Bundle state) {
371 if (state.containsKey(EXTRA_SEARCH_RESTORE)) {
372 this.mRestoreState = state.getParcelable(EXTRA_SEARCH_RESTORE);
374 } catch (Throwable ex) {
375 Log.w(TAG, "The state can't be restored", ex); //$NON-NLS-1$
380 * Method that initializes the titlebar of the activity.
382 private void initTitleActionBar() {
383 //Configure the action bar options
384 getActionBar().setBackgroundDrawable(
385 getResources().getDrawable(R.drawable.bg_holo_titlebar));
386 getActionBar().setDisplayOptions(
387 ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
388 getActionBar().setDisplayHomeAsUpEnabled(true);
389 View customTitle = getLayoutInflater().inflate(R.layout.simple_customtitle, null, false);
391 TextView title = (TextView)customTitle.findViewById(R.id.customtitle_title);
392 title.setText(R.string.search);
393 title.setContentDescription(getString(R.string.search));
394 ButtonItem configuration = (ButtonItem)customTitle.findViewById(R.id.ab_button1);
395 configuration.setImageResource(R.drawable.ic_holo_light_config);
396 configuration.setVisibility(View.VISIBLE);
398 getActionBar().setCustomView(customTitle);
402 * Method that initializes the component of the activity.
404 private void initComponents() {
406 this.mEmptyListMsg = findViewById(R.id.search_empty_msg);
408 this.mSearchListView = (ListView)findViewById(R.id.search_listview);
409 this.mSearchListView.setOnItemClickListener(this);
410 this.mSearchListView.setOnItemLongClickListener(this);
412 // If we should set the listview to response to flinger gesture detection
414 Preferences.getSharedPreferences().getBoolean(
415 FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
416 ((Boolean)FileManagerSettings.
417 SETTINGS_USE_FLINGER.
418 getDefaultValue()).booleanValue());
420 ((FlingerListView)this.mSearchListView).
421 setOnItemFlingerListener(this.mOnItemFlingerListener);
425 this.mSearchWaiting = (ProgressBar)findViewById(R.id.search_waiting);
426 this.mSearchFoundItems = (TextView)findViewById(R.id.search_status_found_items);
427 setFoundItems(0, ""); //$NON-NLS-1$
428 this.mSearchTerms = (TextView)findViewById(R.id.search_status_query_terms);
429 this.mSearchTerms.setText(
430 Html.fromHtml(getString(R.string.search_terms, ""))); //$NON-NLS-1$
434 * Method invoked when an action item is clicked.
436 * @param view The button pushed
438 public void onActionBarItemClick(View view) {
439 switch (view.getId()) {
440 case R.id.ab_button1:
442 Intent settings = new Intent(this, SettingsPreferences.class);
444 PreferenceActivity.EXTRA_SHOW_FRAGMENT,
445 SearchPreferenceFragment.class.getName());
446 startActivity(settings);
455 * Method that initializes the titlebar of the activity.
457 private void initSearch() {
458 //Stop any pending action
460 if (SearchActivity.this.mDrawingSearchResultTask != null
461 && SearchActivity.this.mDrawingSearchResultTask.isRunning()) {
462 SearchActivity.this.mDrawingSearchResultTask.cancel(true);
464 } catch (Throwable ex2) {
468 if (SearchActivity.this.mDialog != null) {
469 SearchActivity.this.mDialog.dismiss();
471 } catch (Throwable ex2) {
475 //Recovery the search directory
476 Bundle bundle = getIntent().getBundleExtra(SearchManager.APP_DATA);
477 //If data is not present, use root directory to do the search
478 this.mSearchDirectory = FileHelper.ROOT_DIRECTORY;
479 if (bundle != null) {
480 this.mSearchDirectory =
481 bundle.getString(EXTRA_SEARCH_DIRECTORY, FileHelper.ROOT_DIRECTORY);
484 //Retrieve the query ¿from voice recognizer?
485 boolean voiceQuery = true;
486 List<String> userQueries =
487 getIntent().getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
488 if (userQueries == null || userQueries.size() == 0) {
490 userQueries = new ArrayList<String>();
491 //Recovers and save the last term search in the memory
492 Preferences.setLastSearch(getIntent().getStringExtra(SearchManager.QUERY));
493 userQueries.add(Preferences.getLastSearch());
497 //Filter the queries? Needed if queries come from voice recognition
498 final List<String> filteredUserQueries =
499 (voiceQuery) ? filterQuery(userQueries) : userQueries;
502 this.mQuery = new Query().fillSlots(filteredUserQueries);
503 List<String> queries = this.mQuery.getQueries();
505 //Check if some queries has lower than allowed, in this case
506 //request the user for stop the search
508 int cc = queries.size();
509 for (int i = 0; i < cc; i++) {
510 if (queries.get(i).trim().length() < MIN_CHARS_SEARCH) {
516 askUserBeforeSearch(voiceQuery, this.mQuery, this.mSearchDirectory);
518 doSearch(voiceQuery, this.mQuery, this.mSearchDirectory);
524 * Method that ask the user before do the search.
526 * @param voiceQuery Indicates if the query is from voice recognition
527 * @param query The terms of the search
528 * @param searchDirectory The directory of the search
530 private void askUserBeforeSearch(
531 final boolean voiceQuery, final Query query, final String searchDirectory) {
532 //Show a dialog asking the user
534 DialogHelper.createYesNoDialog(
536 R.string.search_few_characters_title,
537 R.string.search_few_characters_msg,
538 new DialogInterface.OnClickListener() {
540 public void onClick(DialogInterface alertDialog, int which) {
541 if (which == DialogInterface.BUTTON_POSITIVE) {
542 doSearch(voiceQuery, query, searchDirectory);
546 //Close search activity
547 back(true, null, false);
554 * Method that do the search.
556 * @param voiceQuery Indicates if the query is from voice recognition
557 * @param query The terms of the search
558 * @param searchDirectory The directory of the search
562 final boolean voiceQuery, final Query query, final String searchDirectory) {
564 // Recovers the user preferences about save suggestions
565 boolean saveSuggestions = Preferences.getSharedPreferences().getBoolean(
566 FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.getId(),
567 ((Boolean)FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.
568 getDefaultValue()).booleanValue());
569 if (saveSuggestions) {
570 //Save every query for use as recent suggestions
571 SearchRecentSuggestions suggestions =
572 new SearchRecentSuggestions(this,
573 RecentSearchesContentProvider.AUTHORITY,
574 RecentSearchesContentProvider.MODE);
576 List<String> queries = query.getQueries();
577 int cc = queries.size();
578 for (int i = 0; i < cc; i++) {
579 suggestions.saveRecentQuery(queries.get(i), null);
585 this.mResultList = new ArrayList<FileSystemObject>();
586 SearchResultAdapter adapter =
587 new SearchResultAdapter(this,
588 new ArrayList<SearchResult>(), R.layout.search_item, this.mQuery);
589 this.mSearchListView.setAdapter(adapter);
592 this.mSearchTerms.setText(
593 Html.fromHtml(getString(R.string.search_terms, query.getTerms())));
595 //Now, do the search in background
596 this.mSearchListView.post(new Runnable() {
600 //Retrieve the terms of the search
601 String label = getString(R.string.searching_action_label);
603 //Show a dialog for the progress
604 SearchActivity.this.mDialog =
605 new MessageProgressDialog(
608 R.string.searching, label, true);
612 // Set the cancel listener
613 SearchActivity.this.mDialog.setOnCancelListener(
614 new MessageProgressDialog.OnCancelListener() {
616 public boolean onCancel() {
617 //User has requested the cancellation of the search
618 //Broadcast the cancellation
619 if (!SearchActivity.this.mExecutable.isCancelled()) {
620 if (SearchActivity.this.mExecutable.cancel()) {
621 ListAdapter listAdapter =
623 this.mSearchListView.getAdapter();
624 if (listAdapter != null) {
625 SearchActivity.this.toggleResults(
626 listAdapter.getCount() > 0, true);
635 SearchActivity.this.mDialog.show();
637 //Execute the query (search are process in background)
638 SearchActivity.this.mExecutable =
639 CommandHelper.findFiles(
642 SearchActivity.this.mQuery,
646 } catch (Throwable ex) {
647 //Remove all elements
649 SearchActivity.this.removeAll();
650 } catch (Throwable ex2) {
654 if (SearchActivity.this.mDialog != null) {
655 SearchActivity.this.mDialog.dismiss();
657 } catch (Throwable ex2) {
661 //Capture the exception
662 Log.e(TAG, "Search failed", ex); //$NON-NLS-1$
663 DialogHelper.showToast(
665 R.string.search_error_msg, Toast.LENGTH_SHORT);
666 SearchActivity.this.mSearchListView.setVisibility(View.GONE);
673 * Method that restore the activity from the cached data.
675 private void loadFromCacheData() {
676 this.mSearchListView.post(new Runnable() {
680 List<SearchResult> list = SearchActivity.this.mRestoreState.getSearchResultList();
681 String directory = SearchActivity.this.mRestoreState.getSearchDirectory();
682 SearchActivity.this.toggleResults(list.size() > 0, true);
683 setFoundItems(list.size(), directory);
686 Query query = SearchActivity.this.mRestoreState.getSearchQuery();
688 TextUtils.join(" | ", //$NON-NLS-1$;
689 query.getQueries().toArray(new String[]{}));
690 if (terms.endsWith(" | ")) { //$NON-NLS-1$;
691 terms = ""; //$NON-NLS-1$;
693 SearchActivity.this.mSearchTerms.setText(
694 Html.fromHtml(getString(R.string.search_terms, terms)));
697 if (SearchActivity.this.mSearchWaiting != null) {
698 SearchActivity.this.mSearchWaiting.setVisibility(View.VISIBLE);
701 //Add list to the listview
702 if (SearchActivity.this.mSearchListView.getAdapter() != null) {
703 ((SearchResultAdapter)SearchActivity.this.
704 mSearchListView.getAdapter()).clear();
706 SearchResultAdapter adapter =
707 new SearchResultAdapter(
708 SearchActivity.this.mSearchListView.getContext(),
710 R.layout.search_item,
712 SearchActivity.this.mSearchListView.setAdapter(adapter);
713 SearchActivity.this.mSearchListView.setSelection(0);
715 } catch (Throwable ex) {
716 //Capture the exception
717 ExceptionUtil.translateException(SearchActivity.this, ex);
721 if (SearchActivity.this.mSearchWaiting != null) {
722 SearchActivity.this.mSearchWaiting.setVisibility(View.GONE);
730 * Method that filter the user queries for valid queries only.<br/>
732 * Only allow query strings with more that 3 characters
734 * @param original The original user queries
735 * @return List<String> The list of queries filtered
737 @SuppressWarnings("static-method")
738 private List<String> filterQuery(List<String> original) {
739 List<String> dst = new ArrayList<String>(original);
741 for (int i = cc - 1; i >= 0; i--) {
742 String query = dst.get(i);
743 if (query == null || query.trim().length() < MIN_CHARS_SEARCH) {
751 * Method that removes all items and display a message.
755 SearchResultAdapter adapter = (SearchResultAdapter)this.mSearchListView.getAdapter();
757 adapter.notifyDataSetChanged();
758 this.mSearchListView.setSelection(0);
759 toggleResults(false, true);
763 * Method that toggle the views when there are results.
765 * @param hasResults Indicates if there are results
766 * @param showEmpty Show the empty list message
769 void toggleResults(boolean hasResults, boolean showEmpty) {
770 this.mSearchListView.setVisibility(hasResults ? View.VISIBLE : View.INVISIBLE);
771 this.mEmptyListMsg.setVisibility(!hasResults && showEmpty ? View.VISIBLE : View.INVISIBLE);
775 * Method that display the number of found items.
777 * @param items The number of items
778 * @param searchDirectory The search directory path
781 void setFoundItems(final int items, final String searchDirectory) {
782 if (this.mSearchFoundItems != null) {
783 this.mSearchFoundItems.post(new Runnable() {
786 String directory = searchDirectory;
787 if (SearchActivity.this.mChRooted &&
788 directory != null && directory.length() > 0) {
789 directory = StorageHelper.getChrootedPath(directory);
795 R.plurals.search_found_items, items, Integer.valueOf(items));
796 SearchActivity.this.mSearchFoundItems.setText(
798 R.string.search_found_items_in_directory,
810 public boolean onKeyUp(int keyCode, KeyEvent event) {
812 case KeyEvent.KEYCODE_BACK:
813 back(true, null, false);
816 return super.onKeyUp(keyCode, event);
824 public boolean onOptionsItemSelected(MenuItem item) {
825 switch (item.getItemId()) {
826 case android.R.id.home:
827 back(true, null, false);
830 return super.onOptionsItemSelected(item);
838 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
840 SearchResult result = ((SearchResultAdapter)parent.getAdapter()).getItem(position);
841 FileSystemObject fso = result.getFso();
842 if (fso instanceof Directory) {
843 back(false, fso, false);
844 } else if (fso instanceof Symlink) {
845 Symlink symlink = (Symlink)fso;
846 if (symlink.getLinkRef() != null && symlink.getLinkRef() instanceof Directory) {
847 back(false, symlink.getLinkRef(), false);
850 // Open the file with the preferred registered app
851 back(false, fso, false);
853 } catch (Throwable ex) {
854 ExceptionUtil.translateException(this.mSearchListView.getContext(), ex);
862 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
863 // Different actions depending on user preference
865 // Get the adapter, the search result and the fso
866 SearchResultAdapter adapter = ((SearchResultAdapter)parent.getAdapter());
867 SearchResult searchResult = adapter.getItem(position);
868 FileSystemObject fso = searchResult.getFso();
870 // Open the actions menu
872 return true; //Always consume the event
876 * Method invoked when a request to show the menu associated
877 * with an item is started.
879 * @param item The item for which the request was started
881 public void onRequestMenu(FileSystemObject item) {
882 // Prior to show the dialog, refresh the item reference
883 FileSystemObject fso = null;
885 fso = CommandHelper.getFileInfo(this, item.getFullPath(), false, null);
887 throw new NoSuchFileOrDirectory(item.getFullPath());
890 } catch (Exception e) {
892 ExceptionUtil.translateException(this, e);
895 if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
901 ActionsDialog dialog = new ActionsDialog(this, fso, false, true);
902 dialog.setOnRequestRefreshListener(this);
907 * Method that removes the {@link FileSystemObject} reference
909 * @param fso The file system object
911 private void removeItem(FileSystemObject fso) {
912 SearchResultAdapter adapter =
913 (SearchResultAdapter)this.mSearchListView.getAdapter();
914 if (adapter != null) {
915 int pos = adapter.getPosition(fso);
917 SearchResult sr = adapter.getItem(pos);
922 toggleResults(adapter.getCount() > 0, true);
923 setFoundItems(adapter.getCount(), this.mSearchDirectory);
931 public void onRequestRefresh(Object o) {
932 // Refresh only the item
933 SearchResultAdapter adapter =
934 (SearchResultAdapter)this.mSearchListView.getAdapter();
935 if (adapter != null) {
936 if (o instanceof FileSystemObject) {
938 FileSystemObject fso = (FileSystemObject)o;
939 int pos = adapter.getPosition(fso);
941 SearchResult sr = adapter.getItem(pos);
944 } else if (o == null) {
946 List<SearchResult> results = adapter.getData();
947 this.mResultList = new ArrayList<FileSystemObject>(results.size());
948 int cc = results.size();
949 for (int i = 0; i < cc; i++) {
950 this.mResultList.add(results.get(i).getFso());
961 public void onRequestRemove(Object o) {
962 if (o instanceof FileSystemObject) {
963 removeItem((FileSystemObject)o);
971 public void onNavigateTo(Object o) {
972 if (o instanceof FileSystemObject) {
973 back(false, (FileSystemObject)o, true);
978 * Method that returns to previous activity.
980 * @param cancelled Indicates if the activity was cancelled
981 * @param item The fso
984 void back(final boolean cancelled, FileSystemObject item, boolean isChecked) {
985 Intent intent = new Intent();
987 if (SearchActivity.this.mDrawingSearchResultTask != null
988 && SearchActivity.this.mDrawingSearchResultTask.isRunning()) {
989 SearchActivity.this.mDrawingSearchResultTask.cancel(true);
991 if (this.mRestoreState != null) {
993 NavigationActivity.EXTRA_SEARCH_LAST_SEARCH_DATA,
994 (Parcelable)this.mRestoreState);
996 setResult(RESULT_CANCELED, intent);
998 // Check that the bookmark exists
1000 FileSystemObject fso = item;
1002 fso = CommandHelper.getFileInfo(this, item.getFullPath(), null);
1005 if (FileHelper.isDirectory(fso)) {
1006 intent.putExtra(NavigationActivity.EXTRA_SEARCH_ENTRY_SELECTION, fso);
1008 NavigationActivity.EXTRA_SEARCH_LAST_SEARCH_DATA,
1009 (Parcelable)createSearchInfo());
1010 setResult(RESULT_OK, intent);
1012 // Open the file here, so when focus back to the app, the search activity
1013 // its in top of the stack
1014 IntentsActionPolicy.openFileSystemObject(this, fso, false, null, null);
1018 // The fso not exists, delete the fso from the search
1021 } catch (Exception ex) {/**NON BLOCK**/}
1024 } catch (Exception e) {
1025 // Capture the exception
1026 ExceptionUtil.translateException(this, e);
1027 if (e instanceof NoSuchFileOrDirectory || e instanceof FileNotFoundException) {
1028 // The fso not exists, delete the fso from the search
1031 } catch (Exception ex) {/**NON BLOCK**/}
1043 public void onAsyncStart() {
1044 runOnUiThread(new Runnable() {
1047 SearchActivity.this.toggleResults(false, false);
1056 public void onAsyncEnd(boolean cancelled) {
1057 this.mSearchListView.post(new Runnable() {
1061 //Dismiss the dialog
1062 if (SearchActivity.this.mDialog != null) {
1063 SearchActivity.this.mDialog.dismiss();
1066 // Resolve the symlinks
1067 FileHelper.resolveSymlinks(
1068 SearchActivity.this, SearchActivity.this.mResultList);
1073 } catch (Throwable ex) {
1074 Log.e(TAG, "onAsyncEnd method fails", ex); //$NON-NLS-1$
1084 @SuppressWarnings("unchecked")
1085 public void onPartialResult(final Object partialResults) {
1086 //Saved in the global result list, for save at the end
1087 if (partialResults instanceof FileSystemObject) {
1088 SearchActivity.this.mResultList.add((FileSystemObject)partialResults);
1090 SearchActivity.this.mResultList.addAll((List<FileSystemObject>)partialResults);
1094 this.mSearchListView.post(new Runnable() {
1097 if (SearchActivity.this.mDialog != null) {
1098 int progress = SearchActivity.this.mResultList.size();
1099 setProgressMsg(progress);
1109 public void onAsyncExitCode(int exitCode) {/**NON BLOCK**/}
1115 public void onException(Exception cause) {
1116 //Capture the exception
1117 ExceptionUtil.translateException(this, cause);
1121 * Method that draw the results in the listview
1124 void drawResults() {
1126 this.toggleResults(this.mResultList.size() > 0, true);
1127 setFoundItems(this.mResultList.size(), this.mSearchDirectory);
1129 //Create the task for drawing the data
1130 this.mDrawingSearchResultTask =
1131 new SearchResultDrawingAsyncTask(
1132 this.mSearchListView,
1133 this.mSearchWaiting,
1136 this.mDrawingSearchResultTask.execute();
1140 * Method that creates a {@link SearchInfoParcelable} reference from
1143 * @return SearchInfoParcelable The search info reference
1145 private SearchInfoParcelable createSearchInfo() {
1146 SearchInfoParcelable parcel = new SearchInfoParcelable();
1147 parcel.setSearchDirectory(this.mSearchDirectory);
1148 parcel.setSearchResultList(
1149 ((SearchResultAdapter)this.mSearchListView.getAdapter()).getData());
1150 parcel.setSearchQuery(this.mQuery);
1155 * Method that set the progress of the search
1157 * @param progress The progress
1160 void setProgressMsg(int progress) {
1162 getResources().getQuantityString(
1163 R.plurals.search_found_items,
1165 Integer.valueOf(progress));
1166 SearchActivity.this.mDialog.setProgress(Html.fromHtml(msg));