From 72b4099de0a87bbfa0f9d317d82a1537bd7d7b5d Mon Sep 17 00:00:00 2001
From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>
Date: Thu, 26 Feb 2015 16:04:53 +0000
Subject: [PATCH] Implement daemon API changes to remove early callId usage

* Use debug pretty prints instead of IDs
* Create an historyId
* Create abstract getMime() and fromMime() in CallModel
* Review the call usage sequence

Refs #67104
---
 src/call.cpp                           | 145 ++++++++++++-----------
 src/call.h                             |  19 ++-
 src/callmodel.cpp                      | 154 ++++++++++++++-----------
 src/callmodel.h                        |  22 +++-
 src/codecmodel.h                       |  12 +-
 src/contactproxymodel.cpp              |   2 +-
 src/historymodel.cpp                   |  14 +--
 src/imconversationmanager.cpp          |   2 +-
 src/private/call_p.h                   |  42 +++----
 src/video/manager.cpp                  |   2 +-
 xml/callmanager-introspec.xml          |   9 +-
 xml/configurationmanager-introspec.xml |  16 +--
 12 files changed, 237 insertions(+), 202 deletions(-)

diff --git a/src/call.cpp b/src/call.cpp
index 3234bf80..fc23ec3a 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -228,26 +228,22 @@ CallPrivate::CallPrivate(Call* parent) : QObject(parent),q_ptr(parent),
 m_pStopTimeStamp(0),
 m_pImModel(nullptr),m_pTimer(nullptr),m_Recording(false),m_Account(nullptr),
 m_PeerName(),m_pPeerContactMethod(nullptr),m_HistoryConst(HistoryTimeCategoryModel::HistoryConst::Never),
-m_CallId(),m_pStartTimeStamp(0),m_pDialNumber(nullptr),m_pTransferNumber(nullptr),
+m_pStartTimeStamp(0),m_pDialNumber(nullptr),m_pTransferNumber(nullptr),
 m_History(false),m_Missed(false),m_Direction(Call::Direction::OUTGOING),m_Type(Call::Type::CALL),
 m_pUserActionModel(nullptr),m_HistoryState(Call::LegacyHistoryState::NONE), m_CurrentState(Call::State::ERROR)
 {
 }
 
 ///Constructor
-Call::Call(Call::State startState, const QString& callId, const QString& peerName, ContactMethod* number, Account* account)
+Call::Call(Call::State startState, const QString& peerName, ContactMethod* number, Account* account)
    : ItemBase<QObject>(CallModel::instance()),d_ptr(new CallPrivate(this))
 {
-   Q_ASSERT(!callId.isEmpty());
-
    d_ptr->m_CurrentState     = startState;
    d_ptr->m_Type             = Call::Type::CALL;
    d_ptr->m_Account          = account;
    d_ptr->m_PeerName         = peerName;
    d_ptr->m_pPeerContactMethod = number;
-   d_ptr->m_CallId           = callId;
 
-   setObjectName("Call:"+callId);
    d_ptr->changeCurrentState(startState);
 
    emit changed();
@@ -261,7 +257,7 @@ Call::Call(const QString& confId, const QString& account)
    d_ptr->m_CurrentState = Call::State::CONFERENCE;
    d_ptr->m_Account      = AccountModel::instance()->getById(account.toLatin1());
    d_ptr->m_Type         = (!confId.isEmpty())?Call::Type::CONFERENCE:Call::Type::CALL;
-   d_ptr->m_CallId       = confId;
+   d_ptr->m_DringId      = confId;
 
    setObjectName("Conf:"+confId);
 
@@ -271,7 +267,7 @@ Call::Call(const QString& confId, const QString& account)
       d_ptr->setStartTimeStamp(curTime);
       d_ptr->initTimer();
       CallManagerInterface& callManager = DBus::CallManager::instance();
-      MapStringString        details    = callManager.getConferenceDetails(id())  ;
+      MapStringString        details    = callManager.getConferenceDetails(dringId())  ;
       d_ptr->m_CurrentState             = d_ptr->confStatetoCallState(details[CallPrivate::ConfDetailsMapFields::CONF_STATE]);
       emit stateChanged();
    }
@@ -311,7 +307,8 @@ Call* CallPrivate::buildExistingCall(const QString& callId)
    Call::State   startState    = startStateFromDaemonCallState(details[CallPrivate::DetailsMapFields::STATE], details[CallPrivate::DetailsMapFields::TYPE]);
    Account*      acc           = AccountModel::instance()->getById(account.toLatin1());
    ContactMethod*  nb            = PhoneDirectoryModel::instance()->getNumber(peerNumber,acc);
-   Call*         call          = new Call(startState, callId, peerName, nb, acc);
+   Call*         call          = new Call(startState, peerName, nb, acc);
+   call->d_ptr->m_DringId      = callId;
    call->d_ptr->m_Recording    = callManager.getIsRecording(callId);
    call->d_ptr->m_HistoryState = historyStateFromType(details[Call::HistoryMapFields::STATE]);
 
@@ -333,9 +330,9 @@ Call* CallPrivate::buildExistingCall(const QString& callId)
 } //buildExistingCall
 
 ///Build a call from a dialing call (a call that is about to exist)
-Call* CallPrivate::buildDialingCall(const QString& callId, const QString & peerName, Account* account)
+Call* CallPrivate::buildDialingCall(const QString & peerName, Account* account)
 {
-   Call* call = new Call(Call::State::DIALING, callId, peerName, nullptr, account);
+   Call* call = new Call(Call::State::DIALING, peerName, nullptr, account);
    call->d_ptr->m_HistoryState = Call::LegacyHistoryState::NONE;
    call->d_ptr->m_Direction = Call::Direction::OUTGOING;
    if (Audio::Settings::instance()->isRoomToneEnabled()) {
@@ -348,15 +345,16 @@ Call* CallPrivate::buildDialingCall(const QString& callId, const QString & peerN
 ///Build a call from a dbus event
 Call* CallPrivate::buildIncomingCall(const QString& callId)
 {
-   CallManagerInterface & callManager = DBus::CallManager::instance();
+   CallManagerInterface& callManager = DBus::CallManager::instance();
    MapStringString details = callManager.getCallDetails(callId);
 
    const QString from          = details[ CallPrivate::DetailsMapFields::PEER_NUMBER ];
    const QString account       = details[ CallPrivate::DetailsMapFields::ACCOUNT_ID  ];
    const QString peerName      = details[ CallPrivate::DetailsMapFields::PEER_NAME   ];
    Account*      acc           = AccountModel::instance()->getById(account.toLatin1());
-   ContactMethod*  nb            = PhoneDirectoryModel::instance()->getNumber(from,acc);
-   Call* call                  = new Call(Call::State::INCOMING, callId, peerName, nb, acc);
+   ContactMethod*  nb          = PhoneDirectoryModel::instance()->getNumber(from,acc);
+   Call* call                  = new Call(Call::State::INCOMING, peerName, nb, acc);
+   call->d_ptr->m_DringId      = callId;
    call->d_ptr->m_HistoryState = Call::LegacyHistoryState::MISSED;
    call->d_ptr->m_Direction    = Call::Direction::INCOMING;
    if (call->peerContactMethod()) {
@@ -375,8 +373,9 @@ Call* CallPrivate::buildRingingCall(const QString & callId)
    const QString account       = details[ CallPrivate::DetailsMapFields::ACCOUNT_ID  ];
    const QString peerName      = details[ CallPrivate::DetailsMapFields::PEER_NAME   ];
    Account*      acc           = AccountModel::instance()->getById(account.toLatin1());
-   ContactMethod*  nb            = PhoneDirectoryModel::instance()->getNumber(from,acc);
-   Call* call                  = new Call(Call::State::RINGING, callId, peerName, nb, acc);
+   ContactMethod*  nb          = PhoneDirectoryModel::instance()->getNumber(from,acc);
+   Call* call                  = new Call(Call::State::RINGING, peerName, nb, acc);
+   call->d_ptr->m_DringId      = callId;
    call->d_ptr->m_HistoryState = Call::LegacyHistoryState::OUTGOING;
    call->d_ptr->m_Direction    = Call::Direction::OUTGOING;
 
@@ -420,14 +419,15 @@ Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
    if (!hc[ Call::HistoryMapFields::CONTACT_UID].isEmpty())
       ct = PersonModel::instance()->getPlaceHolder(contactUid.toLatin1());
 
-   Account*      acc       = AccountModel::instance()->getById(accId);
-   ContactMethod*  nb        = PhoneDirectoryModel::instance()->getNumber(number,ct,acc);
+   Account*        acc            = AccountModel::instance()->getById(accId);
+   ContactMethod*  nb             = PhoneDirectoryModel::instance()->getNumber(number,ct,acc);
 
-   Call*         call      = new Call(Call::State::OVER, callId, (name == "empty")?QString():name, nb, acc );
+   Call*           call           = new Call(Call::State::OVER, (name == "empty")?QString():name, nb, acc );
+   call->d_ptr->m_DringId         = callId;
 
    call->d_ptr->m_pStopTimeStamp  = stopTimeStamp ;
-   call->d_ptr->m_History         = true;
    call->d_ptr->setStartTimeStamp(startTimeStamp);
+   call->d_ptr->m_History         = true;
    call->d_ptr->m_HistoryState    = CallPrivate::historyStateFromType(type);
    call->d_ptr->m_Account         = AccountModel::instance()->getById(accId);
 
@@ -456,7 +456,7 @@ Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
       call->d_ptr->m_HistoryState = Call::LegacyHistoryState::MISSED;
    //END
 
-   call->setObjectName("History:"+call->d_ptr->m_CallId);
+   call->setObjectName("History:"+call->d_ptr->m_DringId);
 
    if (call->peerContactMethod()) {
       call->peerContactMethod()->addCall(call);
@@ -636,9 +636,16 @@ const QString Call::dialNumber() const
 }
 
 ///Return the call id
-const QString Call::id() const
+const QString Call::historyId() const
 {
-   return d_ptr->m_CallId;
+   return d_ptr->m_DringId;
+}
+
+///Return the call id
+const QString Call::dringId() const
+{
+   Q_ASSERT(!d_ptr->m_DringId.isEmpty());
+   return d_ptr->m_DringId;
 }
 
 ContactMethod* Call::peerContactMethod() const
@@ -727,6 +734,12 @@ Call::Type Call::type() const
    return d_ptr->m_Type;
 }
 
+
+bool Call::hasRemote() const
+{
+   return !d_ptr->m_DringId.isEmpty();
+}
+
 ///Does this call currently has video
 bool Call::hasVideo() const
 {
@@ -918,7 +931,7 @@ Call::State CallPrivate::stateChanged(const QString& newStateName)
       }
 
       CallManagerInterface & callManager = DBus::CallManager::instance();
-      MapStringString details = callManager.getCallDetails(m_CallId);
+      MapStringString details = callManager.getCallDetails(m_DringId);
       if (details[CallPrivate::DetailsMapFields::PEER_NAME] != m_PeerName)
          m_PeerName = details[CallPrivate::DetailsMapFields::PEER_NAME];
 
@@ -1015,7 +1028,7 @@ Call::State Call::performAction(Call::Action action)
       FORCE_ERROR_STATE()
       return d_ptr->m_CurrentState;
    }
-   qDebug() << "Calling action " << action << " on " << id() << " with state " << previousState << ". Become " << d_ptr->m_CurrentState;
+   qDebug() << "Calling action " << action << " on " << this << " with state " << previousState << ". Become " << d_ptr->m_CurrentState;
    return d_ptr->m_CurrentState;
 } //actionPerformed
 
@@ -1053,7 +1066,7 @@ void CallPrivate::setStartTimeStamp(time_t stamp)
 void Call::sendTextMessage(const QString& message)
 {
    CallManagerInterface& callManager = DBus::CallManager::instance();
-   Q_NOREPLY callManager.sendTextMessage(d_ptr->m_CallId,message);
+   Q_NOREPLY callManager.sendTextMessage(d_ptr->m_DringId,message);
    if (!d_ptr->m_pImModel) {
       d_ptr->m_pImModel = IMConversationManager::instance()->getModel(this);
    }
@@ -1100,8 +1113,8 @@ void CallPrivate::accept()
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Accepting call. callId : " << m_CallId  << "ConfId:" << m_CallId;
-   Q_NOREPLY callManager.accept(m_CallId);
+   qDebug() << "Accepting call. callId : " << q_ptr  << "ConfId:" << q_ptr;
+   Q_NOREPLY callManager.accept(m_DringId);
    time_t curTime;
    ::time(&curTime);
    setStartTimeStamp(curTime);
@@ -1113,8 +1126,8 @@ void CallPrivate::accept()
 void CallPrivate::refuse()
 {
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Refusing call. callId : " << m_CallId  << "ConfId:" << m_CallId;
-   const bool ret = callManager.refuse(m_CallId);
+   qDebug() << "Refusing call. callId : " << q_ptr  << "ConfId:" << q_ptr;
+   const bool ret = callManager.refuse(m_DringId);
    time_t curTime;
    ::time(&curTime);
    setStartTimeStamp(curTime);
@@ -1136,9 +1149,9 @@ void CallPrivate::acceptTransf()
       return;
    }
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Accepting call and transferring it to number : " << m_pTransferNumber->uri() << ". callId : " << m_CallId  << "ConfId:" << m_CallId;
-   callManager.accept(m_CallId);
-   Q_NOREPLY callManager.transfer(m_CallId, m_pTransferNumber->uri());
+   qDebug() << "Accepting call and transferring it to number : " << m_pTransferNumber->uri() << ". callId : " << q_ptr  << "ConfId:" << q_ptr;
+   callManager.accept(m_DringId);
+   Q_NOREPLY callManager.transfer(m_DringId, m_pTransferNumber->uri());
 }
 
 ///Put the call on hold
@@ -1147,9 +1160,9 @@ void CallPrivate::acceptHold()
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Accepting call and holding it. callId : " << m_CallId  << "ConfId:" << m_CallId;
-   callManager.accept(m_CallId);
-   Q_NOREPLY callManager.hold(m_CallId);
+   qDebug() << "Accepting call and holding it. callId : " << q_ptr  << "ConfId:" << q_ptr;
+   callManager.accept(m_DringId);
+   Q_NOREPLY callManager.hold(m_DringId);
    this->m_HistoryState = Call::LegacyHistoryState::INCOMING;
    m_Direction = Call::Direction::INCOMING;
 }
@@ -1163,15 +1176,15 @@ void CallPrivate::hangUp()
    time_t curTime;
    ::time(&curTime);
    m_pStopTimeStamp = curTime;
-   qDebug() << "Hanging up call. callId : " << m_CallId << "ConfId:" << m_CallId;
+   qDebug() << "Hanging up call. callId : " << q_ptr << "ConfId:" << q_ptr;
    bool ret;
    if (q_ptr->videoRenderer()) { //TODO remove, cheap hack
       q_ptr->videoRenderer()->stopRendering();
    }
    if (q_ptr->type() != Call::Type::CONFERENCE)
-      ret = callManager.hangUp(m_CallId);
+      ret = callManager.hangUp(m_DringId);
    else
-      ret = callManager.hangUpConference(m_CallId);
+      ret = callManager.hangUpConference(m_DringId);
    if (!ret) { //Can happen if the daemon crash and open again
       qDebug() << "Error: Invalid call, the daemon may have crashed";
       changeCurrentState(Call::State::OVER);
@@ -1191,9 +1204,9 @@ void CallPrivate::remove()
    //HACK Call hang up again to make sure the busytone stop, this should
    //return true or false, both are valid, no point to check the result
    if (q_ptr->type() != Call::Type::CONFERENCE)
-      callManager.hangUp(m_CallId);
+      callManager.hangUp(q_ptr->dringId());
    else
-      callManager.hangUpConference(q_ptr->id());
+      callManager.hangUpConference(q_ptr->dringId());
 
    emit q_ptr->isOver(q_ptr);
    emit q_ptr->stateChanged();
@@ -1206,10 +1219,10 @@ void CallPrivate::cancel()
 {
    //This one can be over if the peer server failed to comply with the correct sequence
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Canceling call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   qDebug() << "Canceling call. callId : " << q_ptr  << "ConfId:" << q_ptr;
    emit q_ptr->dialNumberChanged(QString());
-//    Q_NOREPLY callManager.hangUp(m_CallId);
-   if (!callManager.hangUp(m_CallId)) {
+//    Q_NOREPLY callManager.hangUp(m_DringId);
+   if (!callManager.hangUp(m_DringId)) {
       qWarning() << "HangUp failed, the call was probably already over";
       changeCurrentState(Call::State::OVER);
    }
@@ -1221,11 +1234,11 @@ void CallPrivate::hold()
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Holding call. callId : " << m_CallId << "ConfId:" << q_ptr->id();
+   qDebug() << "Holding call. callId : " << q_ptr << "ConfId:" << q_ptr;
    if (q_ptr->type() != Call::Type::CONFERENCE)
-      Q_NOREPLY callManager.hold(m_CallId);
+      Q_NOREPLY callManager.hold(q_ptr->dringId());
    else
-      Q_NOREPLY callManager.holdConference(q_ptr->id());
+      Q_NOREPLY callManager.holdConference(q_ptr->dringId());
 }
 
 ///Start the call
@@ -1256,12 +1269,15 @@ void CallPrivate::call()
    }
    //Normal case
    else if(m_Account) {
-      qDebug() << "Calling " << q_ptr->peerContactMethod()->uri() << " with account " << m_Account << ". callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+      qDebug() << "Calling " << q_ptr->peerContactMethod()->uri() << " with account " << m_Account << ". callId : " << q_ptr  << "ConfId:" << q_ptr;
 
       this->m_pPeerContactMethod = PhoneDirectoryModel::instance()->getNumber(m_pDialNumber->uri(),q_ptr->account());
 
       //Warning: m_pDialNumber can become nullptr when linking directly
-      callManager.placeCall(m_Account->id(), m_CallId, m_pDialNumber->uri());
+      m_DringId = callManager.placeCall(m_Account->id(), m_pDialNumber->uri());
+
+      CallModel::instance()->registerCall(q_ptr);
+      setObjectName("Call:"+m_DringId);
 
       if (PersonModel::instance()->hasCollections()) {
          if (q_ptr->peerContactMethod()->contact())
@@ -1283,7 +1299,7 @@ void CallPrivate::call()
    }
    else {
       qDebug() << "Trying to call " << (m_pTransferNumber?QString(m_pTransferNumber->uri()):"ERROR") 
-         << " with no account registered . callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+         << " with no account registered . callId : " << q_ptr  << "ConfId:" << q_ptr;
       this->m_HistoryState = Call::LegacyHistoryState::NONE;
       throw tr("No account registered!");
    }
@@ -1296,8 +1312,8 @@ void CallPrivate::transfer()
 
    if (m_pTransferNumber) {
       CallManagerInterface & callManager = DBus::CallManager::instance();
-      qDebug() << "Transferring call to number : " << m_pTransferNumber->uri() << ". callId : " << m_CallId;
-      Q_NOREPLY callManager.transfer(m_CallId, m_pTransferNumber->uri());
+      qDebug() << "Transferring call to number : " << m_pTransferNumber->uri() << ". callId : " << q_ptr;
+      Q_NOREPLY callManager.transfer(m_DringId, m_pTransferNumber->uri());
       time_t curTime;
       ::time(&curTime);
       m_pStopTimeStamp = curTime;
@@ -1310,26 +1326,26 @@ void CallPrivate::unhold()
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Unholding call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   qDebug() << "Unholding call. callId : " << q_ptr  << "ConfId:" << q_ptr;
    if (q_ptr->type() != Call::Type::CONFERENCE)
-      Q_NOREPLY callManager.unhold(m_CallId);
+      Q_NOREPLY callManager.unhold(q_ptr->dringId());
    else
-      Q_NOREPLY callManager.unholdConference(q_ptr->id());
+      Q_NOREPLY callManager.unholdConference(q_ptr->dringId());
 }
 
 ///Record the call
 void CallPrivate::toggleRecord()
 {
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Setting record " << !m_Recording << " for call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   qDebug() << "Setting record " << !m_Recording << " for call. callId : " << q_ptr  << "ConfId:" << q_ptr;
 
-   callManager.toggleRecording(q_ptr->id());
+   callManager.toggleRecording(q_ptr->dringId());
 }
 
 ///Start the timer
 void CallPrivate::start()
 {
-   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   qDebug() << "Starting call. callId : " << q_ptr  << "ConfId:" << q_ptr;
    time_t curTime;
    ::time(&curTime);
    emit q_ptr->changed();
@@ -1346,7 +1362,7 @@ void CallPrivate::start()
 ///Toggle the timer
 void CallPrivate::startStop()
 {
-   qDebug() << "Starting and stoping call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   qDebug() << "Starting and stoping call. callId : " << q_ptr  << "ConfId:" << q_ptr;
    time_t curTime;
    ::time(&curTime);
    setStartTimeStamp(curTime);
@@ -1356,7 +1372,7 @@ void CallPrivate::startStop()
 ///Stop the timer
 void CallPrivate::stop()
 {
-   qDebug() << "Stoping call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   qDebug() << "Stoping call. callId : " << q_ptr  << "ConfId:" << q_ptr;
    if (q_ptr->videoRenderer()) { //TODO remove, cheap hack
       q_ptr->videoRenderer()->stopRendering();
    }
@@ -1368,17 +1384,17 @@ void CallPrivate::stop()
 ///Handle error instead of crashing
 void CallPrivate::startWeird()
 {
-   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   qDebug() << "Starting call. callId : " << q_ptr  << "ConfId:" << q_ptr;
    time_t curTime;
    ::time(&curTime);
    setStartTimeStamp(curTime);
-   qDebug() << "Warning : call " << m_CallId << " had an unexpected transition of state at its start.";
+   qDebug() << "Warning : call " << q_ptr << " had an unexpected transition of state at its start.";
 }
 
 ///Print a warning
 void CallPrivate::warning()
 {
-   qWarning() << "Warning : call " << m_CallId << " had an unexpected transition of state.(" << m_CurrentState << ")";
+   qWarning() << "Warning : call " << q_ptr << " had an unexpected transition of state.(" << m_CurrentState << ")";
    switch (m_CurrentState) {
       case Call::State::FAILURE        :
       case Call::State::ERROR          :
@@ -1694,9 +1710,6 @@ QVariant Call::roleData(int role) const
       case Call::Role::CallState:
          return static_cast<int>(state()); //TODO Qt5, use the Q_ENUM
          break;
-      case Call::Role::Id:
-         return id();
-         break;
       case Call::Role::StartTime:
          return (int) d_ptr->m_pStartTimeStamp;
       case Call::Role::StopTime:
diff --git a/src/call.h b/src/call.h
index 4f54122c..7a0c2d43 100644
--- a/src/call.h
+++ b/src/call.h
@@ -39,6 +39,7 @@ class TemporaryContactMethod;
 class CollectionInterface;
 namespace Video {
    class Renderer;
+   class Manager;
 }
 
 class Call;
@@ -66,7 +67,10 @@ class  LIB_EXPORT Call : public ItemBase<QObject>
    #pragma GCC diagnostic pop
 public:
    friend class CallModel;
+   friend class HistoryModel;
    friend class CallModelPrivate;
+   friend class IMConversationManager;
+   friend class Video::Manager;
 
    //Enum
 
@@ -90,7 +94,6 @@ public:
       Object             = 117, /*!<  */
       PhotoPtr           = 118, /*!<  */
       CallState          = 119, /*!<  */
-      Id                 = 120, /*!<  */
       StartTime          = 121, /*!<  */
       StopTime           = 122, /*!<  */
       IsRecording        = 123, /*!<  */
@@ -231,7 +234,7 @@ public:
 
    //Read only properties
    Q_PROPERTY( Call::State        state            READ state             NOTIFY stateChanged     )
-   Q_PROPERTY( QString            id               READ id                                        )
+   Q_PROPERTY( QString            historyId        READ historyId                                 )
    Q_PROPERTY( Account*           account          READ account                                   )
    Q_PROPERTY( bool               isHistory        READ isHistory                                 )
    Q_PROPERTY( uint               stopTimeStamp    READ stopTimeStamp                             )
@@ -264,8 +267,8 @@ public:
 
    //Getters
    Call::State              state            () const;
-   const QString            id               () const;
-   ContactMethod*             peerContactMethod  () const;
+   const QString            historyId        () const;
+   ContactMethod*           peerContactMethod() const;
    const QString            peerName         () const;
    Call::LegacyHistoryState historyState     () const;
    bool                     isRecording      () const;
@@ -290,6 +293,7 @@ public:
    bool                     hasVideo         () const;
    Call::LifeCycleState     lifeCycleState   () const;
    Call::Type               type             () const;
+   bool                     hasRemote        () const;
 
    //Automated function
    Call::State performAction(Call::Action action);
@@ -297,7 +301,7 @@ public:
    //Setters
    void setTransferNumber ( const QString&     number     );
    void setDialNumber     ( const QString&     number     );
-   void setDialNumber     ( const ContactMethod* number     );
+   void setDialNumber     ( const ContactMethod* number   );
    void setRecordingPath  ( const QString&     path       );
    void setPeerName       ( const QString&     name       );
    void setAccount        ( Account*           account    );
@@ -314,7 +318,10 @@ public:
 private:
    explicit Call(const QString& confId, const QString& account);
    ~Call();
-   Call(Call::State startState, const QString& callId, const QString& peerName = QString(), ContactMethod* number = nullptr, Account* account = nullptr); //TODO MOVE TO PRIVATE
+   Call(Call::State startState, const QString& peerName = QString(), ContactMethod* number = nullptr, Account* account = nullptr); //TODO MOVE TO PRIVATE
+
+   //Friend API
+   const QString dringId() const;
 
    CallPrivate* d_ptr;
    Q_DECLARE_PRIVATE(Call)
diff --git a/src/callmodel.cpp b/src/callmodel.cpp
index 4b55d17d..ca433c19 100644
--- a/src/callmodel.cpp
+++ b/src/callmodel.cpp
@@ -69,7 +69,7 @@ class CallModelPrivate : public QObject
 public:
       CallModelPrivate(CallModel* parent);
       void init();
-      Call* addCall          ( Call* call                , Call* parent = nullptr );
+      Call* addCall2         ( Call* call                , Call* parent = nullptr );
       Call* addConference    ( const QString& confID                              );
       void  removeConference ( const QString& confId                              );
       void  removeCall       ( Call* call       , bool noEmit = false             );
@@ -78,8 +78,8 @@ public:
 
       //Attributes
       QList<InternalStruct*> m_lInternalModel;
-      QHash< Call*       , InternalStruct* > m_sPrivateCallList_call   ;
-      QHash< QString     , InternalStruct* > m_sPrivateCallList_callId ;
+      QHash< Call*       , InternalStruct* > m_shInternalMapping ;
+      QHash< QString     , InternalStruct* > m_shDringId         ;
       QItemSelectionModel* m_pSelectionModel;
       UserActionModel*     m_pUserActionModel;
 
@@ -179,7 +179,7 @@ void CallModelPrivate::init()
    const QStringList callList = callManager.getCallList();
    foreach (const QString& callId, callList) {
       Call* tmpCall = CallPrivate::buildExistingCall(callId);
-      addCall(tmpCall);
+      addCall2(tmpCall);
    }
 
    const QStringList confList = callManager.getConferenceList();
@@ -192,14 +192,14 @@ void CallModelPrivate::init()
 ///Destructor
 CallModel::~CallModel()
 {
-   const QList<Call*> keys = d_ptr->m_sPrivateCallList_call.keys();
-   const QList<InternalStruct*> values = d_ptr->m_sPrivateCallList_call.values();
+   const QList<Call*> keys = d_ptr->m_shInternalMapping.keys();
+   const QList<InternalStruct*> values = d_ptr->m_shInternalMapping.values();
    foreach (Call* call, keys )
       delete call;
    foreach (InternalStruct* s,  values )
       delete s;
-   d_ptr->m_sPrivateCallList_call.clear  ();
-   d_ptr->m_sPrivateCallList_callId.clear();
+   d_ptr->m_shInternalMapping.clear  ();
+   d_ptr->m_shDringId.clear();
    m_spInstance = nullptr;
 
    //Unregister from the daemon
@@ -236,7 +236,6 @@ QHash<int,QByteArray> CallModel::roleNames() const
       roles.insert(Call::Role::Object        ,QByteArray("object"));
       roles.insert(Call::Role::PhotoPtr      ,QByteArray("photoPtr"));
       roles.insert(Call::Role::CallState     ,QByteArray("callState"));
-      roles.insert(Call::Role::Id            ,QByteArray("id"));
       roles.insert(Call::Role::StartTime     ,QByteArray("startTime"));
       roles.insert(Call::Role::StopTime      ,QByteArray("stopTime"));
       roles.insert(Call::Role::DropState     ,QByteArray("dropState"));
@@ -291,7 +290,7 @@ CallList CallModel::getActiveConferences()
    //That way it can not be invalid
    const QStringList confListS = DBus::CallManager::instance().getConferenceList();
    foreach (const QString& confId, confListS) {
-      InternalStruct* internalS = d_ptr->m_sPrivateCallList_callId[confId];
+      InternalStruct* internalS = d_ptr->m_shDringId[confId];
       if (!internalS) {
          qDebug() << "Warning: Conference not found, creating it, this should not happen";
          Call* conf = d_ptr->addConference(confId);
@@ -353,14 +352,20 @@ Call* CallModel::getCall( const QModelIndex& idx              ) const
 ///Get the call associated with this ID
 Call* CallModel::getCall( const QString& callId ) const
 {
-   if (d_ptr->m_sPrivateCallList_callId[callId]) {
-      return d_ptr->m_sPrivateCallList_callId[callId]->call_real;
+   if (d_ptr->m_shDringId[callId]) {
+      return d_ptr->m_shDringId[callId]->call_real;
    }
    return nullptr;
 }
 
+///Make sure all signals can be mapped back to Call objects
+void CallModel::registerCall(Call* call)
+{
+   d_ptr->m_shDringId[ call->dringId() ] = d_ptr->m_shInternalMapping[call];
+}
+
 ///Add a call in the model structure, the call must exist before being added to the model
-Call* CallModelPrivate::addCall(Call* call, Call* parentCall)
+Call* CallModelPrivate::addCall2(Call* call, Call* parentCall)
 {
    //The current History implementation doesn't support conference
    //if something try to add an history conference, something went wrong
@@ -377,7 +382,7 @@ Call* CallModelPrivate::addCall(Call* call, Call* parentCall)
       //causing a NULL dereference
       return new Call(QString(),QString());
    }
-   if (m_sPrivateCallList_call[call]) {
+   if (m_shInternalMapping[call]) {
       qWarning() << "Trying to add a call that already have been added" << call;
       Q_ASSERT(false);
    }
@@ -387,13 +392,16 @@ Call* CallModelPrivate::addCall(Call* call, Call* parentCall)
    aNewStruct->call_real  = call;
    aNewStruct->conference = false;
 
-   m_sPrivateCallList_call  [ call       ] = aNewStruct;
+   m_shInternalMapping  [ call       ] = aNewStruct;
    if (call->lifeCycleState() != Call::LifeCycleState::FINISHED) {
       q_ptr->beginInsertRows(QModelIndex(),m_lInternalModel.size(),m_lInternalModel.size());
       m_lInternalModel << aNewStruct;
       q_ptr->endInsertRows();
    }
-   m_sPrivateCallList_callId[ call->id() ] = aNewStruct;
+
+   //Dialing calls don't have remote yet, it will be added later
+   if (call->hasRemote())
+      m_shDringId[ call->dringId() ] = aNewStruct;
 
    //If the call is already finished, there is no point to track it here
    if (call->lifeCycleState() != Call::LifeCycleState::FINISHED) {
@@ -425,13 +433,13 @@ Call* CallModel::dialingCall(const QString& peerName, Account* account)
       return nullptr;
    }
 
-   return d_ptr->addCall(CallPrivate::buildDialingCall(QString::number(qrand()), peerName, acc));
+   return d_ptr->addCall2(CallPrivate::buildDialingCall(peerName, acc));
 }  //dialingCall
 
 ///Create a new incoming call when the daemon is being called
 Call* CallModelPrivate::addIncomingCall(const QString& callId)
 {
-   Call* call = addCall(CallPrivate::buildIncomingCall(callId));
+   Call* call = addCall2(CallPrivate::buildIncomingCall(callId));
    //Call without account is not possible
    if (call->account()) {
       if (call->account()->isAutoAnswer()) {
@@ -448,7 +456,7 @@ Call* CallModelPrivate::addIncomingCall(const QString& callId)
 ///Create a ringing call
 Call* CallModelPrivate::addRingingCall(const QString& callId)
 {
-   return addCall(CallPrivate::buildRingingCall(callId));
+   return addCall2(CallPrivate::buildRingingCall(callId));
 }
 
 ///Properly remove an internal from the Qt model
@@ -473,21 +481,21 @@ void CallModelPrivate::removeInternal(InternalStruct* internal)
 void CallModelPrivate::removeCall(Call* call, bool noEmit)
 {
    Q_UNUSED(noEmit)
-   InternalStruct* internal = m_sPrivateCallList_call[call];
+   InternalStruct* internal = m_shInternalMapping[call];
 
    if (!internal || !call) {
-      qDebug() << "Cannot remove " << (internal?internal->call_real->id():"nullptr") << ": call not found";
+      qDebug() << "Cannot remove " << (internal?internal->call_real:nullptr) << ": call not found";
       return;
    }
 
-   if (m_sPrivateCallList_call[call] != nullptr) {
-      removeInternal(m_sPrivateCallList_call[call]);
+   if (m_shInternalMapping[call] != nullptr) {
+      removeInternal(m_shInternalMapping[call]);
       //NOTE Do not free the memory, it can still be used elsewhere or in modelindexes
    }
 
    //TODO DEAD CODE Is this really required?, so far multi conference fail without
-   if (m_sPrivateCallList_callId[m_sPrivateCallList_callId.key(internal)] == internal) {
-      m_sPrivateCallList_callId.remove(m_sPrivateCallList_callId.key(internal));
+   if (m_shDringId[m_shDringId.key(internal)] == internal) {
+      m_shDringId.remove(m_shDringId.key(internal));
    }
 
    removeInternal(internal);
@@ -521,9 +529,9 @@ void CallModelPrivate::removeCall(Call* call, bool noEmit)
 } //removeCall
 
 
-QModelIndex CallModel::getIndex(Call* call)
+QModelIndex CallModel::getIndex(Call* call) const
 {
-   InternalStruct* internal = d_ptr->m_sPrivateCallList_call[call];
+   InternalStruct* internal = d_ptr->m_shInternalMapping[call];
    int idx = d_ptr->m_lInternalModel.indexOf(internal);
    if (idx != -1) {
       return index(idx,0);
@@ -542,7 +550,7 @@ QModelIndex CallModel::getIndex(Call* call)
 void CallModel::attendedTransfer(Call* toTransfer, Call* target)
 {
    if ((!toTransfer) || (!target)) return;
-   Q_NOREPLY DBus::CallManager::instance().attendedTransfer(toTransfer->id(),target->id());
+   Q_NOREPLY DBus::CallManager::instance().attendedTransfer(toTransfer->dringId(),target->dringId());
 
    //TODO [Daemon] Implement this correctly
    toTransfer->d_ptr->changeCurrentState(Call::State::OVER);
@@ -552,7 +560,7 @@ void CallModel::attendedTransfer(Call* toTransfer, Call* target)
 ///Transfer this call to  "target" number
 void CallModel::transfer(Call* toTransfer, const ContactMethod* target)
 {
-   qDebug() << "Transferring call " << toTransfer->id() << "to" << target->uri();
+   qDebug() << "Transferring call " << toTransfer << "to" << target->uri();
    toTransfer->setTransferNumber        ( target->uri()            );
    toTransfer->performAction            ( Call::Action::TRANSFER   );
    toTransfer->d_ptr->changeCurrentState( Call::State::TRANSFERRED );
@@ -580,28 +588,28 @@ Call* CallModelPrivate::addConference(const QString& confID)
       return nullptr;
    }
 
-   if (!m_sPrivateCallList_callId[callList[0]]) {
+   if (!m_shDringId[callList[0]]) {
       qDebug() << "Invalid call";
       return nullptr;
    }
 
    Call* newConf = nullptr;
-   if (m_sPrivateCallList_callId[callList[0]]->call_real->account())
-      newConf =  new Call(confID, m_sPrivateCallList_callId[callList[0]]->call_real->account()->id());
+   if (m_shDringId[callList[0]]->call_real->account())
+      newConf =  new Call(confID, m_shDringId[callList[0]]->call_real->account()->id());
 
    if (newConf) {
       InternalStruct* aNewStruct = new InternalStruct;
       aNewStruct->call_real  = newConf;
       aNewStruct->conference = true;
 
-      m_sPrivateCallList_call[newConf]  = aNewStruct;
-      m_sPrivateCallList_callId[confID] = aNewStruct;
+      m_shInternalMapping[newConf]  = aNewStruct;
+      m_shDringId[confID] = aNewStruct;
       q_ptr->beginInsertRows(QModelIndex(),m_lInternalModel.size(),m_lInternalModel.size());
       m_lInternalModel << aNewStruct;
       q_ptr->endInsertRows();
 
       foreach(const QString& callId,callList) {
-         InternalStruct* callInt = m_sPrivateCallList_callId[callId];
+         InternalStruct* callInt = m_shDringId[callId];
          if (callInt) {
             if (callInt->m_pParent && callInt->m_pParent != aNewStruct)
                callInt->m_pParent->m_lChildren.removeAll(callInt);
@@ -628,8 +636,8 @@ Call* CallModelPrivate::addConference(const QString& confID)
 bool CallModel::createConferenceFromCall(Call* call1, Call* call2)
 {
   if (!call1 || !call2) return false;
-  qDebug() << "Joining call: " << call1->id() << " and " << call2->id();
-  Q_NOREPLY DBus::CallManager::instance().joinParticipant(call1->id(),call2->id());
+  qDebug() << "Joining call: " << call1 << " and " << call2;
+  Q_NOREPLY DBus::CallManager::instance().joinParticipant(call1->dringId(),call2->dringId());
   return true;
 } //createConferenceFromCall
 
@@ -637,7 +645,7 @@ bool CallModel::createConferenceFromCall(Call* call1, Call* call2)
 bool CallModel::addParticipant(Call* call2, Call* conference)
 {
    if (conference->type() == Call::Type::CONFERENCE) {
-      Q_NOREPLY DBus::CallManager::instance().addParticipant(call2->id(), conference->id());
+      Q_NOREPLY DBus::CallManager::instance().addParticipant(call2->dringId(), conference->dringId());
       return true;
    }
    else {
@@ -649,29 +657,29 @@ bool CallModel::addParticipant(Call* call2, Call* conference)
 ///Remove a participant from a conference
 bool CallModel::detachParticipant(Call* call)
 {
-   Q_NOREPLY DBus::CallManager::instance().detachParticipant(call->id());
+   Q_NOREPLY DBus::CallManager::instance().detachParticipant(call->dringId());
    return true;
 }
 
 ///Merge two conferences
 bool CallModel::mergeConferences(Call* conf1, Call* conf2)
 {
-   Q_NOREPLY DBus::CallManager::instance().joinConference(conf1->id(),conf2->id());
+   Q_NOREPLY DBus::CallManager::instance().joinConference(conf1->dringId(),conf2->dringId());
    return true;
 }
 
 ///Remove a conference from the model and the TreeView
 void CallModelPrivate::removeConference(const QString &confId)
 {
-   if (m_sPrivateCallList_callId[confId])
-      qDebug() << "Ending conversation containing " << m_sPrivateCallList_callId[confId]->m_lChildren.size() << " participants";
+   if (m_shDringId[confId])
+      qDebug() << "Ending conversation containing " << m_shDringId[confId]->m_lChildren.size() << " participants";
    removeConference(q_ptr->getCall(confId));
 }
 
 ///Remove a conference using it's call object
 void CallModelPrivate::removeConference(Call* call)
 {
-   const InternalStruct* internal = m_sPrivateCallList_call[call];
+   const InternalStruct* internal = m_shInternalMapping[call];
 
    if (!internal) {
       qDebug() << "Cannot remove conference: call not found";
@@ -850,10 +858,11 @@ QMimeData* CallModel::mimeData(const QModelIndexList& indexes) const
          const QString text = data(idx, Call::Role::Number).toString();
          mData->setData(RingMimes::PLAIN_TEXT , text.toUtf8());
          Call* call = getCall(idx);
-         if (call)
+         if (call) {
             mData->setData(RingMimes::PHONENUMBER, call->peerContactMethod()->toHash().toUtf8());
-         qDebug() << "Setting mime" << idx.data(Call::Role::Id).toString();
-         mData->setData(RingMimes::CALLID  , idx.data(Call::Role::Id).toString().toUtf8());
+            qDebug() << "Setting mime" << getMime(call);
+            mData->setData(RingMimes::CALLID  , getMime(call));
+         }
          return mData;
       }
    }
@@ -865,21 +874,34 @@ bool CallModelPrivate::isPartOf(const QModelIndex& confIdx, Call* call)
    if (!confIdx.isValid() || !call) return false;
 
    for (int i=0;i<confIdx.model()->rowCount(confIdx);i++) { //TODO use model one directly
-      if (confIdx.child(i,0).data(Call::Role::Id) == call->id()) {
+      Call* c = q_ptr->getCall(confIdx);
+      if (c && c->dringId() == call->dringId()) {
          return true;
       }
    }
    return false;
 }
 
+///Try to isolate the MIME id from the dringId() to eventually use something else
+QByteArray CallModel::getMime(const Call* call) const
+{
+   return call->dringId().toLatin1();
+}
+
+Call* CallModel::fromMime( const QByteArray& fromMime) const
+{
+   return getCall(QString(fromMime));
+}
+
 bool CallModel::dropMimeData(const QMimeData* mimedata, Qt::DropAction action, int row, int column, const QModelIndex& parentIdx )
 {
    Q_UNUSED(action)
-   const QModelIndex targetIdx    = index   ( row,column,parentIdx );
+   const QModelIndex targetIdx = index( row,column,parentIdx );
    if (mimedata->hasFormat(RingMimes::CALLID)) {
       const QByteArray encodedCallId = mimedata->data( RingMimes::CALLID    );
-      Call* call                     = getCall ( encodedCallId        );
-      Call* target                   = getCall ( targetIdx            );
+      Call* call                     = fromMime ( encodedCallId        );
+      Call* target                   = getCall  ( targetIdx            );
+      Call* targetParent             = getCall  ( targetIdx.parent()   );
 
       //Call or conference dropped on itself -> cannot transfer or merge, so exit now
       if (target == call) {
@@ -894,19 +916,19 @@ bool CallModel::dropMimeData(const QMimeData* mimedata, Qt::DropAction action, i
       switch (mimedata->property("dropAction").toInt()) {
          case Call::DropAction::Conference:
             //Call or conference dropped on part of itself -> cannot merge conference with itself
-            if (d_ptr->isPartOf(targetIdx,call) || d_ptr->isPartOf(targetIdx.parent(),call) || (call && targetIdx.parent().data(Call::Role::Id) == encodedCallId)) {
+            if (d_ptr->isPartOf(targetIdx,call) || d_ptr->isPartOf(targetIdx.parent(),call) || (call && targetParent && targetParent == call)) {
                qDebug() << "Call/Conf dropped on its own conference (doing nothing)";
                return false;
             }
             //Conference dropped on a conference -> merge both conferences
             else if (call && target && call->type() == Call::Type::CONFERENCE && target->type() == Call::Type::CONFERENCE) {
-               qDebug() << "Merge conferences" << call->id() << "and" << target->id();
+               qDebug() << "Merge conferences" << call << "and" << target;
                mergeConferences(call,target);
                return true;
             }
             //Conference dropped on a call part of a conference -> merge both conferences
-            else if (call && call->type() == Call::Type::CONFERENCE && targetIdx.parent().isValid()) {
-               qDebug() << "Merge conferences" << call->id() << "and" << targetIdx.parent().data(Call::Role::Id).toString();
+            else if (call && call->type() == Call::Type::CONFERENCE && targetParent) {
+               qDebug() << "Merge conferences" << call << "and" << targetParent;
                mergeConferences(call,getCall(targetIdx.parent()));
                return true;
             }
@@ -914,7 +936,7 @@ bool CallModel::dropMimeData(const QMimeData* mimedata, Qt::DropAction action, i
             else if (target && (targetIdx.parent().isValid() || target->type() == Call::Type::CONFERENCE)) {
                Call* conf = target->type() == Call::Type::CONFERENCE?target:qvariant_cast<Call*>(targetIdx.parent().data(Call::Role::Object));
                if (conf) {
-                  qDebug() << "Adding call " << call->id() << "to conference" << conf->id();
+                  qDebug() << "Adding call " << call << "to conference" << conf;
                   addParticipant(call,conf);
                return true;
                }
@@ -985,11 +1007,11 @@ void CallModelPrivate::slotCallStateChanged(const QString& callID, const QString
 {
    //This code is part of the CallModel interface too
    qDebug() << "Call State Changed for call  " << callID << " . New state : " << stateName;
-   InternalStruct* internal = m_sPrivateCallList_callId[callID];
+   InternalStruct* internal = m_shDringId[callID];
    Call* call = nullptr;
    Call::State previousState = Call::State::RINGING;
    if(!internal) {
-      qDebug() << "Call not found";
+      qDebug() << "Call not found" << callID << "new state" << stateName;
       if(stateName == CallPrivate::StateChange::RINGING) {
          call = addRingingCall(callID);
       }
@@ -1044,7 +1066,7 @@ void CallModelPrivate::slotIncomingConference(const QString& confID)
 ///When a conference change
 void CallModelPrivate::slotChangingConference(const QString &confID, const QString& state)
 {
-   InternalStruct* confInt = m_sPrivateCallList_callId[confID];
+   InternalStruct* confInt = m_shDringId[confID];
    if (!confInt) {
       qDebug() << "Error: conference not found";
       return;
@@ -1065,7 +1087,7 @@ void CallModelPrivate::slotChangingConference(const QString &confID, const QStri
 
       //First remove old participants, add them back to the top level list
       foreach(InternalStruct* child,confInt->m_lChildren) {
-         if (participants.indexOf(child->call_real->id()) == -1 && child->call_real->lifeCycleState() != Call::LifeCycleState::FINISHED) {
+         if (participants.indexOf(child->call_real->dringId()) == -1 && child->call_real->lifeCycleState() != Call::LifeCycleState::FINISHED) {
             qDebug() << "Remove" << child->call_real << "from" << conf;
             child->m_pParent = nullptr;
             q_ptr->beginInsertRows(QModelIndex(),m_lInternalModel.size(),m_lInternalModel.size());
@@ -1076,7 +1098,7 @@ void CallModelPrivate::slotChangingConference(const QString &confID, const QStri
       }
       confInt->m_lChildren.clear();
       foreach(const QString& callId,participants) {
-         InternalStruct* callInt = m_sPrivateCallList_callId[callId];
+         InternalStruct* callInt = m_shDringId[callId];
          if (callInt) {
             if (callInt->m_pParent && callInt->m_pParent != confInt)
                callInt->m_pParent->m_lChildren.removeAll(callInt);
@@ -1100,11 +1122,11 @@ void CallModelPrivate::slotChangingConference(const QString &confID, const QStri
       const QStringList deamonCallList = callManager.getCallList();
       foreach(const QString& callId, deamonCallList) {
          const QMap<QString,QString> callDetails = callManager.getCallDetails(callId);
-         InternalStruct* callInt = m_sPrivateCallList_callId[callId];
+         InternalStruct* callInt = m_shDringId[callId];
          if (callInt) {
             const QString confId = callDetails[CallPrivate::DetailsMapFields::CONF_ID];
             if (callInt->m_pParent) {
-               if (!confId.isEmpty()  && callInt->m_pParent->call_real->id() != confId) {
+               if (!confId.isEmpty()  && callInt->m_pParent->call_real->dringId() != confId) {
                   qWarning() << "Conference parent mismatch";
                }
                else if (confId.isEmpty() ){
@@ -1114,7 +1136,7 @@ void CallModelPrivate::slotChangingConference(const QString &confID, const QStri
             }
             else if (!confId.isEmpty()) {
                qWarning() << "Found an orphan call";
-               InternalStruct* confInt2 = m_sPrivateCallList_callId[confId];
+               InternalStruct* confInt2 = m_shDringId[confId];
                if (confInt2 && confInt2->call_real->type() == Call::Type::CONFERENCE 
                 && (callInt->call_real->type() != Call::Type::CONFERENCE)) {
                   removeInternal(callInt);
@@ -1204,7 +1226,7 @@ void CallModelPrivate::slotCallChanged(Call* call)
          break;
    };
 
-   InternalStruct* callInt = m_sPrivateCallList_call[call];
+   InternalStruct* callInt = m_shInternalMapping[call];
    if (callInt) {
       const QModelIndex idx = q_ptr->getIndex(call);
       if (idx.isValid())
@@ -1214,9 +1236,9 @@ void CallModelPrivate::slotCallChanged(Call* call)
 
 ///Add call slot
 void CallModelPrivate::slotAddPrivateCall(Call* call) {
-   if (m_sPrivateCallList_call[call])
+   if (m_shInternalMapping[call])
       return;
-   addCall(call,nullptr);
+   addCall2(call,nullptr);
 }
 
 ///Notice views that a dtmf have been played
diff --git a/src/callmodel.h b/src/callmodel.h
index 9c48a7b5..60c7084f 100644
--- a/src/callmodel.h
+++ b/src/callmodel.h
@@ -32,6 +32,7 @@ class Account;
 struct InternalStruct;
 class ContactMethod;
 class CallModelPrivate;
+class CallPrivate;
 
 //Typedef
 typedef QMap<uint, Call*>  CallMap;
@@ -44,6 +45,12 @@ class LIB_EXPORT CallModel : public QAbstractItemModel
 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
 Q_OBJECT
 #pragma GCC diagnostic pop
+
+   //Handling "in call" text message has been delayed to it's own manager
+   friend class IMConversationManagerPrivate;
+   //Now that the ID is set at a later time, this model need to be notified
+   friend class CallPrivate;
+
 public:
    ///Accepted (mime) payload types
    enum DropPayloadType {
@@ -66,10 +73,12 @@ public:
    Q_PROPERTY(UserActionModel* userActionModel READ userActionModel )
 
    //Call related
-   Q_INVOKABLE Call* dialingCall      ( const QString& peerName=QString(), Account* account=nullptr );
-   Q_INVOKABLE void  attendedTransfer ( Call* toTransfer , Call* target              );
-   Q_INVOKABLE void  transfer         ( Call* toTransfer , const ContactMethod* target );
-   QModelIndex getIndex               ( Call* call                                   );
+   Q_INVOKABLE Call*       dialingCall      ( const QString& peerName=QString(), Account* account=nullptr );
+   Q_INVOKABLE void        attendedTransfer ( Call* toTransfer , Call* target                             );
+   Q_INVOKABLE void        transfer         ( Call* toTransfer , const ContactMethod* target              );
+   Q_INVOKABLE QByteArray  getMime          ( const Call* call                                            ) const;
+   Q_INVOKABLE QModelIndex getIndex         ( Call* call                                                  ) const;
+   Q_INVOKABLE Call*       fromMime         ( const QByteArray& fromMime                                  ) const;
 
    //Conference related
    Q_INVOKABLE bool createConferenceFromCall ( Call* call1, Call* call2      );
@@ -87,7 +96,6 @@ public:
    bool                 isConnected         () const;
    UserActionModel*     userActionModel     () const;
 
-   Q_INVOKABLE Call* getCall ( const QString& callId  ) const;
    Q_INVOKABLE Call* getCall ( const QModelIndex& idx ) const;
 
    //Model implementation
@@ -116,6 +124,10 @@ private:
    QScopedPointer<CallModelPrivate> d_ptr;
    Q_DECLARE_PRIVATE(CallModel)
 
+   //Friend API
+   Call* getCall ( const QString& callId  ) const;
+   void  registerCall(Call* call);
+
    //Singleton
    static CallModel* m_spInstance;
 
diff --git a/src/codecmodel.h b/src/codecmodel.h
index d243ae46..7e361f2d 100644
--- a/src/codecmodel.h
+++ b/src/codecmodel.h
@@ -35,6 +35,9 @@ class LIB_EXPORT CodecModel : public QAbstractListModel {
    #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
    Q_OBJECT
    #pragma GCC diagnostic pop
+
+   friend class Account;
+
 public:
    //friend class Account;
    //Roles
@@ -45,10 +48,6 @@ public:
       SAMPLERATE = 102,
    };
 
-   //Constructor
-   explicit CodecModel(Account* account);
-   virtual ~CodecModel();
-
    //Abstract model member
    virtual QVariant data        (const QModelIndex& index, int role = Qt::DisplayRole      ) const override;
    virtual int rowCount         (const QModelIndex& parent = QModelIndex()                 ) const override;
@@ -66,6 +65,11 @@ public:
    Q_INVOKABLE void save     (                        );
 
 private:
+
+   //Constructor
+   explicit CodecModel(Account* account);
+   virtual ~CodecModel();
+
    QScopedPointer<CodecModelPrivate> d_ptr;
    Q_DECLARE_PRIVATE(CodecModel)
 };
diff --git a/src/contactproxymodel.cpp b/src/contactproxymodel.cpp
index 65a8a82d..6c66aba8 100644
--- a/src/contactproxymodel.cpp
+++ b/src/contactproxymodel.cpp
@@ -370,7 +370,7 @@ bool ContactProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction actio
    if (data->hasFormat(RingMimes::CALLID)) {
       const QByteArray encodedCallId = data->data( RingMimes::CALLID    );
       const QModelIndex targetIdx    = index   ( row,column,parent );
-      Call* call                     = CallModel::instance()->getCall ( encodedCallId        );
+      Call* call                     = CallModel::instance()->fromMime ( encodedCallId        );
       if (call && targetIdx.isValid()) {
          CategorizedCompositeNode* modelItem = (CategorizedCompositeNode*)targetIdx.internalPointer();
          switch (modelItem->type()) {
diff --git a/src/historymodel.cpp b/src/historymodel.cpp
index da0bb0d8..a58fa9b5 100644
--- a/src/historymodel.cpp
+++ b/src/historymodel.cpp
@@ -233,7 +233,6 @@ QHash<int,QByteArray> HistoryModel::roleNames() const
       roles.insert(Call::Role::Object        ,QByteArray("object"        ));
       roles.insert(Call::Role::PhotoPtr      ,QByteArray("photoPtr"      ));
       roles.insert(Call::Role::CallState     ,QByteArray("callState"     ));
-      roles.insert(Call::Role::Id            ,QByteArray("id"            ));
       roles.insert(Call::Role::StartTime     ,QByteArray("startTime"     ));
       roles.insert(Call::Role::StopTime      ,QByteArray("stopTime"      ));
       roles.insert(Call::Role::DropState     ,QByteArray("dropState"     ));
@@ -564,7 +563,7 @@ QMimeData* HistoryModel::mimeData(const QModelIndexList &indexes) const
          mimeData2->setData(RingMimes::PHONENUMBER, call->peerContactMethod()->toHash().toUtf8());
          CategorizedCompositeNode* node = static_cast<CategorizedCompositeNode*>(idx.internalPointer());
          if (node->type() == CategorizedCompositeNode::Type::CALL)
-            mimeData2->setData(RingMimes::HISTORYID  , static_cast<Call*>(node->getSelf())->id().toUtf8());
+            mimeData2->setData(RingMimes::HISTORYID  , static_cast<Call*>(node->getSelf())->dringId().toUtf8());
          return mimeData2;
       }
    }
@@ -583,7 +582,7 @@ bool HistoryModel::dropMimeData(const QMimeData *mime, Qt::DropAction action, in
 
    if (parentIdx.isValid() && mime->hasFormat( RingMimes::CALLID)) {
       QByteArray encodedCallId      = mime->data( RingMimes::CALLID      );
-      Call* call = CallModel::instance()->getCall(encodedCallId);
+      Call* call = CallModel::instance()->fromMime(encodedCallId);
       if (call) {
          const QModelIndex& idx = index(row,column,parentIdx);
          if (idx.isValid()) {
@@ -606,16 +605,11 @@ void HistoryModel::collectionAddedCallback(CollectionInterface* backend)
 ///Call all collections that support clearing
 bool HistoryModel::clearAllCollections() const
 {
-   foreach (CollectionInterface* backend, collections()) {
-      if (backend->supportedFeatures() & CollectionInterface::ADD) {
+   foreach (CollectionInterface* backend, collections()) { //TODO use the filter API
+      if (backend->supportedFeatures() & CollectionInterface::CLEAR) {
          backend->clear();
       }
    }
-
-   //TODO Remove this
-   //Clear the daemon history backend as apparently the Gnome client wont
-   //Use its native backend anytime soon
-   DBus::ConfigurationManager::instance().clearHistory();
    return true;
 }
 
diff --git a/src/imconversationmanager.cpp b/src/imconversationmanager.cpp
index 91d1ad1b..536f7e67 100644
--- a/src/imconversationmanager.cpp
+++ b/src/imconversationmanager.cpp
@@ -87,7 +87,7 @@ void IMConversationManagerPrivate::newMessage(const QString& callId, const QStri
 
 ///Singleton
 InstantMessagingModel* IMConversationManager::getModel(Call* call) {
-   const QString key = call->id();
+   const QString key = call->dringId();
    if (!d_ptr->m_lModels[key]) {
       d_ptr->m_lModels[key] = new InstantMessagingModel(call);
       emit newMessagingModel(call,d_ptr->m_lModels[key]);
diff --git a/src/private/call_p.h b/src/private/call_p.h
index cd1f6e0e..14624dce 100644
--- a/src/private/call_p.h
+++ b/src/private/call_p.h
@@ -99,23 +99,23 @@ public:
    explicit CallPrivate(Call* parent);
 
    //Attributes
-   Account*                 m_Account         ;
-   QString                  m_CallId          ;
-   ContactMethod*             m_pPeerContactMethod;
-   QString                  m_PeerName        ;
-   QString                  m_RecordingPath   ;
-   Call::LegacyHistoryState m_HistoryState    ;
-   time_t                   m_pStartTimeStamp ;
-   time_t                   m_pStopTimeStamp  ;
-   Call::State              m_CurrentState    ;
-   bool                     m_Recording       ;
-   InstantMessagingModel*   m_pImModel        ;
-   QTimer*                  m_pTimer          ;
-   UserActionModel*         m_pUserActionModel;
-   bool                     m_History         ;
-   bool                     m_Missed          ;
-   Call::Direction          m_Direction       ;
-   Call::Type               m_Type            ;
+   Account*                 m_Account           ;
+   QString                  m_DringId           ;
+   ContactMethod*           m_pPeerContactMethod;
+   QString                  m_PeerName          ;
+   QString                  m_RecordingPath     ;
+   Call::LegacyHistoryState m_HistoryState      ;
+   time_t                   m_pStartTimeStamp   ;
+   time_t                   m_pStopTimeStamp    ;
+   Call::State              m_CurrentState      ;
+   bool                     m_Recording         ;
+   InstantMessagingModel*   m_pImModel          ;
+   QTimer*                  m_pTimer            ;
+   UserActionModel*         m_pUserActionModel  ;
+   bool                     m_History           ;
+   bool                     m_Missed            ;
+   Call::Direction          m_Direction         ;
+   Call::Type               m_Type              ;
 
    mutable TemporaryContactMethod* m_pTransferNumber ;
    mutable TemporaryContactMethod* m_pDialNumber     ;
@@ -210,10 +210,10 @@ public:
    static Call::State        startStateFromDaemonCallState ( const QString& daemonCallState, const QString& daemonCallType );
 
    //Constructor
-   static Call* buildDialingCall  (const QString& callId, const QString & peerName, Account* account = nullptr );
-   static Call* buildIncomingCall (const QString& callId                                                       );
-   static Call* buildRingingCall  (const QString& callId                                                       );
-   static Call* buildExistingCall (const QString& callId                                                       );
+   static Call* buildDialingCall  (const QString & peerName, Account* account = nullptr );
+   static Call* buildIncomingCall (const QString& callId                                );
+   static Call* buildRingingCall  (const QString& callId                                );
+   static Call* buildExistingCall (const QString& callId                                );
 
 private:
    Call* q_ptr;
diff --git a/src/video/manager.cpp b/src/video/manager.cpp
index 3847d243..6c6ee4ed 100644
--- a/src/video/manager.cpp
+++ b/src/video/manager.cpp
@@ -96,7 +96,7 @@ Video::Manager* Video::Manager::instance()
 Video::Renderer* Video::Manager::getRenderer(const Call* call) const
 {
    if (!call) return nullptr;
-   return d_ptr->m_lRenderers[call->id()];
+   return d_ptr->m_lRenderers[call->dringId()];
 }
 
 ///Get the video preview renderer
diff --git a/xml/callmanager-introspec.xml b/xml/callmanager-introspec.xml
index 8b896903..3ab2b088 100644
--- a/xml/callmanager-introspec.xml
+++ b/xml/callmanager-introspec.xml
@@ -6,7 +6,7 @@
         <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
             <p>The CallManager interface is used to manage call and conference related actions.</p>
             <p>Since Ring-daemon supports multiple incoming/outgoing calls, any actions involving a specific call must address the method by the means of a unique callID.
-            Ring-clients is responsible for generating the callID on outgoing calls. Conversely, Ring-daemon will generate a unique callID for incoming calls.</p>
+            Ring-daemon will generate a unique callID for outgoing and incoming calls.</p>
         </tp:docstring>
         <method name="placeCall" tp:name-for-bindings="placeCall">
             <tp:docstring>
@@ -17,17 +17,12 @@
                 The ID of the account with which you want to make a call. If the call is to be placed without any account by means of a SIP URI (i.e. sip:num@server), the "IP2IP_PROFILE" is passed as the accountID. For more details on accounts see the configuration manager interface.
               </tp:docstring>
             </arg>
-            <arg type="s" name="callID" direction="in">
-              <tp:docstring>
-                The callID is a unique identifier that must be randomly generated on the client's side. Any subsequent actions refering to this call must use this callID.
-              </tp:docstring>
-            </arg>
             <arg type="s" name="to" direction="in">
               <tp:docstring>
                 If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified.
               </tp:docstring>
             </arg>
-            <arg type="b" name="callSucceeded" direction="out"/>
+            <arg type="s" name="callID" direction="out"/>
         </method>
 
         <method name="refuse" tp:name-for-bindings="refuse">
diff --git a/xml/configurationmanager-introspec.xml b/xml/configurationmanager-introspec.xml
index 4720cd1c..3c219b48 100644
--- a/xml/configurationmanager-introspec.xml
+++ b/xml/configurationmanager-introspec.xml
@@ -383,17 +383,17 @@
        </method>
 
        <method name="getActiveCodecList" tp:name-for-bindings="getActiveCodecList">
+           <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorUInt"/>
            <arg type="s" name="accountID" direction="in">
            </arg>
-           <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorUInt"/>
            <arg type="au" name="list" direction="out">
            </arg>
        </method>
 
        <method name="setActiveCodecList" tp:name-for-bindings="setActiveCodecList">
+           <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorUInt"/>
            <arg type="s" name="accountID" direction="in">
            </arg>
-           <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorUInt"/>
            <arg type="au" name="list" direction="in">
            </arg>
        </method>
@@ -516,21 +516,9 @@
            </arg>
        </method>
 
-       <method name="getHistory" tp:name-for-bindings="getHistory">
-           <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
-           <!-- Return a List of type Dict<string, string> >...a List of Dicts -->
-           <arg type="aa{ss}" name="entries" direction="out"/>
-       </method>
-
-       <method name="clearHistory" tp:name-for-bindings="clearHistory">
-       </method>
-
        <signal name="accountsChanged" tp:name-for-bindings="accountsChanged">
        </signal>
 
-       <signal name="historyChanged" tp:name-for-bindings="historyChanged">
-       </signal>
-
        <!-- FIXME: we should rethink these two signals -->
        <!-- Used by IAX and SIP accounts -->
        <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged">
-- 
GitLab