Skip to content
Snippets Groups Projects
Commit 39c914fe authored by Emmanuel Lepage Vallee's avatar Emmanuel Lepage Vallee
Browse files

Add a basic fallback vCard person/contacts collection

It currently look in /tmp/vcard/. It will be improved soon.
It is intended for testing on new platforms that lack better
collections. Such as Gnome3, OSX and KDE-Plasma2.

Refs #66483
parent b58302eb
Branches
Tags
No related merge requests found
...@@ -221,6 +221,7 @@ SET( libringclient_LIB_SRCS ...@@ -221,6 +221,7 @@ SET( libringclient_LIB_SRCS
src/transitionalpersonbackend.cpp src/transitionalpersonbackend.cpp
src/collectioninterface.cpp src/collectioninterface.cpp
src/collectioneditor.cpp src/collectioneditor.cpp
src/fallbackpersoncollection.cpp
#Communication #Communication
src/dbus/configurationmanager.cpp src/dbus/configurationmanager.cpp
...@@ -300,6 +301,7 @@ SET( libringclient_LIB_HDRS ...@@ -300,6 +301,7 @@ SET( libringclient_LIB_HDRS
src/collectionmediator.hpp src/collectionmediator.hpp
src/collectioneditor.h src/collectioneditor.h
src/collectioneditor.hpp src/collectioneditor.hpp
src/fallbackpersoncollection.h
) )
SET(libringclient_video_LIB_HDRS SET(libringclient_video_LIB_HDRS
......
...@@ -63,9 +63,13 @@ public: ...@@ -63,9 +63,13 @@ public:
///Edit 'item', the implementation may be a GUI or something else ///Edit 'item', the implementation may be a GUI or something else
virtual bool edit ( T* item ) = 0; virtual bool edit ( T* item ) = 0;
///Add a new item to the backend ///Add a new item to the backend
virtual bool addNew ( T* item ) = 0; virtual bool addNew ( T* item ) = 0;
///Add an existing item to the collection
virtual bool addExisting( T* item ) = 0;
///Add a new phone number to an existing item ///Add a new phone number to an existing item
virtual bool addContactMethod( T* item , ContactMethod* number ); virtual bool addContactMethod( T* item , ContactMethod* number );
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/ ***************************************************************************/
#include <collectionmanagerinterface.h>
template<class T> template<class T>
class CollectionMediatorPrivate class CollectionMediatorPrivate
{ {
......
...@@ -190,8 +190,12 @@ ContactProxyModel::ContactProxyModel(int role) : QAbstractItemModel(QCoreApplica ...@@ -190,8 +190,12 @@ ContactProxyModel::ContactProxyModel(int role) : QAbstractItemModel(QCoreApplica
d_ptr->m_Role = role; d_ptr->m_Role = role;
d_ptr->m_lCategoryCounter.reserve(32); d_ptr->m_lCategoryCounter.reserve(32);
d_ptr->m_lMimes << RingMimes::PLAIN_TEXT << RingMimes::PHONENUMBER; d_ptr->m_lMimes << RingMimes::PLAIN_TEXT << RingMimes::PHONENUMBER;
connect(PersonModel::instance(),SIGNAL(reloaded()),d_ptr.data(),SLOT(reloadCategories())); connect(PersonModel::instance(),SIGNAL(reloaded()),d_ptr.data(),SLOT(reloadCategories()));
connect(PersonModel::instance(),SIGNAL(newContactAdded(Person*)),d_ptr.data(),SLOT(slotContactAdded(Person*))); connect(PersonModel::instance(),SIGNAL(newPersonAdded(Person*)),d_ptr.data(),SLOT(slotContactAdded(Person*)));
for (Person* p : PersonModel::instance()->contacts()) {
d_ptr->slotContactAdded(p);
}
} }
ContactProxyModel::~ContactProxyModel() ContactProxyModel::~ContactProxyModel()
......
...@@ -77,7 +77,7 @@ QByteArray PixmapManipulationDelegate::toByteArray(const QVariant& pxm) ...@@ -77,7 +77,7 @@ QByteArray PixmapManipulationDelegate::toByteArray(const QVariant& pxm)
return QByteArray(); return QByteArray();
} }
QVariant PixmapManipulationDelegate::profilePhoto(const QByteArray& data) QVariant PixmapManipulationDelegate::profilePhoto(const QByteArray& data, const QString& type)
{ {
Q_UNUSED(data) Q_UNUSED(data)
return QVariant(); return QVariant();
......
...@@ -49,7 +49,7 @@ public: ...@@ -49,7 +49,7 @@ public:
virtual QVariant numberCategoryIcon(const QVariant& p, const QSize& size, bool displayPresence = false, bool isPresent = false); virtual QVariant numberCategoryIcon(const QVariant& p, const QSize& size, bool displayPresence = false, bool isPresent = false);
virtual QVariant serurityIssueIcon(const QModelIndex& index); virtual QVariant serurityIssueIcon(const QModelIndex& index);
virtual QByteArray toByteArray(const QVariant& pxm); virtual QByteArray toByteArray(const QVariant& pxm);
virtual QVariant profilePhoto(const QByteArray& data); virtual QVariant profilePhoto(const QByteArray& data, const QString& type = "PNG");
/** /**
* Return the icons associated with the action and its state * Return the icons associated with the action and its state
......
/************************************************************************************
* Copyright (C) 2014-2015 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***********************************************************************************/
#include "fallbackpersoncollection.h"
//Qt
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QHash>
#include <QtCore/QUrl>
#include <QtWidgets/QApplication>
#include <QtCore/QStandardPaths>
//Ring
#include "person.h"
#include "vcardutils.h"
#include "contactmethod.h"
#include "collectioneditor.h"
class FallbackPersonBackendEditor : public CollectionEditor<Person>
{
public:
FallbackPersonBackendEditor(CollectionMediator<Person>* m) : CollectionEditor<Person>(m) {}
virtual bool save ( const Person* item ) override;
virtual bool append ( const Person* item ) override;
virtual bool remove ( Person* item ) override;
virtual bool edit ( Person* item ) override;
virtual bool addNew ( Person* item ) override;
virtual bool addExisting( Person* item ) override;
QVector<Person*> m_lItems;
private:
virtual QVector<Person*> items() const override;
};
class FallbackPersonCollectionPrivate
{
public:
FallbackPersonCollectionPrivate(CollectionMediator<Person>* mediator);
CollectionMediator<Person>* m_pMediator;
};
FallbackPersonCollectionPrivate::FallbackPersonCollectionPrivate(CollectionMediator<Person>* mediator) : m_pMediator(mediator)
{
}
FallbackPersonCollection::FallbackPersonCollection(CollectionMediator<Person>* mediator) :
CollectionInterface(new FallbackPersonBackendEditor(mediator)),d_ptr(new FallbackPersonCollectionPrivate(mediator))
{
}
FallbackPersonCollection::~FallbackPersonCollection()
{
}
bool FallbackPersonBackendEditor::save(const Person* item)
{
QFile file("/tmp/vcard/"+item->uid()+".vcf");
file.open(QIODevice::WriteOnly);
file.write(item->toVCard({}));
file.close();
return true;
}
bool FallbackPersonBackendEditor::append(const Person* item)
{
Q_UNUSED(item)
return false;
}
bool FallbackPersonBackendEditor::remove(Person* item)
{
Q_UNUSED(item)
return false;
}
bool FallbackPersonBackendEditor::edit( Person* item)
{
Q_UNUSED(item)
return false;
}
bool FallbackPersonBackendEditor::addNew( Person* item)
{
Q_UNUSED(item)
return false;
}
bool FallbackPersonBackendEditor::addExisting( Person* item)
{
Q_UNUSED(item)
m_lItems << item;
mediator()->addItem(item);
return true;
}
QVector<Person*> FallbackPersonBackendEditor::items() const
{
return m_lItems;
}
QString FallbackPersonCollection::name () const
{
return QObject::tr("vCard backend");
}
QString FallbackPersonCollection::category () const
{
return QObject::tr("Contacts");
}
QVariant FallbackPersonCollection::icon() const
{
return QVariant();
}
bool FallbackPersonCollection::isEnabled() const
{
return true;
}
bool FallbackPersonCollection::load()
{
bool ok;
QList< Person* > ret = VCardUtils::loadDir(QUrl("/tmp/vcard"),ok);
for(Person* p : ret) {
editor<Person>()->addExisting(p);
}
return true;
}
bool FallbackPersonCollection::reload()
{
return false;
}
CollectionInterface::SupportedFeatures FallbackPersonCollection::supportedFeatures() const
{
return (CollectionInterface::SupportedFeatures) (
CollectionInterface::SupportedFeatures::NONE |
CollectionInterface::SupportedFeatures::LOAD |
CollectionInterface::SupportedFeatures::CLEAR |
// CollectionInterface::SupportedFeatures::REMOVE|
CollectionInterface::SupportedFeatures::ADD );
}
bool FallbackPersonCollection::clear()
{
QDir dir("/tmp/vcard");
for (const QString& file : dir.entryList({"*.vcf"},QDir::Files))
dir.remove(file);
return true;
}
QByteArray FallbackPersonCollection::id() const
{
return "fpc2";
}
/************************************************************************************
* Copyright (C) 2014-2015 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***********************************************************************************/
#ifndef FALLBACKPERSONCOLLECTION_H
#define FALLBACKPERSONCOLLECTION_H
#include <collectioninterface.h>
#include <typedefs.h>
class Call;
class Person;
class FallbackPersonCollectionPrivate;
template<typename T> class CollectionMediator;
/**
* This class is used when no other Person collections are available. It will
* provide a basic collection to add and use Persons/Contacts. It is also
* necessary as some metadata required for elements such as auto completion are
* provided by the Person collections.
*/
class LIB_EXPORT FallbackPersonCollection : public CollectionInterface
{
public:
explicit FallbackPersonCollection(CollectionMediator<Person>* mediator);
virtual ~FallbackPersonCollection();
virtual bool load () override;
virtual bool reload() override;
virtual bool clear () override;
virtual QString name () const override;
virtual QString category () const override;
virtual QVariant icon () const override;
virtual bool isEnabled() const override;
virtual QByteArray id () const override;
virtual SupportedFeatures supportedFeatures() const override;
private:
FallbackPersonCollectionPrivate* d_ptr;
Q_DECLARE_PRIVATE(FallbackPersonCollection)
};
Q_DECLARE_METATYPE(FallbackPersonCollection*)
#endif
...@@ -70,6 +70,7 @@ m_pBackendModel(nullptr) ...@@ -70,6 +70,7 @@ m_pBackendModel(nullptr)
PersonModel::PersonModel(QObject* par) : QAbstractItemModel(par?par:QCoreApplication::instance()), CollectionManagerInterface<Person>(this), PersonModel::PersonModel(QObject* par) : QAbstractItemModel(par?par:QCoreApplication::instance()), CollectionManagerInterface<Person>(this),
d_ptr(new PersonModelPrivate(this)) d_ptr(new PersonModelPrivate(this))
{ {
setObjectName("PersonModel");
} }
///Destructor ///Destructor
...@@ -280,9 +281,12 @@ void PersonModel::backendAddedCallback(CollectionInterface* backend) ...@@ -280,9 +281,12 @@ void PersonModel::backendAddedCallback(CollectionInterface* backend)
bool PersonModel::addItemCallback(Person* c) bool PersonModel::addItemCallback(Person* c)
{ {
beginInsertRows(QModelIndex(),d_ptr->m_lPersons.size()-1,d_ptr->m_lPersons.size()); //Add to the model
beginInsertRows(QModelIndex(),d_ptr->m_lPersons.size(),d_ptr->m_lPersons.size());
d_ptr->m_lPersons << c; d_ptr->m_lPersons << c;
d_ptr->m_hPersonsByUid[c->uid()] = c; d_ptr->m_hPersonsByUid[c->uid()] = c;
endInsertRows();
emit newPersonAdded(c);
//Deprecate the placeholder //Deprecate the placeholder
if (d_ptr->m_hPlaceholders.contains(c->uid())) { if (d_ptr->m_hPlaceholders.contains(c->uid())) {
...@@ -292,9 +296,6 @@ bool PersonModel::addItemCallback(Person* c) ...@@ -292,9 +296,6 @@ bool PersonModel::addItemCallback(Person* c)
d_ptr->m_hPlaceholders[c->uid()] = nullptr; d_ptr->m_hPlaceholders[c->uid()] = nullptr;
} }
} }
endInsertRows();
emit layoutChanged();
emit newPersonAdded(c);
return true; return true;
} }
...@@ -345,8 +346,10 @@ const PersonList PersonModel::contacts() const ...@@ -345,8 +346,10 @@ const PersonList PersonModel::contacts() const
bool PersonModel::addNewPerson(Person* c, CollectionInterface* backend) bool PersonModel::addNewPerson(Person* c, CollectionInterface* backend)
{ {
Q_UNUSED(backend); if ((!backend) || (!backends().size()))
return backends()[0]->editor<Person>()->addNew(c); return false;
return (backend?backend:backends()[0])->editor<Person>()->addNew(c);
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
//Qt //Qt
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QMimeData> #include <QMimeData>
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QPointer> #include <QtCore/QPointer>
...@@ -44,94 +45,6 @@ class Person; ...@@ -44,94 +45,6 @@ class Person;
class Account; class Account;
struct Node; struct Node;
typedef void (VCardMapper:: *mapToProperty)(Person*, const QByteArray&);
struct VCardMapper {
QHash<QByteArray, mapToProperty> m_hHash;
VCardMapper() {
m_hHash[VCardUtils::Property::UID] = &VCardMapper::setUid;
m_hHash[VCardUtils::Property::NAME] = &VCardMapper::setNames;
m_hHash[VCardUtils::Property::FORMATTED_NAME] = &VCardMapper::setFormattedName;
m_hHash[VCardUtils::Property::EMAIL] = &VCardMapper::setEmail;
m_hHash[VCardUtils::Property::ORGANIZATION] = &VCardMapper::setOrganization;
}
void setFormattedName(Person* c, const QByteArray& fn) {
c->setFormattedName(QString::fromUtf8(fn));
}
void setNames(Person* c, const QByteArray& fn) {
QList<QByteArray> splitted = fn.split(';');
c->setFamilyName(splitted[0].trimmed());
c->setFirstName(splitted[1].trimmed());
}
void setUid(Person* c, const QByteArray& fn) {
c->setUid(fn);
}
void setEmail(Person* c, const QByteArray& fn) {
c->setPreferredEmail(fn);
}
void setOrganization(Person* c, const QByteArray& fn) {
c->setOrganization(QString::fromUtf8(fn));
}
void setPhoto(Person* c, const QByteArray& fn) {
qDebug() << fn;
QVariant photo = PixmapManipulationDelegate::instance()->profilePhoto(fn);
c->setPhoto(photo);
}
void addContactMethod(Person* c, const QString& key, const QByteArray& fn) {
Q_UNUSED(c)
Q_UNUSED(key)
qDebug() << fn;
}
void addAddress(Person* c, const QString& key, const QByteArray& fn) {
Person::Address* addr = new Person::Address();
QList<QByteArray> fields = fn.split(VCardUtils::Delimiter::SEPARATOR_TOKEN[0]);
addr->setType (key.split(VCardUtils::Delimiter::SEPARATOR_TOKEN)[1] );
addr->setAddressLine (QString::fromUtf8(fields[2]) );
addr->setCity (QString::fromUtf8(fields[3]) );
addr->setState (QString::fromUtf8(fields[4]) );
addr->setZipCode (QString::fromUtf8(fields[5]) );
addr->setCountry (QString::fromUtf8(fields[6]) );
c->addAddress(addr);
}
bool metacall(Person* c, const QByteArray& key, const QByteArray& value) {
if (!m_hHash[key]) {
if(key.contains(VCardUtils::Property::PHOTO)) {
//key must contain additionnal attributes, we don't need them right now (ENCODING, TYPE...)
setPhoto(c, value);
return true;
}
if(key.contains(VCardUtils::Property::ADDRESS)) {
addAddress(c, key, value);
return true;
}
if(key.contains(VCardUtils::Property::TELEPHONE)) {
addContactMethod(c, key, value);
return true;
}
return false;
}
(this->*(m_hHash[key]))(c,value);
return true;
}
};
static VCardMapper* vc_mapper = new VCardMapper;
class ProfileEditor : public CollectionEditor<Person> class ProfileEditor : public CollectionEditor<Person>
{ {
public: public:
...@@ -142,6 +55,7 @@ public: ...@@ -142,6 +55,7 @@ public:
virtual bool remove ( Person* item ) override; virtual bool remove ( Person* item ) override;
virtual bool edit ( Person* item ) override; virtual bool edit ( Person* item ) override;
virtual bool addNew ( Person* item ) override; virtual bool addNew ( Person* item ) override;
virtual bool addExisting( Person* item ) override;
Node* getProfileById(const QByteArray& id); Node* getProfileById(const QByteArray& id);
QList<Account*> getAccountsForProfile(const QString& id); QList<Account*> getAccountsForProfile(const QString& id);
...@@ -259,6 +173,13 @@ bool ProfileEditor::addNew( Person* contact) ...@@ -259,6 +173,13 @@ bool ProfileEditor::addNew( Person* contact)
return true; return true;
} }
bool ProfileEditor::addExisting( Person* contact)
{
m_lProfilePersons << contact;
mediator()->addItem(contact);
return true;
}
QVector<Person*> ProfileEditor::items() const QVector<Person*> ProfileEditor::items() const
{ {
return m_lProfilePersons; return m_lProfilePersons;
...@@ -373,7 +294,7 @@ void ProfileContentBackend::setupDefaultProfile() ...@@ -373,7 +294,7 @@ void ProfileContentBackend::setupDefaultProfile()
if (orphans.size() && (!m_pDefault)) { if (orphans.size() && (!m_pDefault)) {
qDebug() << "No profile found, creating one"; qDebug() << "No profile found, creating one";
Person* profile = new Person(this); Person* profile = new Person(this);
PersonModel::instance()->addPerson(profile); m_pEditor->addNew(profile);
profile->setFormattedName(tr("Default")); profile->setFormattedName(tr("Default"));
m_pDefault = new Node ; m_pDefault = new Node ;
...@@ -417,18 +338,9 @@ void ProfileContentBackend::loadProfiles() ...@@ -417,18 +338,9 @@ void ProfileContentBackend::loadProfiles()
qDebug() << "Loading vcf from:" << profilesDir; qDebug() << "Loading vcf from:" << profilesDir;
QStringList extensions = QStringList(); QStringList entries = profilesDir.entryList({"*.vcf"}, QDir::Files);
extensions << "*.vcf";
QStringList entries = profilesDir.entryList(extensions, QDir::Files);
foreach (const QString& item , entries) { foreach (const QString& item , entries) {
qDebug() << "Loading profile: " << item;
QFile file(profilesDir.absolutePath()+"/"+item);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Error opening vcard: " << item;
continue;
}
Person* profile = new Person(this); Person* profile = new Person(this);
...@@ -437,34 +349,11 @@ void ProfileContentBackend::loadProfiles() ...@@ -437,34 +349,11 @@ void ProfileContentBackend::loadProfiles()
pro->contact = profile ; pro->contact = profile ;
pro->m_Index = m_pEditor->m_lProfiles.size() ; pro->m_Index = m_pEditor->m_lProfiles.size() ;
const QByteArray all = file.readAll(); Account* acc = nullptr;
VCardUtils::mapToPerson(profile,QUrl(item),&acc);
bool propertyInserted = false; if (acc)
for (const QByteArray& property : all.split('\n')){
qDebug() << "property: " << property;
const QList<QByteArray> splitted = property.split(':');
if(splitted.size() < 2){
qDebug() << "Property malformed!";
continue;
}
propertyInserted = vc_mapper->metacall(profile,splitted[0],splitted[1].trimmed());
if(!propertyInserted)
qDebug() << "Could not extract: " << splitted[0];
//Link with accounts
if(splitted[0] == VCardUtils::Property::X_RINGACCOUNT) {
Account* acc = AccountModel::instance()->getById(splitted[1].trimmed(),true);
if(!acc) {
qDebug() << "Could not find account: " << splitted[1].trimmed();
continue;
}
addAccount(pro,acc); addAccount(pro,acc);
}
}
ProfileModel::instance()->beginInsertRows(QModelIndex(), m_pEditor->m_lProfiles.size(), m_pEditor->m_lProfiles.size()); ProfileModel::instance()->beginInsertRows(QModelIndex(), m_pEditor->m_lProfiles.size(), m_pEditor->m_lProfiles.size());
m_pEditor->m_lProfiles << pro; m_pEditor->m_lProfiles << pro;
ProfileModel::instance()->endInsertRows(); ProfileModel::instance()->endInsertRows();
......
...@@ -34,6 +34,7 @@ public: ...@@ -34,6 +34,7 @@ public:
virtual bool remove ( Person* item ) override; virtual bool remove ( Person* item ) override;
virtual bool edit ( Person* item ) override; virtual bool edit ( Person* item ) override;
virtual bool addNew ( Person* item ) override; virtual bool addNew ( Person* item ) override;
virtual bool addExisting( Person* item ) override;
private: private:
virtual QVector<Person*> items() const override; virtual QVector<Person*> items() const override;
...@@ -69,6 +70,13 @@ bool TransitionalPersonEditor::addNew( Person* item) ...@@ -69,6 +70,13 @@ bool TransitionalPersonEditor::addNew( Person* item)
return false; return false;
} }
bool TransitionalPersonEditor::addExisting( Person* item)
{
Q_UNUSED(item)
return false;
}
QVector<Person*> TransitionalPersonEditor::items() const QVector<Person*> TransitionalPersonEditor::items() const
{ {
return QVector<Person*>(); return QVector<Person*>();
......
...@@ -17,7 +17,23 @@ ...@@ -17,7 +17,23 @@
***************************************************************************/ ***************************************************************************/
#include "vcardutils.h" #include "vcardutils.h"
#include <QBuffer>
//Qt
#include <QtCore/QBuffer>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QUrl>
//Ring
#include "phonedirectorymodel.h"
#include "contactmethod.h"
#include "accountmodel.h"
#include "delegates/pixmapmanipulationdelegate.h"
/* https://www.ietf.org/rfc/rfc2045.txt
* https://www.ietf.org/rfc/rfc2047.txt
* https://www.ietf.org/rfc/rfc2426.txt
*/
//BEGIN:VCARD //BEGIN:VCARD
//VERSION:3.0 //VERSION:3.0
...@@ -36,6 +52,118 @@ ...@@ -36,6 +52,118 @@
//REV:20080424T195243Z //REV:20080424T195243Z
//END:VCARD //END:VCARD
struct VCardMapper;
typedef void (VCardMapper:: *mapToProperty)(Person*, const QByteArray&);
struct VCardMapper {
QHash<QByteArray, mapToProperty> m_hHash;
VCardMapper() {
m_hHash[VCardUtils::Property::UID] = &VCardMapper::setUid;
m_hHash[VCardUtils::Property::NAME] = &VCardMapper::setNames;
m_hHash[VCardUtils::Property::FORMATTED_NAME] = &VCardMapper::setFormattedName;
m_hHash[VCardUtils::Property::EMAIL] = &VCardMapper::setEmail;
m_hHash[VCardUtils::Property::ORGANIZATION] = &VCardMapper::setOrganization;
}
void setFormattedName(Person* c, const QByteArray& fn) {
c->setFormattedName(QString::fromUtf8(fn));
}
void setNames(Person* c, const QByteArray& fn) {
QList<QByteArray> splitted = fn.split(';');
c->setFamilyName(splitted[0].trimmed());
c->setFirstName(splitted[1].trimmed());
}
void setUid(Person* c, const QByteArray& fn) {
c->setUid(fn);
}
void setEmail(Person* c, const QByteArray& fn) {
c->setPreferredEmail(fn);
}
void setOrganization(Person* c, const QByteArray& fn) {
c->setOrganization(QString::fromUtf8(fn));
}
void setPhoto(Person* c, const QByteArray& fn, const QByteArray& key) {
QByteArray type = "PNG";
QRegExp rx("TYPE=([A-Za-z]*)");
while ((rx.indexIn(key, 0)) != -1) {
type = rx.cap(1).toLatin1();
break;
}
QVariant photo = PixmapManipulationDelegate::instance()->profilePhoto(fn,type);
c->setPhoto(photo);
}
void addContactMethod(Person* c, const QString& key, const QByteArray& fn) {
Q_UNUSED(c)
Q_UNUSED(key)
QByteArray type;
QRegExp rx("TYPE=([A-Za-z,]*)");
while ((rx.indexIn(key, 0)) != -1) {
type = rx.cap(1).toLatin1();
break;
}
const QStringList categories = QString(type).split(',');
ContactMethod* cm = PhoneDirectoryModel::instance()->getNumber(fn,c,nullptr,categories.size()?categories[0]:QString());
Person::ContactMethods m = c->phoneNumbers();
m << cm;
c->setContactMethods(m);
}
void addAddress(Person* c, const QString& key, const QByteArray& fn) {
Person::Address* addr = new Person::Address();
QList<QByteArray> fields = fn.split(VCardUtils::Delimiter::SEPARATOR_TOKEN[0]);
addr->setType (key.split(VCardUtils::Delimiter::SEPARATOR_TOKEN)[1] );
addr->setAddressLine (QString::fromUtf8(fields[2]) );
addr->setCity (QString::fromUtf8(fields[3]) );
addr->setState (QString::fromUtf8(fields[4]) );
addr->setZipCode (QString::fromUtf8(fields[5]) );
addr->setCountry (QString::fromUtf8(fields[6]) );
c->addAddress(addr);
}
bool metacall(Person* c, const QByteArray& key, const QByteArray& value) {
if (!m_hHash[key]) {
if(key.contains(VCardUtils::Property::PHOTO)) {
//key must contain additionnal attributes, we don't need them right now (ENCODING, TYPE...)
setPhoto(c, value, key);
return true;
}
if(key.contains(VCardUtils::Property::ADDRESS)) {
addAddress(c, key, value);
return true;
}
if(key.contains(VCardUtils::Property::TELEPHONE)) {
addContactMethod(c, key, value);
return true;
}
return false;
}
(this->*(m_hHash[key]))(c,value);
return true;
}
};
static VCardMapper* vc_mapper = new VCardMapper;
VCardUtils::VCardUtils() VCardUtils::VCardUtils()
{ {
...@@ -115,3 +243,82 @@ const QByteArray VCardUtils::endVCard() ...@@ -115,3 +243,82 @@ const QByteArray VCardUtils::endVCard()
const QString result = m_vCard.join(QString::fromUtf8(Delimiter::END_LINE_TOKEN)); const QString result = m_vCard.join(QString::fromUtf8(Delimiter::END_LINE_TOKEN));
return result.toUtf8(); return result.toUtf8();
} }
QList< Person* > VCardUtils::loadDir (const QUrl& path, bool& ok)
{
QList< Person* > ret;
QDir dir(path.toString());
if (!dir.exists())
ok = false;
else {
ok = true;
for (const QString& file : dir.entryList({"*.vcf"},QDir::Files)) {
Person* p = new Person();
mapToPerson(p,QUrl(dir.absoluteFilePath(file)));
ret << p;
}
}
return ret;
}
bool VCardUtils::mapToPerson(Person* p, const QUrl& path, Account** a)
{
qDebug() << "file" << path.toString();
QFile file(path.toString());
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Error opening vcard: " << path;
return false;
}
const QByteArray all = file.readAll();
// bool propertyInserted = false;
QByteArray previousKey,previousValue;
for (const QByteArray& property : all.split('\n')) {
//Ignore empty lines
if (property.size()) {
//Some properties are over multiple lines
if (property[0] == ' ' && previousKey.size()) {
previousValue += property.right(property.size()-1);
}
else {
if (previousKey.size()) {
/*propertyInserted = */vc_mapper->metacall(p,previousKey,previousValue.trimmed());
// if(!propertyInserted)
// qDebug() << "Could not extract: " << previousKey;
}
const QList<QByteArray> splitted = property.split(':');
if(splitted.size() < 2){
qDebug() << "Malformed vCard property!" << splitted[0] << property[0] << (property[0] == ' ');
continue;
}
//Link with accounts
if(splitted[0] == VCardUtils::Property::X_RINGACCOUNT) {
if (a) {
*a = AccountModel::instance()->getById(splitted[1].trimmed(),true);
if(!*a) {
qDebug() << "Could not find account: " << splitted[1].trimmed();
continue;
}
}
}
previousKey = splitted[0];
previousValue = splitted[1];
}
}
}
return true;
}
...@@ -78,6 +78,12 @@ public: ...@@ -78,6 +78,12 @@ public:
void addPhoto(const QByteArray img); void addPhoto(const QByteArray img);
const QByteArray endVCard(); const QByteArray endVCard();
//Loading
static QList<Person*> loadDir(const QUrl& path, bool& ok);
//Mapping
static bool mapToPerson(Person* p, const QUrl& url, Account** a = nullptr);
private: private:
//Attributes //Attributes
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment