Merge branch 'sortingFiles' of https://github.com/tobiasKaminsky/android into sorting...
authorjabarros <jabarros@solidgear.es>
Thu, 9 Oct 2014 15:26:02 +0000 (17:26 +0200)
committerjabarros <jabarros@solidgear.es>
Thu, 9 Oct 2014 15:26:02 +0000 (17:26 +0200)
Conflicts:
res/menu/main_menu.xml
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

res/menu/main_menu.xml
res/values-de/strings.xml
res/values/strings.xml
src/com/owncloud/android/datamodel/AlphanumComparator.java [new file with mode: 0644]
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

index 1df273e..6e64fcf 100644 (file)
         android:orderInCategory="2"
         android:showAsAction="never"
         android:title="@string/actionbar_logger"/>
+       <item
+        android:id="@+id/action_sort"
+        android:orderInCategory="2"
+        android:showAsAction="never"
+        android:title="@string/actionbar_sort"/>
 
     <!-- <item android:id="@+id/search" android:title="@string/actionbar_search" android:icon="@drawable/ic_action_search"></item> -->
 
index 0b536c1..e8f4319 100644 (file)
   <string name="actionbar_settings">Einstellungen</string>
   <string name="actionbar_see_details">Details</string>
   <string name="actionbar_send_file">Senden</string>
+  <string name="actionbar_sort">Sortieren</string>
+  <string name="actionbar_sort_title">Sortieren nach</string>
+  <string-array name="actionbar_sortby">
+       <item>A-Z</item>
+       <item>Neu - Alt</item>
+       <item>Groß - Klein</item>
+  </string-array>
   <string name="prefs_category_general">Allgemein</string>
   <string name="prefs_category_more">Mehr</string>
   <string name="prefs_accounts">Konten</string>
index 4c7cf34..4c5f57b 100644 (file)
     <string name="actionbar_settings">Settings</string>
     <string name="actionbar_see_details">Details</string>
     <string name="actionbar_send_file">Send</string>
+    <string name="actionbar_sort">Sort</string>
+    <string name="actionbar_sort_title">Sort by</string>
+    <string-array name="actionbar_sortby">
+       <item>A-Z</item>
+       <item>Newest - Oldest</item>
+       <item>Biggest - Smallest</item>
+    </string-array>
     <string name="prefs_category_general">General</string>
     <string name="prefs_category_more">More</string>
     <string name="prefs_accounts">Accounts</string>
diff --git a/src/com/owncloud/android/datamodel/AlphanumComparator.java b/src/com/owncloud/android/datamodel/AlphanumComparator.java
new file mode 100644 (file)
index 0000000..f78ef25
--- /dev/null
@@ -0,0 +1,127 @@
+/*\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 c3284fc..7ef9bc5 100644 (file)
@@ -460,7 +460,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         } else if (another.isFolder()) {
             return 1;
         }
-        return getRemotePath().toLowerCase().compareTo(another.getRemotePath().toLowerCase());
+        return new AlphanumComparator().compare(this, another);
     }
 
     @Override
index 21472fd..8560ddb 100644 (file)
@@ -48,7 +48,6 @@ import android.provider.MediaStore;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
@@ -151,7 +150,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
     private String DIALOG_UNTRUSTED_CERT;
     
     private OCFile mWaitingToSend;
-
+    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         Log_OC.d(TAG, "onCreate() start");
@@ -504,6 +503,38 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
             }
             break;
         }
+        case R.id.action_sort: {
+            SharedPreferences appPreferences = PreferenceManager
+                    .getDefaultSharedPreferences(getApplicationContext());
+            
+            // Read sorting order, default to sort by name ascending
+            Integer sortOrder = appPreferences
+                    .getInt("sortOrder", 0);
+            
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            builder.setTitle(R.string.actionbar_sort_title)
+            .setSingleChoiceItems(R.array.actionbar_sortby, sortOrder , new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    
+                    switch (which){
+                    case 0:
+                        sortByName(true);
+                        break;
+                    case 1:
+                        sortByDate(false);
+                        break;
+                    case 2:
+                        sortBySize(false);
+                        break;
+                    }
+                    
+                    dialog.dismiss();
+                    
+                }
+            });
+            builder.create().show();
+            break;
+        }
         default:
             retval = super.onOptionsItemSelected(item);
         }
@@ -1748,4 +1779,16 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
             }
         }
     }
+
+    private void sortByDate(boolean ascending){
+        getListOfFilesFragment().sortByDate(ascending);
+    }
+
+    private void sortBySize(boolean ascending){
+        getListOfFilesFragment().sortBySize(ascending);
+    }
+
+    private void sortByName(boolean ascending){
+        getListOfFilesFragment().sortByName(ascending);
+    }
 }
index ffdad17..ffc2d69 100644 (file)
@@ -19,10 +19,13 @@ package com.owncloud.android.ui.adapter;
 \r
 import java.io.File;\r
 import java.lang.ref.WeakReference;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
 import java.util.Vector;\r
 \r
 import android.accounts.Account;\r
 import android.content.Context;\r
+import android.content.SharedPreferences;\r
 import android.content.res.Resources;\r
 import android.graphics.Bitmap;\r
 import android.graphics.Bitmap.CompressFormat;\r
@@ -31,6 +34,7 @@ import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;\r
 import android.media.ThumbnailUtils;\r
 import android.os.AsyncTask;\r
+import android.preference.PreferenceManager;\r
 import android.util.TypedValue;\r
 import android.view.LayoutInflater;\r
 import android.view.View;\r
@@ -43,6 +47,7 @@ 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
@@ -51,6 +56,8 @@ import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.activity.ComponentsGetter;\r
 import com.owncloud.android.utils.BitmapUtils;\r
 import com.owncloud.android.utils.DisplayUtils;\r
+import com.owncloud.android.utils.FileStorageUtils;\r
+\r
 \r
 \r
 /**\r
@@ -74,6 +81,9 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private FileDataStorageManager mStorageManager;
     private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;\r
+    private Integer sortOrder;\r
+    private Boolean sortAscending;\r
+    private SharedPreferences appPreferences;\r
     \r
     private final Object thumbnailDiskCacheLock = new Object();\r
     private DiskLruImageCache mThumbnailCache;\r
@@ -93,6 +103,15 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         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
         defaultImg = BitmapFactory.decodeResource(mContext.getResources(), \r
                     DisplayUtils.getResourceId("image/png", "default.png"));\r
         \r
@@ -227,7 +246,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 return (Bitmap) mThumbnailCache.getBitmap(key);\r
             }\r
         }\r
-        return null;\r
+        return null;
     }
 \r
     @Override\r
@@ -361,8 +380,13 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 }\r
             } \r
             else {\r
-                fileSizeV.setVisibility(View.INVISIBLE);\r
-                //fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\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
+
                 lastModV.setVisibility(View.VISIBLE);\r
                 lastModV.setText(\r
                         DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp())\r
@@ -395,7 +419,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 \r
         return view;\r
     }\r
-    \r
+
     public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {\r
         final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);\r
 \r
@@ -424,6 +448,48 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
          }\r
          return null;\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
     @Override\r
     public int getViewTypeCount() {\r
@@ -461,6 +527,26 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         } 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
@@ -496,4 +582,103 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 && file.getPermissions() != null \r
                 && 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
 }\r
index 3665fe0..aff51d3 100644 (file)
@@ -386,5 +386,16 @@ public class OCFileListFragment extends ExtendedListFragment {
             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);
+    }    
 }