Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • release/202005
  • release/202001
  • release/201912
  • release/201911
  • release/releaseWindowsTestOne
  • release/releaseTest
  • release/releaseWindowsTest
  • release/windowsReleaseTest
  • release/201910
  • release/qt/201910
  • release/windows-test/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • 1.0.0
  • 0.3.0
  • 0.2.1
  • 0.2.0
  • 0.1.0
25 results

contactmodel.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    contactmodel.cpp 8.69 KiB
    /****************************************************************************
     *   Copyright (C) 2014 by Savoir-Faire Linux                               *
     *   Author : 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/>.  *
     ***************************************************************************/
    
    //Parent
    #include "contactmodel.h"
    
    //SFLPhone library
    #include "contact.h"
    #include "call.h"
    #include "uri.h"
    #include "phonenumber.h"
    #include "abstractitembackend.h"
    #include "itembackendmodel.h"
    #include "visitors/itemmodelstateserializationvisitor.h"
    
    //Qt
    #include <QtCore/QHash>
    #include <QtCore/QDebug>
    #include <QtCore/QCoreApplication>
    
    ContactModel* ContactModel::m_spInstance = nullptr;
    
    ///Constructor
    ContactModel::ContactModel(QObject* par) : QAbstractItemModel(par?par:QCoreApplication::instance()),
    m_pBackendModel(nullptr)
    {
    }
    
    ///Destructor
    ContactModel::~ContactModel()
    {
       m_hContactsByUid.clear();
       while (m_lContacts.size()) {
          Contact* c = m_lContacts[0];
          m_lContacts.remove(0);
          delete c;
       }
    }
    
    ContactModel* ContactModel::instance() {
       if (!m_spInstance)
          m_spInstance = new ContactModel(QCoreApplication::instance());
       return m_spInstance;
    }
    
    /*****************************************************************************
     *                                                                           *
     *                                   Model                                   *
     *                                                                           *
     ****************************************************************************/
    
    
    bool ContactModel::setData( const QModelIndex& idx, const QVariant &value, int role)
    {
       Q_UNUSED(idx)
       Q_UNUSED(value)
       Q_UNUSED(role)
       return false;
    }
    
    QVariant ContactModel::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 = m_lContacts[idx.row()];
          if (c)
             return QVariant(c->formattedName());
       }
       else if (idx.parent().isValid() && (role == Qt::DisplayRole || role == Qt::EditRole)) {
          const Contact* c = m_lContacts[idx.parent().row()];
          if (c)
             return QVariant(c->phoneNumbers()[idx.row()]->uri());
       }
       return QVariant();
    }
    
    QVariant ContactModel::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 ContactModel::rowCount( const QModelIndex& par ) const
    {
       if (!par.isValid()) {
          return m_lContacts.size();
       }
       else if (!par.parent().isValid() && par.row() < m_lContacts.size()) {
          const Contact* c = m_lContacts[par.row()];
          if (c) {
             const int size = c->phoneNumbers().size();
             return size==1?0:size;
          }
       }
       return 0;
    }
    
    Qt::ItemFlags ContactModel::flags( const QModelIndex& idx ) const
    {
       if (!idx.isValid())
          return Qt::NoItemFlags;
       return Qt::ItemIsEnabled | ((idx.parent().isValid())?Qt::ItemIsSelectable:Qt::ItemIsEnabled);
    }
    
    int ContactModel::columnCount ( const QModelIndex& par) const
    {
       Q_UNUSED(par)
       return 1;
    }
    
    QModelIndex ContactModel::parent( const QModelIndex& idx) const
    {
       if (!idx.isValid())
          return QModelIndex();
       CategorizedCompositeNode* modelItem = (CategorizedCompositeNode*)idx.internalPointer();
       if (modelItem && modelItem->type() == CategorizedCompositeNode::Type::NUMBER) {
          int idx2 = m_lContacts.indexOf(((Contact::PhoneNumbers*)modelItem)->contact());
          if (idx2 != -1) {
             return ContactModel::index(idx2,0,QModelIndex());
          }
       }
       return QModelIndex();
    }
    
    QModelIndex ContactModel::index( int row, int column, const QModelIndex& par) const
    {
       if (!par.isValid() && m_lContacts.size() > row) {
          return createIndex(row,column,m_lContacts[row]);
       }
       else if (par.isValid() && m_lContacts[par.row()]->phoneNumbers().size() > row) {
          return createIndex(row,column,(CategorizedCompositeNode*)(&(m_lContacts[par.row()]->phoneNumbers())));
       }
       return QModelIndex();
    }
    
    /*****************************************************************************
     *                                                                           *
     *                                  Mutator                                  *
     *                                                                           *
     ****************************************************************************/
    
    
    ///Find contact by UID
    Contact* ContactModel::getContactByUid(const QByteArray& uid)
    {
       return m_hContactsByUid[uid];
    }
    
    /**
     * Create a temporary contact or return the existing one for an UID
     * This temporary contact should eventually be merged into the real one
     */
    Contact* ContactModel::getPlaceHolder(const QByteArray& uid )
    {
       Contact* ct = m_hContactsByUid[uid];
    
       //Do not create a placeholder if the real deal exist
       if (ct) {
          return ct;
       }
    
       //Do not re-create if it already exist
       ct = m_hPlaceholders[uid];
       if (ct)
          return ct;
    
       ContactPlaceHolder* ct2 = new ContactPlaceHolder(uid);
    
       m_hPlaceholders[ct2->uid()] = ct2;
       return ct2;
    }
    
    ///Return if there is backends
    bool ContactModel::hasBackends() const
    {
       return m_lBackends.size();
    }
    
    
    const QVector<AbstractContactBackend*> ContactModel::enabledBackends() const
    {
       return m_lBackends;
    }
    
    bool ContactModel::hasEnabledBackends() const
    {
       return m_lBackends.size()>0;
    }
    
    CommonItemBackendModel* ContactModel::backendModel() const
    {
       if (!m_pBackendModel) {
          const_cast<ContactModel*>(this)->m_pBackendModel = new CommonItemBackendModel(const_cast<ContactModel*>(this));
       }
       return m_pBackendModel; //TODO
    }
    
    const QVector<AbstractContactBackend*> ContactModel::backends() const
    {
       return m_lBackends;
    }
    
    bool ContactModel::enableBackend(AbstractContactBackend* backend, bool enabled)
    {
       Q_UNUSED(backend)
       Q_UNUSED(enabled)
       //TODO;
       return false;
    }
    
    bool ContactModel::addContact(Contact* c)
    {
       if (!c)
          return false;
       beginInsertRows(QModelIndex(),m_lContacts.size()-1,m_lContacts.size());
       m_lContacts << c;
       m_hContactsByUid[c->uid()] = c;
    
       //Deprecate the placeholder
       if (m_hPlaceholders.contains(c->uid())) {
          Contact* c2 = m_hPlaceholders[c->uid()];
          if (c2) {
             c2->merge(c);
             m_hPlaceholders[c->uid()] = nullptr;
          }
       }
       endInsertRows();
       emit layoutChanged();
       emit newContactAdded(c);
       return true;
    }
    
    
    void ContactModel::disableContact(Contact* c)
    {
       if (c)
          c->setActive(false);
    }
    
    const ContactList ContactModel::contacts() const
    {
       return m_lContacts;
    }
    
    void ContactModel::addBackend(AbstractContactBackend* backend, LoadOptions options)
    {
       m_lBackends << backend;
       connect(backend,SIGNAL(reloaded()),this,SLOT(slotReloaded()));
       connect(backend,SIGNAL(newContactAdded(Contact*)),this,SLOT(slotContactAdded(Contact*)));
       if (options & LoadOptions::FORCE_ENABLED || ItemModelStateSerializationVisitor::instance()->isChecked(backend))
          backend->load();
       emit newBackendAdded(backend);
    }
    
    bool ContactModel::addNewContact(Contact* c, AbstractContactBackend* backend)
    {
       Q_UNUSED(backend);
       return m_lBackends[0]->addNew(c);
    }
    
    
    /*****************************************************************************
     *                                                                           *
     *                                    Slot                                   *
     *                                                                           *
     ****************************************************************************/
    
    void ContactModel::slotReloaded()
    {
       emit reloaded();
    }
    
    void ContactModel::slotContactAdded(Contact* c)
    {
       addContact(c);
    }