From: tobiasKaminsky Date: Fri, 24 Oct 2014 16:34:39 +0000 (+0200) Subject: -rebase on develop X-Git-Tag: oc-android-1.7.0_signed~91^2~3 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/13758253ca8f1acd8974e7bd0d25c9cf1f338060?ds=inline;hp=--cc -rebase on develop --- 13758253ca8f1acd8974e7bd0d25c9cf1f338060 diff --git a/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java b/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java index 5c66bfe7..1b7a1ddf 100644 --- a/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java +++ b/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java @@ -18,6 +18,8 @@ package com.owncloud.android.ui.fragment; +import java.util.ArrayList; + import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.view.LayoutInflater; @@ -30,9 +32,10 @@ import android.widget.ListView; import android.widget.TextView; import com.actionbarsherlock.app.SherlockFragment; -import com.owncloud.android.Log_OC; import com.owncloud.android.R; +import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.ExtendedListView; +import com.owncloud.android.ui.activity.OnEnforceableRefreshListener; /** * TODO extending SherlockListFragment instead of SherlockFragment @@ -70,7 +73,7 @@ implements OnItemClickListener, OnEnforceableRefreshListener { } public void setFooterView(View footer) { - mList.addFooterView(footer); + mList.addFooterView(footer, null, false); mList.invalidate(); } diff --git a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java new file mode 100644 index 00000000..34caa028 --- /dev/null +++ b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -0,0 +1,447 @@ +/* ownCloud Android client application + * Copyright (C) 2011 Bartek Przybylski + * Copyright (C) 2012-2014 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * 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 . + * + */ +package com.owncloud.android.ui.fragment; + +import java.io.File; +import java.util.Vector; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.view.ContextMenu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.AdapterContextMenuInfo; +import android.widget.TextView; +import android.view.LayoutInflater; + +import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.FileMenuFilter; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.ui.activity.FileDisplayActivity; +import com.owncloud.android.ui.activity.MoveActivity; +import com.owncloud.android.ui.activity.OnEnforceableRefreshListener; +import com.owncloud.android.ui.adapter.FileListListAdapter; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; +import com.owncloud.android.ui.dialog.RenameFileDialogFragment; +import com.owncloud.android.ui.preview.PreviewImageFragment; +import com.owncloud.android.ui.preview.PreviewMediaFragment; + +/** + * A Fragment that lists all files and folders in a given path. + * + * TODO refactorize to get rid of direct dependency on FileDisplayActivity + * + * @author Bartek Przybylski + * @author masensio + * @author David A. Velasco + */ +public class OCFileListFragment extends ExtendedListFragment { + + private static final String TAG = OCFileListFragment.class.getSimpleName(); + + private static final String MY_PACKAGE = OCFileListFragment.class.getPackage() != null ? + OCFileListFragment.class.getPackage().getName() : "com.owncloud.android.ui.fragment"; + + public final static String ARG_JUST_FOLDERS = MY_PACKAGE + ".JUST_FOLDERS"; + public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL"; + + private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE"; + + private FileFragment.ContainerActivity mContainerActivity; + + private OCFile mFile = null; + private FileListListAdapter mAdapter; + private View mFooterView; + + private OCFile mTargetFile; + + + /** + * {@inheritDoc} + */ + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + Log_OC.e(TAG, "onAttach"); + try { + mContainerActivity = (FileFragment.ContainerActivity) activity; + + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + " must implement " + + FileFragment.ContainerActivity.class.getSimpleName()); + } + try { + setOnRefreshListener((OnEnforceableRefreshListener) activity); + + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + " must implement " + + SwipeRefreshLayout.OnRefreshListener.class.getSimpleName()); + } + } + + + @Override + public void onDetach() { + setOnRefreshListener(null); + mContainerActivity = null; + super.onDetach(); + } + + /** + * {@inheritDoc} + */ + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + Log_OC.e(TAG, "onActivityCreated() start"); + + if (savedInstanceState != null) { + mFile = savedInstanceState.getParcelable(KEY_FILE); + } + + mFooterView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate( + R.layout.list_footer, null, false); + setFooterView(mFooterView); + + Bundle args = getArguments(); + boolean justFolders = (args == null) ? false : args.getBoolean(ARG_JUST_FOLDERS, false); + mAdapter = new FileListListAdapter( + justFolders, + getSherlockActivity(), + mContainerActivity + ); + setListAdapter(mAdapter); + + registerForContextMenu(getListView()); + getListView().setOnCreateContextMenuListener(this); + } + + /** + * Saves the current listed folder. + */ + @Override + public void onSaveInstanceState (Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(KEY_FILE, mFile); + } + + /** + * Call this, when the user presses the up button. + * + * Tries to move up the current folder one level. If the parent folder was removed from the + * database, it continues browsing up until finding an existing folders. + * + * return Count of folder levels browsed up. + */ + public int onBrowseUp() { + OCFile parentDir = null; + int moveCount = 0; + + if(mFile != null){ + FileDataStorageManager storageManager = mContainerActivity.getStorageManager(); + + String parentPath = null; + if (mFile.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) { + parentPath = new File(mFile.getRemotePath()).getParent(); + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : + parentPath + OCFile.PATH_SEPARATOR; + parentDir = storageManager.getFileByPath(parentPath); + moveCount++; + } else { + parentDir = storageManager.getFileByPath(OCFile.ROOT_PATH); + } + while (parentDir == null) { + parentPath = new File(parentPath).getParent(); + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : + parentPath + OCFile.PATH_SEPARATOR; + parentDir = storageManager.getFileByPath(parentPath); + moveCount++; + } // exit is granted because storageManager.getFileByPath("/") never returns null + mFile = parentDir; + + listDirectory(mFile); + + onRefresh(false); + + // restore index and top position + restoreIndexAndTopPosition(); + + } // else - should never happen now + + return moveCount; + } + + @Override + public void onItemClick(AdapterView l, View v, int position, long id) { + OCFile file = (OCFile) mAdapter.getItem(position); + if (file != null) { + if (file.isFolder()) { + // update state and view of this fragment + listDirectory(file); + // then, notify parent activity to let it update its state and view + mContainerActivity.onBrowsedDownTo(file); + // save index and top position + saveIndexAndTopPosition(position); + + } else { /// Click on a file + if (PreviewImageFragment.canBePreviewed(file)) { + // preview image - it handles the download, if needed + ((FileDisplayActivity)mContainerActivity).startImagePreview(file); + + } else if (file.isDown()) { + if (PreviewMediaFragment.canBePreviewed(file)) { + // media preview + ((FileDisplayActivity)mContainerActivity).startMediaPreview(file, 0, true); + } else { + mContainerActivity.getFileOperationsHelper().openFile(file); + } + + } else { + // automatic download, preview on finish + ((FileDisplayActivity)mContainerActivity).startDownloadForPreview(file); + } + + } + + } else { + Log_OC.d(TAG, "Null object in ListAdapter!!"); + } + + } + + /** + * {@inheritDoc} + */ + @Override + public void onCreateContextMenu ( + ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + Bundle args = getArguments(); + boolean allowContextualActions = + (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true); + if (allowContextualActions) { + MenuInflater inflater = getSherlockActivity().getMenuInflater(); + inflater.inflate(R.menu.file_actions_menu, menu); + AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; + OCFile targetFile = (OCFile) mAdapter.getItem(info.position); + + if (mContainerActivity.getStorageManager() != null) { + FileMenuFilter mf = new FileMenuFilter( + targetFile, + mContainerActivity.getStorageManager().getAccount(), + mContainerActivity, + getSherlockActivity() + ); + mf.filter(menu); + } + + /// additional restrictions for this fragment + // TODO allow in the future 'open with' for previewable files + MenuItem item = menu.findItem(R.id.action_open_file_with); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + /// TODO break this direct dependency on FileDisplayActivity... if possible + FileFragment frag = ((FileDisplayActivity)getSherlockActivity()).getSecondFragment(); + if (frag != null && frag instanceof FileDetailFragment && + frag.getFile().getFileId() == targetFile.getFileId()) { + item = menu.findItem(R.id.action_see_details); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + } + } + } + + + /** + * {@inhericDoc} + */ + @Override + public boolean onContextItemSelected (MenuItem item) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); + mTargetFile = (OCFile) mAdapter.getItem(info.position); + switch (item.getItemId()) { + case R.id.action_share_file: { + mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile); + return true; + } + case R.id.action_unshare_file: { + mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile); + return true; + } + case R.id.action_rename_file: { + RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile); + dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE); + return true; + } + case R.id.action_remove_file: { + RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile); + dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); + return true; + } + case R.id.action_download_file: + case R.id.action_sync_file: { + mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile); + return true; + } + case R.id.action_cancel_download: + case R.id.action_cancel_upload: { + ((FileDisplayActivity)mContainerActivity).cancelTransference(mTargetFile); + return true; + } + case R.id.action_see_details: { + mContainerActivity.showDetails(mTargetFile); + return true; + } + case R.id.action_send_file: { + // Obtain the file + if (!mTargetFile.isDown()) { // Download the file + Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded"); + ((FileDisplayActivity)mContainerActivity).startDownloadForSending(mTargetFile); + + } else { + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile); + } + return true; + } + case R.id.action_move: { + Intent action = new Intent(getActivity(), MoveActivity.class); + + // Pass mTargetFile that contains info of selected file/folder + action.putExtra(MoveActivity.EXTRA_TARGET_FILE, mTargetFile); + getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES); + return true; + } + default: + return super.onContextItemSelected(item); + } + } + + + /** + * Use this to query the {@link OCFile} that is currently + * being displayed by this fragment + * @return The currently viewed OCFile + */ + public OCFile getCurrentFile(){ + return mFile; + } + + /** + * Calls {@link OCFileListFragment#listDirectory(OCFile)} with a null parameter + */ + public void listDirectory(){ + listDirectory(null); + } + + /** + * Lists the given directory on the view. When the input parameter is null, + * it will either refresh the last known directory. list the root + * if there never was a directory. + * + * @param directory File to be listed + */ + public void listDirectory(OCFile directory) { + FileDataStorageManager storageManager = mContainerActivity.getStorageManager(); + if (storageManager != null) { + + // Check input parameters for null + if(directory == null){ + if(mFile != null){ + directory = mFile; + } else { + directory = storageManager.getFileByPath("/"); + if (directory == null) return; // no files, wait for sync + } + } + + + // If that's not a directory -> List its parent + if(!directory.isFolder()){ + Log_OC.w(TAG, "You see, that is not a directory -> " + directory.toString()); + directory = storageManager.getFileById(directory.getParentId()); + } + + mAdapter.swapDirectory(directory, storageManager); + if (mFile == null || !mFile.equals(directory)) { + mList.setSelectionFromTop(0, 0); + } + mFile = directory; + + // Update Footer + TextView footerText = (TextView) mFooterView.findViewById(R.id.footerText); + Log_OC.d("footer", String.valueOf(System.currentTimeMillis())); + footerText.setText(generateFooterText(directory)); + Log_OC.d("footer", String.valueOf(System.currentTimeMillis())); + } + } + + private String generateFooterText(OCFile directory) { + Integer files = 0; + Integer folders = 0; + + FileDataStorageManager storageManager = mContainerActivity.getStorageManager(); + Vector mFiles = storageManager.getFolderContent(mFile); + + for (OCFile ocFile : mFiles) { + if (ocFile.isFolder()) { + folders++; + } else { + files++; + } + } + + String output = ""; + + if (folders == 1) { + output = folders.toString() + " " + getResources().getString(R.string.file_list_folder) + ", "; + } else if (folders > 1) { + output = folders.toString() + " " + getResources().getString(R.string.file_list_folders) + ", "; + } + if (files == 1) { + output = output + files.toString() + " " + getResources().getString(R.string.file_list_file); + } else { + output = output + files.toString() + " " + getResources().getString(R.string.file_list_files); + } + return output; + } + + public void sortByName(boolean descending) { + mAdapter.setSortOrder(FileListListAdapter.SORT_NAME, descending); + } + + public void sortByDate(boolean descending) { + mAdapter.setSortOrder(FileListListAdapter.SORT_DATE, descending); + } + + public void sortBySize(boolean descending) { + mAdapter.setSortOrder(FileListListAdapter.SORT_SIZE, descending); + } + +}