mirror of
https://github.com/nextcloud/android.git
synced 2024-11-23 13:45:35 +03:00
Merge branch 'sortingFiles' of https://github.com/tobiasKaminsky/android into sorting_files
Conflicts: res/menu/main_menu.xml src/com/owncloud/android/ui/activity/FileDisplayActivity.java src/com/owncloud/android/ui/adapter/FileListListAdapter.java
This commit is contained in:
commit
7d9fc6857e
8 changed files with 392 additions and 7 deletions
|
@ -49,6 +49,11 @@
|
|||
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> -->
|
||||
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
<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>
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
<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>
|
||||
|
|
127
src/com/owncloud/android/datamodel/AlphanumComparator.java
Normal file
127
src/com/owncloud/android/datamodel/AlphanumComparator.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* The Alphanum Algorithm is an improved sorting algorithm for strings
|
||||
* containing numbers. Instead of sorting numbers in ASCII order like
|
||||
* a standard sort, this algorithm sorts numbers in numeric order.
|
||||
*
|
||||
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.datamodel;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* This is an updated version with enhancements made by Daniel Migowski,
|
||||
* Andre Bogus, and David Koelle
|
||||
*
|
||||
* To convert to use Templates (Java 1.5+):
|
||||
* - Change "implements Comparator" to "implements Comparator<String>"
|
||||
* - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
|
||||
* - Remove the type checking and casting in compare().
|
||||
*
|
||||
* To use this class:
|
||||
* Use the static "sort" method from the java.util.Collections class:
|
||||
* Collections.sort(your list, new AlphanumComparator());
|
||||
*/
|
||||
public class AlphanumComparator implements Comparator<OCFile>
|
||||
{
|
||||
private final boolean isDigit(char ch)
|
||||
{
|
||||
return ch >= 48 && ch <= 57;
|
||||
}
|
||||
|
||||
/** Length of string is passed in for improved efficiency (only need to calculate it once) **/
|
||||
private final String getChunk(String s, int slength, int marker)
|
||||
{
|
||||
StringBuilder chunk = new StringBuilder();
|
||||
char c = s.charAt(marker);
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
if (isDigit(c))
|
||||
{
|
||||
while (marker < slength)
|
||||
{
|
||||
c = s.charAt(marker);
|
||||
if (!isDigit(c))
|
||||
break;
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
while (marker < slength)
|
||||
{
|
||||
c = s.charAt(marker);
|
||||
if (isDigit(c))
|
||||
break;
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
}
|
||||
}
|
||||
return chunk.toString();
|
||||
}
|
||||
|
||||
public int compare(OCFile o1, OCFile o2)
|
||||
{
|
||||
String s1 = (String)o1.getRemotePath().toLowerCase();
|
||||
String s2 = (String)o2.getRemotePath().toLowerCase();
|
||||
|
||||
int thisMarker = 0;
|
||||
int thatMarker = 0;
|
||||
int s1Length = s1.length();
|
||||
int s2Length = s2.length();
|
||||
|
||||
while (thisMarker < s1Length && thatMarker < s2Length)
|
||||
{
|
||||
String thisChunk = getChunk(s1, s1Length, thisMarker);
|
||||
thisMarker += thisChunk.length();
|
||||
|
||||
String thatChunk = getChunk(s2, s2Length, thatMarker);
|
||||
thatMarker += thatChunk.length();
|
||||
|
||||
// If both chunks contain numeric characters, sort them numerically
|
||||
int result = 0;
|
||||
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
|
||||
{
|
||||
// Simple chunk comparison by length.
|
||||
int thisChunkLength = thisChunk.length();
|
||||
result = thisChunkLength - thatChunk.length();
|
||||
// If equal, the first different number counts
|
||||
if (result == 0)
|
||||
{
|
||||
for (int i = 0; i < thisChunkLength; i++)
|
||||
{
|
||||
result = thisChunk.charAt(i) - thatChunk.charAt(i);
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = thisChunk.compareTo(thatChunk);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
return s1Length - s2Length;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,13 @@ package com.owncloud.android.ui.adapter;
|
|||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Vector;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
|
@ -31,6 +34,7 @@ import android.graphics.drawable.BitmapDrawable;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.os.AsyncTask;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -43,6 +47,7 @@ import android.widget.TextView;
|
|||
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.authentication.AccountUtils;
|
||||
import com.owncloud.android.datamodel.AlphanumComparator;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
|
||||
|
@ -51,6 +56,8 @@ import com.owncloud.android.lib.common.utils.Log_OC;
|
|||
import com.owncloud.android.ui.activity.ComponentsGetter;
|
||||
import com.owncloud.android.utils.BitmapUtils;
|
||||
import com.owncloud.android.utils.DisplayUtils;
|
||||
import com.owncloud.android.utils.FileStorageUtils;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -74,6 +81,9 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
private FileDataStorageManager mStorageManager;
|
||||
private Account mAccount;
|
||||
private ComponentsGetter mTransferServiceGetter;
|
||||
private Integer sortOrder;
|
||||
private Boolean sortAscending;
|
||||
private SharedPreferences appPreferences;
|
||||
|
||||
private final Object thumbnailDiskCacheLock = new Object();
|
||||
private DiskLruImageCache mThumbnailCache;
|
||||
|
@ -93,6 +103,15 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
mContext = context;
|
||||
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
|
||||
mTransferServiceGetter = transferServiceGetter;
|
||||
|
||||
appPreferences = PreferenceManager
|
||||
.getDefaultSharedPreferences(mContext);
|
||||
|
||||
// Read sorting order, default to sort by name ascending
|
||||
sortOrder = appPreferences
|
||||
.getInt("sortOrder", 0);
|
||||
sortAscending = appPreferences.getBoolean("sortAscending", true);
|
||||
|
||||
defaultImg = BitmapFactory.decodeResource(mContext.getResources(),
|
||||
DisplayUtils.getResourceId("image/png", "default.png"));
|
||||
|
||||
|
@ -361,8 +380,13 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
}
|
||||
}
|
||||
else {
|
||||
fileSizeV.setVisibility(View.INVISIBLE);
|
||||
//fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));
|
||||
if (FileStorageUtils.getDefaultSavePathFor(mAccount.name, file) != null){
|
||||
fileSizeV.setVisibility(View.VISIBLE);
|
||||
fileSizeV.setText(getFolderSizeHuman(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)));
|
||||
} else {
|
||||
fileSizeV.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
lastModV.setVisibility(View.VISIBLE);
|
||||
lastModV.setText(
|
||||
DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp())
|
||||
|
@ -425,6 +449,48 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Folder size in human readable format
|
||||
* @param path String
|
||||
* @return Size in human readable format
|
||||
*/
|
||||
private String getFolderSizeHuman(String path) {
|
||||
|
||||
File dir = new File(path);
|
||||
|
||||
if(dir.exists()) {
|
||||
long bytes = getFolderSize(dir);
|
||||
if (bytes < 1024) return bytes + " B";
|
||||
int exp = (int) (Math.log(bytes) / Math.log(1024));
|
||||
String pre = ("KMGTPE").charAt(exp-1) + "";
|
||||
|
||||
return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
|
||||
}
|
||||
|
||||
return "0 B";
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Folder size
|
||||
* @param dir File
|
||||
* @return Size in bytes
|
||||
*/
|
||||
private long getFolderSize(File dir) {
|
||||
if (dir.exists()) {
|
||||
long result = 0;
|
||||
File[] fileList = dir.listFiles();
|
||||
for(int i = 0; i < fileList.length; i++) {
|
||||
if(fileList[i].isDirectory()) {
|
||||
result += getFolderSize(fileList[i]);
|
||||
} else {
|
||||
result += fileList[i].length();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 1;
|
||||
|
@ -461,6 +527,26 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
} else {
|
||||
mFiles = null;
|
||||
}
|
||||
|
||||
sortDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts all filenames, regarding last user decision
|
||||
*/
|
||||
private void sortDirectory(){
|
||||
switch (sortOrder){
|
||||
case 0:
|
||||
sortByName(sortAscending);
|
||||
break;
|
||||
case 1:
|
||||
sortByDate(sortAscending);
|
||||
break;
|
||||
case 2:
|
||||
sortBySize(sortAscending);
|
||||
break;
|
||||
}
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
@ -496,4 +582,103 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
&& file.getPermissions() != null
|
||||
&& file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts list by Date
|
||||
* @param sortAscending true: ascending, false: descending
|
||||
*/
|
||||
private void sortByDate(boolean sortAscending){
|
||||
final Integer val;
|
||||
if (sortAscending){
|
||||
val = 1;
|
||||
} else {
|
||||
val = -1;
|
||||
}
|
||||
|
||||
Collections.sort(mFiles, new Comparator<OCFile>() {
|
||||
public int compare(OCFile o1, OCFile o2) {
|
||||
if (o1.isFolder() && o2.isFolder()) {
|
||||
return val * Long.compare(o1.getModificationTimestamp(), o2.getModificationTimestamp());
|
||||
}
|
||||
else if (o1.isFolder()) {
|
||||
return -1;
|
||||
} else if (o2.isFolder()) {
|
||||
return 1;
|
||||
} else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){
|
||||
return 0;
|
||||
} else {
|
||||
return val * Long.compare(o1.getModificationTimestamp(), o2.getModificationTimestamp());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts list by Size
|
||||
* @param sortAscending true: ascending, false: descending
|
||||
*/
|
||||
private void sortBySize(boolean sortAscending){
|
||||
final Integer val;
|
||||
if (sortAscending){
|
||||
val = 1;
|
||||
} else {
|
||||
val = -1;
|
||||
}
|
||||
|
||||
Collections.sort(mFiles, new Comparator<OCFile>() {
|
||||
public int compare(OCFile o1, OCFile o2) {
|
||||
if (o1.isFolder() && o2.isFolder()) {
|
||||
return val * Long.compare(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1))),
|
||||
getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));
|
||||
}
|
||||
else if (o1.isFolder()) {
|
||||
return -1;
|
||||
} else if (o2.isFolder()) {
|
||||
return 1;
|
||||
} else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){
|
||||
return 0;
|
||||
} else {
|
||||
return val * Long.compare(o1.getFileLength(), o2.getFileLength());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts list by Name
|
||||
* @param sortAscending true: ascending, false: descending
|
||||
*/
|
||||
private void sortByName(boolean sortAscending){
|
||||
final Integer val;
|
||||
if (sortAscending){
|
||||
val = 1;
|
||||
} else {
|
||||
val = -1;
|
||||
}
|
||||
|
||||
Collections.sort(mFiles, new Comparator<OCFile>() {
|
||||
public int compare(OCFile o1, OCFile o2) {
|
||||
if (o1.isFolder() && o2.isFolder()) {
|
||||
return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());
|
||||
} else if (o1.isFolder()) {
|
||||
return -1;
|
||||
} else if (o2.isFolder()) {
|
||||
return 1;
|
||||
}
|
||||
return val * new AlphanumComparator().compare(o1, o2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setSortOrder(Integer order, boolean ascending) {
|
||||
SharedPreferences.Editor editor = appPreferences.edit();
|
||||
editor.putInt("sortOrder", order);
|
||||
editor.putBoolean("sortAscending", ascending);
|
||||
editor.commit();
|
||||
|
||||
sortOrder = order;
|
||||
sortAscending = ascending;
|
||||
|
||||
sortDirectory();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -387,4 +387,15 @@ public class OCFileListFragment extends ExtendedListFragment {
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue