- requested changes by review by davivel
authortobiasKaminsky <tobias@kaminsky.me>
Fri, 17 Oct 2014 19:28:48 +0000 (21:28 +0200)
committertobiasKaminsky <tobias@kaminsky.me>
Fri, 17 Oct 2014 19:28:48 +0000 (21:28 +0200)
src/com/owncloud/android/datamodel/AlphanumComparator.java [deleted file]
src/com/owncloud/android/datamodel/OCFile.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/third_parties/daveKoeller/AlphanumComparator.java [new file with mode: 0644]

diff --git a/src/com/owncloud/android/datamodel/AlphanumComparator.java b/src/com/owncloud/android/datamodel/AlphanumComparator.java
deleted file mode 100644 (file)
index f78ef25..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*\r
- * The Alphanum Algorithm is an improved sorting algorithm for strings\r
- * containing numbers.  Instead of sorting numbers in ASCII order like\r
- * a standard sort, this algorithm sorts numbers in numeric order.\r
- *\r
- * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com\r
- *\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-package com.owncloud.android.datamodel;\r
-import java.util.Comparator;\r
-\r
-/**\r
- * This is an updated version with enhancements made by Daniel Migowski,\r
- * Andre Bogus, and David Koelle\r
- *\r
- * To convert to use Templates (Java 1.5+):\r
- *   - Change "implements Comparator" to "implements Comparator<String>"\r
- *   - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"\r
- *   - Remove the type checking and casting in compare().\r
- *\r
- * To use this class:\r
- *   Use the static "sort" method from the java.util.Collections class:\r
- *   Collections.sort(your list, new AlphanumComparator());\r
- */\r
-public class AlphanumComparator implements Comparator<OCFile>\r
-{\r
-    private final boolean isDigit(char ch)\r
-    {\r
-        return ch >= 48 && ch <= 57;\r
-    }\r
-\r
-    /** Length of string is passed in for improved efficiency (only need to calculate it once) **/\r
-    private final String getChunk(String s, int slength, int marker)\r
-    {\r
-        StringBuilder chunk = new StringBuilder();\r
-        char c = s.charAt(marker);\r
-        chunk.append(c);\r
-        marker++;\r
-        if (isDigit(c))\r
-        {\r
-            while (marker < slength)\r
-            {\r
-                c = s.charAt(marker);\r
-                if (!isDigit(c))\r
-                    break;\r
-                chunk.append(c);\r
-                marker++;\r
-            }\r
-        } else\r
-        {\r
-            while (marker < slength)\r
-            {\r
-                c = s.charAt(marker);\r
-                if (isDigit(c))\r
-                    break;\r
-                chunk.append(c);\r
-                marker++;\r
-            }\r
-        }\r
-        return chunk.toString();\r
-    }\r
-\r
-    public int compare(OCFile o1, OCFile o2)\r
-    {\r
-        String s1 = (String)o1.getRemotePath().toLowerCase();\r
-        String s2 = (String)o2.getRemotePath().toLowerCase();\r
-\r
-        int thisMarker = 0;\r
-        int thatMarker = 0;\r
-        int s1Length = s1.length();\r
-        int s2Length = s2.length();\r
-\r
-        while (thisMarker < s1Length && thatMarker < s2Length)\r
-        {\r
-            String thisChunk = getChunk(s1, s1Length, thisMarker);\r
-            thisMarker += thisChunk.length();\r
-\r
-            String thatChunk = getChunk(s2, s2Length, thatMarker);\r
-            thatMarker += thatChunk.length();\r
-\r
-            // If both chunks contain numeric characters, sort them numerically\r
-            int result = 0;\r
-            if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))\r
-            {\r
-                // Simple chunk comparison by length.\r
-                int thisChunkLength = thisChunk.length();\r
-                result = thisChunkLength - thatChunk.length();\r
-                // If equal, the first different number counts\r
-                if (result == 0)\r
-                {\r
-                    for (int i = 0; i < thisChunkLength; i++)\r
-                    {\r
-                        result = thisChunk.charAt(i) - thatChunk.charAt(i);\r
-                        if (result != 0)\r
-                        {\r
-                            return result;\r
-                        }\r
-                    }\r
-                }\r
-            } else\r
-            {\r
-                result = thisChunk.compareTo(thatChunk);\r
-            }\r
-\r
-            if (result != 0)\r
-                return result;\r
-        }\r
-\r
-        return s1Length - s2Length;\r
-    }\r
-}\r
index 03ec163..c44638b 100644 (file)
@@ -20,8 +20,9 @@ package com.owncloud.android.datamodel;
 
 import java.io.File;
 
-import com.owncloud.android.utils.Log_OC;
+import third_parties.daveKoeller.AlphanumComparator;
 
+import com.owncloud.android.utils.Log_OC;
 
 import android.os.Parcel;
 import android.os.Parcelable;
index c24d88b..12ea118 100644 (file)
@@ -493,7 +493,7 @@ OnSslUntrustedCertListener, SwipeRefreshLayout.OnRefreshListener {
         }
         case R.id.action_sort: {
             SharedPreferences appPreferences = PreferenceManager
-                    .getDefaultSharedPreferences(getApplicationContext());
+                    .getDefaultSharedPreferences(this);
             
             // Read sorting order, default to sort by name ascending
             Integer sortOrder = appPreferences
index a90773e..a2cb3be 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.Comparator;\r
 import java.util.Vector;\r
 \r
+import third_parties.daveKoeller.AlphanumComparator;\r
 import android.accounts.Account;\r
 import android.content.Context;\r
 import android.content.SharedPreferences;\r
@@ -37,7 +38,6 @@ import android.widget.TextView;
 \r
 import com.owncloud.android.R;\r
 import com.owncloud.android.authentication.AccountUtils;\r
-import com.owncloud.android.datamodel.AlphanumComparator;\r
 import com.owncloud.android.datamodel.FileDataStorageManager;\r
 import com.owncloud.android.datamodel.OCFile;\r
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
@@ -45,8 +45,6 @@ import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;\r
 import com.owncloud.android.utils.DisplayUtils;\r
 import com.owncloud.android.utils.FileStorageUtils;\r
-import com.owncloud.android.utils.Log_OC;\r
-\r
 \r
 /**\r
  * This Adapter populates a ListView with all files and folders in an ownCloud\r
@@ -56,409 +54,422 @@ import com.owncloud.android.utils.Log_OC;
  * \r
  */\r
 public class FileListListAdapter extends BaseAdapter implements ListAdapter {\r
-    private final static String PERMISSION_SHARED_WITH_ME = "S";\r
-\r
-    private Context mContext;\r
-    private OCFile mFile = null;\r
-    private Vector<OCFile> mFiles = null;\r
-    private boolean mJustFolders;\r
-\r
-    private FileDataStorageManager mStorageManager;
-    private Account mAccount;
-    private ComponentsGetter mTransferServiceGetter;\r
-    private Integer sortOrder;\r
-    private Boolean sortAscending;\r
-    private SharedPreferences appPreferences;\r
-    \r
-    public FileListListAdapter(\r
-            boolean justFolders, \r
-            Context context, \r
-            ComponentsGetter transferServiceGetter\r
-            ) {\r
-        mJustFolders = justFolders;\r
-        mContext = context;\r
-        mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
-        mTransferServiceGetter = transferServiceGetter;\r
-        \r
-        appPreferences = PreferenceManager\r
-                .getDefaultSharedPreferences(mContext);\r
-        \r
-        // Read sorting order, default to sort by name ascending\r
-        sortOrder = appPreferences\r
-                .getInt("sortOrder", 0);\r
-        sortAscending = appPreferences.getBoolean("sortAscending", true);\r
-        \r
-    }
-\r
-    @Override\r
-    public boolean areAllItemsEnabled() {\r
-        return true;\r
-    }\r
-\r
-    @Override\r
-    public boolean isEnabled(int position) {\r
-        return true;\r
-    }\r
-\r
-    @Override\r
-    public int getCount() {\r
-        return mFiles != null ? mFiles.size() : 0;\r
-    }\r
-\r
-    @Override\r
-    public Object getItem(int position) {\r
-        if (mFiles == null || mFiles.size() <= position)\r
-            return null;\r
-        return mFiles.get(position);\r
-    }\r
-\r
-    @Override\r
-    public long getItemId(int position) {\r
-        if (mFiles == null || mFiles.size() <= position)\r
-            return 0;\r
-        return mFiles.get(position).getFileId();\r
-    }\r
-\r
-    @Override\r
-    public int getItemViewType(int position) {\r
-        return 0;\r
-    }\r
-\r
-    @Override\r
-    public View getView(int position, View convertView, ViewGroup parent) {\r
-        View view = convertView;\r
-        if (view == null) {\r
-            LayoutInflater inflator = (LayoutInflater) mContext\r
-                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
-            view = inflator.inflate(R.layout.list_item, null);\r
-        }\r
-    \r
-        if (mFiles != null && mFiles.size() > position) {\r
-            OCFile file = mFiles.get(position);\r
-            TextView fileName = (TextView) view.findViewById(R.id.Filename);\r
-            String name = file.getFileName();\r
-\r
-            fileName.setText(name);\r
-            ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);\r
-            ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
-            ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);\r
-            sharedWithMeIconV.setVisibility(View.GONE);\r
-\r
-            ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);\r
-            localStateView.bringToFront();\r
-            FileDownloaderBinder downloaderBinder = mTransferServiceGetter.getFileDownloaderBinder();\r
-            FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();\r
-            if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) {\r
-                localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
-                localStateView.setVisibility(View.VISIBLE);\r
-            } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {\r
-                localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
-                localStateView.setVisibility(View.VISIBLE);\r
-            } else if (file.isDown()) {\r
-                localStateView.setImageResource(R.drawable.local_file_indicator);\r
-                localStateView.setVisibility(View.VISIBLE);\r
-            } else {\r
-                localStateView.setVisibility(View.INVISIBLE);\r
-            }\r
-            \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
-            if (!file.isFolder()) {\r
-                fileSizeV.setVisibility(View.VISIBLE);\r
-                fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
-                lastModV.setVisibility(View.VISIBLE);\r
-                lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
-                // this if-else is needed even thoe fav icon is visible by default\r
-                // because android reuses views in listview\r
-                if (!file.keepInSync()) {\r
-                    view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
-                } else {\r
-                    view.findViewById(R.id.imageView3).setVisibility(View.VISIBLE);\r
-                }\r
-                \r
-                ListView parentList = (ListView)parent;\r
-                if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) { \r
-                    checkBoxV.setVisibility(View.GONE);\r
-                } else {\r
-                    if (parentList.isItemChecked(position)) {\r
-                        checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);\r
-                    } else {\r
-                        checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);\r
-                    }\r
-                    checkBoxV.setVisibility(View.VISIBLE);\r
-                }\r
-\r
-                fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
-\r
-                if (checkIfFileIsSharedWithMe(file)) {\r
-                    sharedWithMeIconV.setVisibility(View.VISIBLE);\r
-                }\r
-            } \r
-            else {\r
-                if (FileStorageUtils.getDefaultSavePathFor(mAccount.name, file) != null){\r
-                    fileSizeV.setVisibility(View.VISIBLE);\r
-                    fileSizeV.setText(getFolderSizeHuman(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)));\r
-                } else {\r
-                    fileSizeV.setVisibility(View.INVISIBLE);\r
-                }\r
-                \r
-                lastModV.setVisibility(View.VISIBLE);\r
-                lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
-                checkBoxV.setVisibility(View.GONE);\r
-                view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
-\r
-                if (checkIfFileIsSharedWithMe(file)) {\r
-                    fileIcon.setImageResource(R.drawable.shared_with_me_folder);\r
-                    sharedWithMeIconV.setVisibility(View.VISIBLE);\r
-                } else {\r
-                    fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
-                }\r
-\r
-                // If folder is sharedByLink, icon folder must be changed to\r
-                // folder-public one\r
-                if (file.isShareByLink()) {\r
-                    fileIcon.setImageResource(R.drawable.folder_public);\r
-                }\r
-            }\r
-\r
-            if (file.isShareByLink()) {\r
-                sharedIconV.setVisibility(View.VISIBLE);\r
-            } else {\r
-                sharedIconV.setVisibility(View.GONE);\r
-            }\r
-        }\r
-\r
-        return view;\r
-    }\r
-    \r
-    /**\r
-     * Local Folder size in human readable format\r
-     * @param path String\r
-     * @return Size in human readable format\r
-     */\r
-    private String getFolderSizeHuman(String path) {\r
-\r
-        File dir = new File(path);\r
-\r
-        if(dir.exists()) {\r
-            long bytes = getFolderSize(dir);\r
-            if (bytes < 1024) return bytes + " B";\r
-            int exp = (int) (Math.log(bytes) / Math.log(1024));\r
-            String pre = ("KMGTPE").charAt(exp-1) + "";\r
-\r
-            return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);\r
-        }\r
-\r
-        return "0 B";\r
-    }\r
-\r
-    /**\r
-     * Local Folder size\r
-     * @param dir File\r
-     * @return Size in bytes\r
-     */\r
-    private long getFolderSize(File dir) {\r
-        if (dir.exists()) {\r
-            long result = 0;\r
-            File[] fileList = dir.listFiles();\r
-            for(int i = 0; i < fileList.length; i++) {\r
-                if(fileList[i].isDirectory()) {\r
-                    result += getFolderSize(fileList[i]);\r
-                } else {\r
-                    result += fileList[i].length();\r
-                }\r
-            }\r
-            return result;\r
-        }\r
-        return 0;\r
-    } \r
-\r
-    @Override\r
-    public int getViewTypeCount() {\r
-        return 1;\r
-    }\r
-\r
-    @Override\r
-    public boolean hasStableIds() {\r
-        return true;\r
-    }\r
-\r
-    @Override\r
-    public boolean isEmpty() {\r
-        return (mFiles == null || mFiles.isEmpty());\r
-    }\r
-\r
-    /**\r
-     * Change the adapted directory for a new one\r
-     * @param directory                 New file to adapt. Can be NULL, meaning "no content to adapt".\r
-     * @param updatedStorageManager     Optional updated storage manager; used to replace mStorageManager if is different (and not NULL)\r
-     */\r
-    public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager) {\r
-        mFile = directory;\r
-        if (updatedStorageManager != null && updatedStorageManager != mStorageManager) {\r
-            mStorageManager = updatedStorageManager;\r
-            mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
-        }\r
-        if (mStorageManager != null) {\r
-            mFiles = mStorageManager.getFolderContent(mFile);\r
-            if (mJustFolders) {\r
-                mFiles = getFolders(mFiles);\r
-            }\r
-        } else {\r
-            mFiles = null;\r
-        }\r
-\r
-        sortDirectory();\r
-    }\r
-    \r
-    /**\r
-     * Sorts all filenames, regarding last user decision \r
-     */\r
-    private void sortDirectory(){\r
-        switch (sortOrder){\r
-        case 0:\r
-            sortByName(sortAscending);\r
-            break;\r
-        case 1:\r
-            sortByDate(sortAscending);\r
-            break;\r
-        case 2: \r
-            sortBySize(sortAscending);\r
-            break;\r
-        }\r
-        \r
-        notifyDataSetChanged();\r
-    }\r
-    \r
-    \r
-    /**\r
-     * Filter for getting only the folders\r
-     * @param files\r
-     * @return Vector<OCFile>\r
-     */\r
-    public Vector<OCFile> getFolders(Vector<OCFile> files) {\r
-        Vector<OCFile> ret = new Vector<OCFile>(); \r
-        OCFile current = null; \r
-        for (int i=0; i<files.size(); i++) {\r
-            current = files.get(i);\r
-            if (current.isFolder()) {\r
-                ret.add(current);\r
-            }\r
-        }\r
-        return ret;\r
-    }\r
-    \r
-    \r
-    /**\r
-     * Check if parent folder does not include 'S' permission and if file/folder\r
-     * is shared with me\r
-     * \r
-     * @param file: OCFile\r
-     * @return boolean: True if it is shared with me and false if it is not\r
-     */\r
-    private boolean checkIfFileIsSharedWithMe(OCFile file) {\r
-        return (mFile.getPermissions() != null && !mFile.getPermissions().contains(PERMISSION_SHARED_WITH_ME)\r
-                && file.getPermissions() != null && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));\r
-    }\r
-\r
-    /**\r
-     * Sorts list by Date\r
-     * @param sortAscending true: ascending, false: descending\r
-     */\r
-    private void sortByDate(boolean sortAscending){\r
-        final Integer val;\r
-        if (sortAscending){\r
-            val = 1;\r
-        } else {\r
-            val = -1;\r
-        }\r
-        \r
-        Collections.sort(mFiles, new Comparator<OCFile>() {\r
-            public int compare(OCFile o1, OCFile o2) {\r
-                if (o1.isFolder() && o2.isFolder()) {\r
-                    return val * Long.compare(o1.getModificationTimestamp(), o2.getModificationTimestamp());\r
-                }\r
-                else if (o1.isFolder()) {\r
-                    return -1;\r
-                } else if (o2.isFolder()) {\r
-                    return 1;\r
-                } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){\r
-                    return 0;\r
-                } else {\r
-                    return val * Long.compare(o1.getModificationTimestamp(), o2.getModificationTimestamp());\r
-                }\r
-            }\r
-        });\r
-    }\r
-\r
-    /**\r
-     * Sorts list by Size\r
-     * @param sortAscending true: ascending, false: descending\r
-     */\r
-    private void sortBySize(boolean sortAscending){\r
-        final Integer val;\r
-        if (sortAscending){\r
-            val = 1;\r
-        } else {\r
-            val = -1;\r
-        }\r
-        \r
-        Collections.sort(mFiles, new Comparator<OCFile>() {\r
-            public int compare(OCFile o1, OCFile o2) {\r
-                if (o1.isFolder() && o2.isFolder()) {\r
-                    return val * Long.compare(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1))), \r
-                                              getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));\r
-                }\r
-                else if (o1.isFolder()) {\r
-                    return -1;\r
-                } else if (o2.isFolder()) {\r
-                    return 1;\r
-                } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){\r
-                    return 0;\r
-                } else {\r
-                    return val * Long.compare(o1.getFileLength(), o2.getFileLength());\r
-                }\r
-            }\r
-        });\r
-    }\r
-\r
-    /**\r
-     * Sorts list by Name\r
-     * @param sortAscending true: ascending, false: descending\r
-     */\r
-    private void sortByName(boolean sortAscending){\r
-        final Integer val;\r
-        if (sortAscending){\r
-            val = 1;\r
-        } else {\r
-            val = -1;\r
-        }\r
-\r
-        Collections.sort(mFiles, new Comparator<OCFile>() {\r
-            public int compare(OCFile o1, OCFile o2) {\r
-                if (o1.isFolder() && o2.isFolder()) {\r
-                    return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());\r
-                } else if (o1.isFolder()) {\r
-                    return -1;\r
-                } else if (o2.isFolder()) {\r
-                    return 1;\r
-                }\r
-                return val * new AlphanumComparator().compare(o1, o2);\r
-            }\r
-        });\r
-    }\r
-\r
-    public void setSortOrder(Integer order, boolean ascending) {\r
-        SharedPreferences.Editor editor = appPreferences.edit();\r
-        editor.putInt("sortOrder", order);\r
-        editor.putBoolean("sortAscending", ascending);\r
-        editor.commit();\r
-        \r
-        sortOrder = order;\r
-        sortAscending = ascending;\r
-        \r
-        sortDirectory();\r
-    }    \r
+       private final static String PERMISSION_SHARED_WITH_ME = "S";\r
+\r
+       private final Context mContext;\r
+       private OCFile mFile = null;\r
+       private Vector<OCFile> mFiles = null;\r
+       private final boolean mJustFolders;\r
+\r
+       private FileDataStorageManager mStorageManager;\r
+       private Account mAccount;\r
+       private final ComponentsGetter mTransferServiceGetter;\r
+       private Integer mSortOrder;\r
+       public static final Integer mSortName = 0;\r
+       public static final Integer mSortDate = 1;\r
+       public static final Integer mSortSize = 2;\r
+       private Boolean mSortAscending;\r
+       private final SharedPreferences mAppPreferences;\r
+\r
+       public FileListListAdapter(boolean justFolders, Context context, ComponentsGetter transferServiceGetter) {\r
+               mJustFolders = justFolders;\r
+               mContext = context;\r
+               mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
+               mTransferServiceGetter = transferServiceGetter;\r
+\r
+               mAppPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);\r
+\r
+               // Read sorting order, default to sort by name ascending\r
+               mSortOrder = mAppPreferences.getInt("sortOrder", mSortName);\r
+               mSortAscending = mAppPreferences.getBoolean("sortAscending", true);\r
+\r
+       }\r
+\r
+       @Override\r
+       public boolean areAllItemsEnabled() {\r
+               return true;\r
+       }\r
+\r
+       @Override\r
+       public boolean isEnabled(int position) {\r
+               return true;\r
+       }\r
+\r
+       @Override\r
+       public int getCount() {\r
+               return mFiles != null ? mFiles.size() : 0;\r
+       }\r
+\r
+       @Override\r
+       public Object getItem(int position) {\r
+               if (mFiles == null || mFiles.size() <= position)\r
+                       return null;\r
+               return mFiles.get(position);\r
+       }\r
+\r
+       @Override\r
+       public long getItemId(int position) {\r
+               if (mFiles == null || mFiles.size() <= position)\r
+                       return 0;\r
+               return mFiles.get(position).getFileId();\r
+       }\r
+\r
+       @Override\r
+       public int getItemViewType(int position) {\r
+               return 0;\r
+       }\r
+\r
+       @Override\r
+       public View getView(int position, View convertView, ViewGroup parent) {\r
+               View view = convertView;\r
+               if (view == null) {\r
+                       LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
+                       view = inflator.inflate(R.layout.list_item, null);\r
+               }\r
+\r
+               if (mFiles != null && mFiles.size() > position) {\r
+                       OCFile file = mFiles.get(position);\r
+                       TextView fileName = (TextView) view.findViewById(R.id.Filename);\r
+                       String name = file.getFileName();\r
+\r
+                       fileName.setText(name);\r
+                       ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);\r
+                       ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
+                       ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);\r
+                       sharedWithMeIconV.setVisibility(View.GONE);\r
+\r
+                       ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);\r
+                       localStateView.bringToFront();\r
+                       FileDownloaderBinder downloaderBinder = mTransferServiceGetter.getFileDownloaderBinder();\r
+                       FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();\r
+                       if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) {\r
+                               localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
+                               localStateView.setVisibility(View.VISIBLE);\r
+                       } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {\r
+                               localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
+                               localStateView.setVisibility(View.VISIBLE);\r
+                       } else if (file.isDown()) {\r
+                               localStateView.setImageResource(R.drawable.local_file_indicator);\r
+                               localStateView.setVisibility(View.VISIBLE);\r
+                       } else {\r
+                               localStateView.setVisibility(View.INVISIBLE);\r
+                       }\r
+\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
+                       if (!file.isFolder()) {\r
+                               fileSizeV.setVisibility(View.VISIBLE);\r
+                               fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
+                               lastModV.setVisibility(View.VISIBLE);\r
+                               lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
+                               // this if-else is needed even thoe fav icon is visible by\r
+                               // default\r
+                               // because android reuses views in listview\r
+                               if (!file.keepInSync()) {\r
+                                       view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
+                               } else {\r
+                                       view.findViewById(R.id.imageView3).setVisibility(View.VISIBLE);\r
+                               }\r
+\r
+                               ListView parentList = (ListView) parent;\r
+                               if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) {\r
+                                       checkBoxV.setVisibility(View.GONE);\r
+                               } else {\r
+                                       if (parentList.isItemChecked(position)) {\r
+                                               checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);\r
+                                       } else {\r
+                                               checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);\r
+                                       }\r
+                                       checkBoxV.setVisibility(View.VISIBLE);\r
+                               }\r
+\r
+                               fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
+\r
+                               if (checkIfFileIsSharedWithMe(file)) {\r
+                                       sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                               }\r
+                       } else {\r
+                               // TODO Re-enable when server supports folder-size calculation\r
+                               // if (FileStorageUtils.getDefaultSavePathFor(mAccount.name,\r
+                               // file) != null) {\r
+                               // fileSizeV.setVisibility(View.VISIBLE);\r
+                               // fileSizeV\r
+                               // .setText(getFolderSizeHuman(FileStorageUtils.getDefaultSavePathFor(mAccount.name,\r
+                               // file)));\r
+                               // } else {\r
+                               fileSizeV.setVisibility(View.INVISIBLE);\r
+                               // }\r
+\r
+                               lastModV.setVisibility(View.VISIBLE);\r
+                               lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
+                               checkBoxV.setVisibility(View.GONE);\r
+                               view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
+\r
+                               if (checkIfFileIsSharedWithMe(file)) {\r
+                                       fileIcon.setImageResource(R.drawable.shared_with_me_folder);\r
+                                       sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                               } else {\r
+                                       fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName()));\r
+                               }\r
+\r
+                               // If folder is sharedByLink, icon folder must be changed to\r
+                               // folder-public one\r
+                               if (file.isShareByLink()) {\r
+                                       fileIcon.setImageResource(R.drawable.folder_public);\r
+                               }\r
+                       }\r
+\r
+                       if (file.isShareByLink()) {\r
+                               sharedIconV.setVisibility(View.VISIBLE);\r
+                       } else {\r
+                               sharedIconV.setVisibility(View.GONE);\r
+                       }\r
+               }\r
+\r
+               return view;\r
+       }\r
+\r
+       /**\r
+        * Local Folder size in human readable format\r
+        * \r
+        * @param path\r
+        *            String\r
+        * @return Size in human readable format\r
+        */\r
+       private String getFolderSizeHuman(String path) {\r
+\r
+               File dir = new File(path);\r
+\r
+               if (dir.exists()) {\r
+                       long bytes = getFolderSize(dir);\r
+                       return DisplayUtils.bytesToHumanReadable(bytes);\r
+               }\r
+\r
+               return "0 B";\r
+       }\r
+\r
+       /**\r
+        * Local Folder size\r
+        * \r
+        * @param dir\r
+        *            File\r
+        * @return Size in bytes\r
+        */\r
+       private long getFolderSize(File dir) {\r
+               if (dir.exists()) {\r
+                       long result = 0;\r
+                       File[] fileList = dir.listFiles();\r
+                       for (int i = 0; i < fileList.length; i++) {\r
+                               if (fileList[i].isDirectory()) {\r
+                                       result += getFolderSize(fileList[i]);\r
+                               } else {\r
+                                       result += fileList[i].length();\r
+                               }\r
+                       }\r
+                       return result;\r
+               }\r
+               return 0;\r
+       }\r
+\r
+       @Override\r
+       public int getViewTypeCount() {\r
+               return 1;\r
+       }\r
+\r
+       @Override\r
+       public boolean hasStableIds() {\r
+               return true;\r
+       }\r
+\r
+       @Override\r
+       public boolean isEmpty() {\r
+               return (mFiles == null || mFiles.isEmpty());\r
+       }\r
+\r
+       /**\r
+        * Change the adapted directory for a new one\r
+        * \r
+        * @param directory\r
+        *            New file to adapt. Can be NULL, meaning "no content to adapt".\r
+        * @param updatedStorageManager\r
+        *            Optional updated storage manager; used to replace\r
+        *            mStorageManager if is different (and not NULL)\r
+        */\r
+       public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager) {\r
+               mFile = directory;\r
+               if (updatedStorageManager != null && updatedStorageManager != mStorageManager) {\r
+                       mStorageManager = updatedStorageManager;\r
+                       mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
+               }\r
+               if (mStorageManager != null) {\r
+                       mFiles = mStorageManager.getFolderContent(mFile);\r
+                       if (mJustFolders) {\r
+                               mFiles = getFolders(mFiles);\r
+                       }\r
+               } else {\r
+                       mFiles = null;\r
+               }\r
+\r
+               sortDirectory();\r
+       }\r
+\r
+       /**\r
+        * Sorts all filenames, regarding last user decision\r
+        */\r
+       private void sortDirectory() {\r
+               switch (mSortOrder) {\r
+               case 0:\r
+                       sortByName(mSortAscending);\r
+                       break;\r
+               case 1:\r
+                       sortByDate(mSortAscending);\r
+                       break;\r
+               case 2:\r
+                       sortBySize(mSortAscending);\r
+                       break;\r
+               }\r
+\r
+               notifyDataSetChanged();\r
+       }\r
+\r
+       /**\r
+        * Filter for getting only the folders\r
+        * \r
+        * @param files\r
+        * @return Vector<OCFile>\r
+        */\r
+       public Vector<OCFile> getFolders(Vector<OCFile> files) {\r
+               Vector<OCFile> ret = new Vector<OCFile>();\r
+               OCFile current = null;\r
+               for (int i = 0; i < files.size(); i++) {\r
+                       current = files.get(i);\r
+                       if (current.isFolder()) {\r
+                               ret.add(current);\r
+                       }\r
+               }\r
+               return ret;\r
+       }\r
+\r
+       /**\r
+        * Check if parent folder does not include 'S' permission and if file/folder\r
+        * is shared with me\r
+        * \r
+        * @param file\r
+        *            : OCFile\r
+        * @return boolean: True if it is shared with me and false if it is not\r
+        */\r
+       private boolean checkIfFileIsSharedWithMe(OCFile file) {\r
+               return (mFile.getPermissions() != null && !mFile.getPermissions().contains(PERMISSION_SHARED_WITH_ME)\r
+                               && file.getPermissions() != null && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));\r
+       }\r
+\r
+       /**\r
+        * Sorts list by Date\r
+        * \r
+        * @param sortAscending\r
+        *            true: ascending, false: descending\r
+        */\r
+       private void sortByDate(boolean sortAscending) {\r
+               final Integer val;\r
+               if (sortAscending) {\r
+                       val = 1;\r
+               } else {\r
+                       val = -1;\r
+               }\r
+\r
+               Collections.sort(mFiles, new Comparator<OCFile>() {\r
+                       @Override\r
+                       public int compare(OCFile o1, OCFile o2) {\r
+                               if (o1.isFolder() && o2.isFolder()) {\r
+                                       return val * Long.compare(o1.getModificationTimestamp(), o2.getModificationTimestamp());\r
+                               } else if (o1.isFolder()) {\r
+                                       return -1;\r
+                               } else if (o2.isFolder()) {\r
+                                       return 1;\r
+                               } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0) {\r
+                                       return 0;\r
+                               } else {\r
+                                       return val * Long.compare(o1.getModificationTimestamp(), o2.getModificationTimestamp());\r
+                               }\r
+                       }\r
+               });\r
+       }\r
+\r
+       /**\r
+        * Sorts list by Size\r
+        * \r
+        * @param sortAscending\r
+        *            true: ascending, false: descending\r
+        */\r
+       private void sortBySize(boolean sortAscending) {\r
+               final Integer val;\r
+               if (sortAscending) {\r
+                       val = 1;\r
+               } else {\r
+                       val = -1;\r
+               }\r
+\r
+               Collections.sort(mFiles, new Comparator<OCFile>() {\r
+                       @Override\r
+                       public int compare(OCFile o1, OCFile o2) {\r
+                               if (o1.isFolder() && o2.isFolder()) {\r
+                                       return val\r
+                                                       * Long.compare(\r
+                                                                       getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1))),\r
+                                                                       getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));\r
+                               } else if (o1.isFolder()) {\r
+                                       return -1;\r
+                               } else if (o2.isFolder()) {\r
+                                       return 1;\r
+                               } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0) {\r
+                                       return 0;\r
+                               } else {\r
+                                       return val * Long.compare(o1.getFileLength(), o2.getFileLength());\r
+                               }\r
+                       }\r
+               });\r
+       }\r
+\r
+       /**\r
+        * Sorts list by Name\r
+        * \r
+        * @param sortAscending\r
+        *            true: ascending, false: descending\r
+        */\r
+       private void sortByName(boolean sortAscending) {\r
+               final Integer val;\r
+               if (sortAscending) {\r
+                       val = 1;\r
+               } else {\r
+                       val = -1;\r
+               }\r
+\r
+               Collections.sort(mFiles, new Comparator<OCFile>() {\r
+                       @Override\r
+                       public int compare(OCFile o1, OCFile o2) {\r
+                               if (o1.isFolder() && o2.isFolder()) {\r
+                                       return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());\r
+                               } else if (o1.isFolder()) {\r
+                                       return -1;\r
+                               } else if (o2.isFolder()) {\r
+                                       return 1;\r
+                               }\r
+                               return val * new AlphanumComparator().compare(o1, o2);\r
+                       }\r
+               });\r
+       }\r
+\r
+       public void setSortOrder(Integer order, boolean ascending) {\r
+               SharedPreferences.Editor editor = mAppPreferences.edit();\r
+               editor.putInt("sortOrder", order);\r
+               editor.putBoolean("sortAscending", ascending);\r
+               editor.commit();\r
+\r
+               mSortOrder = order;\r
+               mSortAscending = ascending;\r
+\r
+               sortDirectory();\r
+       }\r
 }\r
index 7cac16e..19829fa 100644 (file)
@@ -54,347 +54,340 @@ import com.owncloud.android.utils.Log_OC;
  * @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 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((SwipeRefreshLayout.OnRefreshListener) 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);
-        }
-        
-        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();
-            
-            // 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;
-        }
-    }
-    
-    public void sortByName(boolean descending){
-        mAdapter.setSortOrder(0, descending);
-    } 
-    
-    public void sortByDate(boolean descending){
-        mAdapter.setSortOrder(1, descending);
-    }
-
-    public void sortBySize(boolean descending){
-        mAdapter.setSortOrder(2, descending);
-    }    
+
+       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 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((SwipeRefreshLayout.OnRefreshListener) 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);
+               }
+
+               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();
+
+                       // 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;
+               }
+       }
+
+       public void sortByName(boolean descending) {
+               mAdapter.setSortOrder(FileListListAdapter.mSortName, descending);
+       }
+
+       public void sortByDate(boolean descending) {
+               mAdapter.setSortOrder(FileListListAdapter.mSortDate, descending);
+       }
+
+       public void sortBySize(boolean descending) {
+               mAdapter.setSortOrder(FileListListAdapter.mSortSize, descending);
+       }
 }
diff --git a/src/third_parties/daveKoeller/AlphanumComparator.java b/src/third_parties/daveKoeller/AlphanumComparator.java
new file mode 100644 (file)
index 0000000..e6bd6f3
--- /dev/null
@@ -0,0 +1,129 @@
+/*\r
+ * The Alphanum Algorithm is an improved sorting algorithm for strings\r
+ * containing numbers.  Instead of sorting numbers in ASCII order like\r
+ * a standard sort, this algorithm sorts numbers in numeric order.\r
+ *\r
+ * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com\r
+ *\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
+ *\r
+ */\r
+\r
+package third_parties.daveKoeller;\r
+import java.util.Comparator;\r
+\r
+import com.owncloud.android.datamodel.OCFile;\r
+\r
+/**\r
+ * This is an updated version with enhancements made by Daniel Migowski,\r
+ * Andre Bogus, and David Koelle\r
+ *\r
+ * To convert to use Templates (Java 1.5+):\r
+ *   - Change "implements Comparator" to "implements Comparator<String>"\r
+ *   - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"\r
+ *   - Remove the type checking and casting in compare().\r
+ *\r
+ * To use this class:\r
+ *   Use the static "sort" method from the java.util.Collections class:\r
+ *   Collections.sort(your list, new AlphanumComparator());\r
+ */\r
+public class AlphanumComparator implements Comparator<OCFile>\r
+{\r
+    private final boolean isDigit(char ch)\r
+    {\r
+        return ch >= 48 && ch <= 57;\r
+    }\r
+\r
+    /** Length of string is passed in for improved efficiency (only need to calculate it once) **/\r
+    private final String getChunk(String s, int slength, int marker)\r
+    {\r
+        StringBuilder chunk = new StringBuilder();\r
+        char c = s.charAt(marker);\r
+        chunk.append(c);\r
+        marker++;\r
+        if (isDigit(c))\r
+        {\r
+            while (marker < slength)\r
+            {\r
+                c = s.charAt(marker);\r
+                if (!isDigit(c))\r
+                    break;\r
+                chunk.append(c);\r
+                marker++;\r
+            }\r
+        } else\r
+        {\r
+            while (marker < slength)\r
+            {\r
+                c = s.charAt(marker);\r
+                if (isDigit(c))\r
+                    break;\r
+                chunk.append(c);\r
+                marker++;\r
+            }\r
+        }\r
+        return chunk.toString();\r
+    }\r
+\r
+    public int compare(OCFile o1, OCFile o2)\r
+    {\r
+        String s1 = (String)o1.getRemotePath().toLowerCase();\r
+        String s2 = (String)o2.getRemotePath().toLowerCase();\r
+\r
+        int thisMarker = 0;\r
+        int thatMarker = 0;\r
+        int s1Length = s1.length();\r
+        int s2Length = s2.length();\r
+\r
+        while (thisMarker < s1Length && thatMarker < s2Length)\r
+        {\r
+            String thisChunk = getChunk(s1, s1Length, thisMarker);\r
+            thisMarker += thisChunk.length();\r
+\r
+            String thatChunk = getChunk(s2, s2Length, thatMarker);\r
+            thatMarker += thatChunk.length();\r
+\r
+            // If both chunks contain numeric characters, sort them numerically\r
+            int result = 0;\r
+            if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))\r
+            {\r
+                // Simple chunk comparison by length.\r
+                int thisChunkLength = thisChunk.length();\r
+                result = thisChunkLength - thatChunk.length();\r
+                // If equal, the first different number counts\r
+                if (result == 0)\r
+                {\r
+                    for (int i = 0; i < thisChunkLength; i++)\r
+                    {\r
+                        result = thisChunk.charAt(i) - thatChunk.charAt(i);\r
+                        if (result != 0)\r
+                        {\r
+                            return result;\r
+                        }\r
+                    }\r
+                }\r
+            } else\r
+            {\r
+                result = thisChunk.compareTo(thatChunk);\r
+            }\r
+\r
+            if (result != 0)\r
+                return result;\r
+        }\r
+\r
+        return s1Length - s2Length;\r
+    }\r
+}\r