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

1  2 
res/menu/main_menu.xml
res/values-de/strings.xml
res/values/strings.xml
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

          android:showAsAction="never"
          android:title="@string/actionbar_settings"/>
      <item
 +        android:id="@+id/action_logger"
 +        android:icon="@drawable/ic_action_settings"
 +        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> -->
  
Simple merge
Simple merge
@@@ -48,7 -50,8 +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.support.v4.widget.SwipeRefreshLayout;
--import android.util.Log;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.ArrayAdapter;
@@@ -1748,4 -1757,17 +1779,16 @@@ OnSslUntrustedCertListener, OnEnforceab
              }
          }
      }
 -    
++
+     private void sortByDate(boolean ascending){
+         getListOfFilesFragment().sortByDate(ascending);
+     }
+     private void sortBySize(boolean ascending){
+         getListOfFilesFragment().sortBySize(ascending);
+     }
+     private void sortByName(boolean ascending){
+         getListOfFilesFragment().sortByName(ascending);
+     }
 -
  }
  package com.owncloud.android.ui.adapter;\r
  \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.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
@@@ -47,10 -42,10 +52,12 @@@ import com.owncloud.android.datamodel.F
  import com.owncloud.android.datamodel.OCFile;\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.Log_OC;\r
+ import com.owncloud.android.utils.FileStorageUtils;\r
++\r
  \r
  \r
  /**\r
@@@ -74,15 -66,10 +81,18 @@@ public class FileListListAdapter extend
      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
          mContext = context;\r
          mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
          mTransferServiceGetter = transferServiceGetter;\r
-         return null;\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
 +        // 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
 +        \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
 +    }\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
      @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
 -                \r
++
                  lastModV.setVisibility(View.VISIBLE);\r
 -                lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
 +                lastModV.setText(\r
 +                        DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp())\r
 +                );\r
                  checkBoxV.setVisibility(View.GONE);\r
                  view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
  \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
 -    } \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 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
 +        return (mFile.getPermissions() != null \r
 +                && !mFile.getPermissions().contains(PERMISSION_SHARED_WITH_ME)\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