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> -->
<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>
<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>
--- /dev/null
+/*\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
} else if (another.isFolder()) {
return 1;
}
- return getRemotePath().toLowerCase().compareTo(another.getRemotePath().toLowerCase());
+ return new AlphanumComparator().compare(this, another);
}
@Override
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;
private String DIALOG_UNTRUSTED_CERT;
private OCFile mWaitingToSend;
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
Log_OC.d(TAG, "onCreate() start");
}
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);
}
}
}
}
+
+ private void sortByDate(boolean ascending){
+ getListOfFilesFragment().sortByDate(ascending);
+ }
+
+ private void sortBySize(boolean ascending){
+ getListOfFilesFragment().sortBySize(ascending);
+ }
+
+ private void sortByName(boolean ascending){
+ getListOfFilesFragment().sortByName(ascending);
+ }
}
\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
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
\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
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
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
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
return (Bitmap) mThumbnailCache.getBitmap(key);\r
}\r
}\r
- return null;\r
+ return null;
}
\r
@Override\r
}\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
\r
return view;\r
}\r
- \r
+
public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {\r
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);\r
\r
}\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
} 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
&& 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
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);
+ }
}