OC-2459: Ask for pincode, when click on an instant upload notification
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / fragment / FileDetailFragment.java
index 88c4889..e024bc6 100644 (file)
@@ -3,9 +3,8 @@
  *   Copyright (C) 2012-2013 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, either version 2 of the License, or
- *   (at your option) any later version.
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 package com.owncloud.android.ui.fragment;
 
 import java.io.File;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.commons.httpclient.methods.GetMethod;
-import org.apache.commons.httpclient.methods.PostMethod;
-import org.apache.commons.httpclient.methods.StringRequestEntity;
-import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
-import org.apache.http.HttpStatus;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.utils.URLEncodedUtils;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.protocol.HTTP;
-import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
-import org.json.JSONObject;
-
 import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.annotation.SuppressLint;
 import android.app.Activity;
-import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapFactory.Options;
-import android.graphics.Point;
-import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
-import android.support.v4.app.DialogFragment;
-import android.support.v4.app.FragmentTransaction;
-import android.util.Log;
-import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.webkit.MimeTypeMap;
-import android.widget.Button;
 import android.widget.CheckBox;
 import android.widget.ImageView;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.actionbarsherlock.app.SherlockFragment;
-import com.owncloud.android.AccountUtils;
-import com.owncloud.android.DisplayUtils;
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuInflater;
+import com.actionbarsherlock.view.MenuItem;
+import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileObserverService;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.network.OwnCloudClientUtils;
-import com.owncloud.android.operations.OnRemoteOperationListener;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
-import com.owncloud.android.ui.activity.FileDetailActivity;
+import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
-import com.owncloud.android.ui.activity.TransferServiceGetter;
 import com.owncloud.android.ui.dialog.EditNameDialog;
 import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
-import com.owncloud.android.utils.OwnCloudVersion;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.Log_OC;
 
-import com.owncloud.android.R;
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
 
 /**
  * This Fragment is used to display the details about a file.
  * 
  * @author Bartek Przybylski
- * 
+ * @author David A. Velasco
  */
-public class FileDetailFragment extends SherlockFragment implements
-        OnClickListener, ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener {
-
-    public static final String EXTRA_FILE = "FILE";
-    public static final String EXTRA_ACCOUNT = "ACCOUNT";
+public class FileDetailFragment extends FileFragment implements
+        OnClickListener, 
+        ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener {
 
-    private FileDetailFragment.ContainerActivity mContainerActivity;
+    private FileFragment.ContainerActivity mContainerActivity;
     
     private int mLayout;
     private View mView;
-    private OCFile mFile;
     private Account mAccount;
     private FileDataStorageManager mStorageManager;
-    private ImageView mPreview;
     
-    private DownloadFinishReceiver mDownloadFinishReceiver;
     private UploadFinishReceiver mUploadFinishReceiver;
+    public ProgressListener mProgressListener;
     
     private Handler mHandler;
     private RemoteOperation mLastRemoteOperation;
-    private DialogFragment mCurrentDialog;
-
+    
     private static final String TAG = FileDetailFragment.class.getSimpleName();
-    public static final String FTAG = "FileDetails"; 
     public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";
-
     
+
     /**
      * Creates an empty details fragment.
      * 
      * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically. 
      */
     public FileDetailFragment() {
-        mFile = null;
+        super();
         mAccount = null;
         mStorageManager = null;
         mLayout = R.layout.file_details_empty;
+        mProgressListener = null;
     }
     
-    
     /**
      * Creates a details fragment.
      * 
@@ -153,10 +117,11 @@ public class FileDetailFragment extends SherlockFragment implements
      * @param ocAccount         An ownCloud account; needed to start downloads
      */
     public FileDetailFragment(OCFile fileToDetail, Account ocAccount) {
-        mFile = fileToDetail;
+        super(fileToDetail);
         mAccount = ocAccount;
         mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment 
         mLayout = R.layout.file_details_empty;
+        mProgressListener = null;
     }
     
     
@@ -164,42 +129,40 @@ public class FileDetailFragment extends SherlockFragment implements
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mHandler = new Handler();
+        setHasOptionsMenu(true);
     }
     
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        super.onCreateView(inflater, container, savedInstanceState);
+        //super.onCreateView(inflater, container, savedInstanceState);
         
         if (savedInstanceState != null) {
-            mFile = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_FILE);
-            mAccount = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_ACCOUNT);
+            setFile((OCFile)savedInstanceState.getParcelable(FileActivity.EXTRA_FILE));
+            mAccount = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
         }
         
-        if(mFile != null && mAccount != null) {
+        if(getFile() != null && mAccount != null) {
             mLayout = R.layout.file_details_fragment;
         }
         
         View view = null;
-        view = inflater.inflate(mLayout, container, false);
+        //view = inflater.inflate(mLayout, container, false);
+        view = inflater.inflate(mLayout, null);
         mView = view;
         
         if (mLayout == R.layout.file_details_fragment) {
             mView.findViewById(R.id.fdKeepInSync).setOnClickListener(this);
-            mView.findViewById(R.id.fdRenameBtn).setOnClickListener(this);
-            mView.findViewById(R.id.fdDownloadBtn).setOnClickListener(this);
-            mView.findViewById(R.id.fdOpenBtn).setOnClickListener(this);
-            mView.findViewById(R.id.fdRemoveBtn).setOnClickListener(this);
-            //mView.findViewById(R.id.fdShareBtn).setOnClickListener(this);
-            mPreview = (ImageView)mView.findViewById(R.id.fdPreview);
+            ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);
+            mProgressListener = new ProgressListener(progressBar);
+            mView.findViewById(R.id.fdCancelBtn).setOnClickListener(this);
         }
         
-        updateFileDetails(false);
+        updateFileDetails(false, false);
         return view;
     }
     
-
     /**
      * {@inheritDoc}
      */
@@ -208,6 +171,7 @@ public class FileDetailFragment extends SherlockFragment implements
         super.onAttach(activity);
         try {
             mContainerActivity = (ContainerActivity) activity;
+            
         } catch (ClassCastException e) {
             throw new ClassCastException(activity.toString() + " must implement " + FileDetailFragment.ContainerActivity.class.getSimpleName());
         }
@@ -221,239 +185,305 @@ public class FileDetailFragment extends SherlockFragment implements
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         if (mAccount != null) {
-            mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;
+            mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
         }
     }
         
 
     @Override
     public void onSaveInstanceState(Bundle outState) {
-        Log_OC.i(getClass().toString(), "onSaveInstanceState() start");
         super.onSaveInstanceState(outState);
-        outState.putParcelable(FileDetailFragment.EXTRA_FILE, mFile);
-        outState.putParcelable(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
-        Log_OC.i(getClass().toString(), "onSaveInstanceState() end");
+        outState.putParcelable(FileActivity.EXTRA_FILE, getFile());
+        outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount);
     }
 
+    @Override
+    public void onStart() {
+        super.onStart();
+        listenForTransferProgress();
+    }
     
     @Override
     public void onResume() {
         super.onResume();
-        
-        mDownloadFinishReceiver = new DownloadFinishReceiver();
-        IntentFilter filter = new IntentFilter(
-                FileDownloader.DOWNLOAD_FINISH_MESSAGE);
-        getActivity().registerReceiver(mDownloadFinishReceiver, filter);
-        
         mUploadFinishReceiver = new UploadFinishReceiver();
-        filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+        IntentFilter filter = new IntentFilter(FileUploader.getUploadFinishMessage());
         getActivity().registerReceiver(mUploadFinishReceiver, filter);
-        
-        mPreview = (ImageView)mView.findViewById(R.id.fdPreview);
+
     }
 
+
     @Override
     public void onPause() {
         super.onPause();
-        
-        getActivity().unregisterReceiver(mDownloadFinishReceiver);
-        mDownloadFinishReceiver = null;
-        
-        getActivity().unregisterReceiver(mUploadFinishReceiver);
-        mUploadFinishReceiver = null;
-        
-        if (mPreview != null) {
-            mPreview = null;
+        if (mUploadFinishReceiver != null) {
+            getActivity().unregisterReceiver(mUploadFinishReceiver);
+            mUploadFinishReceiver = null;
         }
     }
 
+    
+    @Override
+    public void onStop() {
+        super.onStop();
+        leaveTransferProgress();
+    }
+
+    
     @Override
     public View getView() {
         return super.getView() == null ? mView : super.getView();
     }
 
     
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        inflater.inflate(R.menu.file_actions_menu, menu);
+        MenuItem item = menu.findItem(R.id.action_see_details);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+    }
+
     
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public void onClick(View v) {
-        switch (v.getId()) {
-            case R.id.fdDownloadBtn: {
-                FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
-                FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
-                if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
-                    downloaderBinder.cancel(mAccount, mFile);
-                    if (mFile.isDown()) {
-                        setButtonsForDown();
-                    } else {
-                        setButtonsForRemote();
-                    }
+    public void onPrepareOptionsMenu (Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        
+        List<Integer> toHide = new ArrayList<Integer>();
+        List<Integer> toShow = new ArrayList<Integer>();
+        OCFile file = getFile();
+        
+        FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
+        boolean downloading = downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file);
+        FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
+        boolean uploading = uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile());
+        
+        if (downloading || uploading) {
+            toHide.add(R.id.action_download_file);
+            toHide.add(R.id.action_rename_file);
+            toHide.add(R.id.action_remove_file);
+            toHide.add(R.id.action_open_file_with);
+            if (!downloading) {
+                toHide.add(R.id.action_cancel_download);
+                toShow.add(R.id.action_cancel_upload);
+            } else {
+                toHide.add(R.id.action_cancel_upload);
+                toShow.add(R.id.action_cancel_download);
+            }
 
-                } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {
-                    uploaderBinder.cancel(mAccount, mFile);
-                    if (!mFile.fileExists()) {
-                        // TODO make something better
-                        if (getActivity() instanceof FileDisplayActivity) {
-                            // double pane
-                            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
-                            transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FTAG); // empty FileDetailFragment
-                            transaction.commit();
-                            mContainerActivity.onFileStateChanged();
-                        } else {
-                            getActivity().finish();
-                        }
-                        
-                    } else if (mFile.isDown()) {
-                        setButtonsForDown();
-                    } else {
-                        setButtonsForRemote();
-                    }
-                    
-                } else {
-                    mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());
-                    WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
-                    mLastRemoteOperation.execute(wc, this, mHandler);
-                
-                    // update ui 
-                    boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
-                    getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
-                    setButtonsForTransferring(); // disable button immediately, although the synchronization does not result in a file transference
-                    
-                }
-                break;
+        } else if (file != null && file.isDown()) {
+            toHide.add(R.id.action_download_file);
+            toHide.add(R.id.action_cancel_download);
+            toHide.add(R.id.action_cancel_upload);
+            
+            toShow.add(R.id.action_rename_file);
+            toShow.add(R.id.action_remove_file);
+            toShow.add(R.id.action_open_file_with);
+            toShow.add(R.id.action_sync_file);
+            
+        } else if (file != null) {
+            toHide.add(R.id.action_open_file_with);
+            toHide.add(R.id.action_cancel_download);
+            toHide.add(R.id.action_cancel_upload);
+            toHide.add(R.id.action_sync_file);
+            
+            toShow.add(R.id.action_rename_file);
+            toShow.add(R.id.action_remove_file);
+            toShow.add(R.id.action_download_file);
+            
+        } else {
+            toHide.add(R.id.action_open_file_with);
+            toHide.add(R.id.action_cancel_download);
+            toHide.add(R.id.action_cancel_upload);
+            toHide.add(R.id.action_sync_file);
+            toHide.add(R.id.action_download_file);
+            toHide.add(R.id.action_rename_file);
+            toHide.add(R.id.action_remove_file);
+            
+        }
+
+        MenuItem item = null;
+        for (int i : toHide) {
+            item = menu.findItem(i);
+            if (item != null) {
+                item.setVisible(false);
+                item.setEnabled(false);
             }
-            case R.id.fdKeepInSync: {
-                CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);
-                mFile.setKeepInSync(cb.isChecked());
-                mStorageManager.saveFile(mFile);
-                
-                /// register the OCFile instance in the observer service to monitor local updates;
-                /// if necessary, the file is download 
-                Intent intent = new Intent(getActivity().getApplicationContext(),
-                                           FileObserverService.class);
-                intent.putExtra(FileObserverService.KEY_FILE_CMD,
-                           (cb.isChecked()?
-                                   FileObserverService.CMD_ADD_OBSERVED_FILE:
-                                   FileObserverService.CMD_DEL_OBSERVED_FILE));
-                intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, mFile);
-                intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);
-                Log_OC.e(TAG, "starting observer service");
-                getActivity().startService(intent);
-                
-                if (mFile.keepInSync()) {
-                    onClick(getView().findViewById(R.id.fdDownloadBtn));    // force an immediate synchronization
-                }
-                break;
+        }
+        for (int i : toShow) {
+            item = menu.findItem(i);
+            if (item != null) {
+                item.setVisible(true);
+                item.setEnabled(true);
             }
-            case R.id.fdRenameBtn: {
-                EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), mFile.getFileName(), this);
-                dialog.show(getFragmentManager(), "nameeditdialog");
-                break;
-            }   
-            case R.id.fdRemoveBtn: {
-                ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
-                        R.string.confirmation_remove_alert,
-                        new String[]{mFile.getFileName()},
-                        mFile.isDown() ? R.string.confirmation_remove_remote_and_local : R.string.confirmation_remove_remote,
-                        mFile.isDown() ? R.string.confirmation_remove_local : -1,
-                        R.string.common_cancel);
-                confDialog.setOnConfirmationListener(this);
-                mCurrentDialog = confDialog;
-                mCurrentDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
+        }
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_open_file_with: {
+                mContainerActivity.openFile(getFile());
+                return true;
+            }
+            case R.id.action_remove_file: {
+                removeFile();
+                return true;
+            }
+            case R.id.action_rename_file: {
+                renameFile();
+                return true;
+            }
+            case R.id.action_download_file: 
+            case R.id.action_cancel_download:
+            case R.id.action_cancel_upload:
+            case R.id.action_sync_file: {
+                synchronizeFile();
+                return true;
+            }
+            default:
+                return false;
+        }
+    }
+    
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.fdKeepInSync: {
+                toggleKeepInSync();
                 break;
             }
-            case R.id.fdOpenBtn: {
-                String storagePath = mFile.getStoragePath();
-                String encodedStoragePath = WebdavUtils.encodePath(storagePath);
-                try {
-                    Intent i = new Intent(Intent.ACTION_VIEW);
-                    i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
-                    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-                    startActivity(i);
-                    
-                } catch (Throwable t) {
-                    Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
-                    boolean toastIt = true; 
-                    String mimeType = "";
-                    try {
-                        Intent i = new Intent(Intent.ACTION_VIEW);
-                        mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
-                        if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
-                            if (mimeType != null) {
-                                i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
-                            } else {
-                                // desperate try
-                                i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");
-                            }
-                            i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-                            startActivity(i);
-                            toastIt = false;
-                        }
-                        
-                    } catch (IndexOutOfBoundsException e) {
-                        Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
-                        
-                    } catch (ActivityNotFoundException e) {
-                        Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
-                        
-                    } catch (Throwable th) {
-                        Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
-                        
-                    } finally {
-                        if (toastIt) {
-                            Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
-                        }
-                    }
-                    
-                }
+            case R.id.fdCancelBtn: {
+                synchronizeFile();
                 break;
             }
             default:
                 Log_OC.e(TAG, "Incorrect view clicked!");
         }
-        
-        /* else if (v.getId() == R.id.fdShareBtn) {
-            Thread t = new Thread(new ShareRunnable(mFile.getRemotePath()));
-            t.start();
-        }*/
     }
     
     
+    private void toggleKeepInSync() {
+        CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);
+        OCFile file = getFile();
+        file.setKeepInSync(cb.isChecked());
+        mStorageManager.saveFile(file);
+        
+        /// register the OCFile instance in the observer service to monitor local updates;
+        /// if necessary, the file is download 
+        Intent intent = new Intent(getActivity().getApplicationContext(),
+                                   FileObserverService.class);
+        intent.putExtra(FileObserverService.KEY_FILE_CMD,
+                   (cb.isChecked()?
+                           FileObserverService.CMD_ADD_OBSERVED_FILE:
+                           FileObserverService.CMD_DEL_OBSERVED_FILE));
+        intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, file);
+        intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);
+        getActivity().startService(intent);
+        
+        if (file.keepInSync()) {
+            synchronizeFile();   // force an immediate synchronization
+        }
+    }
+
+
+    private void removeFile() {
+        OCFile file = getFile();
+        ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
+                R.string.confirmation_remove_alert,
+                new String[]{file.getFileName()},
+                file.isDown() ? R.string.confirmation_remove_remote_and_local : R.string.confirmation_remove_remote,
+                file.isDown() ? R.string.confirmation_remove_local : -1,
+                R.string.common_cancel);
+        confDialog.setOnConfirmationListener(this);
+        confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
+    }
+
+
+    private void renameFile() {
+        OCFile file = getFile();
+        String fileName = file.getFileName();
+        int extensionStart = file.isFolder() ? -1 : fileName.lastIndexOf(".");
+        int selectionEnd = (extensionStart >= 0) ? extensionStart : fileName.length();
+        EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), fileName, 0, selectionEnd, this);
+        dialog.show(getFragmentManager(), "nameeditdialog");
+    }
+
+    private void synchronizeFile() {
+        OCFile file = getFile();
+        FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
+        FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
+        if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) {
+            downloaderBinder.cancel(mAccount, file);
+            if (file.isDown()) {
+                setButtonsForDown();
+            } else {
+                setButtonsForRemote();
+            }
+
+        } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {
+            uploaderBinder.cancel(mAccount, file);
+            if (!file.fileExists()) {
+                // TODO make something better
+                ((FileDisplayActivity)getActivity()).cleanSecondFragment();
+                
+            } else if (file.isDown()) {
+                setButtonsForDown();
+            } else {
+                setButtonsForRemote();
+            }
+            
+        } else {
+            mLastRemoteOperation = new SynchronizeFileOperation(file, null, mStorageManager, mAccount, true, getActivity());
+            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
+            
+            // update ui 
+            ((FileDisplayActivity) getActivity()).showLoadingDialog();
+            
+        }
+    }
+
     @Override
     public void onConfirmation(String callerTag) {
+        OCFile file = getFile();
         if (callerTag.equals(FTAG_CONFIRMATION)) {
-            if (mStorageManager.getFileById(mFile.getFileId()) != null) {
-                mLastRemoteOperation = new RemoveFileOperation( mFile, 
+            if (mStorageManager.getFileById(file.getFileId()) != null) {
+                mLastRemoteOperation = new RemoveFileOperation( file, 
                                                                 true, 
                                                                 mStorageManager);
-                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
-                mLastRemoteOperation.execute(wc, this, mHandler);
-                
-                boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
-                getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
+                mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
+                                
+                ((FileDisplayActivity) getActivity()).showLoadingDialog();
             }
         }
-        mCurrentDialog.dismiss();
-        mCurrentDialog = null;
     }
     
     @Override
     public void onNeutral(String callerTag) {
-        File f = null;
-        if (mFile.isDown() && (f = new File(mFile.getStoragePath())).exists()) {
-            f.delete();
-            mFile.setStoragePath(null);
-            mStorageManager.saveFile(mFile);
-            updateFileDetails(mFile, mAccount);
+        OCFile file = getFile();
+        mStorageManager.removeFile(file, false, true);    // TODO perform in background task / new thread
+        if (file.getStoragePath() != null) {
+            file.setStoragePath(null);
+            updateFileDetails(file, mAccount);
         }
-        mCurrentDialog.dismiss();
-        mCurrentDialog = null;
     }
     
     @Override
     public void onCancel(String callerTag) {
         Log_OC.d(TAG, "REMOVAL CANCELED");
-        mCurrentDialog.dismiss();
-        mCurrentDialog = null;
     }
     
     
@@ -463,25 +493,17 @@ public class FileDetailFragment extends SherlockFragment implements
      * @return  True when the fragment was created with the empty layout.
      */
     public boolean isEmpty() {
-        return (mLayout == R.layout.file_details_empty || mFile == null || mAccount == null);
+        return (mLayout == R.layout.file_details_empty || getFile() == null || mAccount == null);
     }
 
     
     /**
-     * Can be used to get the file that is currently being displayed.
-     * @return The file on the screen.
-     */
-    public OCFile getDisplayedFile(){
-        return mFile;
-    }
-    
-    /**
      * Use this method to signal this Activity that it shall update its view.
      * 
      * @param file : An {@link OCFile}
      */
     public void updateFileDetails(OCFile file, Account ocAccount) {
-        mFile = file;
+        setFile(file);
         if (ocAccount != null && ( 
                 mStorageManager == null || 
                 (mAccount != null && !mAccount.equals(ocAccount))
@@ -489,50 +511,52 @@ public class FileDetailFragment extends SherlockFragment implements
             mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());
         }
         mAccount = ocAccount;
-        updateFileDetails(false);
+        updateFileDetails(false, false);
     }
-    
 
     /**
      * Updates the view with all relevant details about that file.
      *
      * TODO Remove parameter when the transferring state of files is kept in database. 
      * 
+     * TODO REFACTORING! this method called 5 times before every time the fragment is shown! 
+     * 
      * @param transferring      Flag signaling if the file should be considered as downloading or uploading, 
      *                          although {@link FileDownloaderBinder#isDownloading(Account, OCFile)}  and 
      *                          {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.
-     * 
+     *                          
+     * @param refresh           If 'true', try to refresh the hold file from the database
      */
-    public void updateFileDetails(boolean transferring) {
+    public void updateFileDetails(boolean transferring, boolean refresh) {
 
-        if (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment) {
+        if (readyToShow()) {
+            
+            if (refresh && mStorageManager != null) {
+                setFile(mStorageManager.getFileByPath(getFile().getRemotePath()));
+            }
+            OCFile file = getFile();
             
             // set file details
-            setFilename(mFile.getFileName());
-            setFiletype(mFile.getMimetype());
-            setFilesize(mFile.getFileLength());
+            setFilename(file.getFileName());
+            setFiletype(file.getMimetype());
+            setFilesize(file.getFileLength());
             if(ocVersionSupportsTimeCreated()){
-                setTimeCreated(mFile.getCreationTimestamp());
+                setTimeCreated(file.getCreationTimestamp());
             }
            
-            setTimeModified(mFile.getModificationTimestamp());
+            setTimeModified(file.getModificationTimestamp());
             
             CheckBox cb = (CheckBox)getView().findViewById(R.id.fdKeepInSync);
-            cb.setChecked(mFile.keepInSync());
+            cb.setChecked(file.keepInSync());
 
             // configure UI for depending upon local state of the file
             //if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath()) || FileUploader.isUploading(mAccount, mFile.getRemotePath())) {
             FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
             FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
-            if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile))) {
+            if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file))) {
                 setButtonsForTransferring();
                 
-            } else if (mFile.isDown()) {
-                // Update preview
-                if (mFile.getMimetype().startsWith("image/")) {
-                    BitmapLoader bl = new BitmapLoader();
-                    bl.execute(new String[]{mFile.getStoragePath()});
-                }
+            } else if (file.isDown()) {
                 
                 setButtonsForDown();
                 
@@ -544,7 +568,16 @@ public class FileDetailFragment extends SherlockFragment implements
         getView().invalidate();
     }
     
-    
+    /**
+     * Checks if the fragment is ready to show details of a OCFile
+     *  
+     * @return  'True' when the fragment is ready to show details of a file
+     */
+    private boolean readyToShow() {
+        return (getFile() != null && mAccount != null && mLayout == R.layout.file_details_fragment);        
+    }
+
+
     /**
      * Updates the filename in view
      * @param filename to set
@@ -611,30 +644,34 @@ public class FileDetailFragment extends SherlockFragment implements
      */
     private void setButtonsForTransferring() {
         if (!isEmpty()) {
-            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);
-            downloadButton.setText(R.string.common_cancel);
-            //downloadButton.setEnabled(false);
-        
             // let's protect the user from himself ;)
-            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);
-            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false);
-            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false);
             getView().findViewById(R.id.fdKeepInSync).setEnabled(false);
+            
+            // show the progress bar for the transfer
+            getView().findViewById(R.id.fdProgressBlock).setVisibility(View.VISIBLE);
+            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
+            progressText.setVisibility(View.VISIBLE);
+            FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
+            FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
+            if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, getFile())) {
+                progressText.setText(R.string.downloader_download_in_progress_ticker);
+            } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile())) {
+                progressText.setText(R.string.uploader_upload_in_progress_ticker);
+            }
         }
     }
-    
+
     /**
      * Enables or disables buttons for a file locally available 
      */
     private void setButtonsForDown() {
         if (!isEmpty()) {
-            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);
-            downloadButton.setText(R.string.filedetails_sync_file);
-        
-            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(true);
-            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
-            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
             getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
+            
+            // hides the progress bar
+            getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
+            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
+            progressText.setVisibility(View.GONE);
         }
     }
 
@@ -643,13 +680,12 @@ public class FileDetailFragment extends SherlockFragment implements
      */
     private void setButtonsForRemote() {
         if (!isEmpty()) {
-            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);
-            downloadButton.setText(R.string.filedetails_download);
-            
-            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);
-            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
-            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
             getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
+            
+            // hides the progress bar
+            getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
+            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
+            progressText.setVisibility(View.GONE);
         }
     }
     
@@ -673,55 +709,8 @@ public class FileDetailFragment extends SherlockFragment implements
         return false;
     }
     
-    
-    /**
-     * Interface to implement by any Activity that includes some instance of FileDetailFragment
-     * 
-     * @author David A. Velasco
-     */
-    public interface ContainerActivity extends TransferServiceGetter {
-
-        /**
-         * Callback method invoked when the detail fragment wants to notice its container 
-         * activity about a relevant state the file shown by the fragment.
-         * 
-         * Added to notify to FileDisplayActivity about the need of refresh the files list. 
-         * 
-         * Currently called when:
-         *  - a download is started;
-         *  - a rename is completed;
-         *  - a deletion is completed;
-         *  - the 'inSync' flag is changed;
-         */
-        public void onFileStateChanged();
-        
-    }
-    
 
     /**
-     * Once the file download has finished -> update view
-     * @author Bartek Przybylski
-     */
-    private class DownloadFinishReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
-
-            if (!isEmpty() && accountName.equals(mAccount.name)) {
-                boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
-                String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
-                if (mFile.getRemotePath().equals(downloadedRemotePath)) {
-                    if (downloadWasFine) {
-                        mFile = mStorageManager.getFileByPath(downloadedRemotePath);
-                    }
-                    updateFileDetails(false);    // it updates the buttons; must be called although !downloadWasFine
-                }
-            }
-        }
-    }
-    
-    
-    /**
      * Once the file upload has finished -> update view
      * 
      * Being notified about the finish of an upload is necessary for the next sequence:
@@ -739,11 +728,11 @@ public class FileDetailFragment extends SherlockFragment implements
             if (!isEmpty() && accountName.equals(mAccount.name)) {
                 boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false);
                 String uploadRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH);
-                boolean renamedInUpload = mFile.getRemotePath().equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH));
-                if (mFile.getRemotePath().equals(uploadRemotePath) ||
+                boolean renamedInUpload = getFile().getRemotePath().equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH));
+                if (getFile().getRemotePath().equals(uploadRemotePath) ||
                     renamedInUpload) {
                     if (uploadWasFine) {
-                        mFile = mStorageManager.getFileByPath(uploadRemotePath);
+                        setFile(mStorageManager.getFileByPath(uploadRemotePath));
                     }
                     if (renamedInUpload) {
                         String newName = (new File(uploadRemotePath)).getName();
@@ -751,207 +740,33 @@ public class FileDetailFragment extends SherlockFragment implements
                         msg.show();
                     }
                     getSherlockActivity().removeStickyBroadcast(intent);    // not the best place to do this; a small refactorization of BroadcastReceivers should be done
-                    updateFileDetails(false);    // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server
-                }
-            }
-        }
-    }
-    
-
-    // this is a temporary class for sharing purposes, it need to be replaced in transfer service
-    @SuppressWarnings("unused")
-    private class ShareRunnable implements Runnable {
-        private String mPath;
-
-        public ShareRunnable(String path) {
-            mPath = path;
-        }
-        
-        public void run() {
-            AccountManager am = AccountManager.get(getActivity());
-            Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
-            OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
-            String url = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + AccountUtils.getWebdavPath(ocv);
-
-            Log_OC.d("share", "sharing for version " + ocv.toString());
-
-            if (ocv.compareTo(new OwnCloudVersion(0x040000)) >= 0) {
-                String APPS_PATH = "/apps/files_sharing/";
-                String SHARE_PATH = "ajax/share.php";
-
-                String SHARED_PATH = "/apps/files_sharing/get.php?token=";
-                
-                final String WEBDAV_SCRIPT = "webdav.php";
-                final String WEBDAV_FILES_LOCATION = "/files/";
-                
-                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getActivity().getApplicationContext());
-                HttpConnectionManagerParams params = new HttpConnectionManagerParams();
-                params.setMaxConnectionsPerHost(wc.getHostConfiguration(), 5);
-
-                //wc.getParams().setParameter("http.protocol.single-cookie-header", true);
-                //wc.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
-
-                PostMethod post = new PostMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + APPS_PATH + SHARE_PATH);
-
-                post.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8" );
-                post.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
-                List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-                Log_OC.d("share", mPath+"");
-                formparams.add(new BasicNameValuePair("sources",mPath));
-                formparams.add(new BasicNameValuePair("uid_shared_with", "public"));
-                formparams.add(new BasicNameValuePair("permissions", "0"));
-                post.setRequestEntity(new StringRequestEntity(URLEncodedUtils.format(formparams, HTTP.UTF_8)));
-
-                int status;
-                try {
-                    PropFindMethod find = new PropFindMethod(url+"/");
-                    find.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
-                    Log_OC.d("sharer", ""+ url+"/");
-                    
-                    for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
-                        Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
-                    }
-                    
-                    int status2 = wc.executeMethod(find);
-
-                    Log_OC.d("sharer", "propstatus "+status2);
-                    
-                    GetMethod get = new GetMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + "/");
-                    get.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
-                    
-                    status2 = wc.executeMethod(get);
-
-                    Log_OC.d("sharer", "getstatus "+status2);
-                    Log_OC.d("sharer", "" + get.getResponseBodyAsString());
-                    
-                    for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
-                        Log_OC.d("sharer", a.getName() + ":"+a.getValue());
-                    }
-
-                    status = wc.executeMethod(post);
-                    for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
-                        Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
-                    }
-                    for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
-                        Log_OC.d("sharer", a.getName() + ":"+a.getValue());
-                    }
-                    String resp = post.getResponseBodyAsString();
-                    Log_OC.d("share", ""+post.getURI().toString());
-                    Log_OC.d("share", "returned status " + status);
-                    Log_OC.d("share", " " +resp);
-                    
-                    if(status != HttpStatus.SC_OK ||resp == null || resp.equals("") || resp.startsWith("false")) {
-                        return;
-                     }
-
-                    JSONObject jsonObject = new JSONObject (resp);
-                    String jsonStatus = jsonObject.getString("status");
-                    if(!jsonStatus.equals("success")) throw new Exception("Error while sharing file status != success");
                     
-                    String token = jsonObject.getString("data");
-                    String uri = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + SHARED_PATH + token; 
-                    Log_OC.d("Actions:shareFile ok", "url: " + uri);   
-                    
-                } catch (Exception e) {
-                    e.printStackTrace();
+                    updateFileDetails(false, false);    // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server
+                   
+                    // Force the preview if the file is an image
+                    if (uploadWasFine && PreviewImageFragment.canBePreviewed(getFile())) {
+                        ((FileDisplayActivity) mContainerActivity).startImagePreview(getFile());
+                    } 
                 }
-                
-            } else if (ocv.compareTo(new OwnCloudVersion(0x030000)) >= 0) {
-                
             }
         }
     }
     
+
     public void onDismiss(EditNameDialog dialog) {
         if (dialog.getResult()) {
             String newFilename = dialog.getNewFilename();
             Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename);
-            mLastRemoteOperation = new RenameFileOperation( mFile
+            mLastRemoteOperation = new RenameFileOperation( getFile()
                                                             mAccount, 
                                                             newFilename, 
                                                             new FileDataStorageManager(mAccount, getActivity().getContentResolver()));
-            WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
-            mLastRemoteOperation.execute(wc, this, mHandler);
-            boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
-            getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
+            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
+            ((FileDisplayActivity) getActivity()).showLoadingDialog();
         }
     }
     
     
-    class BitmapLoader extends AsyncTask<String, Void, Bitmap> {
-        @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20
-               @Override
-        protected Bitmap doInBackground(String... params) {
-            Bitmap result = null;
-            if (params.length != 1) return result;
-            String storagePath = params[0];
-            try {
-
-                BitmapFactory.Options options = new Options();
-                options.inScaled = true;
-                options.inPurgeable = true;
-                options.inJustDecodeBounds = true;
-                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
-                    options.inPreferQualityOverSpeed = false;
-                }
-                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
-                    options.inMutable = false;
-                }
-
-                result = BitmapFactory.decodeFile(storagePath, options);
-                options.inJustDecodeBounds = false;
-
-                int width = options.outWidth;
-                int height = options.outHeight;
-                int scale = 1;
-                if (width >= 2048 || height >= 2048) {
-                    scale = (int) Math.ceil((Math.ceil(Math.max(height, width) / 2048.)));
-                    options.inSampleSize = scale;
-                }
-                Display display = getActivity().getWindowManager().getDefaultDisplay();
-                Point size = new Point();
-                int screenwidth;
-                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
-                    display.getSize(size);
-                    screenwidth = size.x;
-                } else {
-                    screenwidth = display.getWidth();
-                }
-
-                Log_OC.e("ASD", "W " + width + " SW " + screenwidth);
-
-                if (width > screenwidth) {
-                    scale = (int) Math.ceil((float)width / screenwidth);
-                    options.inSampleSize = scale;
-                }
-
-                result = BitmapFactory.decodeFile(storagePath, options);
-
-                Log_OC.e("ASD", "W " + options.outWidth + " SW " + options.outHeight);
-
-            } catch (OutOfMemoryError e) {
-                result = null;
-                Log_OC.e(TAG, "Out of memory occured for file with size " + storagePath);
-                
-            } catch (NoSuchFieldError e) {
-                result = null;
-                Log_OC.e(TAG, "Error from access to unexisting field despite protection " + storagePath);
-                
-            } catch (Throwable t) {
-                result = null;
-                Log_OC.e(TAG, "Unexpected error while creating image preview " + storagePath, t);
-            }
-            return result;
-        }
-        @Override
-        protected void onPostExecute(Bitmap result) {
-            if (result != null && mPreview != null) {
-                mPreview.setImageBitmap(result);
-            }
-        }
-        
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -972,22 +787,12 @@ public class FileDetailFragment extends SherlockFragment implements
     
     
     private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {
-        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
-        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
-        
+        ((FileDisplayActivity) getActivity()).dismissLoadingDialog();
         if (result.isSuccess()) {
             Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG);
             msg.show();
-            if (inDisplayActivity) {
-                // double pane
-                FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
-                transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment
-                transaction.commit();
-                mContainerActivity.onFileStateChanged();
-            } else {
-                getActivity().finish();
-            }
-                
+            ((FileDisplayActivity)getActivity()).cleanSecondFragment();
+
         } else {
             Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG); 
             msg.show();
@@ -998,8 +803,7 @@ public class FileDetailFragment extends SherlockFragment implements
     }
     
     private void onRenameFileOperationFinish(RenameFileOperation operation, RemoteOperationResult result) {
-        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
-        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
+        ((FileDisplayActivity) getActivity()).dismissLoadingDialog();
         
         if (result.isSuccess()) {
             updateFileDetails(((RenameFileOperation)operation).getFile(), mAccount);
@@ -1010,6 +814,9 @@ public class FileDetailFragment extends SherlockFragment implements
                 Toast msg = Toast.makeText(getActivity(), R.string.rename_local_fail_msg, Toast.LENGTH_LONG); 
                 msg.show();
                 // TODO throw again the new rename dialog
+            } if (result.getCode().equals(ResultCode.INVALID_CHARACTER_IN_NAME)) {
+                Toast msg = Toast.makeText(getActivity(), R.string.filename_forbidden_characters, Toast.LENGTH_LONG);
+                msg.show();
             } else {
                 Toast msg = Toast.makeText(getActivity(), R.string.rename_server_fail_msg, Toast.LENGTH_LONG); 
                 msg.show();
@@ -1021,22 +828,18 @@ public class FileDetailFragment extends SherlockFragment implements
     }
     
     private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) {
-        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
-        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
-
+        ((FileDisplayActivity) getActivity()).dismissLoadingDialog();
+        OCFile file = getFile();
         if (!result.isSuccess()) {
             if (result.getCode() == ResultCode.SYNC_CONFLICT) {
                 Intent i = new Intent(getActivity(), ConflictsResolveActivity.class);
-                i.putExtra(ConflictsResolveActivity.EXTRA_FILE, mFile);
+                i.putExtra(ConflictsResolveActivity.EXTRA_FILE, file);
                 i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount);
                 startActivity(i);
                 
-            } else {
-                Toast msg = Toast.makeText(getActivity(), R.string.sync_file_fail_msg, Toast.LENGTH_LONG); 
-                msg.show();
-            }
+            } 
             
-            if (mFile.isDown()) {
+            if (file.isDown()) {
                 setButtonsForDown();
                 
             } else {
@@ -1045,12 +848,13 @@ public class FileDetailFragment extends SherlockFragment implements
             
         } else {
             if (operation.transferWasRequested()) {
+                setButtonsForTransferring();
                 mContainerActivity.onFileStateChanged();    // this is not working; FileDownloader won't do NOTHING at all until this method finishes, so 
                                                             // checking the service to see if the file is downloading results in FALSE
             } else {
                 Toast msg = Toast.makeText(getActivity(), R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG); 
                 msg.show();
-                if (mFile.isDown()) {
+                if (file.isDown()) {
                     setButtonsForDown();
                     
                 } else {
@@ -1059,5 +863,64 @@ public class FileDetailFragment extends SherlockFragment implements
             }
         }
     }
+    
+
+    public void listenForTransferProgress() {
+        if (mProgressListener != null) {
+            if (mContainerActivity.getFileDownloaderBinder() != null) {
+                mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, getFile());
+            }
+            if (mContainerActivity.getFileUploaderBinder() != null) {
+                mContainerActivity.getFileUploaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, getFile());
+            }
+        }
+    }
+    
+    
+    public void leaveTransferProgress() {
+        if (mProgressListener != null) {
+            if (mContainerActivity.getFileDownloaderBinder() != null) {
+                mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, getFile());
+            }
+            if (mContainerActivity.getFileUploaderBinder() != null) {
+                mContainerActivity.getFileUploaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, getFile());
+            }
+        }
+    }
+
+
+    
+    /**
+     * Helper class responsible for updating the progress bar shown for file uploading or downloading  
+     * 
+     * @author David A. Velasco
+     */
+    private class ProgressListener implements OnDatatransferProgressListener {
+        int mLastPercent = 0;
+        WeakReference<ProgressBar> mProgressBar = null;
+        
+        ProgressListener(ProgressBar progressBar) {
+            mProgressBar = new WeakReference<ProgressBar>(progressBar);
+        }
+        
+        @Override
+        public void onTransferProgress(long progressRate) {
+            // old method, nothing here
+        };
+
+        @Override
+        public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
+            int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
+            if (percent != mLastPercent) {
+                ProgressBar pb = mProgressBar.get();
+                if (pb != null) {
+                    pb.setProgress(percent);
+                    pb.postInvalidate();
+                }
+            }
+            mLastPercent = percent;
+        }
+
+    };
 
 }