Merge branch 'master' of github.com:owncloud/android into multiSelect
authortobiasKaminsky <tobias@kaminsky.me>
Tue, 29 Sep 2015 19:13:31 +0000 (21:13 +0200)
committertobiasKaminsky <tobias@kaminsky.me>
Tue, 29 Sep 2015 19:13:31 +0000 (21:13 +0200)
12 files changed:
res/layout/grid_image.xml
res/layout/grid_item.xml
res/menu/multiple_file_actions_menu.xml [new file with mode: 0644]
src/com/owncloud/android/datamodel/OCFile.java
src/com/owncloud/android/files/FileOperationsHelper.java
src/com/owncloud/android/ui/activity/FileActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/FolderPickerActivity.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java
src/com/owncloud/android/ui/dialog/AccountActionsDialogFragment.java
src/com/owncloud/android/ui/fragment/ExtendedListFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

index 383c615..b6580e9 100644 (file)
             android:layout_marginBottom="4dp"\r
             android:layout_marginRight="4dp"\r
             android:src="@drawable/ic_favorite" />\r
+\r
+        <ImageView\r
+            android:id="@+id/custom_checkbox"\r
+            android:layout_width="wrap_content"\r
+            android:layout_height="wrap_content"\r
+            android:layout_gravity="center_vertical|bottom"\r
+            android:layout_marginLeft="4dp"\r
+            android:layout_marginRight="4dp"\r
+            android:gravity=""\r
+            android:src="@android:drawable/checkbox_off_background" />\r
     </FrameLayout>\r
 \r
 </LinearLayout>
\ No newline at end of file
index d0f3d0f..23efe9a 100644 (file)
             android:layout_marginRight="2dp"\r
             android:src="@drawable/ic_favorite" />\r
 \r
-\r
+        <ImageView\r
+            android:id="@+id/custom_checkbox"\r
+            android:layout_width="wrap_content"\r
+            android:layout_height="wrap_content"\r
+            android:layout_gravity="center_vertical|bottom"\r
+            android:layout_marginLeft="4dp"\r
+            android:layout_marginRight="4dp"\r
+            android:gravity=""\r
+            android:src="@android:drawable/checkbox_off_background"\r
+            android:elevation="30dp" />\r
 \r
     </FrameLayout>\r
 \r
diff --git a/res/menu/multiple_file_actions_menu.xml b/res/menu/multiple_file_actions_menu.xml
new file mode 100644 (file)
index 0000000..fce1654
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ownCloud Android client application
+
+  Copyright (C) 2012  Bartek Przybylski
+  Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/action_download_file"
+        android:title="@string/filedetails_download"
+        android:icon="@drawable/ic_action_download"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_move"
+        android:title="@string/actionbar_move"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_copy"
+        android:title="@android:string/copy"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_remove_file"
+        android:title="@string/common_remove"
+        android:icon="@android:drawable/ic_menu_delete"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_favorite_file"
+        android:title="@string/favorite"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_unfavorite_file"
+        android:title="@string/unfavorite"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+</menu>
index 4baf1ea..9e77f0d 100644 (file)
@@ -27,17 +27,16 @@ import android.webkit.MimeTypeMap;
 import com.owncloud.android.lib.common.utils.Log_OC;
 
 import java.io.File;
+import java.io.Serializable;
 
 import third_parties.daveKoeller.AlphanumComparator;
 public class OCFile implements Parcelable, Comparable<OCFile> {
 
-    public static final Parcelable.Creator<OCFile> CREATOR = new Parcelable.Creator<OCFile>() {
-        @Override
+    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
         public OCFile createFromParcel(Parcel source) {
             return new OCFile(source);
         }
 
-        @Override
         public OCFile[] newArray(int size) {
             return new OCFile[size];
         }
index 2237028..55368f4 100644 (file)
@@ -43,6 +43,8 @@ import com.owncloud.android.ui.dialog.ShareLinkToDialog;
 
 import org.apache.http.protocol.HTTP;
 
+import java.util.ArrayList;
+
 /**
  *
  */
@@ -205,10 +207,14 @@ public class FileOperationsHelper {
         }
     }
 
+    public void syncFiles(ArrayList<OCFile> files) {
+        for (OCFile file: files) {
+            syncFile(file);
+        }
+    }
 
     public void syncFile(OCFile file) {
-
-        if (!file.isFolder()){
+        if (!file.isFolder()) {
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             intent.setAction(OperationsService.ACTION_SYNC_FILE);
             intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
@@ -216,7 +222,7 @@ public class FileOperationsHelper {
             intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
             mFileActivity.showLoadingDialog();
-            
+
         } else {
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
@@ -226,6 +232,12 @@ public class FileOperationsHelper {
         }
     }
 
+    public void toggleFavorites(ArrayList<OCFile> files, boolean isFavorite){
+        for (OCFile file: files) {
+            toggleFavorite(file, isFavorite);
+        }
+    }
+
     public void toggleFavorite(OCFile file, boolean isFavorite) {
         file.setFavorite(isFavorite);
         mFileActivity.getStorageManager().saveFile(file);
@@ -329,7 +341,8 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
         mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
 
-        mFileActivity.showLoadingDialog();
+        // TODO Tobi loading dialog?
+        // mFileActivity.showLoadingDialog();
     }
 
     /**
index 1c21cab..d74a4a6 100644 (file)
@@ -847,11 +847,15 @@ public class FileActivity extends AppCompatActivity
      */
     public void showLoadingDialog() {
         // Construct dialog
-        LoadingDialog loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
-        FragmentManager fm = getSupportFragmentManager();
-        FragmentTransaction ft = fm.beginTransaction();
-        loading.show(ft, DIALOG_WAIT_TAG);
-
+        Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
+        if (frag == null) {
+            Log_OC.d(TAG, "show loading dialog");
+            LoadingDialog loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
+            FragmentManager fm = getSupportFragmentManager();
+            FragmentTransaction ft = fm.beginTransaction();
+            loading.show(ft, DIALOG_WAIT_TAG);
+            fm.executePendingTransactions();
+        }
     }
 
 
@@ -861,6 +865,7 @@ public class FileActivity extends AppCompatActivity
     public void dismissLoadingDialog() {
         Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
         if (frag != null) {
+            Log_OC.d(TAG, "dismiss loading dialog");
             LoadingDialog loading = (LoadingDialog) frag;
             loading.dismiss();
         }
index 20bcdce..cf9b29b 100644 (file)
@@ -26,6 +26,7 @@ import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.AuthenticatorException;
 import android.annotation.TargetApi;
+import android.os.Parcelable;
 import android.support.v7.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -107,6 +108,8 @@ import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.UriUtils;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
 
 /**
  * Displays, what files the user has available in his ownCloud.
@@ -764,8 +767,12 @@ public class FileDisplayActivity extends HookActivity
      */
     private void requestMoveOperation(Intent data, int resultCode) {
         OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
-        OCFile targetFile = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FILE);
-        getFileOperationsHelper().moveFile(folderToMoveAt, targetFile);
+
+        ArrayList<OCFile> files = data.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
+
+        for (Parcelable file : files) {
+            getFileOperationsHelper().moveFile(folderToMoveAt, (OCFile) file);
+        }
     }
 
     /**
@@ -776,8 +783,12 @@ public class FileDisplayActivity extends HookActivity
      */
     private void requestCopyOperation(Intent data, int resultCode) {
         OCFile folderToMoveAt = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
-        OCFile targetFile = data.getParcelableExtra(FolderPickerActivity.EXTRA_FILE);
-        getFileOperationsHelper().copyFile(folderToMoveAt, targetFile);
+
+        ArrayList<OCFile> files = data.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
+
+        for (Parcelable file : files) {
+            getFileOperationsHelper().copyFile(folderToMoveAt, (OCFile) file);
+        }
     }
 
     @Override
index 4b558f0..56daee7 100644 (file)
@@ -62,6 +62,8 @@ import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.utils.ErrorMessageAdapter;
 
+import java.util.ArrayList;
+
 public class FolderPickerActivity extends FileActivity implements FileFragment.ContainerActivity, 
     OnClickListener, OnEnforceableRefreshListener {
 
@@ -69,6 +71,8 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
                                                             + ".EXTRA_FOLDER";
     public static final String EXTRA_FILE = UploadFilesActivity.class.getCanonicalName()
                                                             + ".EXTRA_FILE";
+    public static final String EXTRA_FILES = UploadFilesActivity.class.getCanonicalName()
+            + ".EXTRA_FILES";
     //TODO: Think something better
 
     private SyncBroadcastReceiver mSyncBroadcastReceiver;
@@ -373,12 +377,16 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
         } else if (v == mChooseBtn) {
             Intent i = getIntent();
             Parcelable targetFile = i.getParcelableExtra(FolderPickerActivity.EXTRA_FILE);
+            ArrayList<Parcelable> targetFiles = i.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
 
             Intent data = new Intent();
             data.putExtra(EXTRA_FOLDER, getCurrentFolder());
             if (targetFile != null) {
                 data.putExtra(EXTRA_FILE, targetFile);
             }
+            if (targetFiles != null){
+                data.putParcelableArrayListExtra(EXTRA_FILES, targetFiles);
+            }
             setResult(RESULT_OK, data);
             finish();
         }
index 5e94e0f..272a7ff 100644 (file)
@@ -25,12 +25,16 @@ package com.owncloud.android.ui.adapter;
 \r
 \r
 import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
 import java.util.Vector;\r
 \r
 import android.accounts.Account;\r
 import android.content.Context;\r
 import android.content.SharedPreferences;\r
 import android.graphics.Bitmap;\r
+import android.graphics.Color;\r
 import android.os.Build;\r
 import android.preference.PreferenceManager;\r
 import android.text.format.DateUtils;\r
@@ -79,6 +83,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };\r
 \r
     private SharedPreferences mAppPreferences;\r
+\r
+    private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();\r
     \r
     public FileListListAdapter(\r
             boolean justFolders, \r
@@ -195,32 +201,32 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 case LIST_ITEM:\r
                     TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
                     TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
-                    ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+\r
 \r
                     lastModV.setVisibility(View.VISIBLE);\r
                     lastModV.setText(showRelativeTimestamp(file));\r
 \r
-                    checkBoxV.setVisibility(View.GONE);\r
+\r
 \r
                     fileSizeV.setVisibility(View.VISIBLE);\r
                     fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
 \r
                     if (!file.isFolder()) {\r
-                        AbsListView parentList = (AbsListView)parent;\r
-                        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
-                            if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
-                                checkBoxV.setVisibility(View.GONE);\r
-                            } else {\r
-                                if (parentList.isItemChecked(position)) {\r
-                                    checkBoxV.setImageResource(\r
-                                            android.R.drawable.checkbox_on_background);\r
-                                } else {\r
-                                    checkBoxV.setImageResource(\r
-                                            android.R.drawable.checkbox_off_background);\r
-                                }\r
-                                checkBoxV.setVisibility(View.VISIBLE);\r
-                            }\r
-                        }\r
+//                        AbsListView parentList = (AbsListView)parent;\r
+//                        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
+//                            if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+//                                checkBoxV.setVisibility(View.GONE);\r
+//                            } else {\r
+//                                if (parentList.isItemChecked(position)) {\r
+//                                    checkBoxV.setImageResource(\r
+//                                            android.R.drawable.checkbox_on_background);\r
+//                                } else {\r
+//                                    checkBoxV.setImageResource(\r
+//                                            android.R.drawable.checkbox_off_background);\r
+//                                }\r
+//                                checkBoxV.setVisibility(View.VISIBLE);\r
+//                            }\r
+//                        }\r
 \r
                     } else { //Folder\r
                         fileSizeV.setVisibility(View.INVISIBLE);\r
@@ -282,6 +288,25 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 \r
                     break;\r
             }\r
+\r
+            ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+            checkBoxV.setVisibility(View.GONE);\r
+\r
+            AbsListView parentList = (AbsListView)parent;\r
+            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
+                if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+                    checkBoxV.setVisibility(View.GONE);\r
+                } else if (parentList.getCheckedItemCount() > 0){\r
+                    if (parentList.isItemChecked(position)) {\r
+                        checkBoxV.setImageResource(\r
+                                android.R.drawable.checkbox_on_background);\r
+                    } else {\r
+                        checkBoxV.setImageResource(\r
+                                android.R.drawable.checkbox_off_background);\r
+                    }\r
+                    checkBoxV.setVisibility(View.VISIBLE);\r
+                }\r
+            }\r
             \r
             // For all Views\r
             \r
@@ -342,6 +367,12 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             }\r
         }\r
 \r
+        if (mSelection.get(position) != null) {\r
+            view.setBackgroundColor(Color.rgb(248, 248, 248));\r
+        } else {\r
+            view.setBackgroundColor(Color.WHITE);\r
+        }\r
+\r
         return view;\r
     }\r
 \r
@@ -487,4 +518,41 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     public void setGridMode(boolean gridMode) {\r
         mGridMode = gridMode;\r
     }\r
+\r
+    public void setNewSelection(int position, boolean checked) {\r
+        mSelection.put(position, checked);\r
+        notifyDataSetChanged();\r
+    }\r
+\r
+    public void removeSelection(int position) {\r
+        mSelection.remove(position);\r
+        notifyDataSetChanged();\r
+    }\r
+\r
+    public void removeSelection(){\r
+         mSelection.clear();\r
+        notifyDataSetChanged();\r
+    }\r
+\r
+    public ArrayList<Integer> getCheckedItemPositions() {\r
+        ArrayList<Integer> ids = new ArrayList<Integer>();\r
+\r
+        for (Map.Entry<Integer, Boolean> entry : mSelection.entrySet()){\r
+            if (entry.getValue()){\r
+                ids.add(entry.getKey());\r
+            }\r
+        }\r
+        return ids;\r
+    }\r
+\r
+    public ArrayList<OCFile> getCheckedItems() {\r
+        ArrayList<OCFile> files = new ArrayList<OCFile>();\r
+\r
+        for (Map.Entry<Integer, Boolean> entry : mSelection.entrySet()){\r
+            if (entry.getValue()){\r
+                files.add((OCFile) getItem(entry.getKey()));\r
+            }\r
+        }\r
+        return files;\r
+    }\r
 }\r
index 96414a0..e8289d0 100644 (file)
@@ -39,6 +39,7 @@ public class AccountActionsDialogFragment extends DialogFragment implements
      * Listener interface for the file action fragment.
      */
     public interface FileActionsDialogFragmentListener {
+        // TODO Tobi change to int array?
         public boolean onFileActionChosen(int menuId, int filePosition);
     }
 
index 24015d0..954b8e4 100644 (file)
@@ -26,7 +26,10 @@ import android.os.Build;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.ActionMode;
 import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AbsListView;
@@ -134,15 +137,61 @@ public class ExtendedListFragment extends Fragment
                              Bundle savedInstanceState) {
         Log_OC.d(TAG, "onCreateView");
 
+        // TODO Tobi remove
+//         AbsListView.MultiChoiceModeListener listener = new AbsListView.MultiChoiceModeListener() {
+//            @Override
+//            public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
+//                // Capture total checked items
+//                final int checkedCount = mListView.getCheckedItemCount();
+//                // Set the CAB title according to total checked items
+//                mode.setTitle(checkedCount + " Selected");
+//                // Calls toggleSelection method from ListViewAdapter Class
+//                 // mAdapter.toggleSelection(position);
+//
+//                if (checked){
+//                    mAdapter.setNewSelection(position,checked);
+//                } else {
+//                    mAdapter.removeSelection(position);
+//                }
+//            }
+//
+//            @Override
+//            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+//                mode.getMenuInflater().inflate(R.menu.context, menu);
+//                return true;
+//            }
+//
+//            @Override
+//            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+//                return false;
+//            }
+//
+//            @Override
+//            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+//                return false;
+//            }
+//
+//            @Override
+//            public void onDestroyActionMode(ActionMode mode) {
+//                // mAdapter.removeSelection();
+//            }
+//        };
+
         View v = inflater.inflate(R.layout.list_fragment, null);
 
         mListView = (ExtendedListView)(v.findViewById(R.id.list_root));
         mListView.setOnItemClickListener(this);
+        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+        // mListView.setMultiChoiceModeListener(listener);
         mListFooterView = inflater.inflate(R.layout.list_footer, null, false);
 
         mGridView = (GridViewWithHeaderAndFooter) (v.findViewById(R.id.grid_root));
         mGridView.setNumColumns(GridView.AUTO_FIT);
         mGridView.setOnItemClickListener(this);
+        mGridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+
+        // mGridView.setMultiChoiceModeListener(listener);
+
         mGridFooterView = inflater.inflate(R.layout.list_footer, null, false);
 
         if (savedInstanceState != null) {
index 02bd845..8a8589d 100644 (file)
@@ -25,12 +25,15 @@ package com.owncloud.android.ui.fragment;
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.Parcelable;
 import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.ActionMode;
 import android.view.ContextMenu;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.AdapterContextMenuInfo;
 import android.widget.PopupMenu;
@@ -57,13 +60,14 @@ import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.ui.preview.PreviewTextFragment;
 
 import java.io.File;
+import java.util.ArrayList;
 
 /**
  * A Fragment that lists all files and folders in a given path.
  *
  * TODO refactor to get rid of direct dependency on FileDisplayActivity
  */
-public class OCFileListFragment extends ExtendedListFragment implements FileActionsDialogFragment.FileActionsDialogFragmentListener {
+public class OCFileListFragment extends ExtendedListFragment {
     
     private static final String TAG = OCFileListFragment.class.getSimpleName();
 
@@ -80,11 +84,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
     private OCFile mFile = null;
     private FileListListAdapter mAdapter;
     private boolean mJustFolders;
-    
-    private OCFile mTargetFile;
-    
-   
-    
+
     /**
      * {@inheritDoc}
      */
@@ -147,16 +147,56 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
   }
 
     private void registerLongClickListener() {
-        getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
-            public boolean onItemLongClick(AdapterView<?> arg0, View v,
-                                           int index, long arg3) {
-                showFileAction(index);
+        getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
+            private Menu menu;
+
+            @Override
+            public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
+                final int checkedCount = getListView().getCheckedItemCount();
+                // TODO Tobi extract to values
+                mode.setTitle(checkedCount + " selected");
+
+                if (checked) {
+                    mAdapter.setNewSelection(position, checked);
+                } else {
+                    mAdapter.removeSelection(position);
+                }
+
+                // TODO maybe change: only recreate menu if count changes
+                menu.clear();
+                if (checkedCount == 1) {
+                    createContextMenu(menu);
+                } else {
+                    // download, move, copy, delete
+                    getActivity().getMenuInflater().inflate(R.menu.multiple_file_actions_menu, menu);
+                }
+
+            }
+
+            @Override
+            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+                this.menu = menu;
                 return true;
             }
+
+            @Override
+            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+                return false;
+            }
+
+            @Override
+            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+                return onFileActionChosen(item.getItemId());
+            }
+
+            @Override
+            public void onDestroyActionMode(ActionMode mode) {
+                mAdapter.removeSelection();
+            }
         });
     }
 
-
+    // TODO Tobi needed?
     private void showFileAction(int fileIndex) {
         Bundle args = getArguments();
         PopupMenu pm = new PopupMenu(getActivity(),null);
@@ -298,17 +338,18 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
     /**
      * {@inheritDoc}
      */
-    @Override
-    public void onCreateContextMenu(
-            ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+    // TODO Tobi needed?
+    public void createContextMenu(Menu menu) {
         Bundle args = getArguments();
         boolean allowContextualActions =
                 (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
         if (allowContextualActions) {
             MenuInflater inflater = getActivity().getMenuInflater();
             inflater.inflate(R.menu.file_actions_menu, menu);
-            AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
-            OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
+            OCFile targetFile = null;
+            if (mAdapter.getCheckedItems().size() == 1){
+                targetFile = mAdapter.getCheckedItems().get(0);
+            }
 
             if (mContainerActivity.getStorageManager() != null) {
                 FileMenuFilter mf = new FileMenuFilter(
@@ -334,86 +375,124 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean onFileActionChosen(int menuId, int filePosition) {
-        mTargetFile = (OCFile) mAdapter.getItem(filePosition);
-        switch (menuId) {
-            case R.id.action_share_file: {
-                mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
-                return true;
-            }
-            case R.id.action_open_file_with: {
-                mContainerActivity.getFileOperationsHelper().openFile(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);
+    public boolean onFileActionChosen(int menuId) {
+        if (mAdapter.getCheckedItems().size() == 1){
+            OCFile mTargetFile = mAdapter.getCheckedItems().get(0);
 
-                } else {
-                    mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
+            switch (menuId) {
+                case R.id.action_share_file: {
+                    mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
+                    return true;
                 }
-                return true;
-            }
-            case R.id.action_move: {
-                Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+                case R.id.action_open_file_with: {
+                    mContainerActivity.getFileOperationsHelper().openFile(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);
 
-                // Pass mTargetFile that contains info of selected file/folder
-                action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
-                getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
-                return true;
-            }
-            case R.id.action_favorite_file: {
-                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
-                return true;
+                    } else {
+                        mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
+                    }
+                    return true;
+                }
+                case R.id.action_move: {
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+
+                    // Pass mTargetFile that contains info of selected file/folder
+                    ArrayList files = new ArrayList();
+                    files.add(mTargetFile);
+                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, files);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
+                    return true;
+                }
+                case R.id.action_favorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
+                    return true;
+                }
+                case R.id.action_unfavorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
+                    return true;
+                }
+                case R.id.action_copy:
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+
+                    // Pass mTargetFile that contains info of selected file/folder
+                    action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
+                    return true;
+                default:
+                    return false;
             }
-            case R.id.action_unfavorite_file: {
-                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
-                return true;
+        } else {
+            ArrayList<OCFile> mTargetFiles = mAdapter.getCheckedItems();
+
+            switch (menuId) {
+//                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().syncFiles(mTargetFiles);
+                    return true;
+                }
+                case R.id.action_move: {
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
+                    return true;
+                }
+                case R.id.action_favorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, true);
+                    return true;
+                }
+                case R.id.action_unfavorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, false);
+                    return true;
+                }
+                case R.id.action_copy:
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
+                    return true;
+                default:
+                    return false;
             }
-            case R.id.action_copy:
-                Intent action = new Intent(getActivity(), FolderPickerActivity.class);
-
-                // Pass mTargetFile that contains info of selected file/folder
-                action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
-                getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
-                return true;
-            default:
-                return false;
         }
+
     }
     
     /**
@@ -422,7 +501,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
     @Override
     public boolean onContextItemSelected (MenuItem item) {
         AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
-        boolean matched = onFileActionChosen(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).position);
+        boolean matched = onFileActionChosen(item.getItemId());
         if(!matched) {
             return super.onContextItemSelected(item);
         } else {