54705dabfe66523228e36804c3f2eb297122ce98
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / adapter / LocalFileListAdapter.java
1 /**
2 * ownCloud Android client application
3 *
4 * @author David A. Velasco
5 * Copyright (C) 2011 Bartek Przybylski
6 * Copyright (C) 2015 ownCloud Inc.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2,
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21 package com.owncloud.android.ui.adapter;
22
23 import java.io.File;
24 import java.util.Arrays;
25 import java.util.Comparator;
26
27 import android.content.Context;
28 import android.graphics.Bitmap;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.BaseAdapter;
33 import android.widget.ImageView;
34 import android.widget.ListAdapter;
35 import android.widget.ListView;
36 import android.widget.TextView;
37
38 import com.owncloud.android.R;
39 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
40 import com.owncloud.android.lib.common.utils.Log_OC;
41 import com.owncloud.android.utils.BitmapUtils;
42 import com.owncloud.android.utils.DisplayUtils;
43 import com.owncloud.android.utils.MimetypeIconUtil;
44
45 /**
46 * This Adapter populates a ListView with all files and directories contained
47 * in a local directory
48 */
49 public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
50
51 private static final String TAG = LocalFileListAdapter.class.getSimpleName();
52
53 private Context mContext;
54 private File mDirectory;
55 private File[] mFiles = null;
56
57 public LocalFileListAdapter(File directory, Context context) {
58 mContext = context;
59 swapDirectory(directory);
60 }
61
62 @Override
63 public boolean areAllItemsEnabled() {
64 return true;
65 }
66
67 @Override
68 public boolean isEnabled(int position) {
69 return true;
70 }
71
72 @Override
73 public int getCount() {
74 return mFiles != null ? mFiles.length : 0;
75 }
76
77 @Override
78 public Object getItem(int position) {
79 if (mFiles == null || mFiles.length <= position)
80 return null;
81 return mFiles[position];
82 }
83
84 @Override
85 public long getItemId(int position) {
86 return mFiles != null && mFiles.length <= position ? position : -1;
87 }
88
89 @Override
90 public int getItemViewType(int position) {
91 return 0;
92 }
93
94 @Override
95 public View getView(int position, View convertView, ViewGroup parent) {
96 View view = convertView;
97 if (view == null) {
98 LayoutInflater inflator = (LayoutInflater) mContext
99 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
100 view = inflator.inflate(R.layout.list_item, null);
101 }
102 if (mFiles != null && mFiles.length > position) {
103 File file = mFiles[position];
104
105 TextView fileName = (TextView) view.findViewById(R.id.Filename);
106 String name = file.getName();
107 fileName.setText(name);
108
109 ImageView fileIcon = (ImageView) view.findViewById(R.id.thumbnail);
110
111 /** Cancellation needs do be checked and done before changing the drawable in fileIcon, or
112 * {@link ThumbnailsCacheManager#cancelPotentialWork} will NEVER cancel any task.
113 **/
114 boolean allowedToCreateNewThumbnail = (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon));
115
116 if (!file.isDirectory()) {
117 fileIcon.setImageResource(R.drawable.file);
118 } else {
119 fileIcon.setImageResource(R.drawable.ic_menu_archive);
120 }
121 fileIcon.setTag(file.hashCode());
122
123 TextView fileSizeV = (TextView) view.findViewById(R.id.last_size);
124 TextView fileSizeSeparatorV = (TextView) view.findViewById(R.id.file_separator);
125 TextView lastModV = (TextView) view.findViewById(R.id.file_mod);
126 ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);
127 if (!file.isDirectory()) {
128 fileSizeSeparatorV.setVisibility(View.VISIBLE);
129 fileSizeV.setVisibility(View.VISIBLE);
130 fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.length()));
131
132 lastModV.setVisibility(View.VISIBLE);
133 lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.lastModified()));
134 ListView parentList = (ListView) parent;
135 if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) {
136 checkBoxV.setVisibility(View.GONE);
137 } else {
138 if (parentList.isItemChecked(position)) {
139 checkBoxV.setImageResource(R.drawable.ic_checkbox_marked);
140 } else {
141 checkBoxV.setImageResource(R.drawable.ic_checkbox_blank_outline);
142 }
143 checkBoxV.setVisibility(View.VISIBLE);
144 }
145
146 // get Thumbnail if file is image
147 if (BitmapUtils.isImage(file)){
148 // Thumbnail in Cache?
149 Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
150 String.valueOf(file.hashCode())
151 );
152 if (thumbnail != null){
153 fileIcon.setImageBitmap(thumbnail);
154 } else {
155
156 // generate new Thumbnail
157 if (allowedToCreateNewThumbnail) {
158 final ThumbnailsCacheManager.ThumbnailGenerationTask task =
159 new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon);
160 if (thumbnail == null) {
161 thumbnail = ThumbnailsCacheManager.mDefaultImg;
162 }
163 final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
164 new ThumbnailsCacheManager.AsyncDrawable(
165 mContext.getResources(),
166 thumbnail,
167 task
168 );
169 fileIcon.setImageDrawable(asyncDrawable);
170 task.execute(file);
171 Log_OC.v(TAG, "Executing task to generate a new thumbnail");
172
173 } // else, already being generated, don't restart it
174 }
175 } else {
176 fileIcon.setImageResource(MimetypeIconUtil.getFileTypeIconId(null, file.getName()));
177 }
178
179 } else {
180 fileSizeSeparatorV.setVisibility(View.GONE);
181 fileSizeV.setVisibility(View.GONE);
182 lastModV.setVisibility(View.GONE);
183 checkBoxV.setVisibility(View.GONE);
184 }
185
186 // not GONE; the alignment changes; ugly way to keep it
187 view.findViewById(R.id.localFileIndicator).setVisibility(View.INVISIBLE);
188 view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE);
189
190 view.findViewById(R.id.sharedIcon).setVisibility(View.GONE);
191 view.findViewById(R.id.sharedWithMeIcon).setVisibility(View.GONE);
192 }
193
194 return view;
195 }
196
197 @Override
198 public int getViewTypeCount() {
199 return 1;
200 }
201
202 @Override
203 public boolean hasStableIds() {
204 return false;
205 }
206
207 @Override
208 public boolean isEmpty() {
209 return (mFiles == null || mFiles.length == 0);
210 }
211
212 /**
213 * Change the adapted directory for a new one
214 * @param directory New file to adapt. Can be NULL, meaning "no content to adapt".
215 */
216 public void swapDirectory(File directory) {
217 mDirectory = directory;
218 mFiles = (mDirectory != null ? mDirectory.listFiles() : null);
219 if (mFiles != null) {
220 Arrays.sort(mFiles, new Comparator<File>() {
221 @Override
222 public int compare(File lhs, File rhs) {
223 if (lhs.isDirectory() && !rhs.isDirectory()) {
224 return -1;
225 } else if (!lhs.isDirectory() && rhs.isDirectory()) {
226 return 1;
227 }
228 return compareNames(lhs, rhs);
229 }
230
231 private int compareNames(File lhs, File rhs) {
232 return lhs.getName().toLowerCase().compareTo(rhs.getName().toLowerCase());
233 }
234
235 });
236 }
237 notifyDataSetChanged();
238 }
239 }