790cfde64967248f0ce29e4933a2306ab244c448
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / preview / PreviewTextFragment.java
1 package com.owncloud.android.ui.preview;
2
3 import android.accounts.Account;
4 import android.content.Context;
5 import android.os.AsyncTask;
6 import android.os.Bundle;
7 import android.view.LayoutInflater;
8 import android.view.View;
9 import android.view.ViewGroup;
10 import android.widget.BaseAdapter;
11 import android.widget.ListView;
12 import android.widget.ProgressBar;
13 import android.widget.TextView;
14
15 import com.actionbarsherlock.view.Menu;
16 import com.actionbarsherlock.view.MenuInflater;
17 import com.actionbarsherlock.view.MenuItem;
18 import com.owncloud.android.R;
19 import com.owncloud.android.datamodel.OCFile;
20 import com.owncloud.android.files.FileMenuFilter;
21 import com.owncloud.android.lib.common.utils.Log_OC;
22 import com.owncloud.android.ui.activity.FileDisplayActivity;
23 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
24 import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
25 import com.owncloud.android.ui.fragment.FileFragment;
26
27 import java.io.BufferedWriter;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.io.StringWriter;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Scanner;
34
35 public class PreviewTextFragment extends FileFragment {
36 private static final String EXTRA_FILE = "FILE";
37 private static final String EXTRA_ACCOUNT = "ACCOUNT";
38 private static final String TAG = PreviewTextFragment.class.getSimpleName();
39
40 private Account mAccount;
41 private ListView mTextPreviewList;
42 private ProgressBar mProgressBar;
43
44 /**
45 * Creates an empty fragment for previews.
46 * <p/>
47 * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
48 * (for instance, when the device is turned a aside).
49 * <p/>
50 * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
51 * construction
52 */
53 public PreviewTextFragment() {
54 super();
55 mAccount = null;
56 }
57
58 /**
59 * {@inheritDoc}
60 */
61 @Override
62 public View onCreateView(LayoutInflater inflater, ViewGroup container,
63 Bundle savedInstanceState) {
64 super.onCreateView(inflater, container, savedInstanceState);
65 Log_OC.e(TAG, "onCreateView");
66
67
68 View ret = inflater.inflate(R.layout.text_file_preview, container, false);
69
70 mTextPreviewList = (ListView) ret.findViewById(R.id.text_preview_list);
71 mTextPreviewList.setAdapter(new TextLineAdapter());
72 mProgressBar = (ProgressBar) ret.findViewById(R.id.progress_bar);
73
74 return ret;
75 }
76
77 /**
78 * {@inheritDoc}
79 */
80 @Override
81 public void onCreate(Bundle savedInstanceState) {
82 super.onCreate(savedInstanceState);
83
84 OCFile file = getFile();
85
86 Bundle args = getArguments();
87
88 if (file == null)
89 file = args.getParcelable(FileDisplayActivity.EXTRA_FILE);
90
91 if (mAccount == null)
92 mAccount = args.getParcelable(FileDisplayActivity.EXTRA_ACCOUNT);
93
94
95 if (savedInstanceState == null) {
96 if (file == null) {
97 throw new IllegalStateException("Instanced with a NULL OCFile");
98 }
99 if (mAccount == null) {
100 throw new IllegalStateException("Instanced with a NULL ownCloud Account");
101 }
102 } else {
103 file = savedInstanceState.getParcelable(EXTRA_FILE);
104 mAccount = savedInstanceState.getParcelable(EXTRA_ACCOUNT);
105 }
106 setFile(file);
107 setHasOptionsMenu(true);
108 }
109
110 /**
111 * {@inheritDoc}
112 */
113 @Override
114 public void onSaveInstanceState(Bundle outState) {
115 super.onSaveInstanceState(outState);
116 outState.putParcelable(PreviewImageFragment.EXTRA_FILE, getFile());
117 outState.putParcelable(PreviewImageFragment.EXTRA_ACCOUNT, mAccount);
118 }
119
120 @Override
121 public void onStart() {
122 super.onStart();
123 Log_OC.e(TAG, "onStart");
124 }
125
126 private void loadAndShowTextPreview() {
127 new TextLoadAsyncTask().execute(getFile().getStoragePath());
128 }
129
130 /**
131 * Reads the file to preview and shows its contents. Too critical to be anonymous.
132 */
133 private class TextLoadAsyncTask extends AsyncTask<Object, StringWriter, Void> {
134
135 @Override
136 protected void onPreExecute() {
137 ((TextLineAdapter) mTextPreviewList.getAdapter()).clear();
138 }
139
140 @Override
141 protected Void doInBackground(java.lang.Object... params) {
142 if (params.length != 1)
143 throw new IllegalArgumentException("The parameter to " + TextLoadAsyncTask.class.getName() + " must be the file location only");
144 final String location = (String) params[0];
145
146 FileInputStream inputStream = null;
147 Scanner sc = null;
148 try {
149 inputStream = new FileInputStream(location);
150 sc = new Scanner(inputStream);
151 while (sc.hasNextLine()) {
152 StringWriter target = new StringWriter();
153 BufferedWriter bufferedWriter = new BufferedWriter(target);
154 if (sc.hasNextLine())
155 bufferedWriter.write(sc.nextLine());
156 bufferedWriter.close();
157 publishProgress(target);
158 }
159 IOException exc = sc.ioException();
160 if (exc != null) throw exc;
161 } catch (IOException e) {
162 finish();
163 } finally {
164 if (inputStream != null) {
165 try {
166 inputStream.close();
167 } catch (IOException e) {
168 finish();
169 }
170 }
171 if (sc != null) {
172 sc.close();
173 }
174 }
175 return null;
176 }
177
178 @Override
179 protected void onProgressUpdate(StringWriter... values) {
180 super.onProgressUpdate(values);
181 //Using a ListView allows to show large text without the UI freeze that happens
182 //when calling TextView#setText() with a large CharSequence
183 ((TextLineAdapter) mTextPreviewList.getAdapter()).add(values[0].toString());
184 }
185
186 @Override
187 protected void onPostExecute(Void aVoid) {
188 super.onPostExecute(aVoid);
189 mProgressBar.setVisibility(View.GONE);
190 mTextPreviewList.setVisibility(View.VISIBLE);
191 }
192 }
193
194 private class TextLineAdapter extends BaseAdapter {
195 private static final int LIST_ITEM_LAYOUT = R.layout.text_file_preview_list_item;
196 private final List<String> items = new ArrayList<>();
197
198 private void add(String line) {
199 items.add(line);
200 notifyDataSetChanged();
201 }
202
203 private void clear() {
204 items.clear();
205 notifyDataSetChanged();
206 }
207
208 @Override
209 public int getCount() {
210 return items.size();
211 }
212
213 @Override
214 public String getItem(int position) {
215 if (position >= items.size())
216 throw new IllegalArgumentException();
217 return items.get(position);
218 }
219
220 @Override
221 public long getItemId(int position) {
222 return position;
223 }
224
225 @Override
226 public View getView(int position, View convertView, ViewGroup parent) {
227 ViewHolder viewHolder;
228 if (convertView == null) {
229 convertView =
230 ((LayoutInflater) getActivity().getApplicationContext()
231 .getSystemService(Context.LAYOUT_INFLATER_SERVICE))
232 .inflate(
233 LIST_ITEM_LAYOUT, null);
234 viewHolder = new ViewHolder();
235 viewHolder.setLineView((TextView) convertView.findViewById(R.id.text_preview));
236 convertView.setTag(viewHolder);
237 } else {
238 viewHolder = (ViewHolder) convertView.getTag();
239 }
240
241 viewHolder.getLineView().setText(items.get(position));
242
243 return convertView;
244 }
245 }
246
247 private static class ViewHolder {
248 private TextView lineView;
249
250 private ViewHolder() {
251 }
252
253 public TextView getLineView() {
254 return lineView;
255 }
256
257 public void setLineView(TextView lineView) {
258 this.lineView = lineView;
259 }
260 }
261
262 /**
263 * {@inheritDoc}
264 */
265 @Override
266 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
267 super.onCreateOptionsMenu(menu, inflater);
268 inflater.inflate(R.menu.file_actions_menu, menu);
269 }
270
271 /**
272 * {@inheritDoc}
273 */
274 @Override
275 public void onPrepareOptionsMenu(Menu menu) {
276 super.onPrepareOptionsMenu(menu);
277
278 if (mContainerActivity.getStorageManager() != null) {
279 FileMenuFilter mf = new FileMenuFilter(
280 getFile(),
281 mContainerActivity.getStorageManager().getAccount(),
282 mContainerActivity,
283 getSherlockActivity()
284 );
285 mf.filter(menu);
286 }
287
288 // additional restriction for this fragment
289 MenuItem item = menu.findItem(R.id.action_rename_file);
290 if (item != null) {
291 item.setVisible(false);
292 item.setEnabled(false);
293 }
294
295 // additional restriction for this fragment
296 item = menu.findItem(R.id.action_move);
297 if (item != null) {
298 item.setVisible(false);
299 item.setEnabled(false);
300 }
301
302 // this one doesn't make sense since the file has to be down in order to be previewed
303 item = menu.findItem(R.id.action_download_file);
304 if (item != null) {
305 item.setVisible(false);
306 item.setEnabled(false);
307 }
308 }
309
310 /**
311 * {@inheritDoc}
312 */
313 @Override
314 public boolean onOptionsItemSelected(MenuItem item) {
315 switch (item.getItemId()) {
316 case R.id.action_share_file: {
317 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
318 return true;
319 }
320 case R.id.action_unshare_file: {
321 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
322 return true;
323 }
324 case R.id.action_open_file_with: {
325 openFile();
326 return true;
327 }
328 case R.id.action_remove_file: {
329 RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
330 dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
331 return true;
332 }
333 case R.id.action_see_details: {
334 seeDetails();
335 return true;
336 }
337 case R.id.action_send_file: {
338 sendFile();
339 return true;
340 }
341 case R.id.action_sync_file: {
342 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
343 return true;
344 }
345
346 default:
347 return false;
348 }
349 }
350
351 /**
352 * Update the file of the fragment with file value
353 *
354 * @param file
355 */
356 public void updateFile(OCFile file) {
357 setFile(file);
358 }
359
360 private void sendFile() {
361 mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
362 }
363
364 private void seeDetails() {
365 mContainerActivity.showDetails(getFile());
366 }
367
368 @Override
369 public void onPause() {
370 Log_OC.e(TAG, "onPause");
371 super.onPause();
372 }
373
374 @Override
375 public void onResume() {
376 super.onResume();
377 Log_OC.e(TAG, "onResume");
378
379 loadAndShowTextPreview();
380 }
381
382 @Override
383 public void onDestroy() {
384 Log_OC.e(TAG, "onDestroy");
385 super.onDestroy();
386 }
387
388 @Override
389 public void onStop() {
390 super.onStop();
391 Log_OC.e(TAG, "onStop");
392 }
393
394 /**
395 * Opens the previewed file with an external application.
396 */
397 private void openFile() {
398 mContainerActivity.getFileOperationsHelper().openFile(getFile());
399 finish();
400 }
401
402 /**
403 * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewTextFragment} to be previewed.
404 *
405 * @param file File to test if can be previewed.
406 * @return 'True' if the file can be handled by the fragment.
407 */
408 public static boolean canBePreviewed(OCFile file) {
409 return (file != null && file.isDown() && file.isText());
410 }
411
412 /**
413 * Finishes the preview
414 */
415 private void finish() {
416 getSherlockActivity().onBackPressed();
417 }
418 }