| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2015 The Qt Company Ltd. |
| 4 | ** Contact: http://www.qt.io/licensing/ |
| 5 | ** |
| 6 | ** This file is part of the QtVersit module of the Qt Toolkit. |
| 7 | ** |
| 8 | ** $QT_BEGIN_LICENSE:LGPL21$ |
| 9 | ** Commercial License Usage |
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 11 | ** accordance with the commercial license agreement provided with the |
| 12 | ** Software or, alternatively, in accordance with the terms contained in |
| 13 | ** a written agreement between you and The Qt Company. For licensing terms |
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
| 15 | ** information use the contact form at http://www.qt.io/contact-us. |
| 16 | ** |
| 17 | ** GNU Lesser General Public License Usage |
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
| 19 | ** General Public License version 2.1 or version 3 as published by the Free |
| 20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
| 21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
| 22 | ** following information to ensure the GNU Lesser General Public License |
| 23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
| 24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 25 | ** |
| 26 | ** As a special exception, The Qt Company gives you certain additional |
| 27 | ** rights. These rights are described in The Qt Company LGPL Exception |
| 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 29 | ** |
| 30 | ** $QT_END_LICENSE$ |
| 31 | ** |
| 32 | ****************************************************************************/ |
| 33 | |
| 34 | #include "qversitcontactimporter.h" |
| 35 | #include "qversitcontactimporter_p.h" |
| 36 | |
| 37 | QT_BEGIN_NAMESPACE_VERSIT |
| 38 | |
| 39 | /*! |
| 40 | \deprecated |
| 41 | \class QVersitContactImporterPropertyHandler |
| 42 | \brief The QVersitContactImporterPropertyHandler class is the legacy interface for specifying |
| 43 | custom import behaviour for vCard properties. |
| 44 | |
| 45 | This interface is replaced by QVersitContactImporterPropertyHandlerV2. For general information on |
| 46 | extending Qt Versit, see the document on \l{Qt Versit Plugins}. |
| 47 | |
| 48 | \sa QVersitContactImporter |
| 49 | */ |
| 50 | |
| 51 | /*! |
| 52 | \fn QVersitContactImporterPropertyHandler::~QVersitContactImporterPropertyHandler() |
| 53 | Frees any memory in use by this handler. |
| 54 | */ |
| 55 | |
| 56 | /*! |
| 57 | \fn bool QVersitContactImporterPropertyHandler::preProcessProperty(const QVersitDocument& document, const QVersitProperty& property, int contactIndex, QContact* contact) |
| 58 | Process \a property and update \a contact with the corresponding QContactDetail(s). |
| 59 | \a document provides the context within which the property was found. |
| 60 | \a contactIndex specifies the position that \a contact will take in the list returned by |
| 61 | \l QVersitContactImporter::importDocuments(). |
| 62 | |
| 63 | Returns true if the property has been handled and requires no further processing, false |
| 64 | otherwise. |
| 65 | |
| 66 | This function is called on every QVersitProperty encountered during an import. Supply this |
| 67 | function and return true to implement custom import behaviour. |
| 68 | */ |
| 69 | |
| 70 | /*! |
| 71 | \fn bool QVersitContactImporterPropertyHandler::postProcessProperty(const QVersitDocument& document, const QVersitProperty& property, bool alreadyProcessed, int contactIndex, QContact* contact) |
| 72 | Process \a property and update \a contact with the corresponding QContactDetail(s). |
| 73 | \a document provides the context within which the property was found. |
| 74 | \a contactIndex specifies the position that \a contact will take in the list returned by |
| 75 | \l QVersitContactImporter::importDocuments(). |
| 76 | \a alreadyProcessed is true if the detail has already been processed either by |
| 77 | \l preProcessProperty() or by QVersitContactImporter itself. |
| 78 | |
| 79 | Returns true if the property has been handled, false otherwise. |
| 80 | |
| 81 | This function is called on every QVersitProperty encountered during an import. This can be |
| 82 | used to implement support for vCard properties not supported by QVersitContactImporter. |
| 83 | */ |
| 84 | |
| 85 | /*! |
| 86 | \class QVersitContactImporterPropertyHandlerV2 |
| 87 | \brief The QVersitContactImporterPropertyHandlerV2 class is an interface for specifying |
| 88 | custom import behaviour for vCard properties. |
| 89 | \ingroup versit-extension |
| 90 | \inmodule QtVersit |
| 91 | |
| 92 | This interface supercedes QVersitContactImporterPropertyHandler. For general information on |
| 93 | extending Qt Versit, see the document on \l{Qt Versit Plugins}. |
| 94 | |
| 95 | \sa QVersitContactImporter |
| 96 | */ |
| 97 | |
| 98 | /*! |
| 99 | \fn QVersitContactImporterPropertyHandlerV2::~QVersitContactImporterPropertyHandlerV2() |
| 100 | Frees any memory in use by this handler. |
| 101 | */ |
| 102 | |
| 103 | /*! |
| 104 | \fn void QVersitContactImporterPropertyHandlerV2::propertyProcessed(const QVersitDocument& document, const QVersitProperty& property, const QContact& contact, bool* alreadyProcessed, QList<QContactDetail>* updatedDetails) |
| 105 | Process \a property and provide a list of updated details by adding them to \a updatedDetails. |
| 106 | |
| 107 | This function is called on every QVersitProperty encountered during an import, after the property |
| 108 | has been processed by the QVersitContactImporter. An implementation of this function can be made |
| 109 | to provide support for vCard properties not supported by QVersitContactImporter. |
| 110 | |
| 111 | The supplied \a document is the container for the \a property. \a alreadyProcessed is true if |
| 112 | the QVersitContactImporter or another handler was successful in processing the property. If it is |
| 113 | false and the handler processes the property, it should be set to true to inform later handlers |
| 114 | that the property requires no further processing. \a contact holds the state of the contact |
| 115 | before the property was processed by the importer. \a updatedDetails is initially filled with a |
| 116 | list of details that the importer will update, and can be modified (by removing, modifying or |
| 117 | adding details to the list) |
| 118 | */ |
| 119 | |
| 120 | /*! |
| 121 | \fn void QVersitContactImporterPropertyHandlerV2::documentProcessed(const QVersitDocument& document, QContact* contact) |
| 122 | Perform any final processing on the \a contact generated by the \a document. This can be |
| 123 | implemented by the handler to clear any internal state before moving onto the next document. |
| 124 | |
| 125 | This function is called after all QVersitProperties have been handled by the |
| 126 | QVersitContactImporter. |
| 127 | */ |
| 128 | |
| 129 | /*! |
| 130 | \class QVersitContactImporter |
| 131 | \brief The QVersitContactImporter class converts \l{QVersitDocument}{QVersitDocuments} to |
| 132 | \l{QContact}{QContacts}. |
| 133 | |
| 134 | \ingroup versit |
| 135 | \inmodule QtVersit |
| 136 | |
| 137 | This class is used to convert lists of \l{QVersitDocument}{QVersitDocuments} (which may be |
| 138 | produced by a QVersitReader) to lists of \l{QContact}{QContacts} (which may be saved into a |
| 139 | QContactManager. Unless there is an error, there is a one-to-one mapping between Versit |
| 140 | documents and QContacts. The importer can be extended by clients by associating resource |
| 141 | and property handlers. |
| 142 | |
| 143 | Here is a simple example of how to use QVersitContactImporter: |
| 144 | \snippet qtversitdocsample/qtversitdocsample.cpp Import example |
| 145 | |
| 146 | \section1 Extension via handlers |
| 147 | |
| 148 | A \l QVersitResourceHandler is associated with the importer to supply the behaviour for saving |
| 149 | files to persistent storage. By default, this is set to a \l QVersitDefaultResourceHandler, |
| 150 | which does not save files to persistent storage. Note that photos found in vCards |
| 151 | are not saved to disk by default. If a full-sized image needs to be loaded from a URL |
| 152 | and persisted on disk, a custom QVersitResourceHandler should be supplied which implements this. |
| 153 | |
| 154 | By associating a QVersitContactImporterPropertyHandlerV2 with the importer using |
| 155 | setPropertyHandler(), the client can pass in a handler to override the processing of properties |
| 156 | and/or handle properties that QVersitContactImporter doesn't support. Also, handlers can be |
| 157 | implicitly associated to an importer through the \l{Qt Versit Plugins}{handler plugin mechanism}. |
| 158 | The importer can be constructed with a profile, which gives hints about what kind of handlers |
| 159 | should be added to it. For example, the backup profile can be used to instruct the importer to |
| 160 | interpret properties that have been generated by a backup-profiled QVersitContactExporter. To |
| 161 | illustrate, a backup importer can be constructed with: |
| 162 | \code |
| 163 | QVersitContactImporter importer(QVersitContactHandlerFactory::ProfileBackup); |
| 164 | \endcode |
| 165 | For more details on how the backup plugin works, see \l{Qt Versit Plugins} |
| 166 | |
| 167 | \section1 Importing categories |
| 168 | The importer imports the vCard CATEGORIES property by converting each category to a QContactTag. |
| 169 | Some managers may not have support for QContactTag, but instead support categorization using the |
| 170 | \l{QContactRelationship::HasMember}{HasMember} QContactRelationship along with contacts of type |
| 171 | \l{QContactType::TypeGroup}{TypeGroup}. For these backends, if the categorization information |
| 172 | needs to be retained through group relationships, extra work needs to be done to do the |
| 173 | conversion. Below is some example code that does this translation. |
| 174 | |
| 175 | \snippet qtversitdocsample/qtversitdocsample.cpp Import relationship example |
| 176 | |
| 177 | \sa QVersitDocument, QVersitProperty, QVersitResourceHandler, QVersitContactImporterPropertyHandlerV2 |
| 178 | */ |
| 179 | |
| 180 | /*! |
| 181 | \enum QVersitContactImporter::Error |
| 182 | This enum specifies an error that occurred during the most recent call to importDocuments() |
| 183 | \value NoError The most recent operation was successful |
| 184 | \value InvalidDocumentError One of the documents is not a vCard |
| 185 | \value EmptyDocumentError One of the documents is empty |
| 186 | */ |
| 187 | |
| 188 | |
| 189 | /*! Constructs a new importer */ |
| 190 | QVersitContactImporter::QVersitContactImporter() |
| 191 | : d(new QVersitContactImporterPrivate) |
| 192 | { |
| 193 | } |
| 194 | |
| 195 | /*! |
| 196 | * Constructs a new importer for the given \a profile. The profile strings should be one of those |
| 197 | * defined by QVersitContactHandlerFactory, or a value otherwise agreed to by a \l{Qt Versit |
| 198 | * Plugins}{Versit plugin}. |
| 199 | * |
| 200 | * The profile determines which plugins will be loaded to supplement the importer. |
| 201 | */ |
| 202 | QVersitContactImporter::QVersitContactImporter(const QString& profile) |
| 203 | { |
| 204 | if (profile.isEmpty()) |
| 205 | d = new QVersitContactImporterPrivate(QStringList()); |
| 206 | else |
| 207 | d = new QVersitContactImporterPrivate(QStringList(profile)); |
| 208 | } |
| 209 | |
| 210 | /*! |
| 211 | * Constructs a new importer for the given \a profiles. The profile strings should be one of those |
| 212 | * defined by QVersitContactHandlerFactory, or a value otherwise agreed to by a \l{Qt Versit |
| 213 | * Plugins}{Versit plugin}. |
| 214 | * |
| 215 | * The profiles determine which plugins will be loaded to supplement the importer. |
| 216 | */ |
| 217 | QVersitContactImporter::QVersitContactImporter(const QStringList& profiles) |
| 218 | : d(new QVersitContactImporterPrivate(profiles)) |
| 219 | { |
| 220 | } |
| 221 | |
| 222 | /*! Frees the memory used by the importer */ |
| 223 | QVersitContactImporter::~QVersitContactImporter() |
| 224 | { |
| 225 | delete d; |
| 226 | } |
| 227 | |
| 228 | /*! |
| 229 | * Converts \a documents into a corresponding list of QContacts. After calling this, the converted |
| 230 | * contacts can be retrieved by calling contacts(). |
| 231 | * Returns true on success. If any of the documents cannot be imported as contacts (eg. they aren't |
| 232 | * vCards), false is returned and errorMap() will return a list describing the errors that occurred. |
| 233 | * The successfully imported documents will still be available via contacts(). |
| 234 | * |
| 235 | * \sa contacts(), errorMap() |
| 236 | */ |
| 237 | bool QVersitContactImporter::importDocuments(const QList<QVersitDocument>& documents) |
| 238 | { |
| 239 | int documentIndex = 0; |
| 240 | int contactIndex = 0; |
| 241 | d->mContacts.clear(); |
| 242 | d->mErrors.clear(); |
| 243 | bool ok = true; |
| 244 | foreach (const QVersitDocument& document, documents) { |
| 245 | QContact contact; |
| 246 | QVersitContactImporter::Error error; |
| 247 | if (d->importContact(versitDocument: document, contactIndex, contact: &contact, error: &error)) { |
| 248 | d->mContacts.append(t: contact); |
| 249 | contactIndex++; |
| 250 | } else { |
| 251 | d->mErrors.insert(akey: documentIndex, avalue: error); |
| 252 | ok = false; |
| 253 | } |
| 254 | documentIndex++; |
| 255 | } |
| 256 | |
| 257 | return ok; |
| 258 | } |
| 259 | |
| 260 | /*! |
| 261 | * Returns the contacts imported in the most recent call to importDocuments(). |
| 262 | * |
| 263 | * \sa importDocuments() |
| 264 | */ |
| 265 | QList<QContact> QVersitContactImporter::contacts() const |
| 266 | { |
| 267 | return d->mContacts; |
| 268 | } |
| 269 | |
| 270 | /*! |
| 271 | * \obsolete |
| 272 | * |
| 273 | * Use \l errorMap() instead. |
| 274 | */ |
| 275 | QMap<int, QVersitContactImporter::Error> QVersitContactImporter::errors() const |
| 276 | { |
| 277 | return d->mErrors; |
| 278 | } |
| 279 | |
| 280 | /*! |
| 281 | * Returns the map of errors encountered in the most recent call to importDocuments(). The key is |
| 282 | * the index into the input list of documents and the value is the error that occurred on that |
| 283 | * document. |
| 284 | * |
| 285 | * \sa importDocuments() |
| 286 | */ |
| 287 | QMap<int, QVersitContactImporter::Error> QVersitContactImporter::errorMap() const |
| 288 | { |
| 289 | return d->mErrors; |
| 290 | } |
| 291 | |
| 292 | /*! |
| 293 | * \deprecated |
| 294 | * Sets \a handler to be the handler for processing QVersitProperties, or 0 to have no handler. |
| 295 | * |
| 296 | * Does not take ownership of the handler. The client should ensure the handler remains valid for |
| 297 | * the lifetime of the exporter. This function is used for version 1 handlers. |
| 298 | * |
| 299 | * Only one property handler can be set. If another property handler (of any version) was |
| 300 | * previously set, it will no longer be associated with the importer. |
| 301 | */ |
| 302 | void QVersitContactImporter::setPropertyHandler(QVersitContactImporterPropertyHandler* handler) |
| 303 | { |
| 304 | d->mPropertyHandlerVersion = 1; |
| 305 | d->mPropertyHandler = handler; |
| 306 | d->mPropertyHandler2 = NULL; |
| 307 | } |
| 308 | |
| 309 | /*! |
| 310 | * Sets \a handler to be the handler for processing QVersitProperties, or 0 to have no handler. |
| 311 | * |
| 312 | * Does not take ownership of the handler. The client should ensure the handler remains valid for |
| 313 | * the lifetime of the exporter. This function is used for version 2 and higher handlers. |
| 314 | * |
| 315 | * Only one property handler can be set. If another property handler (of any version) was |
| 316 | * previously set, it will no longer be associated with the importer. |
| 317 | */ |
| 318 | void QVersitContactImporter::setPropertyHandler(QVersitContactImporterPropertyHandlerV2* handler) |
| 319 | { |
| 320 | d->mPropertyHandlerVersion = 2; |
| 321 | d->mPropertyHandler = 0; |
| 322 | d->mPropertyHandler2 = handler; |
| 323 | } |
| 324 | |
| 325 | /*! |
| 326 | * \deprecated |
| 327 | * Gets the handler for processing QVersitProperties. |
| 328 | */ |
| 329 | QVersitContactImporterPropertyHandler* QVersitContactImporter::propertyHandler() const |
| 330 | { |
| 331 | return d->mPropertyHandler; |
| 332 | } |
| 333 | |
| 334 | /*! |
| 335 | * Sets \a handler to be the handler to save files with, or 0 to have no handler. |
| 336 | * |
| 337 | * Does not take ownership of the handler. The client should ensure the handler remains valid for |
| 338 | * the lifetime of the exporter. |
| 339 | */ |
| 340 | void QVersitContactImporter::setResourceHandler(QVersitResourceHandler* handler) |
| 341 | { |
| 342 | d->mResourceHandler = handler; |
| 343 | } |
| 344 | |
| 345 | /*! |
| 346 | * Returns the associated resource handler. |
| 347 | */ |
| 348 | QVersitResourceHandler* QVersitContactImporter::resourceHandler() const |
| 349 | { |
| 350 | return d->mResourceHandler; |
| 351 | } |
| 352 | |
| 353 | QT_END_NAMESPACE_VERSIT |
| 354 | |