* #26029 First implementation of expanding/retracting
diff --git a/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java b/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java
index 9254e8c..70cae8e 100644
--- a/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java
+++ b/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java
@@ -73,8 +73,12 @@
 
     @Override
     public void run() {
-        Bitmap photo_bmp = loadContactPhoto(cr, cid);
-
+        Bitmap photo_bmp;
+        try{
+        photo_bmp = loadContactPhoto(cr, cid);
+        }catch(IllegalArgumentException e){
+            photo_bmp = null;
+        }
         if (photo_bmp == null) {
             photo_bmp = BitmapFactory.decodeResource(view.getResources(), R.drawable.ic_contact_picture);
         }
diff --git a/src/com/savoirfairelinux/sflphone/adapters/HistoryAdapter.java b/src/com/savoirfairelinux/sflphone/adapters/HistoryAdapter.java
index 27aee1f..628d6cb 100644
--- a/src/com/savoirfairelinux/sflphone/adapters/HistoryAdapter.java
+++ b/src/com/savoirfairelinux/sflphone/adapters/HistoryAdapter.java
@@ -6,48 +6,66 @@
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.TimeZone;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 import android.app.Activity;
 import android.content.Context;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.savoirfairelinux.sflphone.R;
+import com.savoirfairelinux.sflphone.fragments.HistoryFragment;
+import com.savoirfairelinux.sflphone.model.HistoryEntry;
 import com.savoirfairelinux.sflphone.service.ServiceConstants;
 
 public class HistoryAdapter extends BaseAdapter {
 
-    Context mContext;
-    ArrayList<HashMap<String, String>> dataset;
+    HistoryFragment mContext;
+    ArrayList<HistoryEntry> dataset;
     private static final String TAG = HistoryAdapter.class.getSimpleName();
+    private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
 
-    public HistoryAdapter(Activity activity, ArrayList<HashMap<String, String>> entries) {
+
+
+    public HistoryAdapter(HistoryFragment activity, ArrayList<HistoryEntry> history) {
         mContext = activity;
-        dataset = entries;
+        dataset = history;
     }
 
     @Override
-    public View getView(int pos, View convertView, ViewGroup arg2) {
+    public View getView(final int pos, View convertView, ViewGroup arg2) {
         View rowView = convertView;
         HistoryView entryView = null;
 
         if (rowView == null) {
             // Get a new instance of the row layout view
-            LayoutInflater inflater = LayoutInflater.from(mContext);
+            LayoutInflater inflater = LayoutInflater.from(mContext.getActivity());
             rowView = inflater.inflate(R.layout.item_history, null);
 
             // Hold the view objects in an object
             // so they don't need to be re-fetched
             entryView = new HistoryView();
+            entryView.photo = (ImageView) rowView.findViewById(R.id.photo);
             entryView.displayName = (TextView) rowView.findViewById(R.id.display_name);
             entryView.duration = (TextView) rowView.findViewById(R.id.duration);
             entryView.date = (TextView) rowView.findViewById(R.id.date_start);
-
+            entryView.call_button = (ImageButton) rowView.findViewById(R.id.action_call);
+            entryView.call_button.setOnClickListener(new OnClickListener() {
+                
+                @Override
+                public void onClick(View v) {
+                   mContext.makeNewCall(pos);
+                    
+                }
+            } );
             rowView.setTag(entryView);
         } else {
             entryView = (HistoryView) rowView.getTag();
@@ -57,40 +75,31 @@
         // to the view objects
         
 //        SipCall call = (SipCall) mCallList.values().toArray()[position];
-        entryView.displayName.setText(dataset.get(pos).get(ServiceConstants.HISTORY_ACCOUNT_ID_KEY));
+        entryView.displayName.setText(dataset.get(pos).getContact().getmDisplayName());
+        
+        infos_fetcher.execute(new ContactPictureLoader(mContext.getActivity(), entryView.photo, dataset.get(pos).getContact().getId()));
 
         
-        long timestampEnd = Long.parseLong(dataset.get(pos).get(ServiceConstants.HISTORY_TIMESTAMP_STOP_KEY));
-        long timestampStart = Long.parseLong(dataset.get(pos).get(ServiceConstants.HISTORY_TIMESTAMP_START_KEY));
-        entryView.date.setText(getDate(timestampStart,"yyyy-MM-dd"));
-        
-        long duration = timestampEnd - timestampStart;
-        entryView.duration.setText("Duration: "+duration);
+
+        entryView.date.setText(dataset.get(pos).getCalls().lastEntry().getValue().getDate("yyyy-MM-dd"));
+        entryView.duration.setText(dataset.get(pos).getTotalDuration());
+
 
         return rowView;
 
     }
 
-    private String getDate(long timeStamp, String format) {
-        Calendar cal = Calendar.getInstance();
-        TimeZone tz = cal.getTimeZone();
-        SimpleDateFormat objFormatter = new SimpleDateFormat(format, Locale.CANADA);
-        objFormatter.setTimeZone(tz);
-
-        Calendar objCalendar = Calendar.getInstance(tz);
-        objCalendar.setTimeInMillis(timeStamp*1000);
-        String result = objFormatter.format(objCalendar.getTime());
-        objCalendar.clear();
-        return result;
-    }
+    
 
     /*********************
      * ViewHolder Pattern
      *********************/
     public class HistoryView {
+        public ImageView photo;
         protected TextView displayName;
         protected TextView date;
         public TextView duration;
+        private ImageButton call_button;
     }
 
     @Override
@@ -100,7 +109,7 @@
     }
 
     @Override
-    public HashMap<String, String> getItem(int pos) {
+    public HistoryEntry getItem(int pos) {
         return dataset.get(pos);
     }
 
@@ -115,7 +124,7 @@
     }
 
     public void addAll(ArrayList<HashMap<String, String>> history) {
-        dataset.addAll(history);
+//        dataset.addAll(history);
 
     }
 
diff --git a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
index eb43a96..9b6ec03 100644
--- a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
+++ b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
  *
  *  Author: Adrien Beraud <adrien.beraud@gmail.com>
  *          Alexandre Lision <alexandre.lision@savoirfairelinux.com>
@@ -71,6 +71,7 @@
 import com.savoirfairelinux.sflphone.fragments.MenuFragment;
 import com.savoirfairelinux.sflphone.interfaces.AccountsInterface;
 import com.savoirfairelinux.sflphone.interfaces.CallInterface;
+import com.savoirfairelinux.sflphone.loaders.LoaderConstants;
 import com.savoirfairelinux.sflphone.model.CallContact;
 import com.savoirfairelinux.sflphone.model.SipCall;
 import com.savoirfairelinux.sflphone.receivers.AccountsReceiver;
@@ -162,36 +163,12 @@
             bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
         }
 
-        /* getFragment(Bundle, String) */
-        // if (savedInstanceState != null) {
-        // Log.w(TAG, "Activity restarted, recreating PagerAdapter...");
-        // /* getFragment (Bundle bundle, String key) */
-        // mDialingFragment = (DialingFragment) getFragmentManager().getFragment(savedInstanceState,
-        // mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_DIALING));
-        // mCallElementList = (CallElementListFragment) getFragmentManager().getFragment(savedInstanceState,
-        // mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CALL));
-        // mHistorySectionFragment = (HistoryFragment) getFragmentManager().getFragment(savedInstanceState,
-        // mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_HISTORY));
-        // }
-
-        // if (mDialingFragment == null) {
-        // mDialingFragment = new DialingFragment();
-        // Log.w(TAG, "Recreated mDialingFragment=" + mDialingFragment);
-        // }
-        //
         if (mContactsFragment == null) {
             mContactsFragment = new ContactListFragment();
             Log.w(TAG, "Recreated mContactListFragment=" + mContactsFragment);
             getFragmentManager().beginTransaction().replace(R.id.contacts_frame, mContactsFragment).commit();
         }
-        // if (mCallElementList == null) {
-        // mCallElementList = new CallElementListFragment();
-        // Log.w(TAG, "Recreated mCallElementList=" + mCallElementList);
-        // }
-        // if (mHistorySectionFragment == null) {
-        // mHistorySectionFragment = new HistoryFragment();
-        // Log.w(TAG, "Recreated mHistorySectionFragment=" + mHistorySectionFragment);
-        // }
+
 
         mDrawer = (CustomSlidingDrawer) findViewById(R.id.custom_sliding_drawer);
 
@@ -242,34 +219,6 @@
             }
         });
 
-        // getActionBar().setCustomView(R.layout.actionbar);
-        // spinnerAccounts = (Spinner) getActionBar().getCustomView().findViewById(R.id.account_selection);
-        // spinnerAccounts.setOnItemSelectedListener(new OnItemSelectedListener() {
-        //
-        // @Override
-        // public void onItemSelected(AdapterView<?> arg0, View view, int pos, long arg3) {
-        // // public void onClick(DialogInterface dialog, int which) {
-        //
-        // Log.i(TAG, "Selected Account: " + mAdapter.getItem(pos));
-        // if (null != view) {
-        // ((RadioButton) view.findViewById(R.id.account_checked)).toggle();
-        // }
-        // mAdapter.setSelectedAccount(pos);
-        // // accountSelectedNotifyAccountList(mAdapter.getItem(pos));
-        // // setSelection(cursor.getPosition(),true);
-        //
-        // }
-        //
-        // @Override
-        // public void onNothingSelected(AdapterView<?> arg0) {
-        // // TODO Auto-generated method stub
-        //
-        // }
-        // });
-        // ((TextView) getActionBar().getCustomView().findViewById(R.id.activity_title)).setText(getTitle());
-        // getActionBar().setDisplayShowCustomEnabled(true);
-        
-        
 
         fMenu = new MenuFragment();
         getFragmentManager().beginTransaction().replace(R.id.left_drawer, fMenu).commit();
@@ -350,11 +299,20 @@
     
     @Override
     public void onBackPressed() {
+        
+        if(getActionBar().getCustomView() != null){
+            getActionBar().setDisplayShowCustomEnabled(false);
+            getActionBar().setCustomView(null);
+            // Display all the contacts again
+            getLoaderManager().restartLoader(LoaderConstants.CONTACT_LOADER, null, mContactsFragment);
+            return;
+        }
+        
         if (mDrawer.isOpened()) {
             mDrawer.animateClose();
             return;
         }
-        
+
         if (isClosing) {
             super.onBackPressed();
             t.cancel();
@@ -473,6 +431,7 @@
             break;
         case REQUEST_CODE_CALL:
             Log.w(TAG, "Result out of CallActivity");
+            getLoaderManager().restartLoader(LoaderConstants.HISTORY_LOADER, null, (HistoryFragment)mSectionsPagerAdapter.getItem(2));
             break;
         }
 
diff --git a/src/com/savoirfairelinux/sflphone/fragments/AudioManagementFragment.java b/src/com/savoirfairelinux/sflphone/fragments/AudioManagementFragment.java
index 954eb49..022cf2e 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/AudioManagementFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/AudioManagementFragment.java
@@ -1,7 +1,8 @@
 /*
- *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
  *
  *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
+ *          Alexandre Lision <alexandre.lision@savoirfairelinux.com>
  *
  *  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
diff --git a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
index e8df782..124e806 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
  *
  *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
  *
@@ -75,7 +75,7 @@
 
 	private HashMap<CallContact, Bubble> contacts = new HashMap<CallContact, Bubble>();
 
-	private CallContact myself = CallContact.ContactBuilder.buildUserContact("Me");
+	private CallContact myself;
 
 	private Bitmap hangup_icon;
 	private Bitmap call_icon;
@@ -177,6 +177,8 @@
 		//rootView.requestDisallowInterceptTouchEvent(true);
 
 		mCallbacks = (Callbacks) activity;
+		myself = CallContact.ContactBuilder.buildUserContact(activity.getContentResolver(), "");
+		
 	}
 
 	@Override
@@ -208,8 +210,8 @@
 
 		callStatusTxt.setText("0 min");
 
-		getBubbleFor(mCall.getContacts().get(0), model.width/2, model.height/2);
-		getBubbleFor(myself, model.width/2, model.height/3);
+		getBubbleFor(mCall.getContacts().get(0), model.width/2, model.height/3);
+		getBubbleFor(myself, model.width/2, model.height/2);
 
 		model.clearAttractors();
 		model.addAttractor(new Attractor(new PointF(model.width / 2, model.height * .8f), ATTRACTOR_SIZE, new Attractor.Callback() {
@@ -256,7 +258,8 @@
 		callStatusTxt.setText("Calling...");
 
 		// TODO off-thread image loading
-		getBubbleFor(mCall.getContacts().get(0), model.width/2, model.height/2);
+		getBubbleFor(mCall.getContacts().get(0), model.width/2, model.height/3);
+		getBubbleFor(myself, model.width/2, model.height/2);
 
 		model.clearAttractors();
 		model.addAttractor(new Attractor(new PointF(model.width / 2, model.height * .8f), 40, new Attractor.Callback() {
@@ -288,7 +291,7 @@
 
 		// TODO off-thread image loading
 		if (contact.getPhoto_id() > 0) {
-			Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), mCall.getContacts().get(0).getId());
+			Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), contact.getId());
 			contact_bubble = new Bubble(x, y, BUBBLE_SIZE, photo);
 		} else {
 			contact_bubble = new Bubble(x, y, BUBBLE_SIZE, getActivity(), R.drawable.ic_contact_picture);
diff --git a/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java b/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java
index b1d175c..ac9d10e 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
  *
  *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
  *
diff --git a/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java b/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java
index d50fbdd..1f40bd9 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java
@@ -52,7 +52,6 @@
 import android.view.View.OnClickListener;
 import android.view.View.OnDragListener;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemLongClickListener;
@@ -61,13 +60,13 @@
 import android.widget.ListView;
 import android.widget.RelativeLayout;
 import android.widget.SearchView;
-import android.widget.SearchView.OnCloseListener;
 import android.widget.SearchView.OnQueryTextListener;
 
 import com.savoirfairelinux.sflphone.R;
 import com.savoirfairelinux.sflphone.adapters.ContactsAdapter;
 import com.savoirfairelinux.sflphone.adapters.StarredContactsAdapter;
 import com.savoirfairelinux.sflphone.loaders.ContactsLoader;
+import com.savoirfairelinux.sflphone.loaders.LoaderConstants;
 import com.savoirfairelinux.sflphone.model.CallContact;
 import com.savoirfairelinux.sflphone.service.ISipService;
 import com.savoirfairelinux.sflphone.views.TACGridView;
@@ -79,10 +78,6 @@
 
     String mCurFilter;
 
-    private RelativeLayout mHandle;
-
-    public static final int CONTACT_LOADER = 555;
-
     @Override
     public void onCreate(Bundle savedInBundle) {
         super.onCreate(savedInBundle);
@@ -148,7 +143,7 @@
 
         // In order to onCreateOptionsMenu be called
         setHasOptionsMenu(true);
-        getLoaderManager().initLoader(CONTACT_LOADER, null, this);
+        getLoaderManager().initLoader(LoaderConstants.CONTACT_LOADER, null, this);
 
     }
 
@@ -259,7 +254,9 @@
             return true;
         }
         mCurFilter = newFilter;
-        getLoaderManager().restartLoader(CONTACT_LOADER, null, this);
+        Bundle b = new Bundle();
+        b.putString("filter", mCurFilter);
+        getLoaderManager().restartLoader(LoaderConstants.CONTACT_LOADER, b, this);
         return true;
     }
 
@@ -273,8 +270,8 @@
     public Loader<Bundle> onCreateLoader(int id, Bundle args) {
         Uri baseUri;
 
-        if (mCurFilter != null) {
-            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(mCurFilter));
+        if (args != null) {
+            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(args.getString("filter")));
         } else {
             baseUri = Contacts.CONTENT_URI;
         }
@@ -304,7 +301,7 @@
     }
 
     public void setHandleView(RelativeLayout handle) {
-        mHandle = handle;
+//        mHandle = handle;
         
 
 
diff --git a/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java b/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java
index 8711384..e3dcebe 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
  *
  *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
  *
@@ -58,6 +58,7 @@
 import com.savoirfairelinux.sflphone.R;
 import com.savoirfairelinux.sflphone.adapters.AccountSelectionAdapter;
 import com.savoirfairelinux.sflphone.loaders.AccountsLoader;
+import com.savoirfairelinux.sflphone.loaders.LoaderConstants;
 import com.savoirfairelinux.sflphone.model.Account;
 import com.savoirfairelinux.sflphone.service.ISipService;
 import com.savoirfairelinux.sflphone.views.ClearableEditText;
@@ -76,7 +77,7 @@
     private Callbacks mCallbacks = sDummyCallbacks;
     private Spinner spinnerAccounts;
 
-    private static final int ACCOUNTS_LOADER = 555;
+    
 
     /**
      * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
@@ -228,7 +229,7 @@
 
             mAdapter = new AccountSelectionAdapter(getActivity(), service, new ArrayList<Account>());
             spinnerAccounts.setAdapter(mAdapter);
-            getActivity().getLoaderManager().initLoader(ACCOUNTS_LOADER, null, this);
+            getActivity().getLoaderManager().initLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
         }
 
     }
@@ -255,7 +256,7 @@
 
     public void updateAllAccounts() {
         if (getActivity() != null)
-            getActivity().getLoaderManager().restartLoader(ACCOUNTS_LOADER, null, this);
+            getActivity().getLoaderManager().restartLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
 
     }
 
diff --git a/src/com/savoirfairelinux/sflphone/fragments/HistoryFragment.java b/src/com/savoirfairelinux/sflphone/fragments/HistoryFragment.java
index e0fd151..ed2c410 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/HistoryFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/HistoryFragment.java
@@ -1,3 +1,33 @@
+/*
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
+ *
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *
+ *  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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
 package com.savoirfairelinux.sflphone.fragments;
 
 import java.util.ArrayList;
@@ -5,24 +35,32 @@
 
 import android.app.Activity;
 import android.app.ListFragment;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.content.Loader;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.AdapterView.OnItemClickListener;
 
 import com.savoirfairelinux.sflphone.R;
 import com.savoirfairelinux.sflphone.adapters.HistoryAdapter;
+import com.savoirfairelinux.sflphone.loaders.HistoryLoader;
+import com.savoirfairelinux.sflphone.loaders.LoaderConstants;
+import com.savoirfairelinux.sflphone.model.CallContact;
+import com.savoirfairelinux.sflphone.model.HistoryEntry;
 import com.savoirfairelinux.sflphone.model.SipCall;
 import com.savoirfairelinux.sflphone.service.ISipService;
 
-public class HistoryFragment extends ListFragment {
+public class HistoryFragment extends ListFragment implements LoaderCallbacks<ArrayList<HistoryEntry>> {
 
     private static final String TAG = HistoryFragment.class.getSimpleName();
     public static final String ARG_SECTION_NUMBER = "section_number";
-    private boolean isReady;
-    private ISipService service;
+
     HistoryAdapter mAdapter;
     private Callbacks mCallbacks = sDummyCallbacks;
     /**
@@ -30,7 +68,7 @@
      */
     private static Callbacks sDummyCallbacks = new Callbacks() {
         @Override
-        public void onCallSelected(SipCall c) {
+        public void onCallDialed(String account, String to) {
         }
 
         @Override
@@ -42,7 +80,7 @@
     };
 
     public interface Callbacks {
-        public void onCallSelected(SipCall c);
+        public void onCallDialed(String account, String to);
 
         public ISipService getService();
 
@@ -51,7 +89,7 @@
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
-        isReady = false;
+
         if (!(activity instanceof Callbacks)) {
             throw new IllegalStateException("Activity must implement fragment's callbacks.");
         }
@@ -74,10 +112,14 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
         View inflatedView = inflater.inflate(R.layout.frag_history, parent, false);
-        isReady = true;
-        if (isReady) {
-            Log.i(TAG, "C PRET");
-        }
+
+        ((ListView)inflatedView.findViewById(android.R.id.list)).setOnItemClickListener(new OnItemClickListener() {
+
+            @Override
+            public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
+                mAdapter.getItem(pos);
+            }
+        });
         return inflatedView;
     }
 
@@ -85,36 +127,31 @@
     public void onStart() {
         super.onStart();
         Log.w(TAG, "onStart");
-        if (mCallbacks.getService() != null) {
-
-            Log.i(TAG, "oncreateview");
-            onServiceSipBinded(mCallbacks.getService());
-        }
+        getLoaderManager().initLoader(LoaderConstants.HISTORY_LOADER, null, this);
     }
 
-    /**
-     * Called by activity to pass a reference to sipservice to Fragment.
-     * 
-     * @param isip
-     */
-    public void onServiceSipBinded(ISipService isip) {
-        Log.w(TAG, "onServiceSipBinded");
-        if (isReady) {
-            service = isip;
-            ArrayList<HashMap<String, String>> history;
-            try {
-                history = (ArrayList<HashMap<String, String>>) mCallbacks.getService().getHistory();
-                Log.i(TAG, "history size:" + history.size());
-                mAdapter = new HistoryAdapter(getActivity(), history);
-                getListView().setAdapter(mAdapter);
-                mAdapter.notifyDataSetChanged();
+    public void makeNewCall(int position){
+        mCallbacks.onCallDialed(String.valueOf(mAdapter.getItem(position).getAccountID()), mAdapter.getItem(position).getNumber());
+    }
 
-            } catch (RemoteException e) {
-                Log.i(TAG, e.toString());
-            }
-        } else {
-            Log.w(TAG, "nor Ready");
-        }
+    @Override
+    public Loader<ArrayList<HistoryEntry>> onCreateLoader(int id, Bundle args) {
+        HistoryLoader loader = new HistoryLoader(getActivity(), mCallbacks.getService());
+        loader.forceLoad();
+        return loader;
+    }
+
+    @Override
+    public void onLoadFinished(Loader<ArrayList<HistoryEntry>> arg0, ArrayList<HistoryEntry> history) {
+        mAdapter = new HistoryAdapter(this, history);
+        getListView().setAdapter(mAdapter);
+        mAdapter.notifyDataSetChanged();
+
+    }
+
+    @Override
+    public void onLoaderReset(Loader<ArrayList<HistoryEntry>> arg0) {
+        // TODO Auto-generated method stub
 
     }
 }
diff --git a/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java b/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java
index a3dcdd7..d47fc82 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java
@@ -1,7 +1,7 @@
 /*
- *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
  *
- *  Author: Adrien Beraud <adrien.beraud@gmail.com>
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
  *
  *  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
@@ -211,23 +211,7 @@
                             @Override
                             public void onClick(DialogInterface dialog, int item) {
                                 Log.i(TAG, "Selected " + items[item]);
-                                // switch (item) {
-                                // case 0:
-                                // call.notifyServiceHangup(service);
-                                // break;
-                                // case 1:
-                                // call.sendTextMessage();
-                                // // Need to hangup this call immediately since no way to do it after this action
-                                // call.notifyServiceHangup(service);
-                                // break;
-                                // case 2:
-                                // call.addToConference();
-                                // // Need to hangup this call immediately since no way to do it after this action
-                                // call.notifyServiceHangup(service);
-                                // break;
-                                // default:
-                                // break;
-                                // }
+
                             }
                         });
                 AlertDialog alert = builder.create();
@@ -237,15 +221,6 @@
             }
         });
 
-        lv.setOnItemClickListener(new OnItemClickListener() {
-
-            @Override
-            public void onItemClick(AdapterView<?> arg0, View v, int pos, long arg3) {
-                mCallbacks.onCallSelected(mAdapter.getItem(pos));
-
-            }
-
-        });
     }
 
     @Override
diff --git a/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java b/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java
index 3cac94e..8a64d0b 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java
@@ -1,3 +1,33 @@
+/*
+ *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
+ *
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *
+ *  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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
 package com.savoirfairelinux.sflphone.fragments;
 
 import java.util.concurrent.ExecutorService;
@@ -62,8 +92,6 @@
 
     }
 
-    private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
-
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
         View inflatedView = inflater.inflate(R.layout.frag_menu, parent, false);
diff --git a/src/com/savoirfairelinux/sflphone/loaders/ContactsLoader.java b/src/com/savoirfairelinux/sflphone/loaders/ContactsLoader.java
index dd793c2..de15e6b 100644
--- a/src/com/savoirfairelinux/sflphone/loaders/ContactsLoader.java
+++ b/src/com/savoirfairelinux/sflphone/loaders/ContactsLoader.java
@@ -10,13 +10,12 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.Contacts;
-import android.util.Log;
 
 import com.savoirfairelinux.sflphone.model.CallContact;
 
 public class ContactsLoader extends AsyncTaskLoader<Bundle> {
     
-    private static final String TAG = ContactsLoader.class.getSimpleName();
+//    private static final String TAG = ContactsLoader.class.getSimpleName();
 
     // These are the Contacts rows that we will retrieve.
     static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.LOOKUP_KEY, Contacts.STARRED };
diff --git a/src/com/savoirfairelinux/sflphone/loaders/HistoryLoader.java b/src/com/savoirfairelinux/sflphone/loaders/HistoryLoader.java
new file mode 100644
index 0000000..91a83bf
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/loaders/HistoryLoader.java
@@ -0,0 +1,99 @@
+package com.savoirfairelinux.sflphone.loaders;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.util.Log;
+
+import com.savoirfairelinux.sflphone.model.CallContact;
+import com.savoirfairelinux.sflphone.model.CallContact.ContactBuilder;
+import com.savoirfairelinux.sflphone.model.HistoryEntry;
+import com.savoirfairelinux.sflphone.model.HistoryEntry.HistoryCall;
+import com.savoirfairelinux.sflphone.service.ISipService;
+import com.savoirfairelinux.sflphone.service.ServiceConstants;
+
+public class HistoryLoader extends AsyncTaskLoader<ArrayList<HistoryEntry>> {
+
+    private static final String TAG = HistoryLoader.class.getSimpleName();
+    private ISipService service;
+    HashMap<String, HistoryEntry> historyEntries;
+
+    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.LOOKUP_KEY,
+            Contacts.STARRED };
+
+    public HistoryLoader(Context context, ISipService isip) {
+        super(context);
+        service = isip;
+    }
+
+    @Override
+    public ArrayList<HistoryEntry> loadInBackground() {
+
+        historyEntries = new HashMap<String, HistoryEntry>();
+
+        try {
+            ArrayList<HashMap<String, String>> history = (ArrayList<HashMap<String, String>>) service.getHistory();
+            Log.i(TAG, "history size:" + history.size());
+            CallContact.ContactBuilder builder = new CallContact.ContactBuilder();
+            for (HashMap<String, String> entry : history) {
+                entry.get(ServiceConstants.HISTORY_ACCOUNT_ID_KEY);
+                long timestampEnd = Long.parseLong(entry.get(ServiceConstants.HISTORY_TIMESTAMP_STOP_KEY));
+                long timestampStart = Long.parseLong(entry.get(ServiceConstants.HISTORY_TIMESTAMP_START_KEY));
+
+                System.out.println("HISTORY_TIMESTAMP_START_KEY" + entry.get(ServiceConstants.HISTORY_TIMESTAMP_START_KEY));
+                System.out.println("HISTORY_INCOMING_STRING" + entry.get(ServiceConstants.HISTORY_INCOMING_STRING));
+                System.out.println("HISTORY_OUTGOING_STRING" + entry.get(ServiceConstants.HISTORY_OUTGOING_STRING));
+                System.out.println("HISTORY_MISSED_STRING" + entry.get(ServiceConstants.HISTORY_MISSED_STRING));
+                
+                System.out.println("HISTORY_STATE_KEY" + entry.get(ServiceConstants.HISTORY_STATE_KEY));
+
+                String number_called = entry.get(ServiceConstants.HISTORY_PEER_NUMBER_KEY);
+                CallContact c = null;
+                if (historyEntries.containsKey(number_called)) {
+                    historyEntries.get(number_called).addHistoryCall(new HistoryCall(timestampStart, timestampEnd, number_called));
+                } else {
+
+                    Pattern p = Pattern.compile("<sip:([^@]+)@([^>]+)>");
+                    Matcher m = p.matcher(number_called);
+                    if (m.find()) {
+                        String s1 = m.group(1);
+                        System.out.println(s1);
+                        String s2 = m.group(2);
+                        System.out.println(s2);
+
+                        Cursor result = getContext().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
+                                ContactsContract.CommonDataKinds.Phone.NUMBER + " = " + m.group(1), null, null);
+
+                        if (result.getCount() > 0) {
+                            result.moveToFirst();
+                            builder.startNewContact(result.getLong(result.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)),
+                                    result.getString(result.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)),
+                                    result.getLong(result.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_ID)));
+                            builder.addPhoneNumber(number_called, 0);
+                            c = builder.build();
+                        }
+                        result.close();
+                    } else {
+                        c = ContactBuilder.buildUnknownContact(number_called);
+                    }
+                    HistoryEntry e = new HistoryEntry(entry.get(ServiceConstants.HISTORY_ACCOUNT_ID_KEY), c, timestampStart, timestampEnd,
+                            number_called);
+                    historyEntries.put(number_called, e);
+                }
+
+            }
+
+        } catch (RemoteException e) {
+            Log.i(TAG, e.toString());
+        }
+        return new ArrayList<HistoryEntry>(historyEntries.values());
+    }
+}
diff --git a/src/com/savoirfairelinux/sflphone/loaders/LoaderConstants.java b/src/com/savoirfairelinux/sflphone/loaders/LoaderConstants.java
new file mode 100644
index 0000000..3fd27ee
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/loaders/LoaderConstants.java
@@ -0,0 +1,9 @@
+package com.savoirfairelinux.sflphone.loaders;
+
+public class LoaderConstants {
+    
+    public static final int CONTACT_LOADER = 0;
+    public static final int ACCOUNTS_LOADER = 1;
+    public static final int HISTORY_LOADER = 2;
+
+}
diff --git a/src/com/savoirfairelinux/sflphone/model/Bubble.java b/src/com/savoirfairelinux/sflphone/model/Bubble.java
index a45b746..6294dab 100644
--- a/src/com/savoirfairelinux/sflphone/model/Bubble.java
+++ b/src/com/savoirfairelinux/sflphone/model/Bubble.java
@@ -4,6 +4,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.PointF;
@@ -13,127 +14,200 @@
 
 import com.savoirfairelinux.sflphone.R;
 
-public class Bubble
-{
-	public CallContact contact;
-	// A Bitmap object that is going to be passed to the BitmapShader
-	private Bitmap internalBMP, externalBMP;
+public class Bubble {
+    public CallContact contact;
+    // A Bitmap object that is going to be passed to the BitmapShader
+    private Bitmap internalBMP, externalBMP;
 
-	private PointF pos = new PointF();
-	private RectF bounds;
-	public float target_scale = 1.f;
-	private final float radius;
-	private float scale = 1.f;
-	private float density = 1.f;
-	public PointF speed = new PointF(0, 0);
-	public PointF last_speed = new PointF();
-	public PointF attractor = null;
+    private PointF pos = new PointF();
+    private RectF bounds;
+    public float target_scale = 1.f;
+    private float radius;
+    private float scale = 1.f;
+    private float density = 1.f;
+    public PointF speed = new PointF(0, 0);
+    public PointF last_speed = new PointF();
+    public PointF attractor = null;
 
-	public boolean dragged = false;
-	public long last_drag;
+    public boolean dragged = false;
+    public long last_drag;
+    public boolean expanded; // determine if we draw the buttons around the bubble
+    private Bitmap saved_photo;
+    private float expanded_radius = 250;
 
+    public void setAttractor(PointF attractor) {
+        this.attractor = attractor;
+    }
 
-	public void setAttractor(PointF attractor) {
-		this.attractor = attractor;
-	}
+    public Bubble(float x, float y, float size, Bitmap photo) {
+        saved_photo = photo;
+        internalBMP = Bitmap.createScaledBitmap(photo, (int) size, (int) size, false);
+        int w = internalBMP.getWidth(), h = internalBMP.getHeight();
 
-	public Bubble(float x, float y, float size, Bitmap photo) {
-		internalBMP = Bitmap.createScaledBitmap(photo, (int) size, (int) size, false);
-		int w = internalBMP.getWidth(), h = internalBMP.getHeight();
+        pos.set(x, y);
+        radius = w / 2;
+        bounds = new RectF(pos.x - radius, pos.y - radius, pos.x + radius, pos.y + radius);
+        attractor = new PointF(x, y);
 
-		pos.set(x, y);
-		radius = w / 2;
-		bounds = new RectF(pos.x - radius, pos.y - radius, pos.x + radius, pos.y + radius);
-		attractor = new PointF(x, y);
+        Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        circlePaint.setStyle(Paint.Style.FILL);
+        Bitmap circle = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Canvas circle_drawer = new Canvas(circle);
+        circle_drawer.drawOval(new RectF(0, 0, w, h), circlePaint);
 
-		Path path = new Path();
-		path.addCircle(radius, radius, radius, Path.Direction.CW);
+        externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(externalBMP);
 
-		Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-		circlePaint.setStyle(Paint.Style.FILL);
-		Bitmap circle = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-		Canvas circle_drawer = new Canvas(circle);
-		circle_drawer.drawOval(new RectF(0, 0, w, h), circlePaint);
+        circlePaint.setFilterBitmap(false);
+        canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
 
-		externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-		Canvas canvas = new Canvas(externalBMP);
+        circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
+        canvas.drawBitmap(circle, 0, 0, circlePaint);
+    }
 
-		circlePaint.setFilterBitmap(false);
-		canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
+    public Bubble(float x, float y, float rad, Context c, int resID) {
+        // Initialize the bitmap object by loading an image from the resources folder
+        this(x, y, rad, BitmapFactory.decodeResource(c.getResources(), resID == -1 ? resID : R.drawable.ic_contact_picture));
+    }
 
-		circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
-		canvas.drawBitmap(circle, 0, 0, circlePaint);
-	}
+    public Bitmap getBitmap() {
+        return externalBMP;
+    }
 
-	public Bubble(float x, float y, float rad, Context c, int resID) {
-		// Initialize the bitmap object by loading an image from the resources folder
-		this(x, y, rad, BitmapFactory.decodeResource(c.getResources(), resID==-1 ? resID : R.drawable.ic_contact_picture));
-	}
+    public RectF getBounds() {
+        return bounds;
+    }
 
-	public Bitmap getBitmap() {
-		return externalBMP;
-	}
+    public void set(float x, float y, float s) {
+        scale = s;
+        pos.x = x;
+        pos.y = y;
+        float rad = scale * getRadius() * density;
+        bounds.set(pos.x - rad, pos.y - rad, pos.x + rad, pos.y + rad);
+    }
 
-	public RectF getBounds() {
-		return bounds;
-	}
+    public float getPosX() {
+        return pos.x;
+    }
 
-	public void set(float x, float y, float s) {
-		scale = s;
-		pos.x = x;
-		pos.y = y;
-		float rad = scale*radius*density;
-		bounds.set(pos.x-rad, pos.y-rad, pos.x+rad, pos.y+rad);
-	}
+    public float getPosY() {
+        return pos.y;
+    }
 
-	public float getPosX() {
-		return pos.x;
-	}
+    public void setPos(float x, float y) {
+        set(x, y, scale);
+    }
 
-	public float getPosY() {
-		return pos.y;
-	}
+    public PointF getPos() {
+        return pos;
+    }
 
-	public void setPos(float x, float y) {
-		set(x, y, scale);
-	}
+    public float getScale() {
+        return scale;
+    }
 
-	public PointF getPos()
-	{
-		return pos;
-	}
+    public void setScale(float s) {
+        set(pos.x, pos.y, s);
+    }
 
-	public float getScale() {
-		return scale;
-	}
+    public float getRadius() {
+        return expanded ? expanded_radius : radius;
+    }
 
-	public void setScale(float s) {
-		set(pos.x, pos.y, s);
-	}
+    /**
+     * Point intersection test.
+     */
+    boolean intersects(float x, float y) {
+        float dx = x - pos.x, dy = y - pos.y;
+        return dx * dx + dy * dy < getRadius() * getRadius();
+    }
 
-	public float getRadius() {
-		return radius;
-	}
+    /**
+     * Other circle intersection test.
+     */
+    boolean intersects(float x, float y, float radius) {
+        float dx = x - pos.x, dy = y - pos.y;
+        float tot_radius = getRadius() + radius;
+        return dx * dx + dy * dy < tot_radius * tot_radius;
+    }
 
-	/**
-	 * Point intersection test.
-	 */
-	boolean intersects(float x, float y) {
-		float dx = x-pos.x, dy = y-pos.y;
-		return dx*dx + dy*dy < radius*radius;
-	}
+    public void setDensity(float density) {
+        this.density = density;
+    }
 
-	/**
-	 * Other circle intersection test.
-	 */
-	boolean intersects(float x, float y, float radius) {
-		float dx = x-pos.x, dy = y-pos.y;
-		float tot_radius = this.radius + radius;
-		return dx*dx + dy*dy < tot_radius*tot_radius;
-	}
+    public void expand(int i) {
 
-	public void setDensity(float density)
-	{
-		this.density = density;
-	}
+        // bounds = new RectF(pos.x - 200, pos.y - 200, pos.x + 200, pos.y + 200);
+        // Path path = new Path();
+        // path.addCircle(radius, radius, radius, Path.Direction.CW);
+        //
+        // Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        // circlePaint.setStyle(Paint.Style.FILL);
+        // Bitmap circle = Bitmap.createBitmap((int) (2 * radius), (int) (2 * radius), Bitmap.Config.ARGB_8888);
+        // Canvas circle_drawer = new Canvas(circle);
+        // circle_drawer.drawOval(new RectF(800 - radius, 800 - radius, 2 * radius, 2 * radius), circlePaint);
+        //
+        // externalBMP = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
+        // Canvas canvas = new Canvas(externalBMP);
+        //
+        // circlePaint.setFilterBitmap(false);
+        // canvas.drawBitmap(internalBMP, 200 - radius, 200 - radius, circlePaint);
+        //
+        // circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
+        // canvas.drawBitmap(circle, 200 - radius, 200 - radius, circlePaint);
+
+        expanded_radius = i;
+        expanded = true;
+        internalBMP = Bitmap.createScaledBitmap(saved_photo, (int) (2 * radius), (int) (2 * radius), false);
+        int w = internalBMP.getWidth(), h = internalBMP.getHeight();
+
+        bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+
+        Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        circlePaint.setStyle(Paint.Style.FILL);
+        Bitmap circle = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Canvas circle_drawer = new Canvas(circle);
+        circle_drawer.drawOval(new RectF((float) (getRadius() - radius), (float) (getRadius() - radius), w, h), circlePaint);
+
+        externalBMP = Bitmap.createBitmap((int) (getRadius()*2), (int) (getRadius()*2), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(externalBMP);
+
+        circlePaint.setFilterBitmap(false);
+        canvas.drawBitmap(internalBMP, (float) (getRadius() - radius), (float) (getRadius() - radius), circlePaint);
+
+        Paint mPaintPath = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mPaintPath.setStyle(Paint.Style.FILL);
+        mPaintPath.setColor(Color.BLUE);
+//        mPaintPath.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
+
+        canvas.drawOval(new RectF(0, 0, getRadius()*2, getRadius()*2), mPaintPath);
+
+         circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
+         canvas.drawBitmap(circle, (float) (getRadius() - radius), (float) (getRadius() - radius), circlePaint);
+
+    }
+
+    public void retract() {
+        expanded = false;
+        internalBMP = Bitmap.createScaledBitmap(saved_photo, (int) (2 * radius), (int) (2 * radius), false);
+        int w = internalBMP.getWidth(), h = internalBMP.getHeight();
+
+        bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+
+        Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        circlePaint.setStyle(Paint.Style.FILL);
+        Bitmap circle = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Canvas circle_drawer = new Canvas(circle);
+        circle_drawer.drawOval(new RectF(0, 0, w, h), circlePaint);
+
+        externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(externalBMP);
+
+        circlePaint.setFilterBitmap(false);
+        canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
+
+        circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
+        canvas.drawBitmap(circle, 0, 0, circlePaint);
+
+    }
 }
diff --git a/src/com/savoirfairelinux/sflphone/model/BubblesView.java b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
index 6aab070..1beb761 100644
--- a/src/com/savoirfairelinux/sflphone/model/BubblesView.java
+++ b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
@@ -39,6 +39,8 @@
 import android.graphics.Color;

 import android.graphics.Paint;

 import android.graphics.Paint.Align;

+import android.graphics.PointF;

+import android.graphics.RectF;

 import android.os.Handler;

 import android.os.Message;

 import android.util.AttributeSet;

@@ -255,6 +257,7 @@
                         Bubble b = bubbles.get(i);

                         canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);

                         canvas.drawText(b.contact.getmDisplayName(), b.getPosX(), b.getPosY() - 50 * density, name_paint);

+

                     }

 

                 } catch (IndexOutOfBoundsException e) {

@@ -296,11 +299,19 @@
         return gDetector.onTouchEvent(event);

     }

 

+    RectF intern;

+    RectF external;

+

     class MyOnGestureListener implements OnGestureListener {

         @Override

         public boolean onDown(MotionEvent event) {

             List<Bubble> bubbles = model.getBubbles();

             final int n_bubbles = bubbles.size();

+            Bubble expand = getExpandedBubble();

+            if (expand != null && !expand.intersects(event.getX(), event.getY())) {

+

+                expand.retract();

+            }

             Log.d("Main", "onDown");

             for (int i = 0; i < n_bubbles; i++) {

                 Bubble b = bubbles.get(i);

@@ -315,6 +326,18 @@
             return true;

         }

 

+        private Bubble getExpandedBubble() {

+            List<Bubble> bubbles = model.getBubbles();

+            final int n_bubbles = bubbles.size();

+            for (int i = 0; i < n_bubbles; i++) {

+                Bubble b = bubbles.get(i);

+                if (b.expanded) {

+                    return b;

+                }

+            }

+            return null;

+        }

+

         @Override

         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

             Log.d("Main", "onFling");

@@ -324,6 +347,36 @@
         @Override

         public void onLongPress(MotionEvent e) {

             Log.d("Main", "onLongPress");

+            if (isDraggingBubble()) {

+                Bubble b = getDraggedBubble(e);

+

+                calculateBounds(b.getPos(), b.getRadius());

+

+                b.expand(100);

+            }

+        }

+

+        private void calculateBounds(PointF pointF, float radius) {

+            // intern = new RectF();

+            // float half_square = (float) (radius / Math.sqrt(2));

+            // intern.set(pointF.x - half_square, pointF.y - half_square, pointF.x + half_square, pointF.y + half_square);

+

+            external = new RectF();

+            float large_half_square = 200;

+            external.set(pointF.x - large_half_square, pointF.y - large_half_square, pointF.x + large_half_square, pointF.y + large_half_square);

+

+        }

+

+        private Bubble getDraggedBubble(MotionEvent e) {

+            List<Bubble> bubbles = model.getBubbles();

+            final int n_bubbles = bubbles.size();

+            for (int i = 0; i < n_bubbles; i++) {

+                Bubble b = bubbles.get(i);

+                if (b.intersects(e.getX(), e.getY())) {

+                    return b;

+                }

+            }

+            return null;

         }

 

         @Override

diff --git a/src/com/savoirfairelinux/sflphone/model/CallContact.java b/src/com/savoirfairelinux/sflphone/model/CallContact.java
index 0603185..75c8b6b 100644
--- a/src/com/savoirfairelinux/sflphone/model/CallContact.java
+++ b/src/com/savoirfairelinux/sflphone/model/CallContact.java
@@ -32,8 +32,12 @@
 
 import java.util.ArrayList;
 
+import android.content.ContentResolver;
+import android.database.Cursor;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.provider.ContactsContract.Profile;
+import android.util.Log;
 
 public class CallContact implements Parcelable {
 
@@ -155,14 +159,25 @@
         public static CallContact buildUnknownContact(String to) {
             ArrayList<Phone> phones = new ArrayList<Phone>();
             phones.add(new Phone(to, 0));
-            
+
             return new CallContact(-1, to, 0, phones, new ArrayList<CallContact.Phone>(), "");
         }
-        
-        public static CallContact buildUserContact(String displayName) {
-            ArrayList<Phone> phones = new ArrayList<Phone>();
-            
-            return new CallContact(-1, displayName, 0, phones, new ArrayList<CallContact.Phone>(), "");
+
+        public static CallContact buildUserContact(ContentResolver cr, String displayName) {
+            String[] mProjection = new String[] { Profile._ID, Profile.PHOTO_ID };
+            Cursor mProfileCursor = cr.query(Profile.CONTENT_URI, mProjection, null, null, null);
+            CallContact result = null;
+            if (mProfileCursor.getCount() > 0) {
+                mProfileCursor.moveToFirst();
+                Log.i("CallContact", "THERE IS AN ENTRY");
+                result = new CallContact(mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile._ID)), displayName,
+                        mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile.PHOTO_ID)), new ArrayList<Phone>(),
+                        new ArrayList<CallContact.Phone>(), "");
+            } else {
+                result = new CallContact(-1, displayName, 0, new ArrayList<Phone>(), new ArrayList<CallContact.Phone>(), "");
+            }
+            mProfileCursor.close();
+            return result;
         }
 
     }
@@ -180,9 +195,8 @@
         dest.writeTypedList(phones);
 
         dest.writeTypedList(sip_phones);
-        
+
         dest.writeString(mEmail);
-        
 
     }
 
@@ -272,12 +286,12 @@
 
     public void addPhoneNumber(String tel, int type) {
         phones.add(new Phone(tel, type));
-        
+
     }
 
     public void addSipNumber(String tel, int type) {
         sip_phones.add(new Phone(tel, type));
-        
+
     }
 
 }
diff --git a/src/com/savoirfairelinux/sflphone/model/HistoryEntry.java b/src/com/savoirfairelinux/sflphone/model/HistoryEntry.java
new file mode 100644
index 0000000..640016c
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/model/HistoryEntry.java
@@ -0,0 +1,105 @@
+package com.savoirfairelinux.sflphone.model;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.NavigableMap;
+import java.util.TimeZone;
+import java.util.TreeMap;
+
+public class HistoryEntry {
+
+    private CallContact contact;
+    private NavigableMap<Long, HistoryCall> calls;
+    private String accountID;
+
+    public String getAccountID() {
+        return accountID;
+    }
+
+    public void setAccountID(String accountID) {
+        this.accountID = accountID;
+    }
+
+    public NavigableMap<Long, HistoryCall> getCalls() {
+        return calls;
+    }
+
+    public HistoryEntry(String account, CallContact c, long call_start, long call_end, String number) {
+        contact = c;
+        calls = new TreeMap<Long, HistoryEntry.HistoryCall>();
+        calls.put(call_start, new HistoryCall(call_start, call_end, number));
+        accountID = account;
+    }
+
+    public static class HistoryCall {
+        long call_start;
+        long call_end;
+        String number;
+
+        public HistoryCall(long start, long end, String n) {
+            call_start = start;
+            call_end = end;
+            number = n;
+        }
+
+        public String getDate(String format) {
+            Calendar cal = Calendar.getInstance();
+            TimeZone tz = cal.getTimeZone();
+            SimpleDateFormat objFormatter = new SimpleDateFormat(format, Locale.CANADA);
+            objFormatter.setTimeZone(tz);
+
+            Calendar objCalendar = Calendar.getInstance(tz);
+            objCalendar.setTimeInMillis(call_start * 1000);
+            String result = objFormatter.format(objCalendar.getTime());
+            objCalendar.clear();
+            return result;
+        }
+
+        public String getDurationString() {
+            long duration = call_end - call_start;
+            if (duration < 60)
+                return duration + "s";
+
+            return duration / 60 + "min";
+
+        }
+
+        public long getDuration() {
+            return call_end - call_start;
+
+        }
+
+    }
+
+    public CallContact getContact() {
+        return contact;
+    }
+
+    public void setContact(CallContact contact) {
+        this.contact = contact;
+    }
+
+    public void addHistoryCall(HistoryCall historyCall) {
+        calls.put(historyCall.call_start, historyCall);
+
+    }
+
+    public String getNumber() {
+        return calls.lastEntry().getValue().number;
+    }
+
+    public String getTotalDuration() {
+        int duration = 0;
+        ArrayList<HistoryCall> all_calls = new ArrayList<HistoryEntry.HistoryCall>(calls.values());
+        for(int i = 0 ; i < all_calls.size() ; ++i){
+            duration += all_calls.get(i).getDuration();
+        }
+        
+        if (duration < 60)
+            return duration + "s";
+
+        return duration / 60 + "min";
+    }
+}