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.adapters.SearchResultAdapter.OnRequestMenuListener;
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.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.DefaultLongClickAction;
65 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
66 import com.cyanogenmod.filemanager.preferences.ObjectStringIdentifier;
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.InfoActionPolicy;
73 import com.cyanogenmod.filemanager.ui.policy.IntentsActionPolicy;
74 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
75 import com.cyanogenmod.filemanager.util.CommandHelper;
76 import com.cyanogenmod.filemanager.util.DialogHelper;
77 import com.cyanogenmod.filemanager.util.ExceptionUtil;
78 import com.cyanogenmod.filemanager.util.FileHelper;
79 import com.cyanogenmod.filemanager.util.StorageHelper;
81 import java.io.FileNotFoundException;
82 import java.util.ArrayList;
83 import java.util.List;
86 * An activity for search files and folders.
88 public class SearchActivity extends Activity
89 implements AsyncResultListener, OnItemClickListener,
90 OnItemLongClickListener, OnRequestMenuListener, OnRequestRefreshListener {
92 private static final String TAG = "SearchActivity"; //$NON-NLS-1$
94 private static boolean DEBUG = false;
97 * An {@link Intent} action for restore view information.
99 public static final String ACTION_RESTORE =
100 "com.cyanogenmod.filemanager.activities.SearchActivity#Restore"; //$NON-NLS-1$
103 * Intent extra parameter for search in the selected directory on enter.
105 public static final String EXTRA_SEARCH_DIRECTORY = "extra_search_directory"; //$NON-NLS-1$
108 * Intent extra parameter for pass the restore information.
110 public static final String EXTRA_SEARCH_RESTORE = "extra_search_restore"; //$NON-NLS-1$
113 //Minimum characters to allow query
114 private static final int MIN_CHARS_SEARCH = 3;
116 private final BroadcastReceiver mOnSettingChangeReceiver = new BroadcastReceiver() {
118 public void onReceive(Context context, Intent intent) {
119 if (intent != null &&
120 intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
122 // The settings has changed
123 String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
125 if (SearchActivity.this.mSearchListView.getAdapter() != null &&
127 FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.getId()) == 0 ||
129 FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.getId()) == 0 ||
131 FileManagerSettings.SETTINGS_SORT_SEARCH_RESULTS_MODE.getId()) == 0)) {
133 // Recreate the adapter
134 int pos = SearchActivity.this.mSearchListView.getFirstVisiblePosition();
136 SearchActivity.this.mSearchListView.setSelection(pos);
140 // Default long-click action
141 if (key.compareTo(FileManagerSettings.
142 SETTINGS_DEFAULT_LONG_CLICK_ACTION.getId()) == 0) {
143 String defaultValue = ((ObjectStringIdentifier)FileManagerSettings.
144 SETTINGS_DEFAULT_LONG_CLICK_ACTION.getDefaultValue()).getId();
145 String id = FileManagerSettings.SETTINGS_DEFAULT_LONG_CLICK_ACTION.getId();
147 Preferences.getSharedPreferences().getString(id, defaultValue);
148 SearchActivity.this.mDefaultLongClickAction =
149 DefaultLongClickAction.fromId(value);
151 // Register the long-click listener only if needed
152 if (SearchActivity.this.mDefaultLongClickAction.compareTo(
153 DefaultLongClickAction.NONE) != 0) {
155 mSearchListView.setOnItemLongClickListener(SearchActivity.this);
157 SearchActivity.this.mSearchListView.setOnItemLongClickListener(null);
169 MessageProgressDialog mDialog = null;
173 AsyncResultExecutable mExecutable = null;
178 ListView mSearchListView;
182 ProgressBar mSearchWaiting;
186 TextView mSearchFoundItems;
190 TextView mSearchTerms;
191 private View mEmptyListMsg;
195 DefaultLongClickAction mDefaultLongClickAction;
197 private String mSearchDirectory;
201 List<FileSystemObject> mResultList;
210 SearchInfoParcelable mRestoreState;
212 private SearchResultDrawingAsyncTask mDrawingSearchResultTask;
224 protected void onCreate(Bundle state) {
226 Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
229 // Check if app is running in chrooted mode
230 this.mChRooted = !FileManagerApplication.isAdvancedMode();
232 // Default long-click action
233 String defaultValue = ((ObjectStringIdentifier)FileManagerSettings.
234 SETTINGS_DEFAULT_LONG_CLICK_ACTION.getDefaultValue()).getId();
235 String value = Preferences.getSharedPreferences().getString(
236 FileManagerSettings.SETTINGS_DEFAULT_LONG_CLICK_ACTION.getId(),
238 DefaultLongClickAction mode = DefaultLongClickAction.fromId(value);
239 this.mDefaultLongClickAction = mode;
241 // Register the broadcast receiver
242 IntentFilter filter = new IntentFilter();
243 filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
244 registerReceiver(this.mOnSettingChangeReceiver, filter);
247 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
249 overridePendingTransition(R.anim.translate_to_right_in, R.anim.hold_out);
251 //Set the main layout of the activity
252 setContentView(R.layout.search);
259 //Initialize action bars and search
260 initTitleActionBar();
262 if (this.mRestoreState != null) {
263 //Restore activity from cached data
267 if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
269 } else if (ACTION_RESTORE.equals(getIntent().getAction())) {
270 restoreState(getIntent().getExtras());
276 super.onCreate(state);
283 protected void onNewIntent(Intent intent) {
285 if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
294 protected void onPause() {
296 overridePendingTransition(R.anim.hold_in, R.anim.translate_to_left_out);
304 protected void onDestroy() {
307 unregisterReceiver(this.mOnSettingChangeReceiver);
308 } catch (Throwable ex) {/**NON BLOCK**/}
315 protected void onSaveInstanceState(Bundle outState) {
317 Log.d(TAG, "SearchActivity.onSaveInstanceState"); //$NON-NLS-1$
320 super.onSaveInstanceState(outState);
324 * Method that save the instance of the activity.
326 * @param state The current state of the activity
328 private void saveState(Bundle state) {
330 if (this.mSearchListView.getAdapter() != null) {
331 state.putParcelable(EXTRA_SEARCH_RESTORE, createSearchInfo());
333 } catch (Throwable ex) {
334 Log.w(TAG, "The state can't be saved", ex); //$NON-NLS-1$
339 * Method that restore the instance of the activity.
341 * @param state The previous state of the activity
343 private void restoreState(Bundle state) {
345 if (state.containsKey(EXTRA_SEARCH_RESTORE)) {
346 this.mRestoreState = state.getParcelable(EXTRA_SEARCH_RESTORE);
348 } catch (Throwable ex) {
349 Log.w(TAG, "The state can't be restored", ex); //$NON-NLS-1$
354 * Method that initializes the titlebar of the activity.
356 private void initTitleActionBar() {
357 //Configure the action bar options
358 getActionBar().setBackgroundDrawable(
359 getResources().getDrawable(R.drawable.bg_holo_titlebar));
360 getActionBar().setDisplayOptions(
361 ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
362 getActionBar().setDisplayHomeAsUpEnabled(true);
363 View customTitle = getLayoutInflater().inflate(R.layout.simple_customtitle, null, false);
365 TextView title = (TextView)customTitle.findViewById(R.id.customtitle_title);
366 title.setText(R.string.search);
367 title.setContentDescription(getString(R.string.search));
368 ButtonItem configuration = (ButtonItem)customTitle.findViewById(R.id.ab_button1);
369 configuration.setImageResource(R.drawable.ic_holo_light_config);
370 configuration.setVisibility(View.VISIBLE);
372 getActionBar().setCustomView(customTitle);
376 * Method that initializes the component of the activity.
378 private void initComponents() {
380 this.mEmptyListMsg = findViewById(R.id.search_empty_msg);
382 this.mSearchListView = (ListView)findViewById(R.id.search_listview);
383 this.mSearchListView.setOnItemClickListener(this);
385 // Register the long-click listener only if needed
386 if (this.mDefaultLongClickAction.compareTo(
387 DefaultLongClickAction.NONE) != 0) {
388 this.mSearchListView.setOnItemLongClickListener(this);
392 this.mSearchWaiting = (ProgressBar)findViewById(R.id.search_waiting);
393 this.mSearchFoundItems = (TextView)findViewById(R.id.search_status_found_items);
394 setFoundItems(0, ""); //$NON-NLS-1$
395 this.mSearchTerms = (TextView)findViewById(R.id.search_status_query_terms);
396 this.mSearchTerms.setText(
397 Html.fromHtml(getString(R.string.search_terms, ""))); //$NON-NLS-1$
401 * Method invoked when an action item is clicked.
403 * @param view The button pushed
405 public void onActionBarItemClick(View view) {
406 switch (view.getId()) {
407 case R.id.ab_button1:
409 Intent settings = new Intent(this, SettingsPreferences.class);
411 PreferenceActivity.EXTRA_SHOW_FRAGMENT,
412 SearchPreferenceFragment.class.getName());
413 startActivity(settings);
422 * Method that initializes the titlebar of the activity.
424 private void initSearch() {
425 //Stop any pending action
427 if (SearchActivity.this.mDrawingSearchResultTask != null
428 && SearchActivity.this.mDrawingSearchResultTask.isRunning()) {
429 SearchActivity.this.mDrawingSearchResultTask.cancel(true);
431 } catch (Throwable ex2) {
435 if (SearchActivity.this.mDialog != null) {
436 SearchActivity.this.mDialog.dismiss();
438 } catch (Throwable ex2) {
442 //Recovery the search directory
443 Bundle bundle = getIntent().getBundleExtra(SearchManager.APP_DATA);
444 //If data is not present, use root directory to do the search
445 this.mSearchDirectory = FileHelper.ROOT_DIRECTORY;
446 if (bundle != null) {
447 this.mSearchDirectory =
448 bundle.getString(EXTRA_SEARCH_DIRECTORY, FileHelper.ROOT_DIRECTORY);
451 //Retrieve the query ¿from voice recognizer?
452 boolean voiceQuery = true;
453 List<String> userQueries =
454 getIntent().getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
455 if (userQueries == null || userQueries.size() == 0) {
457 userQueries = new ArrayList<String>();
458 //Recovers and save the last term search in the memory
459 Preferences.setLastSearch(getIntent().getStringExtra(SearchManager.QUERY));
460 userQueries.add(Preferences.getLastSearch());
464 //Filter the queries? Needed if queries come from voice recognition
465 final List<String> filteredUserQueries =
466 (voiceQuery) ? filterQuery(userQueries) : userQueries;
469 this.mQuery = new Query().fillSlots(filteredUserQueries);
470 List<String> queries = this.mQuery.getQueries();
472 //Check if some queries has lower than allowed, in this case
473 //request the user for stop the search
475 int cc = queries.size();
476 for (int i = 0; i < cc; i++) {
477 if (queries.get(i).trim().length() < MIN_CHARS_SEARCH) {
483 askUserBeforeSearch(voiceQuery, this.mQuery, this.mSearchDirectory);
485 doSearch(voiceQuery, this.mQuery, this.mSearchDirectory);
491 * Method that ask the user before do the search.
493 * @param voiceQuery Indicates if the query is from voice recognition
494 * @param query The terms of the search
495 * @param searchDirectory The directory of the search
497 private void askUserBeforeSearch(
498 final boolean voiceQuery, final Query query, final String searchDirectory) {
499 //Show a dialog asking the user
501 DialogHelper.createYesNoDialog(
502 this, R.string.search_few_characters_msg,
503 new DialogInterface.OnClickListener() {
505 public void onClick(DialogInterface alertDialog, int which) {
506 if (which == DialogInterface.BUTTON_NEGATIVE) {
507 doSearch(voiceQuery, query, searchDirectory);
511 //Close search activity
512 back(true, null, false);
519 * Method that do the search.
521 * @param voiceQuery Indicates if the query is from voice recognition
522 * @param query The terms of the search
523 * @param searchDirectory The directory of the search
527 final boolean voiceQuery, final Query query, final String searchDirectory) {
529 // Recovers the user preferences about save suggestions
530 boolean saveSuggestions = Preferences.getSharedPreferences().getBoolean(
531 FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.getId(),
532 ((Boolean)FileManagerSettings.SETTINGS_SAVE_SEARCH_TERMS.
533 getDefaultValue()).booleanValue());
534 if (saveSuggestions) {
535 //Save every query for use as recent suggestions
536 SearchRecentSuggestions suggestions =
537 new SearchRecentSuggestions(this,
538 RecentSearchesContentProvider.AUTHORITY,
539 RecentSearchesContentProvider.MODE);
541 List<String> queries = query.getQueries();
542 int cc = queries.size();
543 for (int i = 0; i < cc; i++) {
544 suggestions.saveRecentQuery(queries.get(i), null);
550 this.mResultList = new ArrayList<FileSystemObject>();
551 SearchResultAdapter adapter =
552 new SearchResultAdapter(this,
553 new ArrayList<SearchResult>(), R.layout.search_item, this.mQuery);
554 adapter.setOnRequestMenuListener(this);
555 this.mSearchListView.setAdapter(adapter);
558 this.mSearchTerms.setText(
559 Html.fromHtml(getString(R.string.search_terms, query.getTerms())));
562 //Now, do the search in background
563 this.mSearchListView.post(new Runnable() {
567 //Retrieve the terms of the search
568 String label = getString(R.string.searching_action_label);
570 //Show a dialog for the progress
571 SearchActivity.this.mDialog =
572 new MessageProgressDialog(
574 R.drawable.ic_holo_light_search,
575 R.string.searching, label, true);
579 // Set the cancel listener
580 SearchActivity.this.mDialog.setOnCancelListener(
581 new MessageProgressDialog.OnCancelListener() {
583 public boolean onCancel() {
584 //User has requested the cancellation of the search
585 //Broadcast the cancellation
586 if (!SearchActivity.this.mExecutable.isCancelled()) {
587 if (SearchActivity.this.mExecutable.cancel()) {
588 ListAdapter listAdapter =
590 this.mSearchListView.getAdapter();
591 if (listAdapter != null) {
592 SearchActivity.this.toggleResults(
593 listAdapter.getCount() > 0, true);
602 SearchActivity.this.mDialog.show();
604 //Execute the query (search are process in background)
605 SearchActivity.this.mExecutable =
606 CommandHelper.findFiles(
609 SearchActivity.this.mQuery,
613 } catch (Throwable ex) {
614 //Remove all elements
616 SearchActivity.this.removeAll();
617 } catch (Throwable ex2) {
621 if (SearchActivity.this.mDialog != null) {
622 SearchActivity.this.mDialog.dismiss();
624 } catch (Throwable ex2) {
628 //Capture the exception
629 Log.e(TAG, "Search failed", ex); //$NON-NLS-1$
630 DialogHelper.showToast(
632 R.string.search_error_msg, Toast.LENGTH_SHORT);
633 SearchActivity.this.mSearchListView.setVisibility(View.GONE);
640 * Method that restore the activity from the cached data.
642 private void loadFromCacheData() {
643 this.mSearchListView.post(new Runnable() {
647 List<SearchResult> list = SearchActivity.this.mRestoreState.getSearchResultList();
648 String directory = SearchActivity.this.mRestoreState.getSearchDirectory();
649 SearchActivity.this.toggleResults(list.size() > 0, true);
650 setFoundItems(list.size(), directory);
653 Query query = SearchActivity.this.mRestoreState.getSearchQuery();
655 TextUtils.join(" | ", //$NON-NLS-1$;
656 query.getQueries().toArray(new String[]{}));
657 if (terms.endsWith(" | ")) { //$NON-NLS-1$;
658 terms = ""; //$NON-NLS-1$;
660 SearchActivity.this.mSearchTerms.setText(
661 Html.fromHtml(getString(R.string.search_terms, terms)));
664 if (SearchActivity.this.mSearchWaiting != null) {
665 SearchActivity.this.mSearchWaiting.setVisibility(View.VISIBLE);
668 //Add list to the listview
669 if (SearchActivity.this.mSearchListView.getAdapter() != null) {
670 ((SearchResultAdapter)SearchActivity.this.
671 mSearchListView.getAdapter()).clear();
673 SearchResultAdapter adapter =
674 new SearchResultAdapter(
675 SearchActivity.this.mSearchListView.getContext(),
677 R.layout.search_item,
679 adapter.setOnRequestMenuListener(SearchActivity.this);
680 SearchActivity.this.mSearchListView.setAdapter(adapter);
681 SearchActivity.this.mSearchListView.setSelection(0);
683 } catch (Throwable ex) {
684 //Capture the exception
685 ExceptionUtil.translateException(SearchActivity.this, ex);
689 if (SearchActivity.this.mSearchWaiting != null) {
690 SearchActivity.this.mSearchWaiting.setVisibility(View.GONE);
699 * Method that filter the user queries for valid queries only.<br/>
701 * Only allow query strings with more that 3 characters
703 * @param original The original user queries
704 * @return List<String> The list of queries filtered
706 @SuppressWarnings("static-method")
707 private List<String> filterQuery(List<String> original) {
708 List<String> dst = new ArrayList<String>(original);
710 for (int i = cc - 1; i >= 0; i--) {
711 String query = dst.get(i);
712 if (query == null || query.trim().length() < MIN_CHARS_SEARCH) {
720 * Method that removes all items and display a message.
724 SearchResultAdapter adapter = (SearchResultAdapter)this.mSearchListView.getAdapter();
726 adapter.notifyDataSetChanged();
727 this.mSearchListView.setSelection(0);
728 toggleResults(false, true);
732 * Method that toggle the views when there are results.
734 * @param hasResults Indicates if there are results
735 * @param showEmpty Show the empty list message
738 void toggleResults(boolean hasResults, boolean showEmpty) {
739 this.mSearchListView.setVisibility(hasResults ? View.VISIBLE : View.INVISIBLE);
740 this.mEmptyListMsg.setVisibility(!hasResults && showEmpty ? View.VISIBLE : View.INVISIBLE);
744 * Method that display the number of found items.
746 * @param items The number of items
747 * @param searchDirectory The search directory path
750 void setFoundItems(final int items, final String searchDirectory) {
751 if (this.mSearchFoundItems != null) {
752 this.mSearchFoundItems.post(new Runnable() {
755 String directory = searchDirectory;
756 if (SearchActivity.this.mChRooted &&
757 directory != null && directory.length() > 0) {
758 directory = StorageHelper.getChrootedPath(directory);
764 R.plurals.search_found_items, items, Integer.valueOf(items));
765 SearchActivity.this.mSearchFoundItems.setText(
767 R.string.search_found_items_in_directory,
779 public boolean onKeyUp(int keyCode, KeyEvent event) {
781 case KeyEvent.KEYCODE_BACK:
782 back(true, null, false);
785 return super.onKeyUp(keyCode, event);
793 public boolean onOptionsItemSelected(MenuItem item) {
794 switch (item.getItemId()) {
795 case android.R.id.home:
796 back(true, null, false);
799 return super.onOptionsItemSelected(item);
807 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
809 SearchResult result = ((SearchResultAdapter)parent.getAdapter()).getItem(position);
810 FileSystemObject fso = result.getFso();
811 if (fso instanceof Directory) {
812 back(false, fso, false);
813 } else if (fso instanceof Symlink) {
814 Symlink symlink = (Symlink)fso;
815 if (symlink.getLinkRef() != null && symlink.getLinkRef() instanceof Directory) {
816 back(false, symlink.getLinkRef(), false);
819 // Open the file with the preferred registered app
820 back(false, fso, false);
822 } catch (Throwable ex) {
823 ExceptionUtil.translateException(this.mSearchListView.getContext(), ex);
831 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
832 // Different actions depending on user preference
834 // Get the adapter, the search result and the fso
835 SearchResultAdapter adapter = ((SearchResultAdapter)parent.getAdapter());
836 SearchResult searchResult = adapter.getItem(position);
837 FileSystemObject fso = searchResult.getFso();
839 // Select/deselect. Not apply here
841 // Show content description
842 if (this.mDefaultLongClickAction.compareTo(
843 DefaultLongClickAction.SHOW_CONTENT_DESCRIPTION) == 0) {
844 InfoActionPolicy.showContentDescription(this, fso);
848 else if (this.mDefaultLongClickAction.compareTo(
849 DefaultLongClickAction.OPEN_WITH) == 0) {
850 IntentsActionPolicy.openFileSystemObject(this, fso, true, null, null);
854 else if (this.mDefaultLongClickAction.compareTo(
855 DefaultLongClickAction.SHOW_PROPERTIES) == 0) {
856 InfoActionPolicy.showPropertiesDialog(this, fso, this);
860 else if (this.mDefaultLongClickAction.compareTo(
861 DefaultLongClickAction.SHOW_ACTIONS) == 0) {
864 return true; //Always consume the event
871 public void onRequestMenu(FileSystemObject item) {
872 // Prior to show the dialog, refresh the item reference
873 FileSystemObject fso = null;
875 fso = CommandHelper.getFileInfo(this, item.getFullPath(), false, null);
877 throw new NoSuchFileOrDirectory(item.getFullPath());
880 } catch (Exception e) {
882 ExceptionUtil.translateException(this, e);
885 if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
891 ActionsDialog dialog = new ActionsDialog(this, fso, false, true);
892 dialog.setOnRequestRefreshListener(this);
897 * Method that removes the {@link FileSystemObject} reference
899 * @param fso The file system object
901 private void removeItem(FileSystemObject fso) {
902 SearchResultAdapter adapter =
903 (SearchResultAdapter)this.mSearchListView.getAdapter();
904 if (adapter != null) {
905 int pos = adapter.getPosition(fso);
907 SearchResult sr = adapter.getItem(pos);
912 toggleResults(adapter.getCount() > 0, true);
913 setFoundItems(adapter.getCount(), this.mSearchDirectory);
921 public void onRequestRefresh(Object o) {
922 // Refresh only the item
923 SearchResultAdapter adapter =
924 (SearchResultAdapter)this.mSearchListView.getAdapter();
925 if (adapter != null) {
926 if (o instanceof FileSystemObject) {
928 FileSystemObject fso = (FileSystemObject)o;
929 int pos = adapter.getPosition(fso);
931 SearchResult sr = adapter.getItem(pos);
934 } else if (o == null) {
936 List<SearchResult> results = adapter.getData();
937 this.mResultList = new ArrayList<FileSystemObject>(results.size());
938 int cc = results.size();
939 for (int i = 0; i < cc; i++) {
940 this.mResultList.add(results.get(i).getFso());
951 public void onRequestRemove(Object o) {
952 if (o instanceof FileSystemObject) {
953 removeItem((FileSystemObject)o);
961 public void onNavigateTo(Object o) {
962 if (o instanceof FileSystemObject) {
963 back(false, (FileSystemObject)o, true);
968 * Method that returns to previous activity.
970 * @param cancelled Indicates if the activity was cancelled
971 * @param item The fso
974 void back(final boolean cancelled, FileSystemObject item, boolean isChecked) {
975 Intent intent = new Intent();
977 if (SearchActivity.this.mDrawingSearchResultTask != null
978 && SearchActivity.this.mDrawingSearchResultTask.isRunning()) {
979 SearchActivity.this.mDrawingSearchResultTask.cancel(true);
981 if (this.mRestoreState != null) {
983 NavigationActivity.EXTRA_SEARCH_LAST_SEARCH_DATA,
984 (Parcelable)this.mRestoreState);
986 setResult(RESULT_CANCELED, intent);
988 // Check that the bookmark exists
990 FileSystemObject fso = item;
992 fso = CommandHelper.getFileInfo(this, item.getFullPath(), null);
995 if (FileHelper.isDirectory(fso)) {
996 intent.putExtra(NavigationActivity.EXTRA_SEARCH_ENTRY_SELECTION, fso);
998 NavigationActivity.EXTRA_SEARCH_LAST_SEARCH_DATA,
999 (Parcelable)createSearchInfo());
1000 setResult(RESULT_OK, intent);
1002 // Open the file here, so when focus back to the app, the search activity
1003 // its in top of the stack
1004 IntentsActionPolicy.openFileSystemObject(this, fso, false, null, null);
1008 // The fso not exists, delete the fso from the search
1011 } catch (Exception ex) {/**NON BLOCK**/}
1014 } catch (Exception e) {
1015 // Capture the exception
1016 ExceptionUtil.translateException(this, e);
1017 if (e instanceof NoSuchFileOrDirectory || e instanceof FileNotFoundException) {
1018 // The fso not exists, delete the fso from the search
1021 } catch (Exception ex) {/**NON BLOCK**/}
1033 public void onAsyncStart() {
1034 runOnUiThread(new Runnable() {
1037 SearchActivity.this.toggleResults(false, false);
1046 public void onAsyncEnd(boolean cancelled) {
1047 this.mSearchListView.post(new Runnable() {
1051 //Dismiss the dialog
1052 if (SearchActivity.this.mDialog != null) {
1053 SearchActivity.this.mDialog.dismiss();
1056 // Resolve the symlinks
1057 FileHelper.resolveSymlinks(
1058 SearchActivity.this, SearchActivity.this.mResultList);
1063 } catch (Throwable ex) {
1064 Log.e(TAG, "onAsyncEnd method fails", ex); //$NON-NLS-1$
1074 @SuppressWarnings("unchecked")
1075 public void onPartialResult(final Object partialResults) {
1076 //Saved in the global result list, for save at the end
1077 if (partialResults instanceof FileSystemObject) {
1078 SearchActivity.this.mResultList.add((FileSystemObject)partialResults);
1080 SearchActivity.this.mResultList.addAll((List<FileSystemObject>)partialResults);
1084 this.mSearchListView.post(new Runnable() {
1087 if (SearchActivity.this.mDialog != null) {
1088 int progress = SearchActivity.this.mResultList.size();
1089 setProgressMsg(progress);
1099 public void onAsyncExitCode(int exitCode) {/**NON BLOCK**/}
1105 public void onException(Exception cause) {
1106 //Capture the exception
1107 ExceptionUtil.translateException(this, cause);
1111 * Method that draw the results in the listview
1114 void drawResults() {
1116 this.toggleResults(this.mResultList.size() > 0, true);
1117 setFoundItems(this.mResultList.size(), this.mSearchDirectory);
1119 //Create the task for drawing the data
1120 this.mDrawingSearchResultTask =
1121 new SearchResultDrawingAsyncTask(
1122 this.mSearchListView,
1123 this.mSearchWaiting,
1127 this.mDrawingSearchResultTask.execute();
1131 * Method that creates a {@link SearchInfoParcelable} reference from
1134 * @return SearchInfoParcelable The search info reference
1136 private SearchInfoParcelable createSearchInfo() {
1137 SearchInfoParcelable parcel = new SearchInfoParcelable();
1138 parcel.setSearchDirectory(this.mSearchDirectory);
1139 parcel.setSearchResultList(
1140 ((SearchResultAdapter)this.mSearchListView.getAdapter()).getData());
1141 parcel.setSearchQuery(this.mQuery);
1146 * Method that set the progress of the search
1148 * @param progress The progress
1151 void setProgressMsg(int progress) {
1153 getResources().getQuantityString(
1154 R.plurals.search_found_items,
1156 Integer.valueOf(progress));
1157 SearchActivity.this.mDialog.setProgress(Html.fromHtml(msg));