/* * Copyright (C) 2012 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cyanogenmod.filemanager.activities; import android.app.ActionBar; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.XmlResourceParser; import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; import android.os.storage.StorageVolume; import android.util.Log; import android.view.KeyEvent; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.android.internal.util.XmlUtils; import com.cyanogenmod.filemanager.FileManagerApplication; import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.adapters.BookmarksAdapter; import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory; import com.cyanogenmod.filemanager.model.Bookmark; import com.cyanogenmod.filemanager.model.Bookmark.BOOKMARK_TYPE; import com.cyanogenmod.filemanager.model.FileSystemObject; import com.cyanogenmod.filemanager.preferences.AccessMode; import com.cyanogenmod.filemanager.preferences.Bookmarks; import com.cyanogenmod.filemanager.preferences.FileManagerSettings; import com.cyanogenmod.filemanager.preferences.Preferences; import com.cyanogenmod.filemanager.ui.ThemeManager; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; import com.cyanogenmod.filemanager.ui.dialogs.InitialDirectoryDialog; import com.cyanogenmod.filemanager.ui.widgets.FlingerListView; import com.cyanogenmod.filemanager.ui.widgets.FlingerListView.OnItemFlingerListener; import com.cyanogenmod.filemanager.ui.widgets.FlingerListView.OnItemFlingerResponder; import com.cyanogenmod.filemanager.util.CommandHelper; import com.cyanogenmod.filemanager.util.DialogHelper; import com.cyanogenmod.filemanager.util.ExceptionUtil; import com.cyanogenmod.filemanager.util.StorageHelper; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; /** * An activity for show bookmarks and links. */ public class BookmarksActivity extends Activity implements OnItemClickListener, OnClickListener { private static final String TAG = "BookmarksActivity"; //$NON-NLS-1$ private static boolean DEBUG = false; /** * A listener for flinging events from {@link FlingerListView} */ private final OnItemFlingerListener mOnItemFlingerListener = new OnItemFlingerListener() { @Override public boolean onItemFlingerStart( AdapterView<?> parent, View view, int position, long id) { try { // Response if the item can be removed BookmarksAdapter adapter = (BookmarksAdapter)parent.getAdapter(); Bookmark bookmark = adapter.getItem(position); if (bookmark != null && bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) { return true; } } catch (Exception e) { ExceptionUtil.translateException(BookmarksActivity.this, e, true, false); } return false; } @Override public void onItemFlingerEnd(OnItemFlingerResponder responder, AdapterView<?> parent, View view, int position, long id) { try { // Response if the item can be removed BookmarksAdapter adapter = (BookmarksAdapter)parent.getAdapter(); Bookmark bookmark = adapter.getItem(position); if (bookmark != null && bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) { boolean result = Bookmarks.removeBookmark(BookmarksActivity.this, bookmark); if (!result) { //Show warning DialogHelper.showToast(BookmarksActivity.this, R.string.msgs_operation_failure, Toast.LENGTH_SHORT); responder.cancel(); return; } responder.accept(); adapter.remove(bookmark); adapter.notifyDataSetChanged(); return; } // Cancels the flinger operation responder.cancel(); } catch (Exception e) { ExceptionUtil.translateException(BookmarksActivity.this, e, true, false); responder.cancel(); } } }; private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent != null) { if (intent.getAction().compareTo(FileManagerSettings.INTENT_THEME_CHANGED) == 0) { applyTheme(); } } } }; // Bookmark list XML tags private static final String TAG_BOOKMARKS = "Bookmarks"; //$NON-NLS-1$ private static final String TAG_BOOKMARK = "bookmark"; //$NON-NLS-1$ /** * @hide */ ListView mBookmarksListView; private boolean mChRooted; /** * {@inheritDoc} */ @Override protected void onCreate(Bundle state) { if (DEBUG) { Log.d(TAG, "BookmarksActivity.onCreate"); //$NON-NLS-1$ } // Register the broadcast receiver IntentFilter filter = new IntentFilter(); filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED); registerReceiver(this.mNotificationReceiver, filter); // Is ChRooted? this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0; //Set in transition overridePendingTransition(R.anim.translate_to_right_in, R.anim.hold_out); //Set the main layout of the activity setContentView(R.layout.bookmarks); //Initialize action bars and data initTitleActionBar(); initBookmarks(); // Apply the theme applyTheme(); //Save state super.onCreate(state); } /** * {@inheritDoc} */ @Override protected void onDestroy() { if (DEBUG) { Log.d(TAG, "BookmarksActivity.onDestroy"); //$NON-NLS-1$ } // Unregister the receiver try { unregisterReceiver(this.mNotificationReceiver); } catch (Throwable ex) { /**NON BLOCK**/ } //All destroy. Continue super.onDestroy(); } /** * {@inheritDoc} */ @Override protected void onPause() { //Set out transition overridePendingTransition(R.anim.hold_in, R.anim.translate_to_left_out); super.onPause(); } /** * {@inheritDoc} */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } /** * Method that initializes the titlebar of the activity. */ private void initTitleActionBar() { //Configure the action bar options getActionBar().setBackgroundDrawable( getResources().getDrawable(R.drawable.bg_holo_titlebar)); getActionBar().setDisplayOptions( ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME); getActionBar().setDisplayHomeAsUpEnabled(true); View customTitle = getLayoutInflater().inflate(R.layout.simple_customtitle, null, false); TextView title = (TextView)customTitle.findViewById(R.id.customtitle_title); title.setText(R.string.bookmarks); title.setContentDescription(getString(R.string.bookmarks)); getActionBar().setCustomView(customTitle); } /** * Method that initializes the titlebar of the activity. */ private void initBookmarks() { this.mBookmarksListView = (ListView)findViewById(R.id.bookmarks_listview); List<Bookmark> bookmarks = new ArrayList<Bookmark>(); BookmarksAdapter adapter = new BookmarksAdapter(this, bookmarks, this); this.mBookmarksListView.setAdapter(adapter); this.mBookmarksListView.setOnItemClickListener(this); // If we should set the listview to response to flinger gesture detection boolean useFlinger = Preferences.getSharedPreferences().getBoolean( FileManagerSettings.SETTINGS_USE_FLINGER.getId(), ((Boolean)FileManagerSettings. SETTINGS_USE_FLINGER. getDefaultValue()).booleanValue()); if (useFlinger) { ((FlingerListView)this.mBookmarksListView). setOnItemFlingerListener(this.mOnItemFlingerListener); } // Reload the data refresh(); } /** * Method that makes the refresh of the data. */ void refresh() { // Retrieve the loading view final View waiting = findViewById(R.id.bookmarks_waiting); final BookmarksAdapter adapter = (BookmarksAdapter)this.mBookmarksListView.getAdapter(); // Load the history in background AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() { Exception mCause; List<Bookmark> mBookmarks; @Override protected Boolean doInBackground(Void... params) { try { this.mBookmarks = loadBookmarks(); return Boolean.TRUE; } catch (Exception e) { this.mCause = e; return Boolean.FALSE; } } @Override protected void onPreExecute() { waiting.setVisibility(View.VISIBLE); adapter.clear(); } @Override protected void onPostExecute(Boolean result) { waiting.setVisibility(View.GONE); if (result.booleanValue()) { adapter.addAll(this.mBookmarks); adapter.notifyDataSetChanged(); BookmarksActivity.this.mBookmarksListView.setSelection(0); } else { if (this.mCause != null) { ExceptionUtil.translateException(BookmarksActivity.this, this.mCause); } } } @Override protected void onCancelled() { waiting.setVisibility(View.GONE); } }; task.execute(); } /** * {@inheritDoc} */ @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: back(true, null); return true; default: return super.onKeyUp(keyCode, event); } } /** * {@inheritDoc} */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: back(true, null); return true; default: return super.onOptionsItemSelected(item); } } /** * {@inheritDoc} */ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Bookmark bookmark = ((BookmarksAdapter)parent.getAdapter()).getItem(position); back(false, bookmark.mPath); } /** * {@inheritDoc} */ @Override public void onClick(View v) { //Retrieve the position final int position = ((Integer)v.getTag()).intValue(); final BookmarksAdapter adapter = (BookmarksAdapter)this.mBookmarksListView.getAdapter(); final Bookmark bookmark = adapter.getItem(position); //Configure home if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) { //Show a dialog for configure initial directory InitialDirectoryDialog dialog = new InitialDirectoryDialog(this); dialog.setOnValueChangedListener(new InitialDirectoryDialog.OnValueChangedListener() { @Override public void onValueChanged(String newInitialDir) { adapter.getItem(position).mPath = newInitialDir; adapter.notifyDataSetChanged(); } }); dialog.show(); return; } //Remove bookmark if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) { boolean result = Bookmarks.removeBookmark(this, bookmark); if (!result) { //Show warning DialogHelper.showToast(this, R.string.msgs_operation_failure, Toast.LENGTH_SHORT); return; } adapter.remove(bookmark); adapter.notifyDataSetChanged(); return; } } /** * Method that returns to previous activity and. * * @param cancelled Indicates if the activity was cancelled * @param path The path of the selected bookmark */ private void back(final boolean cancelled, final String path) { Intent intent = new Intent(); if (cancelled) { setResult(RESULT_CANCELED, intent); } else { // Check that the bookmark exists try { FileSystemObject fso = CommandHelper.getFileInfo(this, path, null); if (fso != null) { intent.putExtra(NavigationActivity.EXTRA_BOOKMARK_SELECTION, fso); setResult(RESULT_OK, intent); } else { // The bookmark not exists, delete the user-defined bookmark try { Bookmark b = Bookmarks.getBookmark(getContentResolver(), path); Bookmarks.removeBookmark(this, b); refresh(); } catch (Exception ex) {/**NON BLOCK**/} } } catch (Exception e) { // Capture the exception ExceptionUtil.translateException(this, e); if (e instanceof NoSuchFileOrDirectory || e instanceof FileNotFoundException) { // The bookmark not exists, delete the user-defined bookmark try { Bookmark b = Bookmarks.getBookmark(getContentResolver(), path); Bookmarks.removeBookmark(this, b); refresh(); } catch (Exception ex) {/**NON BLOCK**/} } return; } } finish(); } /** * Method that loads all kind of bookmarks and join in * an array to be used in the listview adapter. * * @return List<Bookmark> * @hide */ List<Bookmark> loadBookmarks() { // Bookmarks = HOME + FILESYSTEM + SD STORAGES + USER DEFINED // In ChRooted mode = SD STORAGES + USER DEFINED (from SD STORAGES) List<Bookmark> bookmarks = new ArrayList<Bookmark>(); if (!this.mChRooted) { bookmarks.add(loadHomeBookmarks()); bookmarks.addAll(loadFilesystemBookmarks()); } bookmarks.addAll(loadSdStorageBookmarks()); bookmarks.addAll(loadUserBookmarks()); return bookmarks; } /** * Method that loads the home bookmark from the user preference. * * @return Bookmark The bookmark loaded */ private Bookmark loadHomeBookmarks() { String initialDir = Preferences.getSharedPreferences().getString( FileManagerSettings.SETTINGS_INITIAL_DIR.getId(), (String)FileManagerSettings.SETTINGS_INITIAL_DIR.getDefaultValue()); return new Bookmark(BOOKMARK_TYPE.HOME, getString(R.string.bookmarks_home), initialDir); } /** * Method that loads the filesystem bookmarks from the internal xml file. * (defined by this application) * * @return List<Bookmark> The bookmarks loaded */ private List<Bookmark> loadFilesystemBookmarks() { try { //Initialize the bookmarks List<Bookmark> bookmarks = new ArrayList<Bookmark>(); //Read the command list xml file XmlResourceParser parser = getResources().getXml(R.xml.filesystem_bookmarks); try { //Find the root element XmlUtils.beginDocument(parser, TAG_BOOKMARKS); while (true) { XmlUtils.nextElement(parser); String element = parser.getName(); if (element == null) { break; } if (TAG_BOOKMARK.equals(element)) { CharSequence name = null; CharSequence directory = null; try { name = getString(parser.getAttributeResourceValue( R.styleable.Bookmark_name, 0)); } catch (Exception e) {/**NON BLOCK**/} try { directory = getString(parser.getAttributeResourceValue( R.styleable.Bookmark_directory, 0)); } catch (Exception e) {/**NON BLOCK**/} if (directory == null) { directory = parser.getAttributeValue(R.styleable.Bookmark_directory); } if (name != null && directory != null) { bookmarks.add( new Bookmark( BOOKMARK_TYPE.FILESYSTEM, name.toString(), directory.toString())); } } } //Return the bookmarks return bookmarks; } finally { parser.close(); } } catch (Throwable ex) { Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$ } //No data return new ArrayList<Bookmark>(); } /** * Method that loads the secure digital card storage bookmarks from the system. * * @return List<Bookmark> The bookmarks loaded */ private List<Bookmark> loadSdStorageBookmarks() { //Initialize the bookmarks List<Bookmark> bookmarks = new ArrayList<Bookmark>(); try { //Recovery sdcards from storage manager StorageVolume[] volumes = StorageHelper.getStorageVolumes(getApplication()); int cc = volumes.length; for (int i = 0; i < cc ; i++) { if (volumes[i].getPath().toLowerCase().indexOf("usb") != -1) { //$NON-NLS-1$ bookmarks.add( new Bookmark( BOOKMARK_TYPE.USB, StorageHelper.getStorageVolumeDescription( getApplication(), volumes[i]), volumes[i].getPath())); } else { bookmarks.add( new Bookmark( BOOKMARK_TYPE.SDCARD, StorageHelper.getStorageVolumeDescription( getApplication(), volumes[i]), volumes[i].getPath())); } } //Return the bookmarks return bookmarks; } catch (Throwable ex) { Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$ } //No data return new ArrayList<Bookmark>(); } /** * Method that loads the user bookmarks (added by the user). * * @return List<Bookmark> The bookmarks loaded */ private List<Bookmark> loadUserBookmarks() { List<Bookmark> bookmarks = new ArrayList<Bookmark>(); Cursor cursor = Bookmarks.getAllBookmarks(this.getContentResolver()); try { if (cursor != null && cursor.moveToFirst()) { do { Bookmark bm = new Bookmark(cursor); if (this.mChRooted && !StorageHelper.isPathInStorageVolume(bm.mPath)) { continue; } bookmarks.add(bm); } while (cursor.moveToNext()); } } finally { try { if (cursor != null) { cursor.close(); } } catch (Exception e) {/**NON BLOCK**/} } return bookmarks; } /** * Method that applies the current theme to the activity * @hide */ void applyTheme() { Theme theme = ThemeManager.getCurrentTheme(this); theme.setBaseTheme(this, false); //- ActionBar theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$ View v = getActionBar().getCustomView().findViewById(R.id.customtitle_title); theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$ // -View theme.setBackgroundDrawable( this, this.mBookmarksListView, "background_drawable"); //$NON-NLS-1$ if (((BookmarksAdapter)this.mBookmarksListView.getAdapter()) != null) { ((BookmarksAdapter)this.mBookmarksListView.getAdapter()).notifyThemeChanged(); ((BookmarksAdapter)this.mBookmarksListView.getAdapter()).notifyDataSetChanged(); } this.mBookmarksListView.setDivider( theme.getDrawable(this, "horizontal_divider_drawable")); //$NON-NLS-1$ this.mBookmarksListView.invalidate(); } }