diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 75c2dd0324e76574c5f57c99eaa6b9cb2008070d..9878034b2466f58b9a9a75eeb1d31fa0223bb75a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -298,6 +298,17 @@ ELSE()
    )
 ENDIF(${ENABLE_QT5} MATCHES true)
 
+# Manually wrap private files
+SET(qtsflphone_PRIVATE_HDRS
+   private/call_p.h
+)
+IF(${ENABLE_QT5} MATCHES true)
+   QT5_WRAP_CPP(LIB_HEADER_MOC ${qtsflphone_PRIVATE_HDRS})
+ELSE()
+   QT4_WRAP_CPP(LIB_HEADER_MOC ${qtsflphone_PRIVATE_HDRS})
+ENDIF(${ENABLE_QT5} MATCHES true)
+
+
 add_library( qtsflphone  SHARED ${qtsflphone_LIB_SRCS} ${LIB_HEADER_MOC} )
 # REMOVE_DEFINITIONS("-w")
 
diff --git a/src/accountmodel.h b/src/accountmodel.h
index 7fca253745cf8984422d0b6353eeac79af309997..3495b24c7ca775ada8181acf30760f93599f4920 100644
--- a/src/accountmodel.h
+++ b/src/accountmodel.h
@@ -49,6 +49,7 @@ public:
 
    friend class Account;
    friend class AccountPrivate;
+
    //Static getter and destructor
    static AccountModel* instance();
    static void destroy();
@@ -74,7 +75,6 @@ public:
    void setPriorAccount          ( const Account*                                           );
    virtual bool setData          ( const QModelIndex& index, const QVariant &value, int role);
    void         setColorVisitor  ( AccountListColorVisitor* visitor                         );
-//    void         setDefaultAccount(Account* a);
 
    //Mutators
    Q_INVOKABLE Account* add                 ( const QString& alias         );
diff --git a/src/call.cpp b/src/call.cpp
index 43e16d6d9a3be819809f97689d8d359139cfee05..cd57dfa24bdf8b888b706b89437089641206abf8 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -53,9 +53,14 @@
 //while not really problematic, it is technically wrong
 #define Q_ASSERT_IS_IN_PROGRESS Q_ASSERT(state() != Call::State::OVER);
 #define FORCE_ERROR_STATE() {qDebug() << "Fatal error on " << this << __FILE__ << __LINE__;\
+   d_ptr->changeCurrentState(Call::State::ERROR);}
+
+#define FORCE_ERROR_STATE_P() {qDebug() << "Fatal error on " << this << __FILE__ << __LINE__;\
    changeCurrentState(Call::State::ERROR);}
 
-const TypedStateMachine< TypedStateMachine< Call::State , Call::Action> , Call::State> Call::actionPerformedStateMap =
+#include "private/call_p.h"
+
+const TypedStateMachine< TypedStateMachine< Call::State , Call::Action> , Call::State> CallPrivate::actionPerformedStateMap =
 {{
 //                           ACCEPT                      REFUSE                  TRANSFER                       HOLD                           RECORD              /**/
 /*INCOMING     */  {{Call::State::INCOMING      , Call::State::INCOMING    , Call::State::ERROR        , Call::State::INCOMING     ,  Call::State::INCOMING     }},/**/
@@ -72,30 +77,30 @@ const TypedStateMachine< TypedStateMachine< Call::State , Call::Action> , Call::
 /*CONF         */  {{Call::State::ERROR         , Call::State::CURRENT     , Call::State::TRANSFERRED  , Call::State::CURRENT      ,  Call::State::CURRENT      }},/**/
 /*CONF_HOLD    */  {{Call::State::ERROR         , Call::State::HOLD        , Call::State::TRANSF_HOLD  , Call::State::HOLD         ,  Call::State::HOLD         }},/**/
 /*INIT         */  {{Call::State::INITIALIZATION, Call::State::OVER        , Call::State::ERROR        , Call::State::ERROR        ,  Call::State::ERROR        }},/**/
-}};//                                                                                                                                                    
+}};//                                                                                                                                                                */
 
-
-const TypedStateMachine< TypedStateMachine< function , Call::Action > , Call::State > Call::actionPerformedFunctionMap =
+#define CP &CallPrivate
+const TypedStateMachine< TypedStateMachine< function , Call::Action > , Call::State > CallPrivate::actionPerformedFunctionMap =
 {{
-//                        ACCEPT               REFUSE            TRANSFER                 HOLD                  RECORD             /**/
-/*INCOMING       */  {{&Call::accept     , &Call::refuse   , &Call::acceptTransf   , &Call::acceptHold  ,  &Call::setRecord     }},/**/
-/*RINGING        */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::setRecord     }},/**/
-/*CURRENT        */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::hold        ,  &Call::setRecord     }},/**/
-/*DIALING        */  {{&Call::call       , &Call::cancel   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
-/*HOLD           */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::unhold      ,  &Call::setRecord     }},/**/
-/*FAILURE        */  {{&Call::nothing    , &Call::remove   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
-/*BUSY           */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
-/*TRANSFERT      */  {{&Call::transfer   , &Call::hangUp   , &Call::transfer       , &Call::hold        ,  &Call::setRecord     }},/**/
-/*TRANSFERT_HOLD */  {{&Call::transfer   , &Call::hangUp   , &Call::transfer       , &Call::unhold      ,  &Call::setRecord     }},/**/
-/*OVER           */  {{&Call::nothing    , &Call::nothing  , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
-/*ERROR          */  {{&Call::nothing    , &Call::remove   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
-/*CONF           */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::hold        ,  &Call::setRecord     }},/**/
-/*CONF_HOLD      */  {{&Call::nothing    , &Call::hangUp   , &Call::nothing        , &Call::unhold      ,  &Call::setRecord     }},/**/
-/*INITIALIZATION */  {{&Call::call       , &Call::cancel   , &Call::nothing        , &Call::nothing     ,  &Call::nothing       }},/**/
-}};//                                                                                                                                 
-
-
-const TypedStateMachine< TypedStateMachine< Call::State , Call::DaemonState> , Call::State> Call::stateChangedStateMap =
+//                      ACCEPT             REFUSE         TRANSFER             HOLD               RECORD            /**/
+/*INCOMING       */  {{CP::accept     , CP::refuse   , CP::acceptTransf   , CP::acceptHold  ,  CP::toggleRecord  }},/**/
+/*RINGING        */  {{CP::nothing    , CP::hangUp   , CP::nothing        , CP::nothing     ,  CP::toggleRecord  }},/**/
+/*CURRENT        */  {{CP::nothing    , CP::hangUp   , CP::nothing        , CP::hold        ,  CP::toggleRecord  }},/**/
+/*DIALING        */  {{CP::call       , CP::cancel   , CP::nothing        , CP::nothing     ,  CP::nothing       }},/**/
+/*HOLD           */  {{CP::nothing    , CP::hangUp   , CP::nothing        , CP::unhold      ,  CP::toggleRecord  }},/**/
+/*FAILURE        */  {{CP::nothing    , CP::remove   , CP::nothing        , CP::nothing     ,  CP::nothing       }},/**/
+/*BUSY           */  {{CP::nothing    , CP::hangUp   , CP::nothing        , CP::nothing     ,  CP::nothing       }},/**/
+/*TRANSFERT      */  {{CP::transfer   , CP::hangUp   , CP::transfer       , CP::hold        ,  CP::toggleRecord  }},/**/
+/*TRANSFERT_HOLD */  {{CP::transfer   , CP::hangUp   , CP::transfer       , CP::unhold      ,  CP::toggleRecord  }},/**/
+/*OVER           */  {{CP::nothing    , CP::nothing  , CP::nothing        , CP::nothing     ,  CP::nothing       }},/**/
+/*ERROR          */  {{CP::nothing    , CP::remove   , CP::nothing        , CP::nothing     ,  CP::nothing       }},/**/
+/*CONF           */  {{CP::nothing    , CP::hangUp   , CP::nothing        , CP::hold        ,  CP::toggleRecord  }},/**/
+/*CONF_HOLD      */  {{CP::nothing    , CP::hangUp   , CP::nothing        , CP::unhold      ,  CP::toggleRecord  }},/**/
+/*INITIALIZATION */  {{CP::call       , CP::cancel   , CP::nothing        , CP::nothing     ,  CP::nothing       }},/**/
+}};//                                                                                                                 */
+
+
+const TypedStateMachine< TypedStateMachine< Call::State , Call::DaemonState> , Call::State> CallPrivate::stateChangedStateMap =
 {{
 //                        RINGING                   CURRENT                   BUSY                  HOLD                        HUNGUP                 FAILURE           /**/
 /*INCOMING     */ {{Call::State::INCOMING    , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
@@ -112,28 +117,29 @@ const TypedStateMachine< TypedStateMachine< Call::State , Call::DaemonState> , C
 /*CONF         */ {{Call::State::CURRENT     , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 /*CONF_HOLD    */ {{Call::State::HOLD        , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
 /*INIT         */ {{Call::State::RINGING     , Call::State::CURRENT    , Call::State::BUSY   , Call::State::HOLD         ,  Call::State::OVER  ,  Call::State::FAILURE  }},/**/
-}};//                                                                                                                                                             
+}};//                                                                                                                                                                        */
 
-const TypedStateMachine< TypedStateMachine< function , Call::DaemonState > , Call::State > Call::stateChangedFunctionMap =
+const TypedStateMachine< TypedStateMachine< function , Call::DaemonState > , Call::State > CallPrivate::stateChangedFunctionMap =
 {{
-//                      RINGING                  CURRENT             BUSY              HOLD                    HUNGUP           FAILURE            /**/
-/*INCOMING       */  {{&Call::nothing    , &Call::start     , &Call::startWeird     , &Call::startWeird   ,  &Call::startStop    , &Call::failure }},/**/
-/*RINGING        */  {{&Call::nothing    , &Call::start     , &Call::start          , &Call::start        ,  &Call::startStop    , &Call::failure }},/**/
-/*CURRENT        */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
-/*DIALING        */  {{&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::warning }},/**/
-/*HOLD           */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
-/*FAILURE        */  {{&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::nothing }},/**/
-/*BUSY           */  {{&Call::nothing    , &Call::nothing   , &Call::nothing        , &Call::warning      ,  &Call::stop         , &Call::nothing }},/**/
-/*TRANSFERT      */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
-/*TRANSFERT_HOLD */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
-/*OVER           */  {{&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::warning }},/**/
-/*ERROR          */  {{&Call::error      , &Call::error     , &Call::error          , &Call::error        ,  &Call::stop         , &Call::error   }},/**/
-/*CONF           */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
-/*CONF_HOLD      */  {{&Call::nothing    , &Call::nothing   , &Call::warning        , &Call::nothing      ,  &Call::stop         , &Call::nothing }},/**/
-/*INIT           */  {{&Call::nothing    , &Call::warning   , &Call::warning        , &Call::warning      ,  &Call::stop         , &Call::warning }},/**/
-}};//                                                                                                                                                   
-
-const TypedStateMachine< Call::LifeCycleState , Call::State > Call::metaStateMap =
+//                      RINGING                  CURRENT             BUSY              HOLD                    HUNGUP                  FAILURE       /**/
+/*INCOMING       */  {{CP::nothing    , CP::start     , CP::startWeird     , CP::startWeird   ,  CP::startStop    , CP::failure }},/**/
+/*RINGING        */  {{CP::nothing    , CP::start     , CP::start          , CP::start        ,  CP::startStop    , CP::failure }},/**/
+/*CURRENT        */  {{CP::nothing    , CP::nothing   , CP::warning        , CP::nothing      ,  CP::stop         , CP::nothing }},/**/
+/*DIALING        */  {{CP::nothing    , CP::warning   , CP::warning        , CP::warning      ,  CP::stop         , CP::warning }},/**/
+/*HOLD           */  {{CP::nothing    , CP::nothing   , CP::warning        , CP::nothing      ,  CP::stop         , CP::nothing }},/**/
+/*FAILURE        */  {{CP::nothing    , CP::warning   , CP::warning        , CP::warning      ,  CP::stop         , CP::nothing }},/**/
+/*BUSY           */  {{CP::nothing    , CP::nothing   , CP::nothing        , CP::warning      ,  CP::stop         , CP::nothing }},/**/
+/*TRANSFERT      */  {{CP::nothing    , CP::nothing   , CP::warning        , CP::nothing      ,  CP::stop         , CP::nothing }},/**/
+/*TRANSFERT_HOLD */  {{CP::nothing    , CP::nothing   , CP::warning        , CP::nothing      ,  CP::stop         , CP::nothing }},/**/
+/*OVER           */  {{CP::nothing    , CP::warning   , CP::warning        , CP::warning      ,  CP::stop         , CP::warning }},/**/
+/*ERROR          */  {{CP::error      , CP::error     , CP::error          , CP::error        ,  CP::stop         , CP::error   }},/**/
+/*CONF           */  {{CP::nothing    , CP::nothing   , CP::warning        , CP::nothing      ,  CP::stop         , CP::nothing }},/**/
+/*CONF_HOLD      */  {{CP::nothing    , CP::nothing   , CP::warning        , CP::nothing      ,  CP::stop         , CP::nothing }},/**/
+/*INIT           */  {{CP::nothing    , CP::warning   , CP::warning        , CP::warning      ,  CP::stop         , CP::warning }},/**/
+}};//                                                                                                                                */
+#undef CP
+
+const TypedStateMachine< Call::LifeCycleState , Call::State > CallPrivate::metaStateMap =
 {{
 /*               *        Life cycle meta-state              **/
 /*INCOMING       */   Call::LifeCycleState::INITIALIZATION ,/**/
@@ -152,7 +158,7 @@ const TypedStateMachine< Call::LifeCycleState , Call::State > Call::metaStateMap
 /*INIT           */   Call::LifeCycleState::INITIALIZATION ,/**/
 }};/*                                                        **/
 
-const TypedStateMachine< TypedStateMachine< bool , Call::LifeCycleState > , Call::State > Call::metaStateTransitionValidationMap =
+const TypedStateMachine< TypedStateMachine< bool , Call::LifeCycleState > , Call::State > CallPrivate::metaStateTransitionValidationMap =
 {{
 /*               *     INITIALIZATION    PROGRESS      FINISHED   **/
 /*INCOMING       */  {{     true     ,    false    ,    false }},/**/
@@ -207,57 +213,70 @@ QDebug LIB_EXPORT operator<<(QDebug dbg, const Call::Action& c)
    return dbg.space();
 }
 
+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_pPeerPhoneNumber(nullptr),m_HistoryConst(HistoryTimeCategoryModel::HistoryConst::Never),
+m_CallId(),m_pStartTimeStamp(0),m_pDialNumber(nullptr),m_pTransferNumber(nullptr),
+m_History(false),m_Missed(false),m_Direction(Call::Direction::OUTGOING),m_pBackend(nullptr),m_Type(Call::Type::CALL),
+m_pUserActionModel(new UserActionModel(parent))
+{
+}
+
 ///Constructor
 Call::Call(Call::State startState, const QString& callId, const QString& peerName, PhoneNumber* number, Account* account)
-   :  QObject(CallModel::instance()),m_pStopTimeStamp(0),
-   m_pImModel(nullptr),m_pTimer(nullptr),m_Recording(false),m_Account(nullptr),
-   m_PeerName(peerName),m_pPeerPhoneNumber(number),m_HistoryConst(HistoryTimeCategoryModel::HistoryConst::Never),
-   m_CallId(callId),m_CurrentState(startState),m_pStartTimeStamp(0),m_pDialNumber(nullptr),m_pTransferNumber(nullptr),
-   m_History(false),m_Missed(false),m_Direction(Call::Direction::OUTGOING),m_pBackend(nullptr),m_Type(Call::Type::CALL)
+   : QObject(CallModel::instance()),d_ptr(new CallPrivate(this))
 {
-   m_Account = account;
    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_pPeerPhoneNumber = number;
+   d_ptr->m_CallId           = callId;
+
    setObjectName("Call:"+callId);
-   changeCurrentState(startState);
-   m_pUserActionModel = new UserActionModel(this);
+   d_ptr->changeCurrentState(startState);
 
    emit changed();
    emit changed(this);
 }
 
-///Destructor
-Call::~Call()
-{
-   if (m_pTimer) delete m_pTimer;
-   this->disconnect();
-   if ( m_pTransferNumber ) delete m_pTransferNumber;
-   if ( m_pDialNumber     ) delete m_pDialNumber;
-}
-
 ///Constructor
-Call::Call(const QString& confId, const QString& account): QObject(CallModel::instance()),
-   m_pStopTimeStamp(0),m_pStartTimeStamp(0),m_pImModel(nullptr),
-   m_Account(AccountModel::instance()->getById(account)),m_CurrentState(Call::State::CONFERENCE),
-   m_pTimer(nullptr),m_pPeerPhoneNumber(nullptr),m_pDialNumber(nullptr),m_pTransferNumber(nullptr),
-   m_HistoryConst(HistoryTimeCategoryModel::HistoryConst::Never),m_History(false),m_Missed(false),
-   m_Direction(Call::Direction::OUTGOING),m_pBackend(nullptr), m_CallId(confId),
-   m_Type((!confId.isEmpty())?Call::Type::CONFERENCE:Call::Type::CALL)
+Call::Call(const QString& confId, const QString& account)
+   : QObject(CallModel::instance()),d_ptr(new CallPrivate(this))
 {
+   d_ptr->m_CurrentState = Call::State::CONFERENCE;
+   d_ptr->m_Account      = AccountModel::instance()->getById(account);
+   d_ptr->m_Type         = (!confId.isEmpty())?Call::Type::CONFERENCE:Call::Type::CALL;
+   d_ptr->m_CallId       = confId;
+
    setObjectName("Conf:"+confId);
-   m_pUserActionModel = new UserActionModel(this);
 
    if (type() == Call::Type::CONFERENCE) {
       time_t curTime;
       ::time(&curTime);
-      setStartTimeStamp(curTime);
-      initTimer();
+      d_ptr->setStartTimeStamp(curTime);
+      d_ptr->initTimer();
       CallManagerInterface& callManager = DBus::CallManager::instance();
       MapStringString        details    = callManager.getConferenceDetails(id())  ;
-      m_CurrentState = confStatetoCallState(details[ConfDetailsMapFields::CONF_STATE]);
+      d_ptr->m_CurrentState             = d_ptr->confStatetoCallState(details[ConfDetailsMapFields::CONF_STATE]);
       emit stateChanged();
    }
 }
 
+///Destructor
+Call::~Call()
+{
+   if (d_ptr->m_pTimer) delete d_ptr->m_pTimer;
+   this->disconnect();
+
+   //m_pTransferNumber and m_pDialNumber are temporary, they are owned by the call
+   if ( d_ptr->m_pTransferNumber ) delete d_ptr->m_pTransferNumber;
+   if ( d_ptr->m_pDialNumber     ) delete d_ptr->m_pDialNumber;
+}
+
 /*****************************************************************************
  *                                                                           *
  *                               Call builder                                *
@@ -273,25 +292,25 @@ Call* Call::buildExistingCall(const QString& callId)
    //Too noisy
    //qDebug() << "Constructing existing call with details : " << details;
 
-   const QString peerNumber  = details[ Call::DetailsMapFields::PEER_NUMBER ];
-   const QString peerName    = details[ Call::DetailsMapFields::PEER_NAME   ];
-   const QString account     = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
-   Call::State   startState  = startStateFromDaemonCallState(details[Call::DetailsMapFields::STATE], details[Call::DetailsMapFields::TYPE]);
-   Account*      acc         = AccountModel::instance()->getById(account);
-   PhoneNumber*  nb          = PhoneDirectoryModel::instance()->getNumber(peerNumber,acc);
-   Call*         call        = new Call(startState, callId, peerName, nb, acc);
-   call->m_Recording      = callManager.getIsRecording(callId);
-   call->m_HistoryState   = historyStateFromType(details[Call::HistoryMapFields::STATE]);
+   const QString peerNumber    = details[ Call::DetailsMapFields::PEER_NUMBER ];
+   const QString peerName      = details[ Call::DetailsMapFields::PEER_NAME   ];
+   const QString account       = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
+   Call::State   startState    = startStateFromDaemonCallState(details[Call::DetailsMapFields::STATE], details[Call::DetailsMapFields::TYPE]);
+   Account*      acc           = AccountModel::instance()->getById(account);
+   PhoneNumber*  nb            = PhoneDirectoryModel::instance()->getNumber(peerNumber,acc);
+   Call*         call          = new Call(startState, callId, peerName, nb, acc);
+   call->d_ptr->m_Recording    = callManager.getIsRecording(callId);
+   call->d_ptr->m_HistoryState = historyStateFromType(details[Call::HistoryMapFields::STATE]);
 
    if (!details[ Call::DetailsMapFields::TIMESTAMP_START ].isEmpty())
-      call->setStartTimeStamp(details[ Call::DetailsMapFields::TIMESTAMP_START ].toInt());
+      call->d_ptr->setStartTimeStamp(details[ Call::DetailsMapFields::TIMESTAMP_START ].toInt());
    else {
       time_t curTime;
       ::time(&curTime);
-      call->setStartTimeStamp(curTime);
+      call->d_ptr->setStartTimeStamp(curTime);
    }
 
-   call->initTimer();
+   call->d_ptr->initTimer();
 
    if (call->peerPhoneNumber()) {
       call->peerPhoneNumber()->addCall(call);
@@ -304,8 +323,8 @@ Call* Call::buildExistingCall(const QString& callId)
 Call* Call::buildDialingCall(const QString& callId, const QString & peerName, Account* account)
 {
    Call* call = new Call(Call::State::DIALING, callId, peerName, nullptr, account);
-   call->m_HistoryState = Call::LegacyHistoryState::NONE;
-   call->m_Direction = Call::Direction::OUTGOING;
+   call->d_ptr->m_HistoryState = Call::LegacyHistoryState::NONE;
+   call->d_ptr->m_Direction = Call::Direction::OUTGOING;
    if (AudioSettingsModel::instance()->isRoomToneEnabled()) {
       AudioSettingsModel::instance()->playRoomTone();
    }
@@ -319,14 +338,14 @@ Call* Call::buildIncomingCall(const QString& callId)
    CallManagerInterface & callManager = DBus::CallManager::instance();
    MapStringString details = callManager.getCallDetails(callId).value();
 
-   const QString from     = details[ Call::DetailsMapFields::PEER_NUMBER ];
-   const QString account  = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
-   const QString peerName = details[ Call::DetailsMapFields::PEER_NAME   ];
-   Account*      acc      = AccountModel::instance()->getById(account);
-   PhoneNumber*  nb       = PhoneDirectoryModel::instance()->getNumber(from,acc);
-   Call* call = new Call(Call::State::INCOMING, callId, peerName, nb, acc);
-   call->m_HistoryState   = Call::LegacyHistoryState::MISSED;
-   call->m_Direction      = Call::Direction::INCOMING;
+   const QString from          = details[ Call::DetailsMapFields::PEER_NUMBER ];
+   const QString account       = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
+   const QString peerName      = details[ Call::DetailsMapFields::PEER_NAME   ];
+   Account*      acc           = AccountModel::instance()->getById(account);
+   PhoneNumber*  nb            = PhoneDirectoryModel::instance()->getNumber(from,acc);
+   Call* call                  = new Call(Call::State::INCOMING, callId, peerName, nb, acc);
+   call->d_ptr->m_HistoryState = Call::LegacyHistoryState::MISSED;
+   call->d_ptr->m_Direction    = Call::Direction::INCOMING;
    if (call->peerPhoneNumber()) {
       call->peerPhoneNumber()->addCall(call);
    }
@@ -339,15 +358,14 @@ Call* Call::buildRingingCall(const QString & callId)
    CallManagerInterface& callManager = DBus::CallManager::instance();
    MapStringString details = callManager.getCallDetails(callId).value();
 
-   const QString from     = details[ Call::DetailsMapFields::PEER_NUMBER ];
-   const QString account  = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
-   const QString peerName = details[ Call::DetailsMapFields::PEER_NAME   ];
-   Account*      acc      = AccountModel::instance()->getById(account);
-   PhoneNumber*  nb       = PhoneDirectoryModel::instance()->getNumber(from,acc);
-
-   Call* call = new Call(Call::State::RINGING, callId, peerName, nb, acc);
-   call->m_HistoryState = LegacyHistoryState::OUTGOING;
-   call->m_Direction    = Call::Direction::OUTGOING;
+   const QString from          = details[ Call::DetailsMapFields::PEER_NUMBER ];
+   const QString account       = details[ Call::DetailsMapFields::ACCOUNT_ID  ];
+   const QString peerName      = details[ Call::DetailsMapFields::PEER_NAME   ];
+   Account*      acc           = AccountModel::instance()->getById(account);
+   PhoneNumber*  nb            = PhoneDirectoryModel::instance()->getNumber(from,acc);
+   Call* call                  = new Call(Call::State::RINGING, callId, peerName, nb, acc);
+   call->d_ptr->m_HistoryState = LegacyHistoryState::OUTGOING;
+   call->d_ptr->m_Direction    = Call::Direction::OUTGOING;
 
    if (call->peerPhoneNumber()) {
       call->peerPhoneNumber()->addCall(call);
@@ -394,47 +412,47 @@ Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
 
    Call*         call      = new Call(Call::State::OVER, callId, (name == "empty")?QString():name, nb, acc );
 
-   call->m_pStopTimeStamp  = stopTimeStamp ;
-   call->m_History         = true;
-   call->setStartTimeStamp(startTimeStamp);
-   call->m_HistoryState    = historyStateFromType(type);
-   call->m_Account         = AccountModel::instance()->getById(accId);
+   call->d_ptr->m_pStopTimeStamp  = stopTimeStamp ;
+   call->d_ptr->m_History         = true;
+   call->d_ptr->setStartTimeStamp(startTimeStamp);
+   call->d_ptr->m_HistoryState    = historyStateFromType(type);
+   call->d_ptr->m_Account         = AccountModel::instance()->getById(accId);
 
    //BEGIN In ~2015, remove the old logic and clean this
-   if (missed || call->m_HistoryState == Call::LegacyHistoryState::MISSED) {
-      call->m_Missed = true;
-      call->m_HistoryState = Call::LegacyHistoryState::MISSED;
+   if (missed || call->d_ptr->m_HistoryState == Call::LegacyHistoryState::MISSED) {
+      call->d_ptr->m_Missed = true;
+      call->d_ptr->m_HistoryState = Call::LegacyHistoryState::MISSED;
    }
    if (!direction.isEmpty()) {
       if (direction == HistoryStateName::INCOMING) {
-         call->m_Direction    = Call::Direction::INCOMING         ;
-         call->m_HistoryState = Call::LegacyHistoryState::INCOMING;
+         call->d_ptr->m_Direction    = Call::Direction::INCOMING         ;
+         call->d_ptr->m_HistoryState = Call::LegacyHistoryState::INCOMING;
       }
       else if (direction == HistoryStateName::OUTGOING) {
-         call->m_Direction    = Call::Direction::OUTGOING         ;
-         call->m_HistoryState = Call::LegacyHistoryState::OUTGOING;
+         call->d_ptr->m_Direction    = Call::Direction::OUTGOING         ;
+         call->d_ptr->m_HistoryState = Call::LegacyHistoryState::OUTGOING;
       }
    }
-   else if (call->m_HistoryState == Call::LegacyHistoryState::INCOMING)
-      call->m_Direction    = Call::Direction::INCOMING            ;
-   else if (call->m_HistoryState == Call::LegacyHistoryState::OUTGOING)
-      call->m_Direction    = Call::Direction::OUTGOING            ;
+   else if (call->d_ptr->m_HistoryState == Call::LegacyHistoryState::INCOMING)
+      call->d_ptr->m_Direction    = Call::Direction::INCOMING            ;
+   else if (call->d_ptr->m_HistoryState == Call::LegacyHistoryState::OUTGOING)
+      call->d_ptr->m_Direction    = Call::Direction::OUTGOING            ;
    else //Getting there is a bug. Pick one, even if it is the wrong one
-      call->m_Direction    = Call::Direction::OUTGOING            ;
+      call->d_ptr->m_Direction    = Call::Direction::OUTGOING            ;
    if (missed)
-      call->m_HistoryState = Call::LegacyHistoryState::MISSED;
+      call->d_ptr->m_HistoryState = Call::LegacyHistoryState::MISSED;
    //END
 
-   call->setObjectName("History:"+call->m_CallId);
+   call->setObjectName("History:"+call->d_ptr->m_CallId);
 
    if (call->peerPhoneNumber()) {
       call->peerPhoneNumber()->addCall(call);
 
       //Reload the glow and number colors
-      connect(call->peerPhoneNumber(),SIGNAL(presentChanged(bool)),call,SLOT(updated()));
+      connect(call->peerPhoneNumber(),SIGNAL(presentChanged(bool)),call->d_ptr.data(),SLOT(updated()));
 
       //Change the display name and picture
-      connect(call->peerPhoneNumber(),SIGNAL(rebased(PhoneNumber*)),call,SLOT(updated()));
+      connect(call->peerPhoneNumber(),SIGNAL(rebased(PhoneNumber*)),call->d_ptr.data(),SLOT(updated()));
    }
 
    return call;
@@ -488,7 +506,7 @@ Call::State Call::startStateFromDaemonCallState(const QString& daemonCallState,
  ****************************************************************************/
 
 ///Transfer state from internal to daemon internal syntaz
-Call::DaemonState Call::toDaemonCallState(const QString& stateName)
+Call::DaemonState CallPrivate::toDaemonCallState(const QString& stateName)
 {
    if(stateName == Call::StateChange::HUNG_UP        )
       return Call::DaemonState::HUNG_UP ;
@@ -510,7 +528,7 @@ Call::DaemonState Call::toDaemonCallState(const QString& stateName)
 } //toDaemonCallState
 
 ///Transform a conference call state to a proper call state
-Call::State Call::confStatetoCallState(const QString& stateName)
+Call::State CallPrivate::confStatetoCallState(const QString& stateName)
 {
    if      ( stateName == Call::ConferenceStateChange::HOLD   )
       return Call::State::CONFERENCE_HOLD;
@@ -579,54 +597,54 @@ QString Call::toHumanStateName() const
 ///Get the time (second from 1 jan 1970) when the call ended
 time_t Call::stopTimeStamp() const
 {
-   return m_pStopTimeStamp;
+   return d_ptr->m_pStopTimeStamp;
 }
 
 ///Get the time (second from 1 jan 1970) when the call started
 time_t Call::startTimeStamp() const
 {
-   return m_pStartTimeStamp;
+   return d_ptr->m_pStartTimeStamp;
 }
 
 ///Get the number where the call have been transferred
 const QString Call::transferNumber() const
 {
-   return m_pTransferNumber?m_pTransferNumber->uri():QString();
+   return d_ptr->m_pTransferNumber?d_ptr->m_pTransferNumber->uri():QString();
 }
 
 ///Get the call / peer number
 const QString Call::dialNumber() const
 {
-   if (m_CurrentState != Call::State::DIALING) return QString();
-   if (!m_pDialNumber) {
-      const_cast<Call*>(this)->m_pDialNumber = new TemporaryPhoneNumber();
+   if (d_ptr->m_CurrentState != Call::State::DIALING) return QString();
+   if (!d_ptr->m_pDialNumber) {
+      d_ptr->m_pDialNumber = new TemporaryPhoneNumber();
    }
-   return m_pDialNumber->uri();
+   return d_ptr->m_pDialNumber->uri();
 }
 
 ///Return the call id
 const QString Call::id() const
 {
-   return m_CallId;
+   return d_ptr->m_CallId;
 }
 
 PhoneNumber* Call::peerPhoneNumber() const
 {
-   if (m_CurrentState == Call::State::DIALING) {
-      if (!m_pTransferNumber) {
-         const_cast<Call*>(this)->m_pTransferNumber = new TemporaryPhoneNumber(m_pPeerPhoneNumber);
+   if (d_ptr->m_CurrentState == Call::State::DIALING) {
+      if (!d_ptr->m_pTransferNumber) {
+         d_ptr->m_pTransferNumber = new TemporaryPhoneNumber(d_ptr->m_pPeerPhoneNumber);
       }
-      if (!m_pDialNumber)
-         const_cast<Call*>(this)->m_pDialNumber = new TemporaryPhoneNumber(m_pPeerPhoneNumber);
-      return m_pDialNumber;
+      if (!d_ptr->m_pDialNumber)
+         d_ptr->m_pDialNumber = new TemporaryPhoneNumber(d_ptr->m_pPeerPhoneNumber);
+      return d_ptr->m_pDialNumber;
    }
-   return m_pPeerPhoneNumber?m_pPeerPhoneNumber:const_cast<PhoneNumber*>(PhoneNumber::BLANK());
+   return d_ptr->m_pPeerPhoneNumber?d_ptr->m_pPeerPhoneNumber:const_cast<PhoneNumber*>(PhoneNumber::BLANK());
 }
 
 ///Get the peer name
 const QString Call::peerName() const
 {
-   return m_PeerName;
+   return d_ptr->m_PeerName;
 }
 
 ///Generate the best possible peer name
@@ -639,7 +657,7 @@ const QString Call::formattedName() const
    else if (peerPhoneNumber()->contact() && !peerPhoneNumber()->contact()->formattedName().isEmpty())
       return peerPhoneNumber()->contact()->formattedName();
    else if (!peerName().isEmpty())
-      return m_PeerName;
+      return d_ptr->m_PeerName;
    else if (peerPhoneNumber())
       return peerPhoneNumber()->uri();
    else
@@ -655,14 +673,14 @@ bool Call::hasRecording() const
 ///Generate an human readable string from the difference between StartTimeStamp and StopTimeStamp (or 'now')
 QString Call::length() const
 {
-   if (m_pStartTimeStamp == m_pStopTimeStamp) return QString(); //Invalid
+   if (d_ptr->m_pStartTimeStamp == d_ptr->m_pStopTimeStamp) return QString(); //Invalid
    int nsec =0;
-   if (m_pStopTimeStamp)
+   if (d_ptr->m_pStopTimeStamp)
       nsec = stopTimeStamp() - startTimeStamp();//If the call is over
    else { //Time to now
       time_t curTime;
       ::time(&curTime);
-      nsec = curTime - m_pStartTimeStamp;
+      nsec = curTime - d_ptr->m_pStartTimeStamp;
    }
    if (nsec/3600)
       return QString("%1:%2:%3 ").arg((nsec%(3600*24))/3600).arg(((nsec%(3600*24))%3600)/60,2,10,QChar('0')).arg(((nsec%(3600*24))%3600)%60,2,10,QChar('0'));
@@ -673,33 +691,33 @@ QString Call::length() const
 ///Is this call part of history
 bool Call::isHistory()
 {
-   if (lifeCycleState() == Call::LifeCycleState::FINISHED && !m_History)
-      m_History = true;
-   return m_History;
+   if (lifeCycleState() == Call::LifeCycleState::FINISHED && !d_ptr->m_History)
+      d_ptr->m_History = true;
+   return d_ptr->m_History;
 }
 
 ///Is this call missed
 bool Call::isMissed() const
 {
-   return m_Missed || m_HistoryState == Call::LegacyHistoryState::MISSED;
+   return d_ptr->m_Missed || d_ptr->m_HistoryState == Call::LegacyHistoryState::MISSED;
 }
 
 ///Is the call incoming or outgoing
 Call::Direction Call::direction() const
 {
-   return m_Direction;
+   return d_ptr->m_Direction;
 }
 
 ///Is the call a conference or something else
 Call::Type Call::type() const
 {
-   return m_Type;
+   return d_ptr->m_Type;
 }
 
 ///Return the backend used to serialize this call
 AbstractHistoryBackend* Call::backend() const
 {
-   return m_pBackend;
+   return d_ptr->m_pBackend;
 }
 
 
@@ -717,49 +735,49 @@ bool Call::hasVideo() const
 ///Get the current state
 Call::State Call::state() const
 {
-   return m_CurrentState;
+   return d_ptr->m_CurrentState;
 }
 
 ///Translate the state into its life cycle equivalent
 Call::LifeCycleState Call::lifeCycleState() const
 {
-   return metaStateMap[m_CurrentState];
+   return d_ptr->metaStateMap[d_ptr->m_CurrentState];
 }
 
 ///Get the call recording
 bool Call::isRecording() const
 {
-   return m_Recording;
+   return d_ptr->m_Recording;
 }
 
 ///Get the call account id
 Account* Call::account() const
 {
-   return m_Account;
+   return d_ptr->m_Account;
 }
 
 ///Get the recording path
 const QString Call::recordingPath() const
 {
-   return m_RecordingPath;
+   return d_ptr->m_RecordingPath;
 }
 
 ///Get the history state
 Call::LegacyHistoryState Call::historyState() const
 {
-   return m_HistoryState;
+   return d_ptr->m_HistoryState;
 }
 
 ///This function could also be called mayBeSecure or haveChancesToBeEncryptedButWeCantTell.
 bool Call::isSecure() const
 {
 
-   if (!m_Account) {
+   if (!d_ptr->m_Account) {
       qDebug() << "Account not set, can't check security";
       return false;
    }
    //BUG this doesn't work
-   return m_Account && ((m_Account->isTlsEnabled()) || (m_Account->tlsMethod() != TlsMethodModel::Type::DEFAULT));
+   return d_ptr->m_Account && ((d_ptr->m_Account->isTlsEnabled()) || (d_ptr->m_Account->tlsMethod() != TlsMethodModel::Type::DEFAULT));
 } //isSecure
 
 ///Return the renderer associated with this call or nullptr
@@ -782,27 +800,27 @@ VideoRenderer* Call::videoRenderer() const
 ///Set the transfer number
 void Call::setTransferNumber(const QString& number)
 {
-   if (!m_pTransferNumber) {
-      m_pTransferNumber = new TemporaryPhoneNumber();
+   if (!d_ptr->m_pTransferNumber) {
+      d_ptr->m_pTransferNumber = new TemporaryPhoneNumber();
    }
-   m_pTransferNumber->setUri(number);
+   d_ptr->m_pTransferNumber->setUri(number);
 }
 
 ///Set the call number
 void Call::setDialNumber(const QString& number)
 {
    //This is not supposed to happen, but this is not a serious issue if it does
-   if (m_CurrentState != Call::State::DIALING) {
+   if (d_ptr->m_CurrentState != Call::State::DIALING) {
       qDebug() << "Trying to set a dial number to a non-dialing call, doing nothing";
       return;
    }
 
-   if (!m_pDialNumber) {
-      m_pDialNumber = new TemporaryPhoneNumber();
+   if (!d_ptr->m_pDialNumber) {
+      d_ptr->m_pDialNumber = new TemporaryPhoneNumber();
    }
 
-   m_pDialNumber->setUri(number);
-   emit dialNumberChanged(m_pDialNumber->uri());
+   d_ptr->m_pDialNumber->setUri(number);
+   emit dialNumberChanged(d_ptr->m_pDialNumber->uri());
    emit changed();
    emit changed(this);
 }
@@ -810,12 +828,12 @@ void Call::setDialNumber(const QString& number)
 ///Set the dial number from a full phone number
 void Call::setDialNumber(const PhoneNumber* number)
 {
-   if (m_CurrentState == Call::State::DIALING && !m_pDialNumber) {
-      m_pDialNumber = new TemporaryPhoneNumber(number);
+   if (d_ptr->m_CurrentState == Call::State::DIALING && !d_ptr->m_pDialNumber) {
+      d_ptr->m_pDialNumber = new TemporaryPhoneNumber(number);
    }
-   if (m_pDialNumber && number)
-      m_pDialNumber->setUri(number->uri());
-   emit dialNumberChanged(m_pDialNumber->uri());
+   if (d_ptr->m_pDialNumber && number)
+      d_ptr->m_pDialNumber->setUri(number->uri());
+   emit dialNumberChanged(d_ptr->m_pDialNumber->uri());
    emit changed();
    emit changed(this);
 }
@@ -823,31 +841,31 @@ void Call::setDialNumber(const PhoneNumber* number)
 ///Set the recording path
 void Call::setRecordingPath(const QString& path)
 {
-   m_RecordingPath = path;
-   if (!m_RecordingPath.isEmpty()) {
-      CallManagerInterface & callManager = DBus::CallManager::instance();
-      connect(&callManager,SIGNAL(recordPlaybackStopped(QString)), this, SLOT(stopPlayback(QString))  );
-      connect(&callManager,SIGNAL(updatePlaybackScale(QString,int,int))  , this, SLOT(updatePlayback(QString,int,int)));
+   d_ptr->m_RecordingPath = path;
+   if (!d_ptr->m_RecordingPath.isEmpty()) {
+      CallManagerInterface& callManager = DBus::CallManager::instance();
+      connect(&callManager,SIGNAL(recordPlaybackStopped(QString)), d_ptr.data(), SLOT(stopPlayback(QString))  );
+      connect(&callManager,SIGNAL(updatePlaybackScale(QString,int,int))  , d_ptr.data(), SLOT(updatePlayback(QString,int,int)));
    }
 }
 
 ///Set peer name
 void Call::setPeerName(const QString& name)
 {
-   m_PeerName = name;
+   d_ptr->m_PeerName = name;
 }
 
 ///Set the account (DIALING only, may be ignored)
 void Call::setAccount( Account* account)
 {
    if (state() == Call::State::DIALING)
-      m_Account = account;
+      d_ptr->m_Account = account;
 }
 
 /// Set the backend to save this call to. It is currently impossible to migrate.
 void Call::setBackend(AbstractHistoryBackend* backend)
 {
-   m_pBackend = backend;
+   d_ptr->m_pBackend = backend;
 }
 
 /*****************************************************************************
@@ -857,10 +875,10 @@ void Call::setBackend(AbstractHistoryBackend* backend)
  ****************************************************************************/
 
 ///The call state just changed (by the daemon)
-Call::State Call::stateChanged(const QString& newStateName)
+Call::State CallPrivate::stateChanged(const QString& newStateName)
 {
    const Call::State previousState = m_CurrentState;
-   if (type() != Call::Type::CONFERENCE) {
+   if (q_ptr->type() != Call::Type::CONFERENCE) {
       Call::DaemonState dcs = toDaemonCallState(newStateName);
       if (dcs == Call::DaemonState::__COUNT || m_CurrentState == Call::State::__COUNT) {
          qDebug() << "Error: Invalid state change";
@@ -875,25 +893,25 @@ Call::State Call::stateChanged(const QString& newStateName)
 
       try {
          //Validate if the transition respect the expected life cycle
-         if (!metaStateTransitionValidationMap[stateChangedStateMap[m_CurrentState][dcs]][lifeCycleState()]) {
-            qWarning() << "Unexpected state transition from" << state() << "to" << stateChangedStateMap[m_CurrentState][dcs];
+         if (!metaStateTransitionValidationMap[stateChangedStateMap[m_CurrentState][dcs]][q_ptr->lifeCycleState()]) {
+            qWarning() << "Unexpected state transition from" << q_ptr->state() << "to" << stateChangedStateMap[m_CurrentState][dcs];
             Q_ASSERT(false);
          }
          changeCurrentState(stateChangedStateMap[m_CurrentState][dcs]);
       }
       catch(Call::State& state) {
          qDebug() << "State change failed (stateChangedStateMap)" << state;
-         FORCE_ERROR_STATE()
+         FORCE_ERROR_STATE_P()
          return m_CurrentState;
       }
       catch(Call::DaemonState& state) {
          qDebug() << "State change failed (stateChangedStateMap)" << state;
-         FORCE_ERROR_STATE()
+         FORCE_ERROR_STATE_P()
          return m_CurrentState;
       }
       catch (...) {
          qDebug() << "State change failed (stateChangedStateMap) other";;
-         FORCE_ERROR_STATE()
+         FORCE_ERROR_STATE_P()
          return m_CurrentState;
       }
 
@@ -907,17 +925,17 @@ Call::State Call::stateChanged(const QString& newStateName)
       }
       catch(Call::State& state) {
          qDebug() << "State change failed (stateChangedFunctionMap)" << state;
-         FORCE_ERROR_STATE()
+         FORCE_ERROR_STATE_P()
          return m_CurrentState;
       }
       catch(Call::DaemonState& state) {
          qDebug() << "State change failed (stateChangedFunctionMap)" << state;
-         FORCE_ERROR_STATE()
+         FORCE_ERROR_STATE_P()
          return m_CurrentState;
       }
       catch (...) {
          qDebug() << "State change failed (stateChangedFunctionMap) other";;
-         FORCE_ERROR_STATE()
+         FORCE_ERROR_STATE_P()
          return m_CurrentState;
       }
    }
@@ -925,7 +943,7 @@ Call::State Call::stateChanged(const QString& newStateName)
       //Until now, it does not worth using stateChangedStateMap, conferences are quite simple
       //update 2014: Umm... wrong
       m_CurrentState = confStatetoCallState(newStateName); //TODO don't do this
-      emit stateChanged();
+      emit q_ptr->stateChanged();
    }
    if (m_CurrentState != Call::State::DIALING && m_pDialNumber) {
       if (!m_pPeerPhoneNumber)
@@ -933,16 +951,26 @@ Call::State Call::stateChanged(const QString& newStateName)
       delete m_pDialNumber;
       m_pDialNumber = nullptr;
    }
-   emit changed();
-   emit changed(this);
+   emit q_ptr->changed();
+   emit q_ptr->changed(q_ptr);
    qDebug() << "Calling stateChanged " << newStateName << " -> " << toDaemonCallState(newStateName) << " on call with state " << previousState << ". Become " << m_CurrentState;
    return m_CurrentState;
 } //stateChanged
 
+void CallPrivate::performAction(Call::State previousState, Call::Action action)
+{
+   changeCurrentState(actionPerformedStateMap[previousState][action]);
+}
+
+void CallPrivate::performActionCallback(Call::State previousState, Call::Action action)
+{
+   (this->*(actionPerformedFunctionMap[previousState][action]))();
+}
+
 ///An account have been performed
 Call::State Call::performAction(Call::Action action)
 {
-   const Call::State previousState = m_CurrentState;
+   const Call::State previousState = d_ptr->m_CurrentState;
 
 //    if (actionPerformedStateMap[previousState][action] == previousState) {
 // #ifndef NDEBUG
@@ -953,7 +981,7 @@ Call::State Call::performAction(Call::Action action)
 
    //update the state
    try {
-      changeCurrentState(actionPerformedStateMap[previousState][action]);
+      d_ptr->performAction(previousState, action);
    }
    catch(Call::State& state) {
       qDebug() << "State change failed (actionPerformedStateMap)" << state;
@@ -963,12 +991,12 @@ Call::State Call::performAction(Call::Action action)
    catch (...) {
       qDebug() << "State change failed (actionPerformedStateMap) other";;
       FORCE_ERROR_STATE()
-      return m_CurrentState;
+      return d_ptr->m_CurrentState;
    }
 
    //execute the action associated with this transition
    try {
-      (this->*(actionPerformedFunctionMap[previousState][action]))();
+      d_ptr->performActionCallback(previousState, action);
    }
    catch(Call::State& state) {
       qDebug() << "State change failed (actionPerformedFunctionMap)" << state;
@@ -983,35 +1011,35 @@ Call::State Call::performAction(Call::Action action)
    catch (...) {
       qDebug() << "State change failed (actionPerformedFunctionMap) other";;
       FORCE_ERROR_STATE()
-      return m_CurrentState;
+      return d_ptr->m_CurrentState;
    }
-   qDebug() << "Calling action " << action << " on " << id() << " with state " << previousState << ". Become " << m_CurrentState;
-   return m_CurrentState;
+   qDebug() << "Calling action " << action << " on " << id() << " with state " << previousState << ". Become " << d_ptr->m_CurrentState;
+   return d_ptr->m_CurrentState;
 } //actionPerformed
 
 ///Change the state, do not abuse of this, but it is necessary for error cases
-void Call::changeCurrentState(Call::State newState)
+void CallPrivate::changeCurrentState(Call::State newState)
 {
    if (newState == Call::State::__COUNT) {
       qDebug() << "Error: Call reach invalid state";
-      FORCE_ERROR_STATE()
+      FORCE_ERROR_STATE_P()
       throw newState;
    }
 
    m_CurrentState = newState;
 
-   emit stateChanged();
-   emit changed();
-   emit changed(this);
+   emit q_ptr->stateChanged();
+   emit q_ptr->changed();
+   emit q_ptr->changed(q_ptr);
 
    initTimer();
 
-   if (lifeCycleState() == Call::LifeCycleState::FINISHED)
-      emit isOver(this);
+   if (q_ptr->lifeCycleState() == Call::LifeCycleState::FINISHED)
+      emit q_ptr->isOver(q_ptr);
 }
 
 ///Set the start timestamp and update the cache
-void Call::setStartTimeStamp(time_t stamp)
+void CallPrivate::setStartTimeStamp(time_t stamp)
 {
    m_pStartTimeStamp = stamp;
    //While the HistoryConst is not directly related to the call concept,
@@ -1023,11 +1051,11 @@ void Call::setStartTimeStamp(time_t stamp)
 void Call::sendTextMessage(const QString& message)
 {
    CallManagerInterface& callManager = DBus::CallManager::instance();
-   Q_NOREPLY callManager.sendTextMessage(m_CallId,message);
-   if (!m_pImModel) {
-      m_pImModel = InstantMessagingModelManager::instance()->getModel(this);
+   Q_NOREPLY callManager.sendTextMessage(d_ptr->m_CallId,message);
+   if (!d_ptr->m_pImModel) {
+      d_ptr->m_pImModel = InstantMessagingModelManager::instance()->getModel(this);
    }
-   m_pImModel->addOutgoingMessage(message);
+   d_ptr->m_pImModel->addOutgoingMessage(message);
 }
 
 
@@ -1039,16 +1067,16 @@ void Call::sendTextMessage(const QString& message)
 ///@warning DO NOT TOUCH THAT, THEY ARE CALLED FROM AN AUTOMATE, HIGH FRAGILITY
 
 ///Do nothing (literally)
-void Call::nothing()
+void CallPrivate::nothing()
 {
    //nop
 }
 
-void Call::error()
+void CallPrivate::error()
 {
-   if (videoRenderer()) {
+   if (q_ptr->videoRenderer()) {
       //Well, in this case we have no choice, it still doesn't belong here
-      videoRenderer()->stopRendering();
+      q_ptr->videoRenderer()->stopRendering();
    }
    throw QString("There was an error handling your call, please restart SFLPhone.Is you encounter this problem often, \
    please open SFLPhone-KDE in a terminal and send this last 100 lines before this message in a bug report at \
@@ -1056,7 +1084,7 @@ void Call::error()
 }
 
 ///Change history state to failure
-void Call::failure()
+void CallPrivate::failure()
 {
    m_Missed = true;
    //This is how it always was done
@@ -1065,25 +1093,25 @@ void Call::failure()
 }
 
 ///Accept the call
-void Call::accept()
+void CallPrivate::accept()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Accepting call. callId : " << m_CallId  << "ConfId:" << id();
+   qDebug() << "Accepting call. callId : " << m_CallId  << "ConfId:" << m_CallId;
    Q_NOREPLY callManager.accept(m_CallId);
    time_t curTime;
    ::time(&curTime);
    setStartTimeStamp(curTime);
-   this->m_HistoryState = LegacyHistoryState::INCOMING;
+   this->m_HistoryState = Call::LegacyHistoryState::INCOMING;
    m_Direction = Call::Direction::INCOMING;
 }
 
 ///Refuse the call
-void Call::refuse()
+void CallPrivate::refuse()
 {
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Refusing call. callId : " << m_CallId  << "ConfId:" << id();
+   qDebug() << "Refusing call. callId : " << m_CallId  << "ConfId:" << m_CallId;
    const bool ret = callManager.refuse(m_CallId);
    time_t curTime;
    ::time(&curTime);
@@ -1093,11 +1121,11 @@ void Call::refuse()
 
    //If the daemon crashed then re-spawned when a call is ringing, this happen.
    if (!ret)
-      FORCE_ERROR_STATE()
+      FORCE_ERROR_STATE_P()
 }
 
 ///Accept the transfer
-void Call::acceptTransf()
+void CallPrivate::acceptTransf()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
@@ -1106,26 +1134,26 @@ void Call::acceptTransf()
       return;
    }
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Accepting call and transferring it to number : " << m_pTransferNumber->uri() << ". callId : " << m_CallId  << "ConfId:" << id();
+   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());
 }
 
 ///Put the call on hold
-void Call::acceptHold()
+void CallPrivate::acceptHold()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Accepting call and holding it. callId : " << m_CallId  << "ConfId:" << id();
+   qDebug() << "Accepting call and holding it. callId : " << m_CallId  << "ConfId:" << m_CallId;
    callManager.accept(m_CallId);
    Q_NOREPLY callManager.hold(m_CallId);
-   this->m_HistoryState = LegacyHistoryState::INCOMING;
+   this->m_HistoryState = Call::LegacyHistoryState::INCOMING;
    m_Direction = Call::Direction::INCOMING;
 }
 
 ///Hang up
-void Call::hangUp()
+void CallPrivate::hangUp()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
@@ -1133,15 +1161,15 @@ void Call::hangUp()
    time_t curTime;
    ::time(&curTime);
    m_pStopTimeStamp = curTime;
-   qDebug() << "Hanging up call. callId : " << m_CallId << "ConfId:" << id();
+   qDebug() << "Hanging up call. callId : " << m_CallId << "ConfId:" << m_CallId;
    bool ret;
-   if (videoRenderer()) { //TODO remove, cheap hack
-      videoRenderer()->stopRendering();
+   if (q_ptr->videoRenderer()) { //TODO remove, cheap hack
+      q_ptr->videoRenderer()->stopRendering();
    }
-   if (type() != Call::Type::CONFERENCE)
+   if (q_ptr->type() != Call::Type::CONFERENCE)
       ret = callManager.hangUp(m_CallId);
    else
-      ret = callManager.hangUpConference(id());
+      ret = callManager.hangUpConference(m_CallId);
    if (!ret) { //Can happen if the daemon crash and open again
       qDebug() << "Error: Invalid call, the daemon may have crashed";
       changeCurrentState(Call::State::OVER);
@@ -1151,33 +1179,33 @@ void Call::hangUp()
 }
 
 ///Remove the call without contacting the daemon
-void Call::remove()
+void CallPrivate::remove()
 {
-   if (lifeCycleState() != Call::LifeCycleState::FINISHED)
-      FORCE_ERROR_STATE()
+   if (q_ptr->lifeCycleState() != Call::LifeCycleState::FINISHED)
+      FORCE_ERROR_STATE_P()
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
 
    //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 (type() != Call::Type::CONFERENCE)
+   if (q_ptr->type() != Call::Type::CONFERENCE)
       callManager.hangUp(m_CallId);
    else
-      callManager.hangUpConference(id());
+      callManager.hangUpConference(q_ptr->id());
 
-   emit isOver(this);
-   emit stateChanged();
-   emit changed();
-   emit changed(this);
+   emit q_ptr->isOver(q_ptr);
+   emit q_ptr->stateChanged();
+   emit q_ptr->changed();
+   emit q_ptr->changed(q_ptr);
 }
 
 ///Cancel this call
-void Call::cancel()
+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:" << id();
-   emit dialNumberChanged(QString());
+   qDebug() << "Canceling call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   emit q_ptr->dialNumberChanged(QString());
 //    Q_NOREPLY callManager.hangUp(m_CallId);
    if (!callManager.hangUp(m_CallId)) {
       qWarning() << "HangUp failed, the call was probably already over";
@@ -1186,20 +1214,20 @@ void Call::cancel()
 }
 
 ///Put on hold
-void Call::hold()
+void CallPrivate::hold()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Holding call. callId : " << m_CallId << "ConfId:" << id();
-   if (type() != Call::Type::CONFERENCE)
+   qDebug() << "Holding call. callId : " << m_CallId << "ConfId:" << q_ptr->id();
+   if (q_ptr->type() != Call::Type::CONFERENCE)
       Q_NOREPLY callManager.hold(m_CallId);
    else
-      Q_NOREPLY callManager.holdConference(id());
+      Q_NOREPLY callManager.holdConference(q_ptr->id());
 }
 
 ///Start the call
-void Call::call()
+void CallPrivate::call()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
@@ -1214,49 +1242,49 @@ void Call::call()
       qDebug() << "Trying to call an empty URI";
       changeCurrentState(Call::State::FAILURE);
       if (!m_pDialNumber) {
-         emit dialNumberChanged(QString());
+         emit q_ptr->dialNumberChanged(QString());
       }
       else {
          delete m_pDialNumber;
          m_pDialNumber = nullptr;
       }
-      setPeerName(tr("Failure"));
-      emit stateChanged();
-      emit changed();
+      q_ptr->setPeerName(tr("Failure"));
+      emit q_ptr->stateChanged();
+      emit q_ptr->changed();
    }
    //Normal case
    else if(m_Account) {
-      qDebug() << "Calling " << peerPhoneNumber()->uri() << " with account " << m_Account << ". callId : " << m_CallId  << "ConfId:" << id();
+      qDebug() << "Calling " << q_ptr->peerPhoneNumber()->uri() << " with account " << m_Account << ". callId : " << m_CallId  << "ConfId:" << q_ptr->id();
       callManager.placeCall(m_Account->id(), m_CallId, m_pDialNumber->uri());
-      this->m_pPeerPhoneNumber = PhoneDirectoryModel::instance()->getNumber(m_pDialNumber->uri(),account());
+      this->m_pPeerPhoneNumber = PhoneDirectoryModel::instance()->getNumber(m_pDialNumber->uri(),q_ptr->account());
       if (ContactModel::instance()->hasBackends()) {
-         if (peerPhoneNumber()->contact())
-            m_PeerName = peerPhoneNumber()->contact()->formattedName();
+         if (q_ptr->peerPhoneNumber()->contact())
+            m_PeerName = q_ptr->peerPhoneNumber()->contact()->formattedName();
       }
-      connect(peerPhoneNumber(),SIGNAL(presentChanged(bool)),this,SLOT(updated()));
+      connect(q_ptr->peerPhoneNumber(),SIGNAL(presentChanged(bool)),this,SLOT(updated()));
       time_t curTime;
       ::time(&curTime);
       setStartTimeStamp(curTime);
-      this->m_HistoryState = LegacyHistoryState::OUTGOING;
+      this->m_HistoryState = Call::LegacyHistoryState::OUTGOING;
       m_Direction = Call::Direction::OUTGOING;
-      if (peerPhoneNumber()) {
-         peerPhoneNumber()->addCall(this);
+      if (q_ptr->peerPhoneNumber()) {
+         q_ptr->peerPhoneNumber()->addCall(q_ptr);
       }
       if (m_pDialNumber)
-         emit dialNumberChanged(QString());
+         emit q_ptr->dialNumberChanged(QString());
       delete m_pDialNumber;
       m_pDialNumber = nullptr;
    }
    else {
       qDebug() << "Trying to call " << (m_pTransferNumber?QString(m_pTransferNumber->uri()):"ERROR") 
-         << " with no account registered . callId : " << m_CallId  << "ConfId:" << id();
-      this->m_HistoryState = LegacyHistoryState::NONE;
+         << " with no account registered . callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+      this->m_HistoryState = Call::LegacyHistoryState::NONE;
       throw tr("No account registered!");
    }
 }
 
 ///Trnasfer the call
-void Call::transfer()
+void CallPrivate::transfer()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
@@ -1271,34 +1299,35 @@ void Call::transfer()
 }
 
 ///Unhold the call
-void Call::unhold()
+void CallPrivate::unhold()
 {
    Q_ASSERT_IS_IN_PROGRESS
 
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Unholding call. callId : " << m_CallId  << "ConfId:" << id();
-   if (type() != Call::Type::CONFERENCE)
+   qDebug() << "Unholding call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   if (q_ptr->type() != Call::Type::CONFERENCE)
       Q_NOREPLY callManager.unhold(m_CallId);
    else
-      Q_NOREPLY callManager.unholdConference(id());
+      Q_NOREPLY callManager.unholdConference(q_ptr->id());
 }
 
 ///Record the call
-void Call::setRecord()
+void CallPrivate::toggleRecord()
 {
    CallManagerInterface & callManager = DBus::CallManager::instance();
-   qDebug() << "Setting record " << !m_Recording << " for call. callId : " << m_CallId  << "ConfId:" << id();
-   callManager.toggleRecording(id());
+   qDebug() << "Setting record " << !m_Recording << " for call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+
+   callManager.toggleRecording(q_ptr->id());
 }
 
 ///Start the timer
-void Call::start()
+void CallPrivate::start()
 {
-   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << id();
+   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
    time_t curTime;
    ::time(&curTime);
-   emit changed();
-   emit changed(this);
+   emit q_ptr->changed();
+   emit q_ptr->changed(q_ptr);
    if (m_pDialNumber) {
       if (!m_pPeerPhoneNumber)
          m_pPeerPhoneNumber = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber);
@@ -1309,9 +1338,9 @@ void Call::start()
 }
 
 ///Toggle the timer
-void Call::startStop()
+void CallPrivate::startStop()
 {
-   qDebug() << "Starting and stoping call. callId : " << m_CallId  << "ConfId:" << id();
+   qDebug() << "Starting and stoping call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
    time_t curTime;
    ::time(&curTime);
    setStartTimeStamp(curTime);
@@ -1319,11 +1348,11 @@ void Call::startStop()
 }
 
 ///Stop the timer
-void Call::stop()
+void CallPrivate::stop()
 {
-   qDebug() << "Stoping call. callId : " << m_CallId  << "ConfId:" << id();
-   if (videoRenderer()) { //TODO remove, cheap hack
-      videoRenderer()->stopRendering();
+   qDebug() << "Stoping call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
+   if (q_ptr->videoRenderer()) { //TODO remove, cheap hack
+      q_ptr->videoRenderer()->stopRendering();
    }
    time_t curTime;
    ::time(&curTime);
@@ -1331,9 +1360,9 @@ void Call::stop()
 }
 
 ///Handle error instead of crashing
-void Call::startWeird()
+void CallPrivate::startWeird()
 {
-   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << id();
+   qDebug() << "Starting call. callId : " << m_CallId  << "ConfId:" << q_ptr->id();
    time_t curTime;
    ::time(&curTime);
    setStartTimeStamp(curTime);
@@ -1341,7 +1370,7 @@ void Call::startWeird()
 }
 
 ///Print a warning
-void Call::warning()
+void CallPrivate::warning()
 {
    qWarning() << "Warning : call " << m_CallId << " had an unexpected transition of state.(" << m_CurrentState << ")";
    switch (m_CurrentState) {
@@ -1382,13 +1411,13 @@ void Call::appendText(const QString& str)
 {
    TemporaryPhoneNumber* editNumber = nullptr;
 
-   switch (m_CurrentState) {
+   switch (d_ptr->m_CurrentState) {
    case Call::State::TRANSFERRED :
    case Call::State::TRANSF_HOLD :
-      editNumber = m_pTransferNumber;
+      editNumber = d_ptr->m_pTransferNumber;
       break;
    case Call::State::DIALING     :
-      editNumber = m_pDialNumber;
+      editNumber = d_ptr->m_pDialNumber;
       break;
    case Call::State::INITIALIZATION:
    case Call::State::INCOMING:
@@ -1425,13 +1454,13 @@ void Call::backspaceItemText()
 {
    TemporaryPhoneNumber* editNumber = nullptr;
 
-   switch (m_CurrentState) {
+   switch (d_ptr->m_CurrentState) {
       case Call::State::TRANSFERRED      :
       case Call::State::TRANSF_HOLD      :
-         editNumber = m_pTransferNumber;
+         editNumber = d_ptr->m_pTransferNumber;
          break;
       case Call::State::DIALING          :
-         editNumber = m_pDialNumber;
+         editNumber = d_ptr->m_pDialNumber;
          break;
       case Call::State::INITIALIZATION:
       case Call::State::INCOMING:
@@ -1458,7 +1487,7 @@ void Call::backspaceItemText()
          emit changed(this);
       }
       else {
-         changeCurrentState(Call::State::OVER);
+         d_ptr->changeCurrentState(Call::State::OVER);
       }
    }
    else
@@ -1470,13 +1499,13 @@ void Call::reset()
 {
    TemporaryPhoneNumber* editNumber = nullptr;
 
-   switch (m_CurrentState) {
+   switch (d_ptr->m_CurrentState) {
       case Call::State::TRANSFERRED      :
       case Call::State::TRANSF_HOLD      :
-         editNumber = m_pTransferNumber;
+         editNumber = d_ptr->m_pTransferNumber;
          break;
       case Call::State::DIALING          :
-         editNumber = m_pDialNumber;
+         editNumber = d_ptr->m_pDialNumber;
          break;
       case Call::State::INITIALIZATION   :
       case Call::State::INCOMING         :
@@ -1491,7 +1520,7 @@ void Call::reset()
       case Call::State::CONFERENCE_HOLD  :
       case Call::State::__COUNT:
       default                            :
-         qDebug() << "Cannot reset" << m_CurrentState << "calls";
+         qDebug() << "Cannot reset" << d_ptr->m_CurrentState << "calls";
          return;
    }
    if (editNumber) {
@@ -1505,10 +1534,10 @@ void Call::reset()
  *                                                                           *
  ****************************************************************************/
 
-void Call::updated()
+void CallPrivate::updated()
 {
-   emit changed();
-   emit changed(this);
+   emit q_ptr->changed();
+   emit q_ptr->changed(q_ptr);
 }
 
 ///Play the record, if any
@@ -1536,30 +1565,30 @@ void Call::seekRecording(double position)
 }
 
 ///Daemon record playback stopped
-void Call::stopPlayback(const QString& filePath)
+void CallPrivate::stopPlayback(const QString& filePath)
 {
-   if (filePath == recordingPath()) {
-      emit playbackStopped();
+   if (filePath == q_ptr->recordingPath()) {
+      emit q_ptr->playbackStopped();
    }
 }
 
 ///Daemon playback position chnaged
-void Call::updatePlayback(const QString& path, int position,int size)
+void CallPrivate::updatePlayback(const QString& path, int position,int size)
 {
    if (path == m_RecordingPath) {
-      emit playbackPositionChanged(position,size);
+      emit q_ptr->playbackPositionChanged(position,size);
    }
 }
 
 UserActionModel* Call::userActionModel() const
 {
-   return m_pUserActionModel;
+   return d_ptr->m_pUserActionModel;
 }
 
 ///Check if creating a timer is necessary
-void Call::initTimer()
+void CallPrivate::initTimer()
 {
-   if (lifeCycleState() == Call::LifeCycleState::PROGRESS) {
+   if (q_ptr->lifeCycleState() == Call::LifeCycleState::PROGRESS) {
       if (!m_pTimer) {
          m_pTimer = new QTimer(this);
          m_pTimer->setInterval(1000);
@@ -1568,7 +1597,7 @@ void Call::initTimer()
       if (!m_pTimer->isActive())
          m_pTimer->start();
    }
-   else if (m_pTimer && lifeCycleState() != Call::LifeCycleState::PROGRESS) {
+   else if (m_pTimer && q_ptr->lifeCycleState() != Call::LifeCycleState::PROGRESS) {
       m_pTimer->stop();
       delete m_pTimer;
       m_pTimer = nullptr;
@@ -1586,7 +1615,7 @@ QVariant Call::roleData(int role) const
             return tr("Conference");
          else if (state() == Call::State::DIALING)
             return dialNumber();
-         else if (m_PeerName.isEmpty())
+         else if (d_ptr->m_PeerName.isEmpty())
             return ct?ct->formattedName():peerPhoneNumber()?peerPhoneNumber()->uri():dialNumber();
          else
             return formattedName();
@@ -1600,7 +1629,7 @@ QVariant Call::roleData(int role) const
          return peerPhoneNumber()->uri();
          break;
       case Call::Role::Direction2:
-         return static_cast<int>(m_Direction); //TODO Qt5, use the Q_ENUM
+         return static_cast<int>(d_ptr->m_Direction); //TODO Qt5, use the Q_ENUM
          break;
       case Call::Role::Date:
          return (int)startTimeStamp();
@@ -1628,7 +1657,7 @@ QVariant Call::roleData(int role) const
          }
          break;
       case Call::Role::FuzzyDate:
-         return (int)m_HistoryConst; //TODO Qt5, use the Q_ENUM
+         return (int)d_ptr->m_HistoryConst; //TODO Qt5, use the Q_ENUM
          break;
       case Call::Role::IsBookmark:
          return false;
@@ -1661,9 +1690,9 @@ QVariant Call::roleData(int role) const
          return id();
          break;
       case Call::Role::StartTime:
-         return (int) m_pStartTimeStamp;
+         return (int) d_ptr->m_pStartTimeStamp;
       case Call::Role::StopTime:
-         return (int) m_pStopTimeStamp;
+         return (int) d_ptr->m_pStopTimeStamp;
       case Call::Role::IsRecording:
          return isRecording();
       case Call::Role::IsPresent:
@@ -1709,3 +1738,6 @@ void Call::playDTMF(const QString& str)
 
 #undef Q_ASSERT_IS_IN_PROGRESS
 #undef FORCE_ERROR_STATE
+#undef FORCE_ERROR_STATE_P
+
+#include <call.moc>
diff --git a/src/call.h b/src/call.h
index 480c1e20a6512f4fc2812b2f5f2e36fc047ff80c..4904f046b9b9188efe947c29507c418808ccd136 100644
--- a/src/call.h
+++ b/src/call.h
@@ -41,7 +41,9 @@ class AbstractHistoryBackend;
 
 class Call;
 
-typedef  void (Call::*function)();
+//Private
+class CallPrivate;
+
 
 /**
  *  This class represents a call either actual (in the call list
@@ -361,7 +363,6 @@ public:
    Call::Type               type             () const;
 
    //Automated function
-   Call::State stateChanged(const QString & newState);
    Call::State performAction(Call::Action action);
 
    //Setters
@@ -383,110 +384,10 @@ public:
    Call* operator<<( Call::Action& c);
 
 private:
-
-   //Attributes
-   Account*                 m_Account         ;
-   QString                  m_CallId          ;
-   PhoneNumber*             m_pPeerPhoneNumber;
-   QString                  m_PeerName        ;
-   QString                  m_RecordingPath   ;
-   Call::LegacyHistoryState m_HistoryState    ;
-   time_t                   m_pStartTimeStamp ;
-   time_t                   m_pStopTimeStamp  ;
-   TemporaryPhoneNumber*    m_pTransferNumber ;
-   TemporaryPhoneNumber*    m_pDialNumber     ;
-   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            ;
-   AbstractHistoryBackend*  m_pBackend        ;
-
-   //Cache
-   HistoryTimeCategoryModel::HistoryConst m_HistoryConst;
-
-   //State machine
-   /**
-    *  actionPerformedStateMap[orig_state][action]
-    *  Map of the states to go to when the action action is 
-    *  performed on a call in state orig_state.
-   **/
-   static const TypedStateMachine< TypedStateMachine< Call::State , Call::Action > , Call::State > actionPerformedStateMap;
-
-   /**
-    *  actionPerformedFunctionMap[orig_state][action]
-    *  Map of the functions to call when the action action is 
-    *  performed on a call in state orig_state.
-   **/
-   static const TypedStateMachine< TypedStateMachine< function , Call::Action > , Call::State > actionPerformedFunctionMap;
-
-   /**
-    *  stateChangedStateMap[orig_state][daemon_new_state]
-    *  Map of the states to go to when the daemon sends the signal 
-    *  callStateChanged with arg daemon_new_state
-    *  on a call in state orig_state.
-   **/
-   static const TypedStateMachine< TypedStateMachine< Call::State , Call::DaemonState > , Call::State > stateChangedStateMap;
-
-   /**
-    *  stateChangedFunctionMap[orig_state][daemon_new_state]
-    *  Map of the functions to call when the daemon sends the signal 
-    *  callStateChanged with arg daemon_new_state
-    *  on a call in state orig_state.
-   **/
-   static const TypedStateMachine< TypedStateMachine< function , Call::DaemonState > , Call::State > stateChangedFunctionMap;
-
-   /**
-    * metaStateTransitionValidationMap help validate if a state transition violate the lifecycle logic.
-    * it should technically never happen, but this is an easy additional safety to implement
-    * and prevent human (developer) errors.
-    */
-   static const TypedStateMachine< TypedStateMachine< bool , Call::LifeCycleState > , Call::State > metaStateTransitionValidationMap;
-
-   /**
-    * Convert the call state into its meta state (life cycle state). The meta state is a flat,
-    * forward only progression from creating to archiving of a call.
-    */
-   static const TypedStateMachine< Call::LifeCycleState , Call::State > metaStateMap;
-
    explicit Call(const QString& confId, const QString& account);
    Call(Call::State startState, const QString& callId, const QString& peerName = QString(), PhoneNumber* number = nullptr, Account* account = nullptr);
-   static Call::DaemonState toDaemonCallState   (const QString& stateName);
-   static Call::State       confStatetoCallState(const QString& stateName);
-
-   //Automate functions
-   // See actionPerformedFunctionMap and stateChangedFunctionMap
-   // to know when it is called.
-   void nothing      () __attribute__ ((const));
-   void error        () __attribute__ ((noreturn));
-   void failure      ();
-   void accept       ();
-   void refuse       ();
-   void acceptTransf ();
-   void acceptHold   ();
-   void hangUp       ();
-   void cancel       ();
-   void hold         ();
-   void call         ();
-   void transfer     ();
-   void unhold       ();
-   void switchRecord ();
-   void setRecord    ();
-   void start        ();
-   void startStop    ();
-   void stop         ();
-   void startWeird   ();
-   void warning      ();
-   void remove       ();
-
-   //Helpers
-   void changeCurrentState(Call::State newState);
-   void setStartTimeStamp(time_t stamp);
-   void initTimer();
+   QScopedPointer<CallPrivate> d_ptr;
+   Q_DECLARE_PRIVATE(Call)
 
 public Q_SLOTS:
    void playRecording();
@@ -494,11 +395,6 @@ public Q_SLOTS:
    void seekRecording(double position);
    void playDTMF(const QString& str);
 
-private Q_SLOTS:
-   void stopPlayback(const QString& filePath);
-   void updatePlayback(const QString& path,int position,int size);
-   void updated();
-
 Q_SIGNALS:
    ///Emitted when a call change (state or details)
    void changed();
diff --git a/src/callmodel.cpp b/src/callmodel.cpp
index ec7d6121458e4043f839a264db979a3e24120cf7..e44595c1999b04e2c6c73db3e2e6910772aef008 100644
--- a/src/callmodel.cpp
+++ b/src/callmodel.cpp
@@ -39,6 +39,9 @@
 #include "visitors/phonenumberselector.h"
 #include "contactmodel.h"
 
+//Private
+#include "private/call_p.h"
+
 //Define
 ///InternalStruct: internal representation of a call
 struct InternalStruct {
@@ -443,19 +446,19 @@ void CallModel::attendedTransfer(Call* toTransfer, Call* target)
    Q_NOREPLY DBus::CallManager::instance().attendedTransfer(toTransfer->id(),target->id());
 
    //TODO [Daemon] Implement this correctly
-   toTransfer->changeCurrentState(Call::State::OVER);
-   target->changeCurrentState(Call::State::OVER);
+   toTransfer->d_ptr->changeCurrentState(Call::State::OVER);
+   target->d_ptr->changeCurrentState(Call::State::OVER);
 } //attendedTransfer
 
 ///Transfer this call to  "target" number
 void CallModel::transfer(Call* toTransfer, const PhoneNumber* target)
 {
    qDebug() << "Transferring call " << toTransfer->id() << "to" << target->uri();
-   toTransfer->setTransferNumber ( target->uri()            );
-   toTransfer->performAction     ( Call::Action::TRANSFER   );
-   toTransfer->changeCurrentState( Call::State::TRANSFERRED );
-   toTransfer->performAction     ( Call::Action::ACCEPT     );
-   toTransfer->changeCurrentState( Call::State::OVER        );
+   toTransfer->setTransferNumber        ( target->uri()            );
+   toTransfer->performAction            ( Call::Action::TRANSFER   );
+   toTransfer->d_ptr->changeCurrentState( Call::State::TRANSFERRED );
+   toTransfer->performAction            ( Call::Action::ACCEPT     );
+   toTransfer->d_ptr->changeCurrentState( Call::State::OVER        );
    emit toTransfer->isOver(toTransfer);
 } //transfer
 
@@ -920,7 +923,7 @@ void CallModel::slotCallStateChanged(const QString& callID, const QString& state
       qDebug() << "Call found" << call << call->state();
       const Call::LifeCycleState oldLifeCycleState = call->lifeCycleState();
       const Call::State          oldState          = call->state();
-      call->stateChanged(stateName);
+      call->d_ptr->stateChanged(stateName);
       //Remove call when they end normally, keep errors and failure one
       if ((stateName == Call::StateChange::HUNG_UP)
          || ((oldState == Call::State::OVER) && (call->state() == Call::State::OVER))
@@ -972,7 +975,7 @@ void CallModel::slotChangingConference(const QString &confID, const QString& sta
          return;
       }
 
-      conf->stateChanged(state);
+      conf->d_ptr->stateChanged(state);
       CallManagerInterface& callManager = DBus::CallManager::instance();
       const QStringList participants = callManager.getParticipantList(confID);
 
@@ -1159,7 +1162,7 @@ void CallModel::slotRecordStateChanged (const QString& callId, bool state)
 {
    Call* call = getCall(callId);
    if (call) {
-      call->m_Recording = state;
+      call->d_ptr->m_Recording = state;
       emit call->changed();
       emit call->changed(call);
    }
diff --git a/src/private/call_p.h b/src/private/call_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b4e591a88453a1689afc27915018f377a380f5b
--- /dev/null
+++ b/src/private/call_p.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+ *   Copyright (C) 2009-2014 by Savoir-Faire Linux                          *
+ *   Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com>          *
+ *            Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
+ *                                                                          *
+ *   This library is free software; you can redistribute it and/or          *
+ *   modify it under the terms of the GNU Lesser General Public             *
+ *   License as published by the Free Software Foundation; either           *
+ *   version 2.1 of the License, or (at your option) any later version.     *
+ *                                                                          *
+ *   This library 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      *
+ *   Lesser General Public License for more details.                        *
+ *                                                                          *
+ *   You should have received a copy of the GNU General Public License      *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+#ifndef CALL_PRIVATE_H
+#define CALL_PRIVATE_H
+
+#include <QtCore/QObject>
+#include "call.h"
+
+//Qt
+class QTimer;
+
+
+//SFLPhone
+class Account;
+class PhoneNumber;
+class UserActionModel;
+class InstantMessagingModel;
+
+class CallPrivate;
+typedef  void (CallPrivate::*function)();
+
+class CallPrivate : public QObject
+{
+   Q_OBJECT
+public:
+   friend class CallModel;
+
+   CallPrivate(Call* parent);
+
+   //Attributes
+   Account*                 m_Account         ;
+   QString                  m_CallId          ;
+   PhoneNumber*             m_pPeerPhoneNumber;
+   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            ;
+   AbstractHistoryBackend*  m_pBackend        ;
+
+   mutable TemporaryPhoneNumber* m_pTransferNumber ;
+   mutable TemporaryPhoneNumber* m_pDialNumber     ;
+
+   //Cache
+   HistoryTimeCategoryModel::HistoryConst m_HistoryConst;
+
+   //State machine
+   /**
+    *  actionPerformedStateMap[orig_state][action]
+    *  Map of the states to go to when the action action is 
+    *  performed on a call in state orig_state.
+   **/
+   static const TypedStateMachine< TypedStateMachine< Call::State , Call::Action > , Call::State > actionPerformedStateMap;
+
+   /**
+    *  actionPerformedFunctionMap[orig_state][action]
+    *  Map of the functions to call when the action action is 
+    *  performed on a call in state orig_state.
+   **/
+   static const TypedStateMachine< TypedStateMachine< function , Call::Action > , Call::State > actionPerformedFunctionMap;
+
+   /**
+    *  stateChangedStateMap[orig_state][daemon_new_state]
+    *  Map of the states to go to when the daemon sends the signal 
+    *  callStateChanged with arg daemon_new_state
+    *  on a call in state orig_state.
+   **/
+   static const TypedStateMachine< TypedStateMachine< Call::State , Call::DaemonState > , Call::State > stateChangedStateMap;
+
+   /**
+    *  stateChangedFunctionMap[orig_state][daemon_new_state]
+    *  Map of the functions to call when the daemon sends the signal 
+    *  callStateChanged with arg daemon_new_state
+    *  on a call in state orig_state.
+   **/
+   static const TypedStateMachine< TypedStateMachine< function , Call::DaemonState > , Call::State > stateChangedFunctionMap;
+
+   /**
+    * metaStateTransitionValidationMap help validate if a state transition violate the lifecycle logic.
+    * it should technically never happen, but this is an easy additional safety to implement
+    * and prevent human (developer) errors.
+    */
+   static const TypedStateMachine< TypedStateMachine< bool , Call::LifeCycleState > , Call::State > metaStateTransitionValidationMap;
+
+   /**
+    * Convert the call state into its meta state (life cycle state). The meta state is a flat,
+    * forward only progression from creating to archiving of a call.
+    */
+   static const TypedStateMachine< Call::LifeCycleState , Call::State > metaStateMap;
+
+   static Call::DaemonState toDaemonCallState   (const QString& stateName);
+   static Call::State       confStatetoCallState(const QString& stateName);
+   Call::State stateChanged(const QString & newState);
+   void performAction(Call::State previousState, Call::Action action);
+   void performActionCallback(Call::State previousState, Call::Action action);
+
+   //Automate functions
+   // See actionPerformedFunctionMap and stateChangedFunctionMap
+   // to know when it is called.
+   void nothing      () __attribute__ ((const));
+   void error        () __attribute__ ((noreturn));
+   void failure      ();
+   void accept       ();
+   void refuse       ();
+   void acceptTransf ();
+   void acceptHold   ();
+   void hangUp       ();
+   void cancel       ();
+   void hold         ();
+   void call         ();
+   void transfer     ();
+   void unhold       ();
+   void switchRecord ();
+   void toggleRecord ();
+   void start        ();
+   void startStop    ();
+   void stop         ();
+   void startWeird   ();
+   void warning      ();
+   void remove       ();
+
+   //Helpers
+   void changeCurrentState(Call::State newState);
+   void setStartTimeStamp(time_t stamp);
+   void initTimer();
+
+private:
+   Call* q_ptr;
+
+private Q_SLOTS:
+   void stopPlayback(const QString& filePath);
+   void updatePlayback(const QString& path,int position,int size);
+   void updated();
+};
+
+#endif
\ No newline at end of file