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 "qvcardrestorehandler_p.h" |
35 | |
36 | #include <QtCore/qdatastream.h> |
37 | #include <QtCore/qdatetime.h> |
38 | #include <QtCore/qurl.h> |
39 | |
40 | #include "qversitproperty.h" |
41 | |
42 | /* |
43 | When these conditions are satisfied, QStringLiteral is implemented by |
44 | gcc's statement-expression extension. However, in this file it will |
45 | not work, because "statement-expressions are not allowed outside functions |
46 | nor in template-argument lists". |
47 | |
48 | Fall back to the less-performant QLatin1String in this case. |
49 | */ |
50 | #if defined(QStringLiteral) && defined(QT_UNICODE_LITERAL_II) && defined(Q_CC_GNU) && !defined(Q_COMPILER_LAMBDA) |
51 | # undef QStringLiteral |
52 | # define QStringLiteral QLatin1String |
53 | #endif |
54 | |
55 | QT_BEGIN_NAMESPACE_VERSIT |
56 | |
57 | const QString QVCardRestoreHandler::PropertyName(QStringLiteral("X-NOKIA-QCONTACTFIELD" )); |
58 | const QString QVCardRestoreHandler::DetailTypeParameter(QStringLiteral("DETAIL" )); |
59 | const QString QVCardRestoreHandler::FieldParameter(QStringLiteral("FIELD" )); |
60 | const QString QVCardRestoreHandler::DatatypeParameter(QStringLiteral("DATATYPE" )); |
61 | const QString QVCardRestoreHandler::DatatypeParameterVariant(QStringLiteral("VARIANT" )); |
62 | const QString QVCardRestoreHandler::DatatypeParameterDate(QStringLiteral("DATE" )); |
63 | const QString QVCardRestoreHandler::DatatypeParameterDateTime(QStringLiteral("DATETIME" )); |
64 | const QString QVCardRestoreHandler::DatatypeParameterTime(QStringLiteral("TIME" )); |
65 | const QString QVCardRestoreHandler::DatatypeParameterBool(QStringLiteral("BOOL" )); |
66 | const QString QVCardRestoreHandler::DatatypeParameterInt(QStringLiteral("INT" )); |
67 | const QString QVCardRestoreHandler::DatatypeParameterUInt(QStringLiteral("UINT" )); |
68 | const QString QVCardRestoreHandler::DatatypeParameterUrl(QStringLiteral("URL" )); |
69 | const QString QVCardRestoreHandler::GroupPrefix(QStringLiteral("G" )); |
70 | |
71 | |
72 | /* |
73 | * Returns a list of details generated from a Versit group. |
74 | */ |
75 | QList<QContactDetail> DetailGroupMap::detailsInGroup(const QString& groupName) const |
76 | { |
77 | QList<int> detailIds = mDetailGroupName.keys(avalue: groupName); |
78 | QList<QContactDetail> details; |
79 | foreach (int detailId, detailIds) { |
80 | details << mDetailById[detailId]; |
81 | } |
82 | return details; |
83 | } |
84 | |
85 | /* |
86 | * Inserts the association between \a detail and \a groupName to the map. |
87 | * The detail must have a key (ie. have already been saved in a contact) and the group name must not |
88 | * be the empty string. |
89 | */ |
90 | void DetailGroupMap::insert(const QString& groupName, const QContactDetail& detail) |
91 | { |
92 | Q_ASSERT(!groupName.isEmpty()); |
93 | mDetailGroupName[detail.key()] = groupName; |
94 | mDetailById[detail.key()] = detail; |
95 | } |
96 | |
97 | /* |
98 | * Replaces the detail currently in the map with \a detail. |
99 | * The detail must have a key (ie. have already been saved in a contact). |
100 | */ |
101 | void DetailGroupMap::update(const QContactDetail& detail) |
102 | { |
103 | Q_ASSERT(detail.key()); |
104 | mDetailById[detail.key()] = detail; |
105 | } |
106 | |
107 | /*! |
108 | * Removes details and groups from the map. |
109 | */ |
110 | void DetailGroupMap::clear() |
111 | { |
112 | mDetailGroupName.clear(); |
113 | mDetailById.clear(); |
114 | } |
115 | |
116 | |
117 | |
118 | |
119 | bool QVCardRestoreHandler::propertyProcessed( |
120 | const QVersitProperty& property, |
121 | QList<QContactDetail>* updatedDetails) |
122 | { |
123 | bool success = false; |
124 | QString group; |
125 | if (!property.groups().isEmpty()) |
126 | group = property.groups().first(); |
127 | if (property.name() == PropertyName) { |
128 | if (property.groups().size() != 1) |
129 | return false; |
130 | QMultiHash<QString, QString> parameters = property.parameters(); |
131 | QContactDetail::DetailType detailType = QContactDetail::DetailType(parameters.value(akey: DetailTypeParameter).toUInt()); |
132 | QString fieldName = parameters.value(akey: FieldParameter); |
133 | // Find a detail previously seen with the same definitionName, which was generated from |
134 | // a property from the same group |
135 | QContactDetail detail(detailType); |
136 | foreach (const QContactDetail& previousDetail, mDetailGroupMap.detailsInGroup(group)) { |
137 | if (previousDetail.type() == detailType) { |
138 | detail = previousDetail; |
139 | } |
140 | } |
141 | // If not found, it's a new empty detail with the definitionName set. |
142 | |
143 | detail.setValue(field: fieldName.toInt(), value: deserializeValue(property)); |
144 | |
145 | // Replace the equivalent detail in updatedDetails with the new one |
146 | QMutableListIterator<QContactDetail> it(*updatedDetails); |
147 | while (it.hasNext()) { |
148 | if (it.next().key() == detail.key()) { |
149 | it.remove(); |
150 | break; |
151 | } |
152 | } |
153 | updatedDetails->append(t: detail); |
154 | success = true; |
155 | } |
156 | if (!group.isEmpty()) { |
157 | // Keep track of which details were generated from which Versit groups |
158 | foreach (const QContactDetail& detail, *updatedDetails) { |
159 | mDetailGroupMap.insert(groupName: group, detail); |
160 | } |
161 | } |
162 | return success; |
163 | } |
164 | |
165 | QVariant QVCardRestoreHandler::deserializeValue(const QVersitProperty& property) |
166 | { |
167 | // Import the field |
168 | if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterVariant)) { |
169 | // The value was stored as a QVariant serialized in a QByteArray |
170 | QDataStream stream(property.variantValue().toByteArray()); |
171 | QVariant value; |
172 | stream >> value; |
173 | return value; |
174 | } else if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterDate)) { |
175 | // The value was a QDate serialized as a string |
176 | return QDate::fromString(s: property.value(), f: Qt::ISODate); |
177 | } else if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterTime)) { |
178 | // The value was a QTime serialized as a string |
179 | return QTime::fromString(s: property.value(), f: Qt::ISODate); |
180 | } else if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterDateTime)) { |
181 | // The value was a QDateTime serialized as a string |
182 | return QDateTime::fromString(s: property.value(), f: Qt::ISODate); |
183 | } else if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterBool)) { |
184 | // The value was a bool serialized as a string |
185 | return property.value().toInt() != 0; |
186 | } else if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterInt)) { |
187 | // The value was an int serialized as a string |
188 | return property.value().toInt(); |
189 | } else if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterUInt)) { |
190 | // The value was a uint serialized as a string |
191 | return property.value().toUInt(); |
192 | } else if (property.parameters().contains(key: DatatypeParameter, value: DatatypeParameterUrl)) { |
193 | // The value was a QUrl serialized as a string |
194 | return QUrl(property.value()); |
195 | } else { |
196 | // The value was stored as a QString or QByteArray |
197 | return property.variantValue(); |
198 | } |
199 | } |
200 | |
201 | void QVCardRestoreHandler::documentProcessed() |
202 | { |
203 | mDetailGroupMap.clear(); |
204 | } |
205 | |
206 | QT_END_NAMESPACE_VERSIT |
207 | |