This repository has been archived by the owner on Sep 4, 2021. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libcontacts] Move photo handling logic into libcontacts
- Loading branch information
1 parent
ddaa210
commit c98b29a
Showing
3 changed files
with
255 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
/* | ||
* Copyright (C) 2013 Jolla Ltd. | ||
* Contact: Chris Adams <chris.adams@jollamobile.com> | ||
* | ||
* You may use this file under the terms of the BSD license as follows: | ||
* | ||
* "Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are | ||
* met: | ||
* * Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* * Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in | ||
* the documentation and/or other materials provided with the | ||
* distribution. | ||
* * Neither the name of Nemo Mobile nor Jolla Ltd nor the names of its | ||
* contributors may be used to endorse or promote products derived | ||
* from this software without specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
*/ | ||
|
||
#include "seasidephotohandler.h" | ||
|
||
#ifndef QT_VERSION_5 | ||
#include <QDesktopServices> | ||
#include <QContactThumbnail> | ||
#endif | ||
#include <QContactAvatar> | ||
#include <QCryptographicHash> | ||
#include <QDir> | ||
#include <QImage> | ||
|
||
SeasidePhotoHandler::SeasidePhotoHandler() | ||
{ | ||
} | ||
|
||
SeasidePhotoHandler::~SeasidePhotoHandler() | ||
{ | ||
} | ||
|
||
void SeasidePhotoHandler::documentProcessed(const QVersitDocument &, QContact *) | ||
{ | ||
// do nothing, have no state to clean. | ||
} | ||
|
||
void SeasidePhotoHandler::propertyProcessed(const QVersitDocument &, const QVersitProperty &property, const QContact &, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails) | ||
{ | ||
// if the property is a PHOTO property, store the data to disk | ||
// and then create an avatar detail which points to it. | ||
if (property.name().toLower() != QLatin1String("photo")) | ||
return; | ||
|
||
#ifndef QT_VERSION_5 | ||
// The Qt4 / QtMobility version has QContactThumbnail support. | ||
// We need to remove any such thumbnail detail from the output, | ||
// as some backends (such as qtcontacts-sqlite) do not support | ||
// that detail type. | ||
for (int i = 0; i < updatedDetails->size(); ++i) { | ||
if (updatedDetails->at(i).definitionName() == QContactThumbnail::DefinitionName) { | ||
updatedDetails->removeAt(i); | ||
--i; | ||
} | ||
} | ||
#endif | ||
|
||
// The data might be either a URL, a file path, or encoded image data | ||
bool encodedData = false; | ||
foreach (const QString ¶meter, property.parameters().keys()) { | ||
// If there is an 'encoding=' or 'type=' parameter, assume encoded data | ||
if ((parameter.compare(QString::fromLatin1("encoding"), Qt::CaseInsensitive) == 0) || | ||
(parameter.compare(QString::fromLatin1("type"), Qt::CaseInsensitive) == 0)) { | ||
encodedData = true; | ||
break; | ||
} | ||
} | ||
|
||
QUrl url; | ||
|
||
if (!encodedData) { | ||
// Assume the data is a URL | ||
QString path(property.variantValue().toString()); | ||
url = QUrl(path); | ||
|
||
// Treat remote URL as a true URL; local file should be copied into our cache | ||
if (url.isValid() && !url.scheme().isEmpty() && !url.isLocalFile()) { | ||
QContactAvatar newAvatar; | ||
newAvatar.setImageUrl(url); | ||
updatedDetails->append(newAvatar); | ||
|
||
// we have successfully processed this PHOTO property. | ||
*alreadyProcessed = true; | ||
return; | ||
} else { | ||
// See if we can resolve the data as a local file | ||
url = QUrl::fromLocalFile(path); | ||
} | ||
} | ||
|
||
QByteArray photoData; | ||
|
||
if (!encodedData) { | ||
QFile file(url.toLocalFile()); | ||
if (!file.open(QIODevice::ReadOnly)) { | ||
qWarning() << "Unable to process photo data as file:" << property.variantValue().toString(); | ||
return; | ||
} else { | ||
photoData = file.readAll(); | ||
} | ||
} else { | ||
photoData = property.variantValue().toByteArray(); | ||
} | ||
|
||
if (photoData.isEmpty()) { | ||
qWarning() << "Failed to extract avatar data from vCard PHOTO property"; | ||
return; | ||
} | ||
|
||
QImage img; | ||
bool loaded = img.loadFromData(photoData); | ||
if (!loaded) { | ||
qWarning() << "Failed to load avatar image from vCard PHOTO data"; | ||
return; | ||
} | ||
|
||
// We will save the avatar image to disk in the system's data location | ||
// Since we're importing user data, it should not require privileged access | ||
const QString subdirectory(QString::fromLatin1(".local/share/system/Contacts/avatars")); | ||
const QString photoDirPath(QDir::home().filePath(subdirectory)); | ||
|
||
// create the photo file dir if it doesn't exist. | ||
QDir photoDir; | ||
if (!photoDir.mkpath(photoDirPath)) { | ||
qWarning() << "Failed to create avatar image directory when loading avatar image from vCard PHOTO data"; | ||
return; | ||
} | ||
|
||
// construct the filename of the new avatar image. | ||
QString photoFilePath = QString::fromLatin1(QCryptographicHash::hash(photoData, QCryptographicHash::Md5).toHex()); | ||
photoFilePath = photoDirPath + QDir::separator() + photoFilePath + QString::fromLatin1(".jpg"); | ||
|
||
// save the file to disk | ||
bool saved = img.save(photoFilePath); | ||
if (!saved) { | ||
qWarning() << "Failed to save avatar image from vCard PHOTO data to" << photoFilePath; | ||
return; | ||
} | ||
|
||
qWarning() << "Successfully saved avatar image from vCard PHOTO data to" << photoFilePath; | ||
|
||
// save the avatar detail - TODO: mark the avatar as "owned by the contact" (remove on delete) | ||
QContactAvatar newAvatar; | ||
newAvatar.setImageUrl(QUrl::fromLocalFile(photoFilePath)); | ||
updatedDetails->append(newAvatar); | ||
|
||
// we have successfully processed this PHOTO property. | ||
*alreadyProcessed = true; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Copyright (C) 2013 Jolla Ltd. | ||
* Contact: Chris Adams <chris.adams@jollamobile.com> | ||
* | ||
* You may use this file under the terms of the BSD license as follows: | ||
* | ||
* "Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are | ||
* met: | ||
* * Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* * Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in | ||
* the documentation and/or other materials provided with the | ||
* distribution. | ||
* * Neither the name of Nemo Mobile nor Jolla Ltd nor the names of its | ||
* contributors may be used to endorse or promote products derived | ||
* from this software without specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
*/ | ||
|
||
#ifndef PHOTOHANDLER_H | ||
#define PHOTOHANDLER_H | ||
|
||
#include "contactcacheexport.h" | ||
|
||
#include <QString> | ||
#include <QByteArray> | ||
|
||
#include <QContact> | ||
|
||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | ||
# include <QVersitContactImporterPropertyHandlerV2> | ||
#else | ||
# include <QVersitContactImporterPropertyHandler> | ||
#endif | ||
|
||
#include <QVersitResourceHandler> | ||
#include <QVersitDocument> | ||
#include <QVersitProperty> | ||
|
||
#ifdef USING_QTPIM | ||
QTCONTACTS_USE_NAMESPACE | ||
QTVERSIT_USE_NAMESPACE | ||
#else | ||
QTM_USE_NAMESPACE | ||
#endif | ||
|
||
/* | ||
SeasidePhotoHandler | ||
Some backends don't support saving PHOTO data directly. | ||
Instead, the PHOTO data needs to be extracted, saved to | ||
a file, and then the path to the file needs to be saved | ||
to the backend as a contact avatar url detail. | ||
*/ | ||
class CONTACTCACHE_EXPORT SeasidePhotoHandler : public QVersitContactImporterPropertyHandlerV2 | ||
{ | ||
public: | ||
SeasidePhotoHandler(); | ||
~SeasidePhotoHandler(); | ||
|
||
// QVersitContactImporterPropertyHandlerV2 | ||
void documentProcessed(const QVersitDocument &, QContact *); | ||
void propertyProcessed(const QVersitDocument &, const QVersitProperty &property, | ||
const QContact &, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails); | ||
}; | ||
|
||
#endif // PHOTOHANDLER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters