*/\r
package com.owncloud.android.ui.adapter;\r
\r
- import java.lang.ref.WeakReference;\r
++
+import java.io.File;\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.res.Resources;\r
+import android.content.SharedPreferences;\r
import android.graphics.Bitmap;\r
- import android.graphics.Bitmap.CompressFormat;\r
- import android.graphics.BitmapFactory;\r
- import android.graphics.drawable.BitmapDrawable;\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
import android.view.ViewGroup;\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.datamodel.ThumbnailsCacheManager;\r
+ import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;\r
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
- import com.owncloud.android.lib.common.utils.Log_OC;\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
public class FileListListAdapter extends BaseAdapter implements ListAdapter {\r
private final static String PERMISSION_SHARED_WITH_ME = "S";\r
\r
- private static final String TAG = FileListListAdapter.class.getSimpleName();\r
- \r
private Context mContext;\r
private OCFile mFile = null;\r
private Vector<OCFile> mFiles = null;\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
- private boolean mThumbnailCacheStarting = true;\r
- private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB\r
- private static final CompressFormat mCompressFormat = CompressFormat.JPEG;\r
- private static final int mCompressQuality = 70;\r
- private Bitmap defaultImg;\r
- \r
public FileListListAdapter(\r
boolean justFolders, \r
Context context, \r
mJustFolders = justFolders;\r
mContext = context;\r
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
-- mTransferServiceGetter = transferServiceGetter;\r
++ mTransferServiceGetter = transferServiceGetter;
+ \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
- // Initialise disk cache on background thread\r
- new InitDiskCacheTask().execute();\r
- }\r
- \r
- class InitDiskCacheTask extends AsyncTask<File, Void, Void> {\r
- @Override\r
- protected Void doInBackground(File... params) {\r
- synchronized (thumbnailDiskCacheLock) {\r
- try {\r
- mThumbnailCache = new DiskLruImageCache(mContext, "thumbnailCache", \r
- DISK_CACHE_SIZE, mCompressFormat, mCompressQuality);\r
- } catch (Exception e) {\r
- Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);\r
- mThumbnailCache = null;\r
- }\r
- mThumbnailCacheStarting = false; // Finished initialization\r
- thumbnailDiskCacheLock.notifyAll(); // Wake any waiting threads\r
- }\r
- return null;\r
- }\r
- }\r
- \r
- static class AsyncDrawable extends BitmapDrawable {\r
- private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;\r
- \r
- public AsyncDrawable(Resources res, Bitmap bitmap,\r
- ThumbnailGenerationTask bitmapWorkerTask) {\r
- super(res, bitmap);\r
- bitmapWorkerTaskReference =\r
- new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);\r
- }\r
- \r
- public ThumbnailGenerationTask getBitmapWorkerTask() {\r
- return bitmapWorkerTaskReference.get();\r
- }\r
- }\r
- \r
- class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {\r
- private final WeakReference<ImageView> imageViewReference;\r
- private OCFile file;\r
- \r
- \r
- public ThumbnailGenerationTask(ImageView imageView) {\r
- // Use a WeakReference to ensure the ImageView can be garbage collected\r
- imageViewReference = new WeakReference<ImageView>(imageView);\r
- }\r
- \r
- // Decode image in background.\r
- @Override\r
- protected Bitmap doInBackground(OCFile... params) {\r
- Bitmap thumbnail = null;\r
- \r
- try {\r
- file = params[0];\r
- final String imageKey = String.valueOf(file.getRemoteId());\r
- \r
- // Check disk cache in background thread\r
- thumbnail = getBitmapFromDiskCache(imageKey);\r
- \r
- // Not found in disk cache\r
- if (thumbnail == null || file.needsUpdateThumbnail()) { \r
- // Converts dp to pixel\r
- Resources r = mContext.getResources();\r
- int px = (int) Math.round(TypedValue.applyDimension(\r
- TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()\r
- ));\r
- \r
- if (file.isDown()){\r
- Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(\r
- file.getStoragePath(), px, px);\r
- \r
- if (bitmap != null) {\r
- thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);\r
- \r
- // Add thumbnail to cache\r
- addBitmapToCache(imageKey, thumbnail);\r
- \r
- file.setNeedsUpdateThumbnail(false);\r
- mStorageManager.saveFile(file);\r
- }\r
- \r
- }\r
- }\r
- \r
- } catch (Throwable t) {\r
- // the app should never break due to a problem with thumbnails\r
- Log_OC.e(TAG, "Generation of thumbnail for " + file + " failed", t);\r
- if (t instanceof OutOfMemoryError) {\r
- System.gc();\r
- }\r
- }\r
- \r
- return thumbnail;\r
- }\r
++ sortAscending = appPreferences.getBoolean("sortAscending", true);
\r
- protected void onPostExecute(Bitmap bitmap){\r
- if (isCancelled()) {\r
- bitmap = null;\r
- }\r
- \r
- if (imageViewReference != null && bitmap != null) {\r
- final ImageView imageView = imageViewReference.get();\r
- final ThumbnailGenerationTask bitmapWorkerTask =\r
- getBitmapWorkerTask(imageView);\r
- if (this == bitmapWorkerTask && imageView != null) {\r
- imageView.setImageBitmap(bitmap);\r
- }\r
- }\r
- }\r
- }\r
- \r
- public void addBitmapToCache(String key, Bitmap bitmap) {\r
- synchronized (thumbnailDiskCacheLock) {\r
- if (mThumbnailCache != null) {\r
- mThumbnailCache.put(key, bitmap);\r
- }\r
- }\r
+ // initialise thumbnails cache on background thread\r
+ new ThumbnailsCacheManager.InitDiskCacheTask().execute();\r
}\r
- \r
- public Bitmap getBitmapFromDiskCache(String key) {\r
- synchronized (thumbnailDiskCacheLock) {\r
- // Wait while disk cache is started from background thread\r
- while (mThumbnailCacheStarting) {\r
- try {\r
- thumbnailDiskCacheLock.wait();\r
- } catch (InterruptedException e) {}\r
- }\r
- if (mThumbnailCache != null) {\r
- return (Bitmap) mThumbnailCache.getBitmap(key);\r
- }\r
- }\r
- return null;
- }
- \r
- \r
++
@Override\r
public boolean areAllItemsEnabled() {\r
return true;\r
\r
fileName.setText(name);\r
ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);\r
+ fileIcon.setTag(file.getFileId());\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
\r
// get Thumbnail if file is image\r
- if (file.isImage()){\r
+ if (file.isImage() && file.getRemoteId() != null){\r
// Thumbnail in Cache?\r
- Bitmap thumbnail = getBitmapFromDiskCache(String.valueOf(file.getRemoteId()));\r
+ Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(\r
+ String.valueOf(file.getRemoteId())\r
+ );\r
if (thumbnail != null && !file.needsUpdateThumbnail()){\r
fileIcon.setImageBitmap(thumbnail);\r
} else {\r
// generate new Thumbnail\r
- if (cancelPotentialWork(file, fileIcon)) {\r
- final ThumbnailGenerationTask task = \r
- new ThumbnailGenerationTask(fileIcon);\r
- final AsyncDrawable asyncDrawable =\r
- new AsyncDrawable(mContext.getResources(), defaultImg, task);\r
+ if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {\r
+ final ThumbnailsCacheManager.ThumbnailGenerationTask task = \r
+ new ThumbnailsCacheManager.ThumbnailGenerationTask(\r
+ fileIcon, mStorageManager\r
+ );\r
+ if (thumbnail == null) {\r
+ thumbnail = ThumbnailsCacheManager.mDefaultImg;\r
+ }\r
+ final AsyncDrawable asyncDrawable = new AsyncDrawable(\r
+ mContext.getResources(), \r
+ thumbnail, \r
+ task\r
+ );\r
fileIcon.setImageDrawable(asyncDrawable);\r
task.execute(file);\r
}\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
- if (bitmapWorkerTask != null) {\r
- final OCFile bitmapData = bitmapWorkerTask.file;\r
- // If bitmapData is not yet set or it differs from the new data\r
- if (bitmapData == null || bitmapData != file) {\r
- // Cancel previous task\r
- bitmapWorkerTask.cancel(true);\r
- } else {\r
- // The same work is already in progress\r
- return false;\r
- }\r
- }\r
- // No task associated with the ImageView, or an existing task was cancelled\r
- return true;\r
- }\r
- \r
- private static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {\r
- if (imageView != null) {\r
- final Drawable drawable = imageView.getDrawable();\r
- if (drawable instanceof AsyncDrawable) {\r
- final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;\r
- return asyncDrawable.getBitmapWorkerTask();\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
return 1;\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