diff --git a/src/profilemodel.cpp b/src/profilemodel.cpp
index 9024c6ec74f8d8f0de9745d2180f08e7df627ae5..70a10e67307b1a508075e909a5f11d290b94fd0e 100644
--- a/src/profilemodel.cpp
+++ b/src/profilemodel.cpp
@@ -61,19 +61,25 @@ public:
    virtual bool addNew     ( Person*       item ) override;
    virtual bool addExisting( const Person* item ) override;
 
+   //Attributes
    Node* getProfileById(const QByteArray& id);
    QList<Account*> getAccountsForProfile(const QString& id);
    QList<Node*> m_lProfiles;
    QHash<QByteArray,Node*> m_hProfileByAccountId;
    QHash<QByteArray,Node*> m_hAccountIdToNode;
    QVector<Person*> m_lProfilePersons;
+   QSet<Person*> m_bSaveBuffer;
+
+   //Helpers
+   QString path(const Person* p) const;
 
 private:
    virtual QVector<Person*> items() const override;
 };
 
 ///ProfileContentBackend: Implement a backend for Profiles
-class ProfileContentBackend final : public QObject, public CollectionInterface {
+class ProfileContentBackend final : public QObject, public CollectionInterface
+{
    Q_OBJECT
 public:
    template<typename T>
@@ -96,25 +102,28 @@ public:
    bool m_needSaving;
    bool m_DelayedLoading {false};
 
-   QList<Person*> m_bSaveBuffer;
    bool saveAll();
 
    Node* m_pDefault;
    ProfileEditor* m_pEditor;
 
    //Helper
-   void  setupDefaultProfile();
-   void  addAccount(Node* parent, Account* acc);
+   void setupDefaultProfile();
+   void addAccount(Node* parent, Account* acc);
+   bool disableAndRemove(Person* p);
 
 public Q_SLOTS:
-   void contactChanged();
    void save();
    void loadProfiles();
 };
 
+struct Node
+{
+   explicit Node(): account(nullptr),contact(nullptr),type(Node::Type::PROFILE), parent(nullptr),m_Index(0) {}
 
-struct Node {
-   Node(): account(nullptr),contact(nullptr),type(Node::Type::PROFILE), parent(nullptr),m_Index(0) {}
+   virtual ~Node() {
+      QObject::disconnect(m_ChangedConn);
+   }
 
    enum class Type : bool {
       PROFILE,
@@ -123,13 +132,52 @@ struct Node {
 
    Node*           parent;
    QVector<Node*>  children;
-   Type            type;
+   Type            type {Node::Type::ACCOUNT};
    Account*        account;
    Person*         contact;
    int             m_Index;
    uint            m_ParentIndex {(uint)-1}; //INT_MAX
+   QMetaObject::Connection m_ChangedConn;
 };
 
+class ProfileModelPrivate final : public QObject
+{
+   Q_OBJECT
+public:
+   ProfileModelPrivate(ProfileModel* parent);
+   ProfileContentBackend* m_pProfileBackend;
+   QStringList m_lMimes;
+   QItemSelectionModel* m_pSelectionModel {nullptr};
+   QItemSelectionModel* m_pSortedProxySelectionModel {nullptr};
+   QSortFilterProxyModel* m_pSortedProxyModel {nullptr};
+
+   //Helpers
+   void updateIndexes();
+   void regenParentIndexes();
+   inline QModelIndex addProfile(Person* person, const QString& name);
+   Node* insertProfile(Person* p);
+
+private Q_SLOTS:
+   void slotDataChanged(const QModelIndex& tl,const QModelIndex& br);
+   void slotLayoutchanged();
+   void slotDelayedInit();
+   void slotRowsRemoved (const QModelIndex& index, int first, int last);
+   void slotRowsInserted(const QModelIndex& index, int first, int last);
+   void slotRowsMoved   (const QModelIndex& index, int first, int last, const QModelIndex& newPar, int newIdx);
+
+private:
+   ProfileModel* q_ptr;
+};
+
+QString ProfileEditor::path(const Person* p) const
+{
+   const QDir profilesDir = GlobalInstances::profilePersister().profilesDir();
+
+   return QString("%1/%2.vcf")
+      .arg(profilesDir.absolutePath())
+      .arg(QString(p->uid()));
+}
+
 bool ProfileEditor::save(const Person* contact)
 {
     try {
@@ -140,8 +188,7 @@ bool ProfileEditor::save(const Person* contact)
             QTimer::singleShot(0,[this,contact]() {
                 const_cast<Person*>(contact)->setProperty("delayedSaving", false);
 #endif
-                const auto& profilesDir = GlobalInstances::profilePersister().profilesDir();
-                const auto& filename = profilesDir.absolutePath() + '/' + contact->uid() + ".vcf";
+                const auto& filename = path(contact);
                 qDebug() << "Saving vcf in:" << filename;
                 const auto& result = contact->toVCard(getAccountsForProfile(contact->uid()));
 
@@ -171,7 +218,29 @@ ProfileEditor::~ProfileEditor()
 bool ProfileEditor::remove(const Person* item)
 {
    Q_UNUSED(item)
-   mediator()->removeItem(item);
+
+   if (QFile::remove(path(item))) {
+      mediator()->removeItem(item);
+
+      foreach (Node* n, m_lProfiles) {
+         if (n->contact == item) {
+            m_lProfiles.removeAll(n);
+            break;
+         }
+      }
+
+      m_bSaveBuffer.remove(const_cast<Person*>(item));
+
+      const int idx = m_lProfilePersons.indexOf(const_cast<Person*>(item));
+
+      if (idx != -1)
+         m_lProfilePersons.removeAt(idx);
+
+      return true;
+   }
+   else
+      qDebug() << "Failed to remove" << path(item);
+
    return false;
 }
 
@@ -187,6 +256,8 @@ bool ProfileEditor::addNew( Person* contact)
    m_lProfilePersons << contact;
    mediator()->addItem(contact);
    save(contact);
+
+   ProfileModel::instance()->d_ptr->insertProfile(contact);
 //    load(); //FIXME
    return true;
 }
@@ -310,22 +381,14 @@ void ProfileContentBackend::setupDefaultProfile()
          orphans << i.key();
       }
    }
-   qDebug() << "ORPHAN" << orphans.size() << m_pEditor << m_pEditor->m_lProfiles.size();
 
    if (orphans.size() && (!m_pDefault)) {
       qDebug() << "No profile found, creating one";
-      Person* profile = new Person(this,QString::number(QDateTime::currentDateTime().currentMSecsSinceEpoch()).toUtf8());
+      Person* profile = new Person(this, QString::number(QDateTime::currentDateTime().currentMSecsSinceEpoch()).toUtf8());
       m_pEditor->addNew(profile);
       profile->setFormattedName(tr("Default"));
 
-      m_pDefault          = new Node           ;
-      m_pDefault->type    = Node::Type::PROFILE;
-      m_pDefault->contact = profile            ;
-      m_pDefault->m_Index = m_pEditor->m_lProfiles.size() ;
-
-      ProfileModel::instance()->beginInsertRows(QModelIndex(), m_pEditor->m_lProfiles.size(), m_pEditor->m_lProfiles.size());
-      m_pEditor->m_lProfiles << m_pDefault;
-      ProfileModel::instance()->endInsertRows();
+      m_pDefault = ProfileModel::instance()->d_ptr->insertProfile(profile);
    }
 
    foreach(Account* a, orphans) {
@@ -333,6 +396,11 @@ void ProfileContentBackend::setupDefaultProfile()
    }
 }
 
+bool ProfileContentBackend::disableAndRemove(Person* p)
+{
+   return remove(p);
+}
+
 void ProfileContentBackend::addAccount(Node* parent, Account* acc)
 {
    Node* account_pro = new Node;
@@ -362,29 +430,21 @@ void ProfileContentBackend::loadProfiles()
 
       qDebug() << "Loading vcf from:" << profilesDir;
 
-      const QStringList entries = profilesDir.entryList({"*.vcf"}, QDir::Files);
+      const QStringList entries = profilesDir.entryList({QStringLiteral("*.vcf")}, QDir::Files);
 
       foreach (const QString& item , entries) {
 
          Person* profile = new Person(this);
 
-         Node* pro    = new Node           ;
-         pro->type    = Node::Type::PROFILE;
-         pro->contact = profile            ;
-         pro->m_Index = m_pEditor->m_lProfiles.size() ;
-
          QList<Account*> accs;
          VCardUtils::mapToPerson(profile,QUrl(profilesDir.path()+'/'+item),&accs);
 
-         ProfileModel::instance()->beginInsertRows(QModelIndex(), m_pEditor->m_lProfiles.size(), m_pEditor->m_lProfiles.size());
-         m_pEditor->m_lProfiles << pro;
-         ProfileModel::instance()->endInsertRows();
+         Node* pro = ProfileModel::instance()->d_ptr->insertProfile(profile);
 
          /* must be done after inserting profile, or else we try to insert to non existing parent */
          foreach(Account* a, accs)
             addAccount(pro,a);
 
-         connect(profile, SIGNAL(changed()), this, SLOT(contactChanged()));
          PersonModel::instance()->addPerson(profile);
       }
 
@@ -412,7 +472,7 @@ bool ProfileContentBackend::reload()
 
 bool ProfileContentBackend::saveAll()
 {
-   for(Node* pro : m_pEditor->m_lProfiles) {
+   foreach (Node* pro, m_pEditor->m_lProfiles) {
       editor<Person>()->save(pro->contact);
    }
    return true;
@@ -460,35 +520,21 @@ QList<Account*> ProfileEditor::getAccountsForProfile(const QString& id)
 
 Node* ProfileEditor::getProfileById(const QByteArray& id)
 {
-   for (Node* p : m_lProfiles) {
+   foreach(Node* p, m_lProfiles) {
       if(p->contact->uid() == id)
          return p;
    }
    return nullptr;
 }
 
-void ProfileContentBackend::contactChanged()
-{
-   Person* c = qobject_cast<Person*>(sender());
-   qDebug() << c->formattedName();
-   qDebug() << "contactChanged!";
-
-   if(m_needSaving) {
-      m_bSaveBuffer << c;
-      QTimer::singleShot(0,this,SLOT(save()));
-   }
-   else
-      m_needSaving = true;
-}
-
 void ProfileContentBackend::save()
 {
-   for (Person* item : m_bSaveBuffer) {
+   foreach (Person* item, m_pEditor->m_bSaveBuffer) {
       qDebug() << "saving:" << item->formattedName();
       editor<Person>()->save(item);
    }
 
-   m_bSaveBuffer.clear();
+   m_pEditor->m_bSaveBuffer.clear();
    m_needSaving = false;
    load();
 }
@@ -500,32 +546,6 @@ ProfileModel* ProfileModel::instance()
    return m_spInstance;
 }
 
-class ProfileModelPrivate final : public QObject {
-   Q_OBJECT
-public:
-   ProfileModelPrivate(ProfileModel* parent);
-   ProfileContentBackend*                 m_pProfileBackend;
-   QStringList m_lMimes;
-   QItemSelectionModel* m_pSelectionModel {nullptr};
-   QItemSelectionModel* m_pSortedProxySelectionModel {nullptr};
-   QSortFilterProxyModel* m_pSortedProxyModel {nullptr};
-
-   //Helpers
-   void updateIndexes();
-   void regenParentIndexes();
-
-private Q_SLOTS:
-   void slotDataChanged(const QModelIndex& tl,const QModelIndex& br);
-   void slotLayoutchanged();
-   void slotDelayedInit();
-   void slotRowsRemoved (const QModelIndex& index, int first, int last);
-   void slotRowsInserted(const QModelIndex& index, int first, int last);
-   void slotRowsMoved   (const QModelIndex& index, int first, int last, const QModelIndex& newPar, int newIdx);
-
-private:
-   ProfileModel* q_ptr;
-};
-
 ProfileModelPrivate::ProfileModelPrivate(ProfileModel* parent) : QObject(parent), q_ptr(parent),m_pProfileBackend(nullptr)
 {
 
@@ -896,11 +916,136 @@ QVariant ProfileModel::headerData(int section, Qt::Orientation orientation, int
    return QVariant();
 }
 
-// bool ProfileModel::addNewProfile(Person* c, CollectionInterface* backend)
-// {
-//    Q_UNUSED(backend);
-//    return d_ptr->m_pProfileBackend->addNew(c);
-// }
+/**
+ * Remove an unused profile
+ *
+ * @return If removing the profile has been successful
+ */
+bool ProfileModel::remove(const QModelIndex& idx)
+{
+   QModelIndex realIdx = idx;
+
+   // Helper to unwind the proxies
+   while(realIdx.isValid() && realIdx.model() != this) {
+      if (qobject_cast<const QAbstractProxyModel*>(realIdx.model()))
+         realIdx = qobject_cast<const QAbstractProxyModel*>(realIdx.model())->mapToSource(realIdx);
+      else {
+         realIdx = QModelIndex();
+         break;
+      }
+   }
+
+   // Ensure it is a profile that can be removed
+   if (!realIdx.isValid()) {
+      qDebug() << "Failed to remove account: invalid index";
+      return false;
+   }
+
+   Node* n = static_cast<Node*>(realIdx.internalPointer());
+
+   if (n->type != Node::Type::PROFILE) {
+      qDebug() << "Failed to remove profile: It is not a profile" << (int)n->type << n->contact << realIdx.data(Qt::DisplayRole);
+      return false;
+   }
+
+   if (n->children.size()) {
+      qDebug() << "Failed to remove profile: It is in use";
+      return false;
+   }
+
+   Q_ASSERT(n->contact);
+
+   // Remove the profile
+   beginRemoveRows(QModelIndex(), n->m_Index, n->m_Index);
+   d_ptr->m_pProfileBackend->disableAndRemove(n->contact);
+   delete n;
+   endRemoveRows();
+
+   return true;
+}
+
+QModelIndex ProfileModelPrivate::addProfile(Person* person, const QString& name)
+{
+   Person* p = nullptr;
+
+   if (person && person->collection() == m_pProfileBackend)
+      return QModelIndex(); //Nothing to do
+   else if (person) {
+      p = new Person(*person);
+      m_pProfileBackend->editor<Person>()->addNew(p);
+   }
+   else {
+      p = new Person(m_pProfileBackend, QString::number(QDateTime::currentDateTime().currentMSecsSinceEpoch()).toUtf8());
+
+      QString profileName = name;
+
+      if (profileName.isEmpty()) {
+         profileName = tr("New profile");
+      }
+
+      p->setFormattedName(profileName);
+
+      m_pProfileBackend->editor<Person>()->addNew(p);
+
+   }
+
+   if (auto n = m_pProfileBackend->m_pEditor->m_hProfileByAccountId[p->uid()]) {
+      return q_ptr->index(n->m_Index, 0);
+   }
+
+   return QModelIndex();
+}
+
+Node* ProfileModelPrivate::insertProfile(Person* p)
+{
+   Node* pro    = new Node           ;
+   pro->type    = Node::Type::PROFILE;
+   pro->contact = p                  ;
+   pro->m_Index = m_pProfileBackend->m_pEditor->m_lProfiles.size();
+
+   m_pProfileBackend->m_pEditor->m_hProfileByAccountId[p->uid()] = pro;
+
+   q_ptr->beginInsertRows({}, m_pProfileBackend->m_pEditor->m_lProfiles.size(), m_pProfileBackend->m_pEditor->m_lProfiles.size());
+   m_pProfileBackend->m_pEditor->m_lProfiles << pro;
+   q_ptr->endInsertRows();
+
+   pro->m_ChangedConn = connect(p, &Person::changed, [this, pro]() {
+      if (pro->contact->isActive()) {
+         const QModelIndex idx = q_ptr->index(pro->m_Index, 0);
+         emit q_ptr->dataChanged(idx, idx);
+
+         //TODO eventually replace with an edition state machine like other models
+         if(m_pProfileBackend->m_needSaving)
+            QTimer::singleShot(0,this,SLOT(m_pProfileBackend->save()));
+         else
+            m_pProfileBackend->m_needSaving = true;
+
+         m_pProfileBackend->m_pEditor->m_bSaveBuffer << pro->contact;
+      }
+   });
+
+   return pro;
+}
+
+/**
+ * Create a new profile
+ *
+ * @param person an optional person to use for the vCard template
+ */
+QModelIndex ProfileModel::add(Person* person)
+{
+   return d_ptr->addProfile(person, QString());
+}
+
+/**
+ * Create a new profile
+ *
+ * @param name The new profile name
+ */
+QModelIndex ProfileModel::add(const QString& name)
+{
+   return d_ptr->addProfile(nullptr, name);
+}
 
 void ProfileModelPrivate::slotDataChanged(const QModelIndex& tl,const QModelIndex& br)
 {
diff --git a/src/profilemodel.h b/src/profilemodel.h
index 65b66d553d5d07e34a776c9528dbfd6a382a9952..000665d94327aa23c583db00f486df6131d98290 100644
--- a/src/profilemodel.h
+++ b/src/profilemodel.h
@@ -36,6 +36,7 @@ template<typename T> class CollectionMediator;
 class LIB_EXPORT ProfileModel : public QAbstractItemModel {
    Q_OBJECT
    friend class ProfileContentBackend;
+   friend class ProfileEditor;
 public:
    explicit ProfileModel(QObject* parent = nullptr);
    virtual ~ProfileModel();
@@ -72,7 +73,8 @@ private:
    static ProfileModel* m_spInstance;
 
 public Q_SLOTS:
-//    bool addNewProfile(Person* c, CollectionInterface* backend = nullptr);
-//    bool createProfile(const QString& name);
+   bool remove(const QModelIndex& idx);
+   QModelIndex add(Person* person = nullptr);
+   QModelIndex add(const QString& name);
 };