From c2db6c290126cc8a1add4219bbf6b1cb67209e2c Mon Sep 17 00:00:00 2001
From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>
Date: Thu, 6 Feb 2014 16:55:11 -0500
Subject: [PATCH] [ #39729 ] Remove dependency on AkonadiBackend singleton

---
 src/abstractcontactbackend.cpp     | 107 -----------------------------
 src/abstractcontactbackend.h       |   8 +--
 src/contact.cpp                    |  17 ++++-
 src/contact.h                      |  32 +++++----
 src/contactmodel.cpp               |  49 ++++++++++++-
 src/contactmodel.h                 |  25 +++----
 src/contactproxymodel.cpp          |  11 ++-
 src/contactproxymodel.h            |   7 +-
 src/phonedirectorymodel.cpp        |   2 +-
 src/transitionalcontactbackend.cpp |   9 ++-
 src/transitionalcontactbackend.h   |   6 +-
 11 files changed, 109 insertions(+), 164 deletions(-)

diff --git a/src/abstractcontactbackend.cpp b/src/abstractcontactbackend.cpp
index f9d00f68..fa838c08 100644
--- a/src/abstractcontactbackend.cpp
+++ b/src/abstractcontactbackend.cpp
@@ -39,115 +39,8 @@ AbstractContactBackend::AbstractContactBackend(QObject* par) : QObject(par?par:Q
 ///Destructor
 AbstractContactBackend::~AbstractContactBackend()
 {
-//    if (Call::contactBackend() == this)
-//       Call::setContactBackend(nullptr);
-//    foreach (Contact* c,m_ContactByUid) {
-//       delete c;
-//    } //TODO uncomment
 }
 
-///Update slot
-// ContactList AbstractContactBackend::update()
-// {
-//    return update_slot();
-   //TODO do something
-// }
-
-
-/*****************************************************************************
- *                                                                           *
- *                                   Model                                   *
- *                                                                           *
- ****************************************************************************/
-
-
-// bool AbstractContactBackend::setData( const QModelIndex& idx, const QVariant &value, int role)
-// {
-//    Q_UNUSED(idx)
-//    Q_UNUSED(value)
-//    Q_UNUSED(role)
-//    return false;
-// }
-
-// QVariant AbstractContactBackend::data( const QModelIndex& idx, int role) const
-// {
-//    if (!idx.isValid())
-//       return QVariant();
-//    if (!idx.parent().isValid() && (role == Qt::DisplayRole || role == Qt::EditRole)) {
-//       const Contact* c = getContactList()[idx.row()];
-//       if (c)
-//          return QVariant(c->formattedName());
-//    }
-//    else if (idx.parent().isValid() && (role == Qt::DisplayRole || role == Qt::EditRole)) {
-//       const Contact* c = getContactList()[idx.parent().row()];
-//       if (c)
-//          return QVariant(c->phoneNumbers()[idx.row()]->uri());
-//    }
-//    return QVariant();
-// }
-
-// QVariant AbstractContactBackend::headerData(int section, Qt::Orientation orientation, int role) const
-// {
-//    Q_UNUSED(section)
-//    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
-//       return QVariant(tr("Contacts"));
-//    return QVariant();
-// }
-
-// int AbstractContactBackend::rowCount( const QModelIndex& par ) const
-// {
-//    if (!par.isValid()) {
-//       return getContactList().size();
-//    }
-//    else if (!par.parent().isValid() && par.row() < getContactList().size()) {
-//       const Contact* c = getContactList()[par.row()];
-//       if (c) {
-//          const int size = c->phoneNumbers().size();
-//          return size==1?0:size;
-//       }
-//    }
-//    return 0;
-// }
-
-// Qt::ItemFlags AbstractContactBackend::flags( const QModelIndex& idx ) const
-// {
-//    if (!idx.isValid())
-//       return Qt::NoItemFlags;
-//    return Qt::ItemIsEnabled | ((idx.parent().isValid())?Qt::ItemIsSelectable:Qt::ItemIsEnabled);
-// }
-
-// int AbstractContactBackend::columnCount ( const QModelIndex& par) const
-// {
-//    Q_UNUSED(par)
-//    return 1;
-// }
-
-// QModelIndex AbstractContactBackend::parent( const QModelIndex& idx) const
-// {
-//    if (!idx.isValid())
-//       return QModelIndex();
-//    CategorizedCompositeNode* modelItem = (CategorizedCompositeNode*)idx.internalPointer();
-//    if (modelItem && modelItem->type() == CategorizedCompositeNode::Type::NUMBER) {
-//       int idx2 = getContactList().indexOf(((Contact::PhoneNumbers*)modelItem)->contact());
-//       if (idx2 != -1) {
-//          return AbstractContactBackend::index(idx2,0,QModelIndex());
-//       }
-//    }
-//    return QModelIndex();
-// }
-
-// QModelIndex AbstractContactBackend::index( int row, int column, const QModelIndex& par) const
-// {
-//    if (!par.isValid() && getContactList().size() > row) {
-//       return createIndex(row,column,getContactList()[row]);
-//    }
-//    else if (par.isValid() && getContactList()[par.row()]->phoneNumbers().size() > row) {
-//       return createIndex(row,column,(CategorizedCompositeNode*)(&(getContactList()[par.row()]->phoneNumbers())));
-//    }
-//    return QModelIndex();
-// }
-
-
 bool AbstractContactBackend::saveContacts(const QList<Contact*> contacts)
 {
    bool ret = true;
diff --git a/src/abstractcontactbackend.h b/src/abstractcontactbackend.h
index c41d4062..1bf3990d 100644
--- a/src/abstractcontactbackend.h
+++ b/src/abstractcontactbackend.h
@@ -57,16 +57,16 @@ public:
    virtual SupportedFeatures  supportedFeatures() const =0;
 
    ///Edit 'contact', the implementation may be a GUI or somehting else
-   virtual void        editContact       ( Contact*       contact     ) = 0;
+   virtual bool        editContact       ( Contact*       contact     ) = 0;
    ///Add a new contact to the backend
-   virtual void        addNewContact     ( Contact*       contact     ) = 0;
+   virtual bool        addNewContact     ( Contact*       contact     ) = 0;
 
    ///Add a new phone number to an existing contact
-   virtual void addPhoneNumber( Contact*       contact , PhoneNumber* number )=0;
+   virtual bool addPhoneNumber( Contact*       contact , PhoneNumber* number )=0;
 
 
 Q_SIGNALS:
-   void collectionChanged();
+   void reloaded();
    void newContactAdded(Contact* c);
 };
 
diff --git a/src/contact.cpp b/src/contact.cpp
index 7b1e4185..4999be7b 100644
--- a/src/contact.cpp
+++ b/src/contact.cpp
@@ -107,7 +107,7 @@ const QString& Contact::preferredEmail()  const
 }
 
 ///Get the unique identifier (used for drag and drop) 
-const QString& Contact::uid() const
+const QByteArray& Contact::uid() const
 {
    return m_Uid;
 }
@@ -191,7 +191,7 @@ void Contact::setPreferredEmail(const QString& name)
 }
 
 ///Set UID
-void Contact::setUid(const QString& id)
+void Contact::setUid(const QByteArray& id)
 {
    m_Uid = id;
    emit changed();
@@ -281,3 +281,16 @@ bool Contact::save() const
 {
    return m_pBackend->saveContact(this);
 }
+
+///Show an implementation dependant dialog to edit the contact
+bool Contact::edit()
+{
+   return m_pBackend->editContact(this);
+}
+
+///Add a new phone number to the backend
+///@note The backend is expected to notify the Contact (asynchronously) when done
+bool Contact::addPhoneNumber(PhoneNumber* n)
+{
+   return m_pBackend->addPhoneNumber(this,n);
+}
diff --git a/src/contact.h b/src/contact.h
index ccb6d7fa..699fc141 100644
--- a/src/contact.h
+++ b/src/contact.h
@@ -68,7 +68,7 @@ public:
    Q_PROPERTY( QString               secondName     READ secondName     WRITE setFamilyName                          )
    Q_PROPERTY( QString               formattedName  READ formattedName  WRITE setFormattedName                       )
    Q_PROPERTY( QString               organization   READ organization   WRITE setOrganization                        )
-   Q_PROPERTY( QString               uid            READ uid            WRITE setUid                                 )
+   Q_PROPERTY( QByteArray            uid            READ uid            WRITE setUid                                 )
    Q_PROPERTY( QString               preferredEmail READ preferredEmail WRITE setPreferredEmail                      )
 //    Q_PROPERTY( QPixmap*              photo          READ photo          WRITE setPhoto                               )
    Q_PROPERTY( QString               group          READ group          WRITE setGroup                               )
@@ -77,6 +77,8 @@ public:
 
    //Mutator
    Q_INVOKABLE bool save() const;
+   Q_INVOKABLE bool edit()      ;
+   Q_INVOKABLE bool addPhoneNumber(PhoneNumber* n);
 
 private:
    QString      m_FirstName      ;
@@ -86,7 +88,7 @@ private:
    QString      m_FormattedName  ;
    QString      m_PreferredEmail ;
    QString      m_Organization   ;
-   QString      m_Uid            ;
+   QByteArray   m_Uid            ;
    QString      m_Group          ;
    QString      m_Department     ;
    bool         m_DisplayPhoto   ;
@@ -106,7 +108,7 @@ public:
    const QString& secondName       () const;
    const QString& formattedName    () const;
    const QString& organization     () const;
-   const QString& uid              () const;
+   const QByteArray& uid           () const;
    const QString& preferredEmail   () const;
    const QPixmap* photo            () const;
    const QString& group            () const;
@@ -119,18 +121,18 @@ public:
    bool supportPresence            () const;
 
    //Setters
-   void setPhoneNumbers   ( PhoneNumbers        );
-   void setFormattedName  ( const QString& name );
-   void setNickName       ( const QString& name );
-   void setFirstName      ( const QString& name );
-   void setFamilyName     ( const QString& name );
-   void setOrganization   ( const QString& name );
-   void setPreferredEmail ( const QString& name );
-   void setGroup          ( const QString& name );
-   void setDepartment     ( const QString& name );
-   void setUid            ( const QString& id   );
-   void setPhoto          ( QPixmap* photo      );
-   void setActive         ( bool  active        );
+   void setPhoneNumbers   ( PhoneNumbers             );
+   void setFormattedName  ( const QString&    name   );
+   void setNickName       ( const QString&    name   );
+   void setFirstName      ( const QString&    name   );
+   void setFamilyName     ( const QString&    name   );
+   void setOrganization   ( const QString&    name   );
+   void setPreferredEmail ( const QString&    name   );
+   void setGroup          ( const QString&    name   );
+   void setDepartment     ( const QString&    name   );
+   void setUid            ( const QByteArray& id     );
+   void setPhoto          ( QPixmap*          photo  );
+   void setActive         ( bool              active );
 
 private Q_SLOTS:
    void slotPresenceChanged();
diff --git a/src/contactmodel.cpp b/src/contactmodel.cpp
index ff693581..71bd814a 100644
--- a/src/contactmodel.cpp
+++ b/src/contactmodel.cpp
@@ -23,6 +23,7 @@
 #include "contact.h"
 #include "call.h"
 #include "phonenumber.h"
+#include "abstractcontactbackend.h"
 
 //Qt
 #include <QtCore/QHash>
@@ -147,11 +148,17 @@ QModelIndex ContactModel::index( int row, int column, const QModelIndex& par) co
    return QModelIndex();
 }
 
+/*****************************************************************************
+ *                                                                           *
+ *                                  Mutator                                  *
+ *                                                                           *
+ ****************************************************************************/
+
 
 ///Find contact by UID
-Contact* ContactModel::getContactByUid(const QString& uid)
+Contact* ContactModel::getContactByUid(const QByteArray& uid)
 {
-   return m_ContactByUid[uid];
+   return m_hContactsByUid[uid];
 }
 
 ///Return if there is backends
@@ -162,8 +169,14 @@ bool ContactModel::hasBackends() const
 
 bool ContactModel::addContact(Contact* c)
 {
+   if (!c)
+      return false;
+   beginInsertRows(QModelIndex(),m_lContacts.size()-1,m_lContacts.size());
    m_lContacts << c;
-   m_ContactByUid[c->uid()] = c;
+   m_hContactsByUid[c->uid()] = c;
+   endInsertRows();
+   emit layoutChanged();
+   emit newContactAdded(c);
    return true;
 }
 
@@ -178,3 +191,33 @@ const ContactList ContactModel::contacts() const
 {
    return m_lContacts;
 }
+
+void ContactModel::addBackend(AbstractContactBackend* backend)
+{
+   m_lBackends << backend;
+   connect(backend,SIGNAL(reloaded()),this,SLOT(slotReloaded()));
+   connect(backend,SIGNAL(newContactAdded(Contact*)),this,SLOT(slotContactAdded(Contact*)));
+}
+
+bool ContactModel::addNewContact(Contact* c, AbstractContactBackend* backend)
+{
+   Q_UNUSED(backend);
+   return m_lBackends[0]->addNewContact(c);
+}
+
+
+/*****************************************************************************
+ *                                                                           *
+ *                                    Slot                                   *
+ *                                                                           *
+ ****************************************************************************/
+
+void ContactModel::slotReloaded()
+{
+   emit reloaded();
+}
+
+void ContactModel::slotContactAdded(Contact* c)
+{
+   addContact(c);
+}
diff --git a/src/contactmodel.h b/src/contactmodel.h
index 9d9cdc6e..cb312857 100644
--- a/src/contactmodel.h
+++ b/src/contactmodel.h
@@ -64,9 +64,10 @@ public:
    //Mutator
    bool addContact(Contact* c);
    void disableContact(Contact* c);
+   void addBackend(AbstractContactBackend* backend);
 
    //Getters
-   Contact* getContactByUid   ( const QString& uid );
+   Contact* getContactByUid   ( const QByteArray& uid );
    bool     hasBackends       () const;
    const ContactList contacts() const;
 
@@ -83,33 +84,25 @@ public:
    //Singleton
    static ContactModel* instance();
 
-protected:
-//    virtual ContactList update_slot() = 0;
-
-   //Helper
-//    QString getUserFromPhone    (const QString &phoneNumber);
-
-   //Attributes
-   QHash<QString,Contact*>        m_ContactByUid   ;
-   int m_UpdatesCounter;
-
 private:
    //Attributes
    static ContactModel* m_spInstance;
    QList<AbstractContactBackend*> m_lBackends;
+   int m_UpdatesCounter;
 
    //Indexes
    QHash<QByteArray,Contact*> m_hContactsByUid;
    QVector<Contact*> m_lContacts;
 
-// public Q_SLOTS:
-//    ContactList update();
+public Q_SLOTS:
+   bool addNewContact(Contact* c, AbstractContactBackend* backend = nullptr);
 
-// private Q_SLOTS:
-//    void slotReloadModel();
+private Q_SLOTS:
+   void slotReloaded();
+   void slotContactAdded(Contact* c);
 
 Q_SIGNALS:
-   void collectionChanged();
+   void reloaded();
    void newContactAdded(Contact* c);
 };
 
diff --git a/src/contactproxymodel.cpp b/src/contactproxymodel.cpp
index c9e7068e..0dbc34a8 100644
--- a/src/contactproxymodel.cpp
+++ b/src/contactproxymodel.cpp
@@ -24,7 +24,6 @@
 #include <QtCore/QCoreApplication>
 
 //SFLPhone
-#include "abstractcontactbackend.h"
 #include "callmodel.h"
 #include "historymodel.h"
 #include "phonenumber.h"
@@ -136,14 +135,14 @@ void ContactTreeBinder::slotPhoneNumberCountAboutToChange(int count, int oldCoun
 }
 
 //
-ContactProxyModel::ContactProxyModel(AbstractContactBackend* parent,int role, bool showAll) : QAbstractItemModel(QCoreApplication::instance()),
-m_pModel(parent),m_Role(role),m_ShowAll(showAll),m_lCategoryCounter()
+ContactProxyModel::ContactProxyModel(int role, bool showAll) : QAbstractItemModel(QCoreApplication::instance()),
+m_Role(role),m_ShowAll(showAll),m_lCategoryCounter()
 {
    setObjectName("ContactProxyModel");
    m_lCategoryCounter.reserve(32);
    m_lMimes << MIME_PLAIN_TEXT << MIME_PHONENUMBER;
-   connect(m_pModel,SIGNAL(collectionChanged()),this,SLOT(reloadCategories()));
-   connect(m_pModel,SIGNAL(newContactAdded(Contact*)),this,SLOT(slotContactAdded(Contact*)));
+   connect(ContactModel::instance(),SIGNAL(reloaded()),this,SLOT(reloadCategories()));
+   connect(ContactModel::instance(),SIGNAL(newContactAdded(Contact*)),this,SLOT(slotContactAdded(Contact*)));
    QHash<int, QByteArray> roles = roleNames();
    roles.insert(ContactModel::Role::Organization      ,QByteArray("organization")     );
    roles.insert(ContactModel::Role::Group             ,QByteArray("group")            );
@@ -467,7 +466,7 @@ QMimeData* ContactProxyModel::mimeData(const QModelIndexList &indexes) const
                   if (ct->phoneNumbers().size() == 1) {
                      mimeData->setData(MIME_PHONENUMBER , ct->phoneNumbers()[0]->toHash().toUtf8());
                   }
-                  mimeData->setData(MIME_CONTACT , ct->uid().toUtf8());
+                  mimeData->setData(MIME_CONTACT , ct->uid());
                }
                return mimeData;
                } break;
diff --git a/src/contactproxymodel.h b/src/contactproxymodel.h
index 6b315d37..0995a4ec 100644
--- a/src/contactproxymodel.h
+++ b/src/contactproxymodel.h
@@ -25,7 +25,7 @@
 //SFLPhone
 #include "../lib/typedefs.h"
 #include "../lib/contact.h"
-class AbstractContactBackend;
+class ContactModel;
 class ContactTreeNode;
 class TopLevelItem;
 class ContactTreeBinder;
@@ -37,10 +37,10 @@ class LIB_EXPORT ContactProxyModel :  public QAbstractItemModel
    Q_OBJECT
    #pragma GCC diagnostic pop
 public:
-   friend class AbstractContactBackend;
+   friend class ContactModel;
    friend class ContactTreeNode;
    friend class ContactTreeBinder;
-   explicit ContactProxyModel(AbstractContactBackend* parent,int role = Qt::DisplayRole, bool showAll = false);
+   explicit ContactProxyModel(int role = Qt::DisplayRole, bool showAll = false);
    virtual ~ContactProxyModel();
 
    //Setters
@@ -70,7 +70,6 @@ private:
 
    //Attributes
    QHash<Contact*, time_t>      m_hContactByDate   ;
-   AbstractContactBackend*      m_pModel           ;
    QVector<TopLevelItem*>       m_lCategoryCounter ;
    QHash<QString,TopLevelItem*> m_hCategories      ;
    int                          m_Role             ;
diff --git a/src/phonedirectorymodel.cpp b/src/phonedirectorymodel.cpp
index 20e3cd76..5e901eb4 100644
--- a/src/phonedirectorymodel.cpp
+++ b/src/phonedirectorymodel.cpp
@@ -406,7 +406,7 @@ PhoneNumber* PhoneDirectoryModel::fromHash(const QString& hash)
    if (fields.size() == 3) {
       const QString uri = fields[0];
       Account* account = AccountListModel::instance()->getAccountById(fields[1]);
-      Contact* contact = ContactModel::instance()->getContactByUid(fields[2]);
+      Contact* contact = ContactModel::instance()->getContactByUid(fields[2].toUtf8());
       return getNumber(uri,contact,account);
    }
    else if (fields.size() == 1) {
diff --git a/src/transitionalcontactbackend.cpp b/src/transitionalcontactbackend.cpp
index f9ac5bd7..24b0ff66 100644
--- a/src/transitionalcontactbackend.cpp
+++ b/src/transitionalcontactbackend.cpp
@@ -51,20 +51,23 @@ bool TransitionalContactBackend::saveContact(const Contact* contact)
    return false;
 }
 
-void TransitionalContactBackend::editContact( Contact* contact)
+bool TransitionalContactBackend::editContact( Contact* contact)
 {
    Q_UNUSED(contact)
+   return false;
 }
 
-void TransitionalContactBackend::addNewContact( Contact* contact)
+bool TransitionalContactBackend::addNewContact( Contact* contact)
 {
    Q_UNUSED(contact)
+   return false;
 }
 
-void TransitionalContactBackend::addPhoneNumber( Contact* contact , PhoneNumber* number )
+bool TransitionalContactBackend::addPhoneNumber( Contact* contact , PhoneNumber* number )
 {
    Q_UNUSED(contact)
    Q_UNUSED(number)
+   return false;
 }
 
 
diff --git a/src/transitionalcontactbackend.h b/src/transitionalcontactbackend.h
index 4393b862..cf35009e 100644
--- a/src/transitionalcontactbackend.h
+++ b/src/transitionalcontactbackend.h
@@ -37,12 +37,12 @@ public:
    virtual bool saveContact(const Contact* contact);
 
    ///Edit 'contact', the implementation may be a GUI or somehting else
-   virtual void        editContact       ( Contact*       contact     );
+   virtual bool        editContact       ( Contact*       contact     );
    ///Add a new contact to the backend
-   virtual void        addNewContact     ( Contact*       contact     );
+   virtual bool        addNewContact     ( Contact*       contact     );
 
    ///Add a new phone number to an existing contact
-   virtual void addPhoneNumber( Contact*       contact , PhoneNumber* number );
+   virtual bool addPhoneNumber( Contact*       contact , PhoneNumber* number );
 
    SupportedFeatures supportedFeatures() const;
 
-- 
GitLab