Java tutorial
/* Open Explorer, an open source file explorer & text editor Copyright (C) 2011 Brandon Bowles <brandroid64@gmail.com> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.brandroid.openmanager.fragments; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.Hashtable; import java.util.List; import java.util.Locale; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; import org.brandroid.openmanager.R; import org.brandroid.openmanager.activities.OpenApplication; import org.brandroid.openmanager.activities.OpenExplorer; import org.brandroid.openmanager.activities.ServerSetupActivity; import org.brandroid.openmanager.adapters.ContentAdapter; import org.brandroid.openmanager.adapters.OpenClipboard; import org.brandroid.openmanager.adapters.OpenPathAdapter; import org.brandroid.openmanager.adapters.OpenPathDbAdapter; import org.brandroid.openmanager.data.OpenCursor; import org.brandroid.openmanager.data.OpenDrive; import org.brandroid.openmanager.data.OpenFile; import org.brandroid.openmanager.data.OpenFileRoot; import org.brandroid.openmanager.data.OpenLZMA; import org.brandroid.openmanager.data.OpenLZMA.OpenLZMAEntry; import org.brandroid.openmanager.data.OpenNetworkPath; import org.brandroid.openmanager.data.OpenNetworkPath.Cancellable; import org.brandroid.openmanager.data.OpenNetworkPath.CloudOpsHandler; import org.brandroid.openmanager.data.OpenNetworkPath.CloudProgressListener; import org.brandroid.openmanager.data.OpenPath; import org.brandroid.openmanager.data.OpenPath.ListHandler; import org.brandroid.openmanager.data.OpenPath.OpenContentUpdateListener; import org.brandroid.openmanager.data.OpenPath.OpenPathUpdateHandler; import org.brandroid.openmanager.data.OpenPath.SpaceListener; import org.brandroid.openmanager.data.OpenPath.ThumbnailOverlayInterface; import org.brandroid.openmanager.data.OpenPathArray; import org.brandroid.openmanager.data.OpenPathMerged; import org.brandroid.openmanager.data.OpenRAR; import org.brandroid.openmanager.data.OpenServers; import org.brandroid.openmanager.data.OpenTar; import org.brandroid.openmanager.data.OpenTar.OpenTarEntry; import org.brandroid.openmanager.data.OpenZip; import org.brandroid.openmanager.interfaces.OnAuthTokenListener; import org.brandroid.openmanager.util.EventHandler; import org.brandroid.openmanager.util.EventHandler.CompressionType; import org.brandroid.openmanager.util.EventHandler.EventType; import org.brandroid.openmanager.util.EventHandler.OnWorkerUpdateListener; import org.brandroid.openmanager.util.FileManager; import org.brandroid.openmanager.util.InputDialog; import org.brandroid.openmanager.util.IntentManager; import org.brandroid.openmanager.util.NetworkIOTask; import org.brandroid.openmanager.util.NetworkIOTask.OnTaskUpdateListener; import org.brandroid.openmanager.util.SortType; import org.brandroid.openmanager.util.ThumbnailCreator; import org.brandroid.utils.Logger; import org.brandroid.utils.MenuUtils; import org.brandroid.utils.Preferences; import org.brandroid.utils.Utils; import org.brandroid.utils.ViewUtils; import org.kamranzafar.jtar.TarUtils; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.ResolveInfo; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.net.Uri; import android.os.AsyncTask.Status; import android.os.Build; import android.os.Bundle; import android.os.MessageQueue; import android.support.v4.app.FragmentManager; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnCreateContextMenuListener; import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.GridView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.PopupMenu; import android.widget.PopupMenu.OnMenuItemClickListener; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.actionbarsherlock.internal.view.menu.MenuBuilder; import com.actionbarsherlock.view.ActionMode; import com.actionbarsherlock.view.ActionMode.Callback; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.widget.ShareActionProvider; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.googleapis.json.GoogleJsonResponseException; @SuppressLint("NewApi") public class ContentFragment extends OpenFragment implements OnItemLongClickListener, OnItemClickListener, OnWorkerUpdateListener, OpenPathFragmentInterface, OnTaskUpdateListener, ContentAdapter.SelectionCallback { // private static MultiSelectHandler mMultiSelect; // private LinearLayout mPathView; // private SlidingDrawer mMultiSelectDrawer; // private GridView mMultiSelectView; protected GridView mGrid = null; private TextView mStatus = null; private View mStatusBar = null; // private View mProgressBarLoading = null; // private ArrayList<OpenPath> mData2 = null; //the data that is bound to // our array adapter. private int mListScrollingState = 0; private int mListVisibleStartIndex = 0; private int mListVisibleLength = 0; private int mListScrollY = 0; public static int mGridImageSize = 128; public static int mListImageSize = 36; public Boolean mShowLongDate = false; private boolean isCancelled = false; private int mTopIndex = 0; private OpenPath mTopPath = null; protected OpenPath mPath = null; protected int mMenuContextItemIndex = -1; private boolean mRefreshReady = true; private static String mLoadingMessage = null; public static final SortType.Type[] sortTypes = new SortType.Type[] { SortType.Type.ALPHA, SortType.Type.ALPHA_DESC, SortType.Type.SIZE, SortType.Type.SIZE_DESC, SortType.Type.DATE, SortType.Type.DATE_DESC, SortType.Type.TYPE }; public static final int[] sortMenuOpts = new int[] { R.id.menu_sort_name_asc, R.id.menu_sort_name_desc, R.id.menu_sort_size_asc, R.id.menu_sort_size_desc, R.id.menu_sort_date_asc, R.id.menu_sort_date_desc, R.id.menu_sort_type }; private Bundle mBundle; private NetworkIOTask mTask; private boolean mIsViewCreated; protected Integer mViewMode = null; protected ContentAdapter mContentAdapter; private OnCreateContextMenuListener mConvListOnCreateContextMenuListener; /** * If true, we disable the CAB even if there are selected messages. It's * used in portrait on the tablet when the message view becomes visible and * the message list gets pushed out of the screen, in which case we want to * keep the selection but the CAB should be gone. */ private boolean mDisableCab; /** * {@link ActionMode} shown when 1 or more message is selected. */ private SelectionModeCallback mLastSelectionModeCallback; // private static Hashtable<OpenPath, ContentFragment> instances = new // Hashtable<OpenPath, ContentFragment>(); public ContentFragment() { if (getArguments() != null && getArguments().containsKey("path")) { mPath = (OpenPath) getArguments().getParcelable("path"); // Logger.LogDebug("ContentFragment Restoring to " + mPath); } } // private ContentFragment(OpenPath path) { // mPath = path; // } // // private ContentFragment(OpenPath path, int view) { // mPath = path; // mViewMode = view; // } public static ContentFragment getInstance(OpenPath path, int mode) { return getInstance(path, mode, null); } public static ContentFragment getInstance(OpenPath path, int mode, FragmentManager fm) { ContentFragment ret = null; if (fm != null) try { ret = (ContentFragment) fm.findFragmentByTag(path.getPath()); } catch (NullPointerException e) { } if (ret == null) ret = new ContentFragment(); // if(path instanceof OpenFile) return ret; Bundle args = ret.getArguments(); if (args == null) args = new Bundle(); if (path != null) { // Logger.LogDebug("ContentFragment.getInstance(" + path + // ", mode, " + fm + ")"); args.putParcelable("path", path); ret.setArguments(args); } else return null; // Logger.LogVerbose("ContentFragment.getInstance(" + path.getPath() + // ", " + mode + ")"); return ret; } public static ContentFragment getInstance(OpenPath path) { return getInstance(path, new Bundle()); } public static ContentFragment getInstance(OpenPath path, Bundle args) { ContentFragment ret = new ContentFragment(); if (args == null) args = new Bundle(); args.putParcelable("path", path); ret.setArguments(args); // Logger.LogVerbose("ContentFragment.getInstance(" + path.getPath() + // ")"); return ret; } public static ContentFragment getInstance(Bundle args) { ContentFragment ret = new ContentFragment(); ret.setArguments(args); return ret; } public static void cancelAllTasks() { NetworkIOTask.cancelAllTasks(); } protected ContentAdapter getContentAdapter() { if (mContentAdapter == null) { mContentAdapter = new ContentAdapter(getExplorer(), this, getViewMode(), mPath); mContentAdapter.setShowHiddenFiles( getViewSetting(getPath(), "show", getViewSetting(null, "pref_show", false))); SortType sort = new SortType(getViewSetting(getPath(), "sort", getViewSetting(null, "pref_sorting", SortType.ALPHA.toString()))); if (getViewSetting(getPath(), "ff", (Boolean) null) != null) sort.setFoldersFirst(getViewSetting(getPath(), "ff", true)); else sort.setFoldersFirst(getSetting(null, "pref_sorting_folders", true)); try { mContentAdapter.setSorting(sort); } catch (Exception e) { Logger.LogWarning("Unable to set sorting!", e); } } return mContentAdapter; } public int getViewMode() { if (mViewMode == null) mViewMode = getViewSetting(mPath, "view", getGlobalViewMode()); return mViewMode; } public int getGlobalViewMode() { if (mPath instanceof OpenPathMerged) return OpenExplorer.VIEW_GRID; String pref = getSetting(null, "pref_view", "list"); if (pref.equals("list")) return OpenExplorer.VIEW_LIST; if (pref.equals("grid")) return OpenExplorer.VIEW_GRID; return OpenExplorer.VIEW_LIST; } // @Override public void setListAdapter(ListAdapter adapter) { // super.setListAdapter(adapter); /* * ListView lv = getListView(); if(getViewMode() == * OpenExplorer.VIEW_GRID) { if(lv != null && lv.isShown()) * lv.setVisibility(View.GONE); if(mGrid == null) mGrid = * (GridView)getView().findViewById(R.id.content_grid); * mGrid.setVisibility(View.VISIBLE); mGrid.setAdapter(adapter); * updateGridView(); } else { if(mGrid != null && mGrid.isShown()) * mGrid.setVisibility(View.GONE); lv.setVisibility(View.VISIBLE); * lv.setAdapter(adapter); } */ if (mGrid.getAdapter() == null || !mGrid.getAdapter().equals(adapter)) mGrid.setAdapter(adapter); mGrid.setColumnWidth(getResources().getDimensionPixelSize( getViewMode() == OpenExplorer.VIEW_GRID ? R.dimen.grid_width : R.dimen.list_width)); if (adapter != null && adapter.equals(mContentAdapter)) { // Logger.LogDebug("ContentFragment.setListAdapter updateData()"); mContentAdapter.updateData(); if (mPath != null && mContentAdapter.getCount() == 0 && !isDetached()) { ViewUtils.setText(getView(), getResources().getString(!mPath.isLoaded() ? R.string.s_status_loading : R.string.no_items), android.R.id.empty); ViewUtils.setViewsVisible(getView(), true, android.R.id.empty); } else ViewUtils.setViewsVisible(getView(), false, android.R.id.empty); updateStatus(); } } // @Override public ListAdapter getListAdapter() { return getContentAdapter(); } private void setViewMode(int mode) { mViewMode = mode; setViewSetting(mPath, "view", mode); Logger.LogVerbose("Content View Mode: " + mode); setListAdapter(null); mContentAdapter = null; setListAdapter(getContentAdapter()); mContentAdapter.setViewMode(mode); setListAdapter(mContentAdapter); refreshData(null, false); } // @Override @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGridImageSize = (int) (OpenExplorer.DP_RATIO * OpenExplorer.IMAGE_SIZE_GRID); mListImageSize = (int) (OpenExplorer.DP_RATIO * OpenExplorer.IMAGE_SIZE_LIST); if (savedInstanceState != null) mBundle = savedInstanceState; if (getArguments() != null && getArguments().containsKey("path")) mBundle = getArguments(); if (mBundle != null && mBundle.containsKey("path")) mPath = (OpenPath) mBundle.getParcelable("path"); if (mBundle != null && mBundle.containsKey("view")) mViewMode = mBundle.getInt("view"); else mViewMode = getSetting(mPath, "view", getGlobalViewMode()); if (mLoadingMessage == null) mLoadingMessage = getString(R.string.s_status_loading); // if (mPath == null) // Logger.LogDebug("Creating empty ContentFragment", new Exception( // "Creating empty ContentFragment")); // else // Logger.LogDebug("Creating ContentFragment @ " + mPath); // OpenExplorer.getEventHandler().setOnWorkerThreadFinishedListener(this); } /** * The Fragment's UI is just a list fragment */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.content_layout, container, false); mGrid = (GridView) v.findViewById(R.id.content_grid); mStatus = (TextView) v.findViewById(R.id.content_status); mStatusBar = v.findViewById(R.id.content_status_bar); mIsViewCreated = true; return v; } /** * Called when the activity's onCreate() method has returned. */ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getExplorer().setViewPagerLocked(false); // final ListView lv = getListView(); // lv.setOnItemLongClickListener(this); // lv.setOnItemClickListener(this); // lv.setItemsCanFocus(false); // lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE); mGrid.setOnItemClickListener(this); mGrid.setOnItemLongClickListener(this); // mGrid.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); initListAdapter(); // if (savedInstanceState != null) { // // Fragment doesn't have this method. Call it manually. // restoreInstanceState(savedInstanceState); // } } private void initListAdapter() { setListAdapter(getContentAdapter()); } /* * public synchronized void notifyDataSetChanged() { if(mListAdapter == * null) { mContentAdapter = new ContentAdapter(getActivity(), this, * mViewMode, mPath); if(mGrid != null) mGrid.setAdapter(mContentAdapter); } * //if(!Thread.currentThread().equals(OpenExplorer.UiThread)) // * getActivity().runOnUiThread(new Runnable(){public void * run(){mContentAdapter.updateData();}}); //else * mContentAdapter.updateData(); } */ public synchronized void refreshData() { refreshData(getArguments(), false); } public synchronized void refreshData(Bundle savedInstanceState, boolean allowSkips) { if (!mRefreshReady) { Logger.LogWarning("ContentFragment.refreshData warning: Not ready!"); return; } if (!isVisible()) { // Logger.LogDebug("I'm invisible! " + mPath); // return; } if (isDetached()) { // Logger.LogDebug("I'm detached! " + mPath); return; } if (getContext() == null) { Logger.LogError("RefreshData out of context"); return; } if (savedInstanceState == null && getArguments() != null) savedInstanceState = getArguments(); OpenPath path = mPath; if (path == null) if (savedInstanceState != null && savedInstanceState.containsKey("path")) path = (OpenFile) savedInstanceState.getParcelable("path"); if (path == null) { Logger.LogWarning("ContentFragment.refreshData warning: path is null!"); return; } if (path instanceof OpenFile && !path.canRead()) if (OpenApplication.hasRootAccess(true)) path = new OpenFileRoot(path); // if (DEBUG) // Logger.LogDebug("refreshData running..."); mRefreshReady = false; mContentAdapter = null; final String sPath = path.getPath(); if (path instanceof OpenFile && !sPath.startsWith("/")) { if (sPath.equals("Photos")) path = OpenExplorer.getPhotoParent(); if (sPath.equals("Videos")) path = OpenExplorer.getVideoParent(); if (sPath.equals("Music")) path = OpenExplorer.getMusicParent(); if (sPath.equals("Downloads")) path = OpenExplorer.getDownloadParent(); } /* * if (path instanceof OpenFile && * (((path.getName().equalsIgnoreCase("data") || sPath.indexOf("/data") * > -1) && !sPath * .startsWith(OpenFile.getExternalMemoryDrive(true).getParent * ().getPath())) || sPath.startsWith("/mnt/shell") || * (sPath.indexOf("/emulated/") > -1 && sPath.indexOf("/emulated/0") == * -1) || sPath .startsWith("/system"))) path = new OpenFileRoot(path); */ mPath = path; getContentAdapter(); // if (DEBUG) // Logger.LogDebug("Refreshing Data for " + mPath); SortType sort = SortType.ALPHA; if (getExplorer() != null) { String ds = getExplorer().getSetting(null, "pref_sorting", SortType.ALPHA.toString()); // Logger.LogVerbose("Default Sort String: " + ds); SortType defSort = new SortType(ds); defSort.setFoldersFirst(getExplorer().getSetting(null, "pref_sorting_folders", true)); // Logger.LogVerbose("Default Sort: " + defSort.toString()); sort = new SortType(getViewSetting(path, "sort", defSort.toString())); // Logger.LogVerbose("Path Sort: " + sort.toString()); } try { mContentAdapter.mShowThumbnails = getViewSetting(path, "thumbs", getExplorer() != null ? getExplorer().getSetting(null, "pref_thumbs", true) : true); } catch (NullPointerException npe) { Logger.LogWarning("Null while getting prefs", npe); } mContentAdapter.setSorting(sort); // Logger.LogVerbose("View options for " + sPath + " : " + // (mShowHiddenFiles ? "show" : "hide") + " + " + (mShowThumbnails ? // "thumbs" : "icons") + " + " + mSorting.toString()); // if(path.getClass().equals(OpenCursor.class) && // !OpenExplorer.BEFORE_HONEYCOMB) // mShowThumbnails = true; if (getActivity() != null && getActivity().getWindow() != null) mShowLongDate = getResources().getBoolean(R.bool.show_long_date) && mPath != null; if (path.listFromDb(mContentAdapter.getSorting())) { int loaded = mContentAdapter.getCount(); if (path instanceof OpenNetworkPath) { OpenNetworkPath[] kids = ((OpenNetworkPath) path).getChildren(); mContentAdapter.updateData(kids); loaded = kids.length; } Logger.LogDebug("Loaded " + loaded + " entries from cache"); } runUpdateTask(!allowSkips); mRefreshReady = true; // OpenExplorer.setOnSettingsChangeListener(this); // new FileIOTask().execute(new FileIOCommand(FileIOCommandType.ALL, // path)); // if(mGrid != null && savedInstanceState.containsKey("first")) } public void runUpdateTask() { runUpdateTask(false); } public void runUpdateTask(boolean reconnect) { if (mPath == null) { Logger.LogWarning("ContentFragment.runUpdateTask warning: mPath is null!"); return; } if (mPath instanceof OpenPathUpdateHandler) { mContentAdapter.clearData(); setProgressVisibility(true); final OpenContentUpdateListener updateCallback = new OpenContentUpdateListener() { @Override public void addContentPath(final OpenPath... files) { OpenExplorer.getHandler().post(new Runnable() { public void run() { mContentAdapter.addAll(Arrays.asList(files)); } }); if (OpenPath.AllowDBCache) { new Thread(new Runnable() { public void run() { OpenPathDbAdapter db = OpenPath.getDb(); if (db != null) db.createItem(files); else for (OpenPath kid : files) if (kid != null) kid.addToDb(); OpenPath.closeDb(); } }).start(); } } @Override public void doneUpdating() { getHandler().post(new Runnable() { public void run() { setProgressVisibility(false); notifyDataSetChanged(); ViewUtils.setViewsVisible(getView(), false, android.R.id.empty); } }); } @Override public void onException(final Exception e) { setProgressVisibility(false); if (e instanceof UserRecoverableAuthIOException) { UserRecoverableAuthIOException ue = (UserRecoverableAuthIOException) e; Intent intent = ue.getIntent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); return; } else if (interceptOldToken(e)) return; Logger.LogError("Unable to run Task!", e); getHandler().post(new Runnable() { public void run() { Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show(); } }); } }; final Cancellable mUpdateTask = ((OpenPathUpdateHandler) mPath).list(updateCallback); final Cancellable cancellor = new Cancellable() { public boolean cancel() { updateCallback.doneUpdating(); return mUpdateTask.cancel(); } }; setProgressClickHandler(new View.OnClickListener() { public void onClick(View v) { cancellor.cancel(); } }); return; } else if (mPath instanceof OpenPath.ListHandler) { setProgressVisibility(true); ListHandler lh = (ListHandler) mPath; lh.list(new OpenPath.ListListener() { public void onException(final Exception e) { if (interceptOldToken(e)) return; Logger.LogWarning("Unable to list.", e); try { Toast.makeText(getContext(), "Unable to list. " + e, Toast.LENGTH_LONG).show(); } catch (Exception e2) { } } public void onListReceived(final OpenPath[] list) { setProgressVisibility(false); mContentAdapter.updateData(list); notifyDataSetChanged(); ViewUtils.setViewsVisible(getView(), false, android.R.id.empty); if (OpenPath.AllowDBCache) { new Thread(new Runnable() { public void run() { OpenPathDbAdapter db = OpenPath.getDb(); if (db != null) db.createItem(list); else for (OpenPath kid : list) if (kid != null) kid.addToDb(); OpenPath.closeDb(); } }).start(); } } }); return; } else if (mPath instanceof OpenFile) { mContentAdapter.updateData(((OpenFile) mPath).listFiles()); notifyDataSetChanged(); return; } final String sPath = mPath.getPath(); // NetworkIOTask.cancelTask(sPath); if (mTask != null) mTask.cancel(true); mTask = new NetworkIOTask(this); setProgressVisibility(true); /* * if(reconnect && (mPath instanceof OpenNetworkPath)) * ((OpenNetworkPath)mPath).disconnect(); */ Logger.LogDebug("Running Task for " + sPath); NetworkIOTask.addTask(sPath, mTask); EventHandler.executeNetwork(mTask, mPath); new Thread(new Runnable() { public void run() { try { Thread.sleep(30000); } catch (InterruptedException e) { } if (mTask.getStatus() == Status.RUNNING) mTask.doCancel(false); } }).start(); } private boolean has401occurred = false; private boolean interceptOldToken(Exception e) { if (!(mPath instanceof OpenDrive)) return false; if (!(e instanceof GoogleJsonResponseException)) return false; GoogleJsonResponseException re = (GoogleJsonResponseException) e; if (re.getStatusCode() != 401) return false; if (has401occurred) return false; if (((OpenDrive) mPath).getServer() == null) return false; has401occurred = true; final OpenDrive drive = (OpenDrive) mPath; final GoogleCredential cred = drive.getCredential(); final String refresh = drive.getServer().get("refresh"); if (DEBUG) Logger.LogDebug("Refreshing drive token with [" + refresh + "]"); return ServerSetupActivity.interceptOldToken(e, cred.getAccessToken(), refresh, drive.getServer().getUser(), getExplorer(), new OnAuthTokenListener() { @Override public void onException(Exception e) { Logger.LogWarning("Unable to intercept bad token.", e); } @Override public void onDriveAuthTokenReceived(String account, String token) { if (token.equals("")) { Logger.LogWarning("Refresh token empty! :("); return; } Toast.makeText(getContext(), "Token for " + account + " refreshed! " + token, Toast.LENGTH_SHORT).show(); cred.setAccessToken(token); drive.setCredential(cred); drive.getServer().setPassword(token); ServerSetupActivity.SaveToDefaultServers(OpenServers.getDefaultServers(), getContext()); runUpdateTask(true); } }); } /** * @return true if the content view is created and not destroyed yet. (i.e. * between {@link #onCreateView} and {@link #onDestroyView}. */ private boolean isViewCreated() { // Note that we don't use "getView() != null". This method is used in // updateSelectionMode() // to determine if CAB shold be shown. But because it's called from // onDestroyView(), at // this point the fragment still has views but we want to hide CAB, we // can't use getView() here. return mIsViewCreated; } @Override public boolean onBackPressed() { return false; } // @Override public void onListItemClick(ListView list, View view, int position, long id) { // super.onListItemClick(list, view, position, id); onItemClick(list, view, position, id); } private void untarAll(final OpenPath tar, final OpenPath dest, final String... includes) { if (TarUtils.checkUntar(tar.getPath(), dest.getPath(), includes)) DialogHandler.showConfirmationDialog(getContext(), getResources().getString(R.string.s_msg_file_exists), getResources().getString(R.string.s_title_file_exists), new OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (dialog != null) dialog.dismiss(); getEventHandler().extractSet(tar, dest, getContext(), includes); } }); else getEventHandler().extractSet(tar, dest, getContext(), includes); } private void extractSet(final OpenPath archive, final OpenPath dest, final String... includes) { getEventHandler().extractSet(archive, dest, getContext(), includes); } private void browseArchive(OpenPath archive) { if (archive.getExtension().equalsIgnoreCase("zip")) getExplorer().changePath(new OpenZip((OpenFile) archive)); else if (archive.getMimeType().endsWith("rar")) getExplorer().changePath(new OpenRAR((OpenFile) archive)); else if (archive.getMimeType().contains("7z") || archive.getMimeType().contains("lzma")) getExplorer().changePath(new OpenLZMA((OpenFile) archive)); else getExplorer().changePath(new OpenTar((OpenFile) archive)); } private void extractArchive(OpenPath archive) { if (archive.getMimeType().contains("tar")) untarAll(archive, archive.getParent()); else { OpenPath into = archive.getParent(); if (archive.getMimeType().contains("tar")) into = into.getChild(archive.getName().replace("." + archive.getExtension(), "")); getEventHandler().extractSet(archive, into, getContext()); } } @Override public void onItemClick(final AdapterView<?> list, final View view, final int position, final long id) { OpenPath file = (OpenPath) list.getItemAtPosition(position); Logger.LogInfo("ContentFragment.onItemClick (" + file.getPath() + ")"); if (getActionMode() == null) { if (file instanceof OpenFile && (file.getMimeType().contains("tar") || file.getMimeType().endsWith("rar") || file.getMimeType().endsWith("compressed") || file.getMimeType().contains("bz") || file.getMimeType().contains("gz") || file.getMimeType().endsWith("zip"))) { final OpenPath archive = file; final String prefType = file.getMimeType().replace("application/", "").replace("x-", "") .replace("-compressed", ""); DialogHandler.showExtractDialog(getExplorer(), getString(R.string.s_extract) + " " + prefType, archive, "pref_archives_" + prefType, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { switch (which) { case R.string.s_browse: browseArchive(archive); break; case R.string.s_extract: extractArchive(archive); break; } if (dialog != null) dialog.dismiss(); } }); return; } } if (getActionMode() != null) { if (mLastSelectionModeCallback != null) { toggleSelection(view, file); } else { // Animation anim = Animation. /* * Drawable dIcon = * ((ImageView)view.findViewById(R.id.content_icon * )).getDrawable(); if(dIcon instanceof BitmapDrawable) { * IconAnimationPanel panel = new * IconAnimationPanel(getExplorer()) * .setIcon(((BitmapDrawable)dIcon).getBitmap()) .setStart(new * Point(view.getLeft(), view.getRight())) .setEnd(new * Point(getActivity * ().getWindow().getWindowManager().getDefaultDisplay * ().getWidth() / 2, * getActivity().getWindowManager().getDefaultDisplay * ().getHeight())) .setDuration(500); * ((ViewGroup)getView()).addView(panel); } */ addToMultiSelect(file); ((TextView) view.findViewById(R.id.content_text)).setTextAppearance(list.getContext(), R.style.Text_Large_Highlight); } return; } if (file instanceof OpenNetworkPath && getActionMode() == null) { if (file.isTextFile()) { if (file.length() < Preferences.Pref_Text_Max_Size && getExplorer() != null) getExplorer().editFile(file); else downloadFile((OpenNetworkPath) file); return; } } if ((file.isDirectory() || (file.isArchive() && Preferences.Pref_Zip_Internal) || file.getMimeType().contains("tar")) && getActionMode() == null) { /* * if (mThumbnail != null) { mThumbnail.setCancelThumbnails(true); * mThumbnail = null; } */ // setContentPath(file, true); getExplorer().changePath(file); } else { if (file.requiresThread() && FileManager.hasOpenCache(file.getAbsolutePath())) { // getExplorer().showToast("Still need to handle this."); if (file.isTextFile() && getExplorer().editFile(file)) return; else { showCopyFromNetworkDialog(file); // getEventHandler().copyFile(file, mPath, mContext); } return; } else if (file.isTextFile() && Preferences.Pref_Text_Internal && getExplorer().editFile(file)) return; else if (!IntentManager.startIntent(file, getExplorer(), Preferences.Pref_Intents_Internal)) { getExplorer().showToast(R.string.noApplications); getExplorer().editFile(file); } } } private void addToMultiSelect(final OpenPath file) { getContentAdapter().getSelectedSet().add(file); } private void showCopyFromNetworkDialog(OpenPath source) { // / TODO Implement Copy From Network getExplorer().showToast("Not yet implemented (" + source.getMimeType() + ")"); return; /* * final View view = FolderPickerActivity.createPickerView(mContext); * new DialogBuilder(mContext) .setTitle("Choose a folder to copy " + * source.getName() + " into:") .setView(view) * .setPositiveButton(android.R.string.ok, new OnClickListener() { * public void onClick(DialogInterface dialog, int which) { } }); */ } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); getMenuInflater().inflate(R.menu.context_file, menu); onPrepareOptionsMenu(menu); } @Override public boolean onLongClick(View v) { if (v.equals(mGrid)) { if (v.getTag() != null && v.getTag() instanceof MotionEvent) { MotionEvent lastEvent = (MotionEvent) v.getTag(); int x = (int) Math.floor(lastEvent.getX()); int y = (int) Math.floor(lastEvent.getY()); return createContextMenu(mPath, mGrid, mGrid, 0, x, y); } else return v.showContextMenu(); } return false; } // public boolean onItemLongClick(AdapterView<?> list, final View view, int // pos, long id) { // mMenuContextItemIndex = pos; // //view.setBackgroundResource(R.drawable.selector_blue); // //list.setSelection(pos); // //if(list.showContextMenu()) return true; // // final OpenPath file = // (OpenPath)((BaseAdapter)list.getAdapter()).getItem(pos); // // return createContextMenu(file, list, view, pos); // } public boolean createContextMenu(final OpenPath file, final AdapterView<?> list, final View view, final int pos) { return createContextMenu(file, list, view, pos, 0, 0); } public boolean createContextMenu(final OpenPath file, final AdapterView<?> list, final View view, final int pos, final int xOffset, final int yOffset) { Logger.LogInfo(getClassName() + ".onItemLongClick: " + file); final OpenContextMenuInfo info = new OpenContextMenuInfo(file); if (!OpenExplorer.USE_PRETTY_CONTEXT_MENUS) { if (Build.VERSION.SDK_INT > 10) { final PopupMenu pop = new PopupMenu(view.getContext(), view); pop.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(android.view.MenuItem item) { if (onOptionsItemSelected(item)) { pop.dismiss(); return true; } else if (getExplorer() != null) return getExplorer().onIconContextItemSelected(pop, MenuUtils.getMenuItem(item, new MenuBuilder(getActivity())), item.getMenuInfo(), view); return false; } }); pop.getMenuInflater().inflate(R.menu.context_file, pop.getMenu()); onPrepareOptionsMenu(pop.getMenu()); if (DEBUG) Logger.LogDebug("PopupMenu.show()"); pop.show(); return true; } else return list.showContextMenu(); } if (!file.isDirectory() && getActionMode() == null) { getSherlockActivity().startActionMode(new Callback() { // @Override @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } // @Override @Override public void onDestroyActionMode(ActionMode mode) { setActionMode(null); } // @Override @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { setActionMode(mode); mode.getMenuInflater().inflate(R.menu.context_file, menu); return true; } // @Override @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { // ArrayList<OpenPath> files = new ArrayList<OpenPath>(); // OpenPath file = // mLastPath.getChild(mode.getTitle().toString()); // files.add(file); if (item.getItemId() != R.id.menu_context_cut && item.getItemId() != R.id.menu_multi && item.getItemId() != R.id.menu_context_copy) { mode.finish(); } return executeMenu(item.getItemId(), mode, file); } }); getActionMode().setTitle(file.getName()); return true; } if (file.isDirectory() && getActionMode() == null) { getSherlockActivity().startActionMode(new Callback() { // @Override @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } // @Override @Override public void onDestroyActionMode(ActionMode mode) { setActionMode(null); } // @Override @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.getMenuInflater().inflate(R.menu.context_file, menu); menu.findItem(R.id.menu_context_paste).setEnabled(getClipboard().size() > 0); // menu.findItem(R.id.menu_context_unzip).setEnabled(mHoldingZip); setActionMode(mode); return true; } // @Override @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return executeMenu(item.getItemId(), mode, file); } }); getActionMode().setTitle(file.getName()); return true; } return false; } public static void prepareContextMenu(ContextMenu menu, OpenPath path) { MenuUtils.setMenuEnabled(menu, !path.isDirectory(), R.id.menu_context_edit); MenuUtils.setMenuEnabled(menu, path.canWrite(), R.id.menu_context_delete, R.id.menu_context_cut, R.id.menu_context_rename); MenuUtils.setMenuEnabled(menu, path.getParent().canWrite(), R.id.menu_context_paste); } @Override public boolean onClick(int id, View view) { super.onClick(id, view); if (getActivity() == null) return false; if (view == null) view = getActivity().findViewById(id); if (view != null && view.getTag() != null && view.getTag() instanceof Menu) { Logger.LogDebug("Showing Tagged Menu! " + view.getTag()); if (showMenu((Menu) view.getTag(), view, ViewUtils.getText(view))) return true; } return false; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item == null) return false; if (super.onOptionsItemSelected(item)) return true; if (DEBUG) Logger.LogDebug("ContentFragment.onOptionsItemSelected(0x" + Integer.toHexString(item.getItemId()) + ":" + item.getTitle() + ")"); OpenPath path = null; if (getSelectedCount() > 0) path = mContentAdapter.getSelectedSet().get(getSelectedCount() - 1); else if (mMenuContextItemIndex > -1 && mMenuContextItemIndex < getContentAdapter().getCount()) path = getContentAdapter().getItem(mMenuContextItemIndex); if (path != null && executeMenu(item.getItemId(), getActionMode(), path)) return true; switch (item.getItemId()) { case R.id.menu_sort: case R.id.menu_view: return true; case R.id.menu_context_heatmap: DialogHandler.showFileHeatmap(getExplorer(), getPath()); return true; case R.id.menu_new_file: EventHandler.createNewFile(getPath(), getActivity(), this); return true; case R.id.menu_new_folder: EventHandler.createNewFolder(getPath(), getActivity(), this); return true; case R.id.menu_sort_name_asc: onSortingChanged(SortType.Type.ALPHA); return true; case R.id.menu_sort_name_desc: onSortingChanged(SortType.Type.ALPHA_DESC); return true; case R.id.menu_sort_date_asc: onSortingChanged(SortType.Type.DATE); return true; case R.id.menu_sort_date_desc: onSortingChanged(SortType.Type.DATE_DESC); return true; case R.id.menu_sort_size_asc: onSortingChanged(SortType.Type.SIZE); return true; case R.id.menu_sort_size_desc: onSortingChanged(SortType.Type.SIZE_DESC); return true; case R.id.menu_sort_type: onSortingChanged(SortType.Type.TYPE); return true; case R.id.menu_view_hidden: onHiddenFilesChanged(!getShowHiddenFiles()); return true; case R.id.menu_view_thumbs: onThumbnailChanged(!getShowThumbnails()); return true; case R.id.menu_sort_folders_first: onFoldersFirstChanged(!getFoldersFirst()); return true; default: if (executeMenu(item.getItemId(), null, mPath)) return true; } return false; } public void downloadFile(OpenPath... paths) { if (DEBUG) Logger.LogDebug("ContentFragment.downloadFile: " + Utils.joinArray(paths, ", ")); OpenPath dl = OpenExplorer.getDownloadParent().getFirstDir(); if (dl == null) dl = OpenFile.getExternalMemoryDrive(true); if (dl == null) { getExplorer().showToast(R.string.s_error_ftp); return; } for (OpenPath p : paths) { getEventHandler().copyFile(p, dl, getContext()); } refreshOperations(); } public boolean executeMenu(final int id, final ActionMode mode, final OpenPath file) { Logger.LogInfo("ContentFragment.executeMenu(0x" + Integer.toHexString(id) + ") on " + file); final String path = file != null ? file.getPath() : null; OpenPath parent = file != null ? file.getParent() : mPath; if (parent == null || parent instanceof OpenCursor) parent = OpenFile.getExternalMemoryDrive(true); final OpenPath folder = parent; String name = file != null ? file.getName() : null; List<OpenPath> selection = mContentAdapter.getSelectedSet(); final boolean fromPasteMenu = file.equals(mPath); switch (id) { case R.id.menu_refresh2: case R.id.menu_refresh: if (DEBUG) Logger.LogDebug("Refreshing " + getPath().getPath()); //getPath().clearChildren(); FileManager.removeOpenCache(getPath().getPath()); getPath().deleteFolderFromDb(); refreshData(new Bundle(), false); return true; case R.id.menu_context_download: if (selection != null && selection.size() > 0) { downloadFile(selection.toArray(new OpenPath[selection.size()])); finishMode(mode); return true; } break; case R.id.menu_context_selectall: if (getContentAdapter() == null) return false; getContentAdapter().selectAll(); return true; case R.id.menu_context_view: Intent vintent = IntentManager.getIntent(file, getExplorer(), Intent.ACTION_VIEW); if (vintent != null) getActivity().startActivity(vintent); else { if (getExplorer() != null) getExplorer().showToast(R.string.noApplications); if (file.length() < OpenExplorer.TEXT_EDITOR_MAX_SIZE) getExplorer().editFile(file); } break; case R.id.menu_context_edit: Intent intent = IntentManager.getIntent(file, getExplorer(), Intent.ACTION_EDIT); if (intent != null) { if (intent.getPackage() != null && intent.getPackage().equals(getActivity().getPackageName())) getExplorer().editFile(file); else try { intent.setAction(Intent.ACTION_EDIT); Logger.LogVerbose("Starting Intent: " + intent.toString()); getExplorer().startActivity(intent); } catch (ActivityNotFoundException e) { getExplorer().showToast(R.string.noApplications); getExplorer().editFile(file); } } else if (file.length() < OpenExplorer.TEXT_EDITOR_MAX_SIZE) { getExplorer().editFile(file); } else { getExplorer().showToast(R.string.noApplications); } break; case R.id.menu_multi: // changeMultiSelectState(getActionMode() != null); if (!fromPasteMenu) getClipboard().add(file); return true; case R.id.menu_context_bookmark: if (getSelectedCount() > 0) for (OpenPath p : mContentAdapter.getSelectedSet()) getExplorer().addBookmark(p); else getExplorer().addBookmark(file); finishMode(mode); return true; case R.id.menu_context_delete: // fileList.add(file); getEventHandler().deleteFile(file, this, true); finishMode(mode); return true; case R.id.menu_context_rename: getEventHandler().renameFile(file, true, getActivity()); finishMode(mode); return true; case R.id.menu_context_copy: case R.id.menu_context_cut: getClipboard().DeleteSource = id == R.id.menu_context_cut; file.setTag(id); getClipboard().add(file); return true; case R.id.menu_context_paste: case R.id.content_paste: OpenPath into = file; if (fromPasteMenu) into = mPath; if (!file.isDirectory()) { Logger.LogWarning("Can't paste into file (" + file.getPath() + "). Using parent directory (" + folder.getPath() + ")"); into = folder; } OpenClipboard cb = getClipboard(); if (cb != null) { cb.setCurrentPath(into); checkClipboardForTar(cb, into); checkClipboardForLZMA(cb, into); if (cb.size() > 0) { if (cb.DeleteSource) getEventHandler().cutFile(cb, into, getActivity()); else getEventHandler().copyFile(cb, into, getActivity()); refreshOperations(); } cb.DeleteSource = false; if (cb.ClearAfter) cb.clear(); } if (getExplorer() != null) getExplorer().updateTitle(path); finishMode(mode); return true; case R.id.menu_context_zip: if (getClipboard() == null || getClipboard().size() == 0) return false; OpenPath intoPath = mPath; if (!(intoPath instanceof OpenFile)) intoPath = OpenFile.getExternalMemoryDrive(true); if (!fromPasteMenu) getClipboard().add(file); else getClipboard().setCurrentPath(intoPath); getClipboard().ClearAfter = true; String zname = getClipboard().get(0).getName() + "." + EventHandler.DefaultCompressionType.toString().toLowerCase(Locale.US); if (getClipboard().size() > 1) { OpenPath last = getClipboard().get(getClipboard().getCount() - 1); if (last != null && last.getParent() != null) { if (last.getParent() instanceof OpenCursor) zname = folder.getPath(); zname = last.getParent().getName() + "."; if (EventHandler.DefaultCompressionType == CompressionType.BZ2 || EventHandler.DefaultCompressionType == CompressionType.GZ) zname += "t"; zname += EventHandler.DefaultCompressionType.toString().toLowerCase(); } } final String def = zname; showZipDialog(intoPath, def, folder, getClipboard(), new OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (dialog != null) dialog.dismiss(); switch (which) { case DialogInterface.BUTTON_NEGATIVE: if (!fromPasteMenu && getClipboard().size() <= 1) getClipboard().clear(); break; case DialogInterface.BUTTON_NEUTRAL: if (fromPasteMenu && getClipboard().size() <= 1) getClipboard().clear(); break; case DialogInterface.BUTTON_POSITIVE: finishMode(mode); break; } } }); return true; // case R.id.menu_context_unzip: // getEventHandler().unzipFile(file, getExplorer()); // return true; case R.id.menu_context_info: DialogHandler.showFileInfo(getExplorer(), file); finishMode(mode); return true; case R.id.menu_context_heatmap: if (getSelectedCount() > 0) { OpenPathArray sels = new OpenPathArray( mContentAdapter.getSelectedSet().toArray(new OpenPath[getSelectedCount()])); DialogHandler.showFileHeatmap(getExplorer(), sels); } else DialogHandler.showFileHeatmap(getExplorer(), file); finishMode(mode); return true; case R.id.menu_multi_all_clear: getClipboard().clear(); return true; case R.id.menu_context_share: // TODO: WTF is this? Intent mail = new Intent(); mail.setType("application/mail"); mail.setAction(android.content.Intent.ACTION_SEND); mail.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path))); startActivity(mail); // mode.finish(); return true; // this is for bluetooth // files.add(path); // getEventHandler().sendFile(files); // mode.finish(); // return true; } return false; } private void showZipDialog(OpenPath intoPath, final String defaultName, final OpenPath folder, final List<OpenPath> files, final DialogInterface.OnClickListener onClick) { final InputDialog dZip = new InputDialog(getExplorer()).setIcon(R.drawable.sm_zip) .setTitle(R.string.s_menu_zip).setMessageTop(R.string.s_prompt_path) .setDefaultTop(intoPath.getPath()).setMessage(R.string.s_prompt_zip).setCancelable(true) .setNegativeButton(android.R.string.no, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { onClick.onClick(dialog, which); } }); final Context context = getContext(); ViewGroup mCompressLayout = (ViewGroup) LayoutInflater.from(getContext()) .inflate(R.layout.compression_spinner, null); Spinner mCompressType = (Spinner) mCompressLayout.findViewById(R.id.compression_type); ViewGroup view = (ViewGroup) dZip.getView(); View v = new View(context); LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 2); v.setLayoutParams(lp); v.setBackgroundColor(context.getResources().getColor(R.color.blue)); view.addView(v); mCompressType.setSelection(EventHandler.DefaultCompressionType.ordinal()); mCompressType.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String name = dZip.getInputText().replace(".zip", "").replace(".tar", "").replace(".tgz", "") .replace(".tbz2", "").replace(".gz", "").replace(".bz2", ""); switch (position) { case 0: name += ".zip"; dZip.setDefaultText(name); EventHandler.DefaultCompressionType = CompressionType.ZIP; break; case 1: name += ".tar"; dZip.setDefaultText(name); EventHandler.DefaultCompressionType = CompressionType.TAR; break; case 2: name += "." + (files.size() > 1 ? "t" : "") + "gz"; dZip.setDefaultText(name); EventHandler.DefaultCompressionType = CompressionType.GZ; break; case 3: name += "." + (files.size() > 1 ? "t" : "") + "bz2"; dZip.setDefaultText(name); EventHandler.DefaultCompressionType = CompressionType.BZ2; break; } } public void onNothingSelected(AdapterView<?> parent) { } }); view.addView(mCompressLayout); CheckBox mDeleteAfter = new CheckBox(getContext()); mDeleteAfter.setText(R.string.s_delete_after); if (getPreferences().getBoolean("global", "pref_archive_postdelete", false)) mDeleteAfter.setChecked(true); mDeleteAfter.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { getPreferences().setSetting("global", "pref_archive_postdelete", isChecked); } }); view.addView(mDeleteAfter); dZip.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { onClick.onClick(dialog, DialogInterface.BUTTON_NEUTRAL); } }).setPositiveButton(android.R.string.ok, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { OpenPath zFolder = new OpenFile(dZip.getInputTopText()); if (zFolder == null || !zFolder.exists()) zFolder = folder; OpenPath zipFile = zFolder.getChild(dZip.getInputText()); Logger.LogVerbose("Zipping " + files.size() + " items to " + zipFile.getPath()); getEventHandler().zipFile(zipFile, files, getExplorer()); refreshOperations(); onClick.onClick(dialog, which); } }).setDefaultText(defaultName); dZip.create().show(); } private boolean checkClipboardForTar(final OpenClipboard cb, final OpenPath into) { final Hashtable<OpenTar, Vector<OpenTarEntry>> tarKids = new Hashtable<OpenTar, Vector<OpenTar.OpenTarEntry>>(); for (OpenPath p : cb) if (p instanceof OpenTarEntry) { OpenTarEntry kid = (OpenTarEntry) p; OpenTar tar = kid.getTar(); if (!tarKids.containsKey(tar)) tarKids.put(tar, new Vector<OpenTar.OpenTarEntry>()); Vector<OpenTarEntry> kids = tarKids.get(tar); kids.add(kid); tarKids.put(tar, kids); } if (tarKids.size() == 0) return false; for (Vector<OpenTarEntry> kids : tarKids.values()) for (OpenTarEntry kid : kids) cb.remove(kid); new Thread(new Runnable() { public void run() { for (OpenTar tar : tarKids.keySet()) { Vector<OpenTarEntry> kids = tarKids.get(tar); String[] includes = new String[kids.size()]; for (int i = 0; i < kids.size(); i++) { OpenTarEntry kid = kids.get(i); includes[i] = kid.getRelativePath(); } untarAll(tar, into, includes); } } }).start(); return true; } private boolean checkClipboardForLZMA(final OpenClipboard cb, final OpenPath into) { final Hashtable<OpenLZMA, Vector<OpenLZMAEntry>> lzKids = new Hashtable<OpenLZMA, Vector<OpenLZMA.OpenLZMAEntry>>(); for (OpenPath p : cb) if (p instanceof OpenLZMAEntry) { OpenLZMAEntry kid = (OpenLZMAEntry) p; OpenLZMA lz = kid.getLZMA(); if (!lzKids.containsKey(lz)) lzKids.put(lz, new Vector<OpenLZMA.OpenLZMAEntry>()); Vector<OpenLZMAEntry> kids = lzKids.get(lz); kids.add(kid); lzKids.put(lz, kids); } if (lzKids.size() == 0) return false; for (Vector<OpenLZMAEntry> kids : lzKids.values()) for (OpenLZMAEntry kid : kids) cb.remove(kid); new Thread(new Runnable() { public void run() { for (OpenLZMA tar : lzKids.keySet()) { Vector<OpenLZMAEntry> kids = lzKids.get(tar); String[] includes = new String[kids.size()]; for (int i = 0; i < kids.size(); i++) { OpenLZMAEntry kid = kids.get(i); includes[i] = kid.getRelativePath(); } extractSet(tar, into, includes); } } }).start(); return true; } @Override protected void finishMode(ActionMode mode) { super.finishMode(mode); if (getSelectedCount() > 0) mContentAdapter.clearSelection(); } /* * @Override public boolean onContextItemSelected(android.view.MenuItem * item) { if(item == null) return false; OpenPath path = null; * if(item.getMenuInfo() != null && item.getMenuInfo() instanceof * OpenContextMenuInfo) path = ((OpenContextMenuInfo) * item.getMenuInfo()).getPath(); else if(mMenuContextItemIndex >= 0 && * mMenuContextItemIndex < getContentAdapter().getCount()) path = * getContentAdapter().getItem(mMenuContextItemIndex); if(path == null) { * Logger.LogWarning("Couldn't find path for context menu"); return false; } * return executeMenu(item.getItemId(), null, path); } */ @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // if (DEBUG) // Logger.LogDebug(getClassName() + ".onCreateOptionsMenu (" + getPath() // + ")"); super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.content_full, menu); MenuUtils.setMenuEnabled(menu, true, R.id.menu_view); // MenuInflater inflater = new MenuInflater(mContext); // if(!OpenExplorer.USE_PRETTY_MENUS||!OpenExplorer.BEFORE_HONEYCOMB) } @Override public void onPrepareOptionsMenu(Menu menu) { // Logger.LogVerbose("ContentFragment.onPrepareOptionsMenu"); if (getActivity() == null) return; if (menu == null) return; if (isDetached() || !isVisible()) return; super.onPrepareOptionsMenu(menu); MenuUtils.setMenuEnabled(menu, getPath().canWrite(), R.id.menu_new_file, R.id.menu_new_folder); MenuUtils.setMenuVisible(menu, mPath instanceof OpenNetworkPath, R.id.menu_context_download); MenuUtils.setMenuVisible(menu, !(mPath instanceof OpenNetworkPath), R.id.menu_context_edit, R.id.menu_context_view); MenuItem mMenuFF = menu.findItem(R.id.menu_sort_folders_first); if (mMenuFF != null) { if (mMenuFF.isCheckable()) { mMenuFF.setChecked(getSorting().foldersFirst()); } else { if (getSorting().foldersFirst()) mMenuFF.setIcon(getThemedResourceId(R.styleable.AppTheme_checkboxButtonOn, R.drawable.btn_check_on_holo_blue)); else mMenuFF.setIcon( getThemedResourceId(R.styleable.AppTheme_checkboxButtonOff, R.drawable.btn_check_off)); } } // MenuUtils.setMenuChecked(menu, getSorting().foldersFirst(), // R.id.menu_sort_folders_first); if (mPath != null) MenuUtils.setMenuEnabled(menu, !mPath.requiresThread() && mPath.canWrite() && !mPath.isArchive(), R.id.menu_multi_all_copy, R.id.menu_multi_all_move, R.id.menu_new_file, R.id.menu_new_folder); SortType.Type st = getSorting().getType(); int sti = Utils.getArrayIndex(sortTypes, st); if (sti > -1) MenuUtils.setMenuChecked(menu, true, sortMenuOpts[sti], sortMenuOpts); if (getClipboard() == null || getClipboard().size() == 0) { MenuUtils.setMenuVisible(menu, false, R.id.content_paste); } else { MenuItem mPaste = menu.findItem(R.id.content_paste); if (mPaste != null && getClipboard() != null && !isDetached()) mPaste.setTitle(getString(R.string.s_menu_paste) + " (" + getClipboard().size() + ")"); if (mPaste != null) mPaste.setVisible(true); } MenuUtils.setMenuEnabled(menu, true, R.id.menu_view, R.id.menu_sort, R.id.menu_content_ops); int mViewMode = getViewMode(); if (mViewMode == OpenExplorer.VIEW_GRID) MenuUtils.setMenuChecked(menu, true, R.id.menu_view_grid, R.id.menu_view_list); else MenuUtils.setMenuChecked(menu, true, R.id.menu_view_list, R.id.menu_view_grid); MenuUtils.setMenuChecked(menu, getShowHiddenFiles(), R.id.menu_view_hidden); MenuUtils.setMenuChecked(menu, getShowThumbnails(), R.id.menu_view_thumbs); } /* * @Override public void setInitialSavedState(SavedState state) { * super.setInitialSavedState(state); if(state == null) return; Bundle b = * state.getBundle(); if(b != null && b.containsKey("last") && mPath == * null) setPath(b.getString("last")); * Logger.LogVerbose("setInitialSavedState :: " + state.toString()); } */ @Override public void onSaveInstanceState(Bundle outState) { try { super.onSaveInstanceState(outState); outState.putInt("view", mViewMode); if (mPath != null) outState.putParcelable("path", mPath); if (mListVisibleStartIndex > 0) outState.putInt("first", mListVisibleStartIndex); if (mListScrollY > 0) outState.putInt("scroll", mListScrollY); if (mGrid != null) outState.putParcelable("grid", mGrid.onSaveInstanceState()); } catch (NullPointerException e) { Logger.LogError("Not sure why this is causing NPE crashes", e); } /* * if(mPath != null && mPath.getPath() != null) { * Logger.LogDebug("Content location saving to " + mPath.getPath()); * outState.putString("location", mPath.getPath()); } */ } @Override public void onViewCreated(View v, Bundle savedInstanceState) { super.onViewCreated(v, savedInstanceState); if (mBundle == null && savedInstanceState != null) mBundle = savedInstanceState; if (mBundle == null) mBundle = new Bundle(); // mPathView = (LinearLayout)v.findViewById(R.id.scroll_path); // if(mGrid == null) mGrid = (GridView) v.findViewById(R.id.content_grid); // if(mProgressBarLoading == null) mProgressBarLoading = // v.findViewById(R.id.content_progress); setProgressVisibility(false); if (mGrid == null) Logger.LogError("WTF, where are they?"); else updateGridView(); // refreshData(mBundle, true); if (mGrid != null) { if (mBundle.containsKey("scroll") && mBundle.getInt("scroll") > 0) { // Logger.LogDebug("Returning Scroll to " + // mBundle.getInt("scroll")); mGrid.scrollTo(0, mBundle.getInt("scroll")); } else if (mBundle.containsKey("grid")) mGrid.onRestoreInstanceState(mBundle.getParcelable("grid")); if (mBundle.containsKey("first")) { // Logger.LogDebug("Returning first item #" + // mBundle.getInt("first")); mGrid.setSelection(mBundle.getInt("first")); } } } @Override public void onDestroy() { if (mTask != null) mTask.cancel(true); super.onDestroy(); } @TargetApi(11) public void updateGridView() { // Logger.LogDebug("updateGridView() @ " + mPath); if (mGrid == null) mGrid = (GridView) getView().findViewById(R.id.content_grid); if (mGrid == null) { Logger.LogWarning("This shouldn't happen"); mGrid = (GridView) ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)) .inflate(R.layout.content_grid, null); ((ViewGroup) getView()).addView(mGrid); setupGridView(); } if (mGrid != null) mGrid.invalidateViews(); if (getExplorer() == null) { Logger.LogWarning("ContentFragment.updateGridView warning: getExplorer() is null"); return; } invalidateOptionsMenu(); setupGridView(); refreshData(getArguments(), false); } public void setupGridView() { mGrid.setVisibility(View.VISIBLE); mGrid.setOnItemClickListener(this); mGrid.setOnItemLongClickListener(this); mGrid.setColumnWidth(getResources().getDimensionPixelSize( getViewMode() == OpenExplorer.VIEW_GRID ? R.dimen.grid_width : R.dimen.list_width)); mGrid.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { mListScrollingState = scrollState; if (view != null) mListScrollY = view.getScrollY(); // if(scrollState == 0) // onScrollStopped(view); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisibleItem != mListVisibleStartIndex) mListVisibleStartIndex = firstVisibleItem; if (visibleItemCount != mListVisibleLength) mListVisibleLength = visibleItemCount; } }); if (!OpenExplorer.USE_PRETTY_CONTEXT_MENUS) // || !USE_ACTIONMODE) registerForContextMenu(mGrid); } /* * protected void onScrollStopped(AbsListView view) { boolean skipThis = * true; if(skipThis) return; int start = Math.max(0, * mListVisibleStartIndex); int end = Math.min(mData2.size() - 1, * mListVisibleStartIndex + mListVisibleLength); int mWidth = 128, mHeight = * 128; ThumbnailStruct[] thumbs = new ThumbnailStruct[end - start]; for(int * i = start; i < end; i++) { Object o = view.getItemAtPosition(i); if(o != * null) { OpenPath file = (OpenPath)o; if(file.getTag() != null && * file.getTag().getClass().equals(BookmarkHolder.class)) { BookmarkHolder * mHolder = (BookmarkHolder)file.getTag(); ImageView v = * mHolder.getIconView(); thumbs[i - start] = new ThumbnailStruct(file, * mHolder, mWidth, mHeight); //new ThumbnailTask().execute(new * ThumbnailStruct(file, mHolder, mWidth, mHeight)); } } * //view.getItemAtPosition(i); } new ThumbnailTask().execute(thumbs); * //Logger.LogDebug("Visible items " + * mData2.get(mListVisibleStartIndex).getName() + " - " + * mData2.get().getName()); } */ @Override public int getPagerPriority() { return 1; } @Override public void onWorkerThreadFailure(EventType type, OpenPath... files) { for (OpenPath path : files) sendToLogView(type.name() + " error on " + path, Color.RED); setProgressVisibility(false); } @Override public void onWorkerThreadComplete(EventType type, String... results) { Logger.LogVerbose("Need to refresh!"); switch (type) { case SEARCH: if (results == null || results.length < 1) { Toast.makeText(getApplicationContext(), "Sorry, zero items found", Toast.LENGTH_LONG).show(); return; } ArrayList<OpenPath> files = new ArrayList<OpenPath>(); for (String s : results) files.add(new OpenFile(s)); Toast.makeText(getActivity(), "Unimplemented", Toast.LENGTH_LONG).show(); break; default: if (results.length == 1) Toast.makeText(getContext(), results[0], Toast.LENGTH_LONG).show(); // Logger.LogDebug("Worker thread complete (" + type + ")?"); if (!mPath.requiresThread() || FileManager.hasOpenCache(mPath.getAbsolutePath())) try { if (mPath.requiresThread()) mPath = FileManager.getOpenCache(mPath.getPath()); if (mPath != null) updateData(mPath.list()); } catch (IOException e) { Logger.LogWarning("Couldn't update data after thread completion", e); } else { // if(mProgressBarLoading == null) mProgressBarLoading = // getView().findViewById(R.id.content_progress); EventHandler.executeNetwork(new NetworkIOTask(this), mPath); } // changePath(mPath, false); notifyDataSetChanged(); refreshData(new Bundle(), false); // changePath(getManager().peekStack(), false); } setProgressVisibility(false); } @Override public void onWorkerProgressUpdate(int pos, int total) { setProgressVisibility(pos < total); } private void saveTopPath() { if (mGrid == null) return; mTopIndex = mGrid.getFirstVisiblePosition(); if (mContentAdapter != null && mTopIndex > -1 && mTopIndex < mContentAdapter.getCount()) { mTopPath = mContentAdapter.getItem(mTopIndex); Logger.LogVerbose( "Top Path saved to " + mTopIndex + (mTopPath != null ? " :: " + mTopPath.getName() : "")); } } private Boolean restoreTopPath() { if (mTopPath != null) { // Logger.LogDebug("Looking for top path (" + mTopPath.getName() + // ")"); for (int i = 0; i < mContentAdapter.getCount(); i++) if (mContentAdapter.getItem(i).getName().equals(mTopPath.getName())) return restoreTopPath(i); } if (mTopIndex > 0) { // Logger.LogDebug("Falling back to top index (" + mTopIndex + ")"); return restoreTopPath(mTopIndex); } else return true; } private Boolean restoreTopPath(int index) { Logger.LogVerbose("Top Path restored to " + index); mGrid.setSelection(index); mTopIndex = 0; mTopPath = null; return true; } public void onFoldersFirstChanged(boolean first) { setSorting(null, first); refreshData(null, false); } public void onHiddenFilesChanged() { onHiddenChanged(!getShowHiddenFiles()); } // @Override public void onHiddenFilesChanged(boolean toShow) { Logger.LogInfo("onHiddenFilesChanged(" + toShow + ")"); saveTopPath(); setViewSetting(getPath(), "show", toShow); if (mContentAdapter != null) mContentAdapter.setShowHiddenFiles(toShow); // getManager().setShowHiddenFiles(state); refreshData(new Bundle(), false); } public void onThumbnailChanged() { onThumbnailChanged(!getShowThumbnails()); } // @Override public void onThumbnailChanged(boolean state) { saveTopPath(); setShowThumbnails(state); refreshData(new Bundle(), false); } // @Override public void onSortingChanged(SortType.Type type) { setSorting(type, null); // getManager().setSorting(type); refreshData(new Bundle(), false); } public void setSorting(SortType.Type newType, Boolean foldersFirst) { SortType newSort = getContentAdapter() != null ? getContentAdapter().getSorting() : SortType.ALPHA; newSort.setType(newType).setFoldersFirst(foldersFirst); setViewSetting(mPath, "sort", newSort.toString()); getContentAdapter().setSorting(newSort); } public void setShowThumbnails(boolean thumbs) { mContentAdapter.mShowThumbnails = thumbs; setViewSetting(mPath, "thumbs", thumbs); } public void setSettings(SortType sort, boolean thumbs, boolean hidden) { setSorting(sort.getType(), thumbs); refreshData(new Bundle(), false); } // @Override public void onViewChanged(int state) { setViewMode(state); } @Override public void setProgressVisibility(boolean visible) { // if(mProgressBarLoading == null && mGrid != null && mGrid.getParent() // != null) mProgressBarLoading = // ((View)mGrid.getParent()).findViewById(R.id.content_progress); // if(mProgressBarLoading != null && mData.length == 0) // mProgressBarLoading.setVisibility(visible ? View.VISIBLE : // View.GONE); ViewUtils.setViewsVisible(getView(), visible, R.id.content_cancel); if (visible) setStatus(mLoadingMessage); else { updateStatus(); ViewUtils.setViewsVisible(getView(), false, android.R.id.empty); } if (getExplorer() != null) getExplorer().setProgressVisibility(visible); } private void setProgressClickHandler(android.view.View.OnClickListener listener) { ViewUtils.setOnClicks(getView(), listener, R.id.content_cancel); if (getExplorer() != null) getExplorer().setProgressClickHandler(listener); } public SortType getSorting() { return mContentAdapter != null ? mContentAdapter.getSorting() : SortType.ALPHA; } public boolean getFoldersFirst() { return getSorting().foldersFirst(); } public boolean getShowHiddenFiles() { if (mContentAdapter != null) return mContentAdapter.getShowHiddenFiles(); else return getViewSetting(getPath(), "show", false); } public boolean getShowThumbnails() { return mContentAdapter != null ? mContentAdapter.mShowThumbnails : true; } public void updateStatus() { ViewUtils.setViewsVisible(mStatusBar, false); new Thread(new Runnable() { public void run() { final CharSequence cs = getContentAdapter().getStatus(); getHandler().post(new Runnable() { public void run() { setStatus(cs); } }); } }).start(); getContentAdapter().getStatus2(new SpaceListener() { public void onException(Exception e) { ViewUtils.setViewsVisible(getView(), false, R.id.content_status_right); } @Override public void onSpaceReturned(long total, long used, long third) { String txt = ""; if (used > 0) { txt = OpenPath.formatSize(used); if (total > 0) txt += "/"; } if (total > 0) txt += OpenPath.formatSize(total); if (third > 0) txt += "(" + OpenPath.formatSize(third) + ")"; if (txt.equals("")) { ViewUtils.setViewsVisible(getView(), false, R.id.content_status_right); return; } txt += " " + getContext().getString(R.string.s_total); ViewUtils.setText(getView(), txt, R.id.content_status_right); ViewUtils.setViewsVisible(getView(), true, R.id.content_status_bar, R.id.content_status_right); } }); } public void setStatus(CharSequence status) { boolean empty = status == null || status.length() == 0 || status.toString().startsWith("Loading"); ViewUtils.setViewsVisible(mStatusBar, !empty); if (!empty) ViewUtils.setText(mStatus, status); } @Override public CharSequence getTitle() { if (mPath == null) return "???"; CharSequence tit = mPath.getTitle(getContext()); if (!Utils.isNullOrEmpty(tit)) return tit; String ret = mPath.getName(); if (Utils.isNullOrEmpty(ret) && mPath != null && mPath.getUri() != null) ret = mPath.getUri().getLastPathSegment(); if ((ret == null || ret.equals("")) && mPath != null) ret = mPath.toString(); if ((mPath instanceof OpenFile || mPath instanceof OpenNetworkPath) && mPath.isDirectory() && !ret.endsWith("/")) ret += "/"; return ret; } @Override public OpenPath getPath() { if (mPath == null && getArguments() != null && getArguments().containsKey("path")) return mPath = (OpenPath) getArguments().getParcelable("path"); return mPath; } @Override public Drawable getIcon() { if (isDetached()) return null; if (getActivity() == null || getResources() == null) return null; OpenPath path = getPath(); if (path == null) return null; Drawable ret = getResources().getDrawable(ThumbnailCreator.getDefaultResourceId(getPath(), 96, 96)); if (path instanceof OpenPath.ThumbnailOverlayInterface) { Drawable overlay = ((ThumbnailOverlayInterface) path).getOverlayDrawable(getActivity(), true); ret = new LayerDrawable(new Drawable[] { ret, overlay }); } return ret; } @Override public void updateData(final OpenPath[] result) { if (mContentAdapter == null) { Logger.LogWarning("ContentFragment.updateData warning: mContentAdapter is null"); return; } if (Thread.currentThread().equals(OpenExplorer.UiThread)) { mContentAdapter.updateData(result); notifyDataSetChanged(); } else { OpenExplorer.getHandler().post(new Runnable() { @Override public void run() { mContentAdapter.updateData(result); notifyDataSetChanged(); } }); } updateStatus(); // notifyDataSetChanged(); } @Override public void addFiles(OpenPath[] files) { mContentAdapter.addAll(Arrays.asList(files)); } /** * Show/hide the "selection" action mode, according to the number of * selected messages and the visibility of the fragment. Also update the * content (title and menus) if necessary. */ public void updateSelectionMode() { final int numSelected = getSelectedCount(); if ((numSelected == 0) || mDisableCab || !isViewCreated()) { finishSelectionMode(); return; } if (isInSelectionMode()) { updateSelectionModeView(); } else { mLastSelectionModeCallback = new SelectionModeCallback(); /* * for(OpenPath clip : getClipboard().getAll()) * addToMultiSelect(clip); */ if (getExplorer() != null) getExplorer().startActionMode(mLastSelectionModeCallback); // mGrid.invalidateViews(); } } /** * Finish the "selection" action mode. Note this method finishes the * contextual mode, but does *not* clear the selection. If you want to do so * use {@link #onDeselectAll()} instead. */ private void finishSelectionMode() { if (isInSelectionMode()) { mLastSelectionModeCallback.mClosedByUser = false; getActionMode().finish(); } } /** Update the "selection" action mode bar */ private void updateSelectionModeView() { if (isInSelectionMode()) getActionMode().invalidate(); // notifyDataSetChanged(); } /** * @return the number of messages that are currently selected. */ private int getSelectedCount() { if (mContentAdapter != null && mContentAdapter.getSelectedSet() != null) return mContentAdapter.getSelectedSet().size(); else return 0; } /** * @return true if the list is in the "selection" mode. */ public boolean isInSelectionMode() { return getActionMode() != null; } public void deselectAll() { mContentAdapter.clearSelection(); if (isInSelectionMode()) { finishSelectionMode(); } } @Override public void onAdapterSelectedChanged(OpenPath path, boolean newSelected, int mSelectedCount) { updateSelectionMode(); } private class SelectionModeCallback implements ActionMode.Callback { private MenuItem mShare; private int viewPageNum; private ShareActionProvider mShareActionProvider; private boolean pasteReady = false; /* package */boolean mClosedByUser = true; private MenuItem mRename; private MenuItem mInfo; @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { setActionMode(mode); MenuInflater inflater = getExplorer().getSupportMenuInflater(); inflater.inflate(R.menu.content_action, menu); mRename = menu.findItem(R.id.menu_context_rename); mInfo = menu.findItem(R.id.menu_context_info); // Set file with share history to the provider and set the share // intent. mShare = menu.findItem(R.id.menu_context_share); if (mShare != null && mShare.getActionProvider() != null) { mShareActionProvider = (ShareActionProvider) mShare.getActionProvider(); if (mShareActionProvider != null) { int cnt = getSelectedCount(); OpenPath first = mContentAdapter.getSelectedSet().get(0); Intent shareIntent = null; shareIntent = new Intent(cnt > 1 ? Intent.ACTION_SEND_MULTIPLE : Intent.ACTION_VIEW); if (first != null) { shareIntent.setType(first.getMimeType()); shareIntent.putExtra(Intent.EXTRA_STREAM, first.getUri()); } mShareActionProvider.setShareIntent(shareIntent); mShareActionProvider .setShareHistoryFileName(ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME); } } return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { int num = getSelectedCount(); // Set title -- "# selected" if (num > 1) mode.setTitle(getExplorer().getResources().getQuantityString(R.plurals.num_selected, num, num)); else mode.setTitle(mContentAdapter.getSelectedSet().get(0).getName()); if (mShareActionProvider != null) { Intent shareIntent = null; int cnt = getSelectedCount(); menu.removeGroup(10); OpenPath first = mContentAdapter.getSelectedSet().get(0); if (cnt > 1) { shareIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); String type = Utils.ifNull(first.getMimeType(), "*/*"); ArrayList<Uri> uris = new ArrayList<Uri>(); for (OpenPath sel : mContentAdapter.getSelectedSet()) { if (!type.equals(sel.getMimeType())) type = "*/*"; uris.add(sel.getUri()); } shareIntent.setType(type); shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); } else { shareIntent = new Intent(Intent.ACTION_VIEW); shareIntent.setDataAndType(first.getUri(), Utils.ifNull(first.getMimeType(), "*/*")); } List<ResolveInfo> resolves = IntentManager.getResolvesAvailable(shareIntent, getExplorer()); int numIntents = resolves.size(); boolean hasIntents = numIntents > 1; MenuUtils.setMenuVisible(menu, hasIntents, R.id.menu_context_share); if (hasIntents) mShareActionProvider.setShareIntent(shareIntent); else if (numIntents == 1) { ResolveInfo app = resolves.get(0); shareIntent.setPackage(app.activityInfo.packageName); final Intent theIntent = shareIntent; menu.add(10, Menu.NONE, Menu.FIRST, app.loadLabel(getContext().getPackageManager())) .setIcon(app.loadIcon(getContext().getPackageManager())) .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { getActivity().startActivity(theIntent); return true; } }).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); } } boolean writable = true, readable = true; for (OpenPath p : mContentAdapter.getSelectedSet()) { if (writable && !p.canWrite()) writable = false; if (readable && !p.canRead()) readable = false; if (!readable) break; } OpenPath last = mContentAdapter.getSelectedSet().get(getSelectedCount() - 1); MenuUtils.setMenuEnabled(menu, writable, R.id.menu_context_delete, R.id.menu_context_cut); MenuUtils.setMenuEnabled(menu, readable, R.id.menu_context_copy, R.id.menu_context_cut, R.id.menu_context_download, R.id.menu_context_rename, R.id.menu_context_zip); if (last instanceof CloudOpsHandler) MenuUtils.setMenuShowAsAction(menu, MenuItem.SHOW_AS_ACTION_ALWAYS, R.id.menu_context_download); if (num == 1) { MenuUtils.setMenuVisible(menu, true, R.id.menu_context_bookmark); if (!last.isDirectory()) MenuUtils.setMenuShowAsAction(menu, MenuItem.SHOW_AS_ACTION_NEVER, R.id.menu_context_bookmark); if (last.isFile()) mRename.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS); } else { mRename.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); MenuUtils.setMenuVisible(menu, false, R.id.menu_context_heatmap); } mRename.setVisible(num == 1); mInfo.setVisible(num == 1); viewPageNum = num; return true; } @SuppressLint("NewApi") @Override public boolean onActionItemClicked(final ActionMode mode, MenuItem item) { final CopyOnWriteArrayList<OpenPath> selections = mContentAdapter.getSelectedSet(); final OpenPath last = selections.get(selections.size() - 1); switch (item.getItemId()) { case R.id.menu_context_selectall: mContentAdapter.selectAll(); mode.invalidate(); break; case R.id.menu_context_copy: getClipboard().addAll(selections); deselectAll(); break; case R.id.menu_context_delete: getEventHandler().deleteFile(selections, ContentFragment.this, true); deselectAll(); break; case R.id.menu_context_zip: OpenPath intoPath = mPath; if (!(intoPath instanceof OpenFile)) intoPath = OpenFile.getExternalMemoryDrive(true); final OpenPath folder = intoPath; final OpenPath[] toZip = selections.toArray(new OpenPath[selections.size()]); if (toZip.length == 0) return false; String zname = toZip[0].getName(); String type = EventHandler.DefaultCompressionType.toString().toLowerCase(); if (toZip.length > 1) { if (last != null && last.getParent() != null) zname = last.getParent().getName() + "-" + new SimpleDateFormat("yyyyMMdd-HHmm").format(new Date()); if (type.equals("gz") || type.equals("bz2")) type = "t" + type; } zname += "." + type; final String def = zname; showZipDialog(intoPath, def, folder, selections, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (which != DialogInterface.BUTTON_NEUTRAL) deselectAll(); } }); break; case R.id.menu_context_rename: getEventHandler().renameFile(last, last.isDirectory(), getActivity()); finishMode(mode); break; case R.id.menu_context_info: DialogHandler.showFileInfo(getExplorer(), last); break; default: if (onOptionsItemSelected(item)) return true; break; } // } return true; } @Override public void onDestroyActionMode(ActionMode mode) { // Clear this before onDeselectAll() to prevent onDeselectAll() from // trying to close the // contextual mode again. setActionMode(null); if (mClosedByUser) { // Clear selection, only when the contextual mode is explicitly // closed by the user. // // We close the contextual mode when the fragment becomes // temporary invisible // (i.e. mIsVisible == false) too, in which case we want to keep // the selection. deselectAll(); } if (mGrid != null) mGrid.invalidateViews(); } } @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { if (position == 0 && Preferences.Pref_ShowUp) return false; OpenPath path = getContentAdapter().getItem(position); toggleSelection(view, path); return true; } private void toggleSelection(View view, OpenPath path) { // view.invalidate(); mContentAdapter.toggleSelected(path, view); } public void notifyDataSetChanged() { if (getExplorer() == null) return; if (!Thread.currentThread().equals(OpenExplorer.UiThread)) { OpenExplorer.getHandler().post(new Runnable() { public void run() { notifyDataSetChanged(); } }); return; } if (mContentAdapter == null) { mContentAdapter = getContentAdapter(); } mContentAdapter.finalize(); if (mGrid != null && (mGrid.getAdapter() == null || !mGrid.getAdapter().equals(mContentAdapter))) mGrid.setAdapter(mContentAdapter); // if(mContentAdapter != null) // mContentAdapter.updateData(); mContentAdapter.notifyDataSetChanged(); boolean empty = mContentAdapter == null || mContentAdapter.getCount() == 0; if (empty) ViewUtils.setText(getView(), getString(!mPath.isLoaded() ? R.string.s_status_loading : R.string.no_items, ""), android.R.id.empty); ViewUtils.setViewsVisibleNow(getView(), empty, android.R.id.empty); updateStatus(); // TODO check to see if this is the source of inefficiency // if(mGrid != null) // mGrid.invalidateViews(); } }