diff --git a/src/contactmethod.cpp b/src/contactmethod.cpp
index 84a3878cb876906918cc06606a3592d72c3a855c..27cd53cedac24b304efb882aa3f015ebcd33b12e 100644
--- a/src/contactmethod.cpp
+++ b/src/contactmethod.cpp
@@ -632,9 +632,9 @@ void ContactMethod::contactRebased(Person* other)
 {
    d_ptr->m_PrimaryName_cache = other->formattedName();
    d_ptr->primaryNameChanged(d_ptr->m_PrimaryName_cache);
-   d_ptr->changed();
+   setPerson(other);
 
-   //It is a "partial" rebase, so the ContactMethod data stay the same
+   d_ptr->changed();
    d_ptr->rebased(this);
 }
 
diff --git a/src/recentmodel.cpp b/src/recentmodel.cpp
index 464a96c2c05c784d0447dd47a51f460a9cb6b9b4..40395a6e3dc3b48758f69905a5f31337e856ec77 100644
--- a/src/recentmodel.cpp
+++ b/src/recentmodel.cpp
@@ -1,6 +1,7 @@
 /************************************************************************************
- *   Copyright (C) 2015 by Savoir-Faire Linux                                       *
+ *   Copyright (C) 2015 by Savoir-faire Linux                                       *
  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>         *
+ *            Alexandre Lision <alexandre.lision@savoirfairelinux.com>              *
  *                                                                                  *
  *   This library is free software; you can redistribute it and/or                  *
  *   modify it under the terms of the GNU Lesser General Public                     *
@@ -27,6 +28,10 @@
 #include <personmodel.h>
 #include <contactmethod.h>
 #include <phonedirectorymodel.h>
+#include <callmodel.h>
+#include <categorizedhistorymodel.h>
+#include <media/recordingmodel.h>
+#include <media/textrecording.h>
 
 struct CallGroup
 {
@@ -58,7 +63,7 @@ struct RecentViewNode
    RecentViewNode*        m_pParent  ;
    QList<RecentViewNode*> m_lChildren;
    union {
-      Person*        m_pPerson       ;
+      const Person*  m_pPerson       ;
       ContactMethod* m_pContactMethod;
       Call*          m_pCall         ;
       CallGroup*     m_pCallGroup    ;
@@ -76,14 +81,15 @@ public:
    RecentModelPrivate(RecentModel* p);
 
    /*
-    * m_lTopLevelReverted hold the elements in the reverse order of
-    * QAbstractItemModel::index. This cause most of the energy to be
-    * in the bottom half of the vector, preventing std::move every time
-    * someone is contacted
-    */
+   * m_lTopLevelReverted hold the elements in the reverse order of
+   * QAbstractItemModel::index. This cause most of the energy to be
+   * in the bottom half of the vector, preventing std::move every time
+   * someone is contacted
+   */
    QList<RecentViewNode*>                m_lTopLevelReverted;
-   QHash<Person*,RecentViewNode*>        m_hPersonsToNodes  ;
+   QHash<const Person*,RecentViewNode*>  m_hPersonsToNodes  ;
    QHash<ContactMethod*,RecentViewNode*> m_hCMsToNodes      ;
+   QList<Call*>                          m_lCallBucket      ;
 
    //Helper
    void insertNode(RecentViewNode* n, time_t t, bool isNew);
@@ -93,9 +99,13 @@ private:
    RecentModel* q_ptr;
 
 public Q_SLOTS:
-   void slotLastUsedTimeChanged(Person*        p , time_t t              );
+   void slotLastUsedTimeChanged(const Person*  p , time_t t              );
+   void slotPersonAdded        (const Person*  p                         );
    void slotLastUsedChanged    (ContactMethod* cm, time_t t              );
    void slotContactChanged     (ContactMethod* cm, Person* np, Person* op);
+   void slotCallAdded          (Call* call       , Call* parent          );
+   void slotCallStateChanged   (Call* call       , Call::State previousState);
+   void slotUpdate             (                                         );
 };
 
 RecentModelPrivate::RecentModelPrivate(RecentModel* p) : q_ptr(p)
@@ -105,23 +115,26 @@ RecentModelPrivate::RecentModelPrivate(RecentModel* p) : q_ptr(p)
 RecentModel::RecentModel(QObject* parent) : QAbstractItemModel(parent), d_ptr(new RecentModelPrivate(this))
 {
    connect(PersonModel::instance()        , &PersonModel::lastUsedTimeChanged    , d_ptr, &RecentModelPrivate::slotLastUsedTimeChanged);
+   connect(PersonModel::instance()        , &PersonModel::newPersonAdded         , d_ptr, &RecentModelPrivate::slotPersonAdded        );
    connect(PhoneDirectoryModel::instance(), &PhoneDirectoryModel::lastUsedChanged, d_ptr, &RecentModelPrivate::slotLastUsedChanged    );
    connect(PhoneDirectoryModel::instance(), &PhoneDirectoryModel::contactChanged , d_ptr, &RecentModelPrivate::slotContactChanged     );
+   connect(CallModel::instance()          , &CallModel::callAdded                , d_ptr, &RecentModelPrivate::slotCallAdded          );
+   connect(CallModel::instance()          , &CallModel::callStateChanged         , d_ptr, &RecentModelPrivate::slotCallStateChanged   );
 
    //Fill the contacts
    for (int i=0; i < PersonModel::instance()->rowCount(); i++) {
-      Person* p = qvariant_cast<Person*>(PersonModel::instance()->data(
+      auto person = qvariant_cast<Person*>(PersonModel::instance()->data(
          PersonModel::instance()->index(i,0),
          static_cast<int>(Person::Role::Object)
       ));
 
-      if (p && p->lastUsedTime())
-         d_ptr->slotLastUsedTimeChanged(p, p->lastUsedTime());
+      if (person && person->lastUsedTime())
+         d_ptr->slotLastUsedTimeChanged(person, person->lastUsedTime());
    }
 
    //Fill the "orphan" contact methods
-   for (int i=0; i < PhoneDirectoryModel::instance()->rowCount(); i++) {
-      ContactMethod* cm = qvariant_cast<ContactMethod*>(PhoneDirectoryModel::instance()->data(
+   for (int i = 0; i < PhoneDirectoryModel::instance()->rowCount(); i++) {
+      auto cm = qvariant_cast<ContactMethod*>(PhoneDirectoryModel::instance()->data(
          PhoneDirectoryModel::instance()->index(i,0),
          static_cast<int>(PhoneDirectoryModel::Role::Object)
       ));
@@ -129,6 +142,12 @@ RecentModel::RecentModel(QObject* parent) : QAbstractItemModel(parent), d_ptr(ne
       if (cm && cm->lastUsed() && !cm->contact())
          d_ptr->slotLastUsedChanged(cm, cm->lastUsed());
    }
+
+   //Fill node with history data
+   //const CallMap callMap = CategorizedHistoryModel::instance()->getHistoryCalls();
+   //Q_FOREACH(auto const &call , callMap) {
+   //    d_ptr->slotCallAdded(call, nullptr);
+   //}
 }
 
 RecentModel::~RecentModel()
@@ -172,8 +191,47 @@ time_t RecentViewNode::lastUsed() const
 
 RecentModel* RecentModel::instance()
 {
-   RecentModel* m_spInstance =  new RecentModel(QCoreApplication::instance());
-   return m_spInstance;
+   static RecentModel* instance = new RecentModel(QCoreApplication::instance());
+   return instance;
+}
+
+/**
+ * Check if given index has an ongoing call
+ * returns true if one of its child is also in the CallModel
+ */
+bool RecentModel::hasActiveCall(const QModelIndex &idx)
+{
+   if (not idx.isValid())
+      return false;
+
+   auto node = static_cast<RecentViewNode*>(idx.internalPointer());
+
+   auto reverseEnd = std::make_reverse_iterator(node->m_lChildren.begin());
+   auto it = std::find_if (std::make_reverse_iterator(node->m_lChildren.end()),
+            reverseEnd, [] (RecentViewNode* child) {
+                     return child->m_Type == RecentViewNode::Type::CALL;
+               });
+
+   return it != reverseEnd;
+}
+
+/**
+ * Return the first found ongoing call of the given parent index
+ */
+Call* RecentModel::getActiveCall(const QModelIndex &idx)
+{
+   if (not idx.isValid())
+      return nullptr;
+
+   RecentViewNode* node = static_cast<RecentViewNode*>(idx.internalPointer());
+
+   auto reverseEnd = std::make_reverse_iterator(node->m_lChildren.begin());
+   auto it = std::find_if (std::make_reverse_iterator(node->m_lChildren.end()),
+            reverseEnd, [] (RecentViewNode* child) {
+                     return child->m_Type == RecentViewNode::Type::CALL;
+               });
+
+   return it != reverseEnd ? (*it)->m_uContent.m_pCall : nullptr;
 }
 
 QHash<int,QByteArray> RecentModel::roleNames() const
@@ -226,7 +284,6 @@ int RecentModel::rowCount( const QModelIndex& parent ) const
       return d_ptr->m_lTopLevelReverted.size();
 
    RecentViewNode* node = static_cast<RecentViewNode*>(parent.internalPointer());
-
    return node->m_lChildren.size();
 }
 
@@ -306,15 +363,18 @@ void RecentModelPrivate::insertNode(RecentViewNode* n, time_t t, bool isNew)
          return a->lastUsed() < t2->m_Index;
       });
 
-      newPos = (*lower)->m_Index+1;
+      // the value pointed by the iterator returned by this function may also
+      // be equivalent to val, and not only greater
+      if (!isNew && n->m_Index == (*lower)->m_Index) {
+         newPos = (*lower)->m_Index;
+      } else
+         newPos = (*lower)->m_Index+1;
    }
 
    //Begin the transaction
    if (!isNew) {
-
       if (newPos == n->m_Index)
          return; //Nothing to do
-
       q_ptr->beginMoveRows(QModelIndex(), n->m_Index, n->m_Index, QModelIndex(), newPos ? newPos+1 : newPos );
       m_lTopLevelReverted.removeAt(m_lTopLevelReverted.size()-1-n->m_Index);
    }
@@ -322,22 +382,9 @@ void RecentModelPrivate::insertNode(RecentViewNode* n, time_t t, bool isNew)
       q_ptr->beginInsertRows(QModelIndex(),newPos,newPos);
 
    //Apply the transaction
-   const int updateBound = n->m_Index;
-   if (m_lTopLevelReverted.last()->lastUsed() <= t) {
-
-      //TODO this happen often and is O(N), inverting m_Index would "fix" this
-      for (int i = m_lTopLevelReverted.size()-1; i >= updateBound; i--)
-         m_lTopLevelReverted[m_lTopLevelReverted.size()-1-i]->m_Index = i+1;
-
-      m_lTopLevelReverted << n;
-   }
-   else {
-      m_lTopLevelReverted.insert(m_lTopLevelReverted.size()-newPos,n);
-      n->m_Index = newPos;
-
-      for (int i = m_lTopLevelReverted.size()-1; i >= updateBound; i--)
-         m_lTopLevelReverted[m_lTopLevelReverted.size()-1-i]->m_Index = i;
-
+   m_lTopLevelReverted.insert(m_lTopLevelReverted.size() - newPos,n);
+   for (int i = 0 ; i < m_lTopLevelReverted.size(); ++i) {
+      m_lTopLevelReverted[i]->m_Index = m_lTopLevelReverted.size() - 1 - i;
    }
 
    //Notify that the transaction is complete
@@ -346,32 +393,41 @@ void RecentModelPrivate::insertNode(RecentViewNode* n, time_t t, bool isNew)
    else
       q_ptr->endInsertRows();
 
-   //Uncomment if there is issues
-   //qDebug() << "\n\nList:" << m_lTopLevelReverted.size() << isNew;
-   //for (int i = 0; i<m_lTopLevelReverted.size();i++)
-   //  qDebug() << "|||" << m_lTopLevelReverted[i]->lastUsed() << m_lTopLevelReverted[i]->m_Index << q_ptr->data(q_ptr->index(m_lTopLevelReverted.size()-1-i,0),Qt::DisplayRole);
-
+#if 0
+    //Uncomment if there is issues
+    qDebug() << "\n\nList:" << m_lTopLevelReverted.size() << isNew;
+    for (int i = 0; i<m_lTopLevelReverted.size();i++) {
+        qDebug() << "|||" << m_lTopLevelReverted[i]->lastUsed() << m_lTopLevelReverted[i]->m_Index << q_ptr->data(q_ptr->index(m_lTopLevelReverted.size()-1-i,0),Qt::DisplayRole);
+        for (auto child : m_lTopLevelReverted[i]->m_lChildren) {
+            qDebug() << "|||" << "|||" << child << child->m_uContent.m_pCall->formattedName();
+        }
+     }
+#endif
 }
 
 void RecentModelPrivate::removeNode(RecentViewNode* n)
 {
    const int idx  = n->m_Index;
-   const int size = m_lTopLevelReverted.size();
 
    q_ptr->beginRemoveRows(QModelIndex(), idx, idx);
 
-   //If this assert, the data is corrupted anyway, it will crash later on
-   Q_ASSERT(m_lTopLevelReverted[size-idx-1] == n);
-
-   m_lTopLevelReverted.removeAt(size-idx-1);
-
-   for (int i = 0; i <= idx; i++)
-      m_lTopLevelReverted[i]->m_Index--;
+   m_lTopLevelReverted.removeOne(n);
 
+   if (idx < m_lTopLevelReverted.size()) {
+      for (int i = 0; i <= idx; i++) {
+         m_lTopLevelReverted[i]->m_Index--;
+      }
+   }
    q_ptr->endRemoveRows();
 }
 
-void RecentModelPrivate::slotLastUsedTimeChanged(Person* p, time_t t)
+void RecentModelPrivate::slotPersonAdded(const Person* p)
+{
+   if (p)
+      slotLastUsedTimeChanged(p, p->lastUsedTime());
+}
+
+void RecentModelPrivate::slotLastUsedTimeChanged(const Person* p, time_t t)
 {
    RecentViewNode* n = m_hPersonsToNodes[p];
    const bool isNew = !n;
@@ -383,9 +439,15 @@ void RecentModelPrivate::slotLastUsedTimeChanged(Person* p, time_t t)
       n->m_pParent            = nullptr                     ;
       n->m_Index              = 0                           ;
       m_hPersonsToNodes[p]    = n                           ;
+      Q_FOREACH(auto cm, p->phoneNumbers()) {
+         if (auto cmNode = m_hCMsToNodes[cm])
+            n->m_lChildren.append(cmNode->m_lChildren);
+      }
+
    }
 
    insertNode(n, t, isNew);
+   slotUpdate();
 }
 
 void RecentModelPrivate::slotLastUsedChanged(ContactMethod* cm, time_t t)
@@ -403,19 +465,91 @@ void RecentModelPrivate::slotLastUsedChanged(ContactMethod* cm, time_t t)
          n->m_Index                     = 0                                   ;
          m_hCMsToNodes[cm]              = n                                   ;
       }
-
       insertNode(n, t, isNew);
+      slotUpdate();
    }
 }
 
 ///Remove the contact method once they are associated with a contact
 void RecentModelPrivate::slotContactChanged(ContactMethod* cm, Person* np, Person* op)
 {
-   if (op)
-      return;
-
+   Q_UNUSED(np)
    RecentViewNode* n = m_hCMsToNodes[cm];
 
    if (n)
       removeNode(n);
 }
+
+void RecentModelPrivate::slotCallStateChanged(Call* call, Call::State previousState)
+{
+   //qDebug() << "STATE CHANGED:" << call->peerContactMethod();
+   RecentViewNode* n;
+   if (auto p = call->peerContactMethod()->contact()) {
+      n = m_hPersonsToNodes[p];
+   } else {
+      n = m_hCMsToNodes[call->peerContactMethod()];
+   }
+   if (!n)
+      return;
+
+   if (call->state() == Call::State::OVER) {
+      // Find the active call in children of this node and remove it
+      auto itEnd = n->m_lChildren.end();
+      auto it = std::find_if (n->m_lChildren.begin(),
+                  itEnd, [call] (RecentViewNode* child) {
+                        return child->m_uContent.m_pCall == call;
+                  });
+
+      if (it == itEnd) {
+         // Call can be in the bucket (after callAdded) but not inserted
+         // because it failed before lastUsedChanged to be emitted
+         m_lCallBucket.removeOne(call);
+         return;
+      }
+
+      q_ptr->beginRemoveRows(q_ptr->index(n->m_Index,0), (*it)->m_Index, (*it)->m_Index);
+      n->m_lChildren.removeAt((*it)->m_Index);
+      q_ptr->endRemoveRows();
+   } else
+      emit q_ptr->dataChanged(q_ptr->index(n->m_Index,0),q_ptr->index(n->m_Index,0));
+}
+
+void RecentModelPrivate::slotCallAdded(Call* call, Call* parent)
+{
+   Q_UNUSED(parent)
+
+   RecentViewNode* n = nullptr;
+   if (auto p = call->peerContactMethod()->contact()) {
+      n = m_hPersonsToNodes[p];
+   } else {
+      n = m_hCMsToNodes[call->peerContactMethod()];
+   }
+   if (!n && !m_lCallBucket.contains(call)) {
+      m_lCallBucket.append(call);
+      connect(call, &Call::lifeCycleStateChanged, this, &RecentModelPrivate::slotUpdate);
+      return;
+   } else if (n && m_lCallBucket.contains(call)) {
+      m_lCallBucket.removeOne(call);
+      //TODO: remove the connection store callbucket as a map key = call value = metaconnection
+   } else if (!n && m_lCallBucket.contains(call)) {
+      return;
+   }
+
+   auto callNode = new RecentViewNode();
+   callNode->m_Type = RecentViewNode::Type::CALL;
+   callNode->m_uContent.m_pCall = call;
+   callNode->m_pParent = n;
+   callNode->m_Index = n->m_lChildren.size();
+
+   q_ptr->beginInsertRows(q_ptr->index(n->m_Index,0), n->m_lChildren.size(), n->m_lChildren.size());
+   n->m_lChildren.append(callNode);
+   q_ptr->endInsertRows();
+}
+
+void RecentModelPrivate::slotUpdate()
+{
+   Q_FOREACH(auto call, m_lCallBucket) {
+      qDebug() << "trying to empty bucket call:" << call;
+      slotCallAdded(call, nullptr);
+   }
+}
diff --git a/src/recentmodel.h b/src/recentmodel.h
index db21e50dec895bfb9c4f6842f3267abceeddeb9c..30a66bd213174758466f111b02854c027c9d453d 100644
--- a/src/recentmodel.h
+++ b/src/recentmodel.h
@@ -1,6 +1,7 @@
 /************************************************************************************
- *   Copyright (C) 2015 by Savoir-Faire Linux                                       *
+ *   Copyright (C) 2015 by Savoir-faire Linux                                       *
  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>         *
+ *            Alexandre Lision <alexandre.lision@savoirfairelinux.com>              *
  *                                                                                  *
  *   This library is free software; you can redistribute it and/or                  *
  *   modify it under the terms of the GNU Lesser General Public                     *
@@ -23,6 +24,7 @@
 #include <typedefs.h>
 
 class RecentModelPrivate;
+class Call;
 
 class LIB_EXPORT RecentModel : public QAbstractItemModel
 {
@@ -41,6 +43,9 @@ public:
    virtual QHash<int,QByteArray> roleNames() const override;
 
    static RecentModel* instance();
+
+   bool hasActiveCall(const QModelIndex& parent);
+   Call* getActiveCall(const QModelIndex& parent);
 private:
    explicit RecentModel(QObject* parent = nullptr);
    virtual ~RecentModel();