38 ** $QT_END_LICENSE$ |
38 ** $QT_END_LICENSE$ |
39 ** |
39 ** |
40 ****************************************************************************/ |
40 ****************************************************************************/ |
41 |
41 |
42 #include "cntsymbiansimengine.h" |
42 #include "cntsymbiansimengine.h" |
43 #include <qtcontacts.h> |
|
44 #include <mmtsy_names.h> |
|
45 |
|
46 #include "cntsymbiansimtransformerror.h" |
43 #include "cntsymbiansimtransformerror.h" |
47 #include "cntsimstore.h" |
44 #include "cntsimstore.h" |
48 #include "cntsimcontactfetchrequest.h" |
45 #include "cntsimcontactfetchrequest.h" |
49 #include "cntsimcontactlocalidfetchrequest.h" |
46 #include "cntsimcontactlocalidfetchrequest.h" |
50 #include "cntsimcontactsaverequest.h" |
47 #include "cntsimcontactsaverequest.h" |
51 #include "cntsimcontactremoverequest.h" |
48 #include "cntsimcontactremoverequest.h" |
52 #include "cntsimdetaildefinitionfetchrequest.h" |
49 #include "cntsimdetaildefinitionfetchrequest.h" |
53 |
50 #include <qtcontacts.h> |
54 #ifdef SYMBIANSIM_BACKEND_USE_ETEL_TESTSERVER |
|
55 #include <mpbutil_etel_test_server.h> |
|
56 #else |
|
57 #include <mpbutil.h> |
|
58 #endif |
|
59 |
51 |
60 #include <QEventLoop> |
52 #include <QEventLoop> |
61 #include <QTimer> |
53 #include <QTimer> |
62 |
54 #include <QDebug> |
63 |
55 |
|
56 const int KRequestTimeout = 30000; // in ms |
64 |
57 |
65 CntSymbianSimEngineData::CntSymbianSimEngineData() |
58 CntSymbianSimEngineData::CntSymbianSimEngineData() |
66 :m_simStore(0) |
59 :m_simStore(0) |
67 { |
60 { |
68 |
61 |
80 qWarning("Dangling async request!"); |
73 qWarning("Dangling async request!"); |
81 } |
74 } |
82 } |
75 } |
83 } |
76 } |
84 |
77 |
85 CntSymbianSimEngine::CntSymbianSimEngine(const QMap<QString, QString>& parameters, QContactManager::Error& error) |
78 CntSymbianSimEngine::CntSymbianSimEngine(const QMap<QString, QString>& parameters, QContactManager::Error* error) |
86 { |
79 { |
87 error = QContactManager::NoError; |
80 *error = QContactManager::NoError; |
88 |
81 |
89 d = new CntSymbianSimEngineData(); |
82 d = new CntSymbianSimEngineData(); |
90 d->m_simStore = new CntSimStore(this, parameters.value(KParameterKeySimStoreName)); |
83 d->m_simStore = new CntSimStore(this, parameters.value(KParameterKeySimStoreName), error); |
|
84 if (*error != QContactManager::NoError) { |
|
85 //qDebug() << "Failed to open SIM store" << error; |
|
86 return; |
|
87 } |
91 |
88 |
92 if(d->m_simStore->storeName() == KParameterValueSimStoreNameSdn) { |
89 if(d->m_simStore->storeName() == KParameterValueSimStoreNameSdn) { |
93 // In case of SDN store we need to check if any SDN contacts exist to |
90 // In case of SDN store we need to check if any SDN contacts exist to |
94 // determine if the store is supported or not |
91 // determine if the store is supported or not |
95 if(d->m_simStore->storeInfo().iUsedEntries == 0) |
92 if(d->m_simStore->storeInfo().iUsedEntries == 0) |
96 error = QContactManager::NotSupportedError; |
93 *error = QContactManager::NotSupportedError; |
97 } |
94 } |
98 } |
95 } |
99 |
96 |
100 CntSymbianSimEngine::CntSymbianSimEngine(const CntSymbianSimEngine &other) |
97 CntSymbianSimEngine::CntSymbianSimEngine(const CntSymbianSimEngine &other) |
101 :d(other.d) |
98 :d(other.d) |
106 CntSymbianSimEngine::~CntSymbianSimEngine() |
103 CntSymbianSimEngine::~CntSymbianSimEngine() |
107 { |
104 { |
108 |
105 |
109 } |
106 } |
110 |
107 |
111 void CntSymbianSimEngine::deref() |
|
112 { |
|
113 delete this; |
|
114 } |
|
115 |
|
116 QString CntSymbianSimEngine::managerName() const |
108 QString CntSymbianSimEngine::managerName() const |
117 { |
109 { |
118 return CNT_SYMBIANSIM_MANAGER_NAME; |
110 return CNT_SYMBIANSIM_MANAGER_NAME; |
119 } |
|
120 |
|
121 /*! |
|
122 * Returns a list of the ids of contacts that match the supplied \a filter. |
|
123 * Any error that occurs will be stored in \a error. |
|
124 */ |
|
125 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const |
|
126 { |
|
127 QContactLocalIdFetchRequest req; |
|
128 req.setSorting(sortOrders); |
|
129 executeRequest(&req, error); |
|
130 return req.ids(); |
|
131 } |
111 } |
132 |
112 |
133 /*! |
113 /*! |
134 * Returns a list of the ids of contacts that match the supplied \a filter, sorted according to the given \a sortOrders. |
114 * Returns a list of the ids of contacts that match the supplied \a filter, sorted according to the given \a sortOrders. |
135 * Any error that occurs will be stored in \a error. Uses the generic (slow) filtering of QContactManagerEngine. |
115 * Any error that occurs will be stored in \a error. Uses the generic (slow) filtering of QContactManagerEngine. |
136 */ |
116 */ |
137 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const |
117 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const |
138 { |
118 { |
139 QContactLocalIdFetchRequest req; |
119 QContactLocalIdFetchRequest req; |
140 req.setFilter(filter); |
120 req.setFilter(filter); |
141 req.setSorting(sortOrders); |
121 req.setSorting(sortOrders); |
142 executeRequest(&req, error); |
122 executeRequest(&req, error); |
143 return req.ids(); |
123 return req.ids(); |
144 } |
124 } |
145 |
125 |
146 QList<QContact> CntSymbianSimEngine::contacts(const QList<QContactSortOrder>& sortOrders, const QStringList& definitionRestrictions, QContactManager::Error& error) const |
126 QList<QContact> CntSymbianSimEngine::contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, const QContactFetchHint& fetchHint, QContactManager::Error* error) const |
147 { |
|
148 QContactFetchRequest req; |
|
149 req.setSorting(sortOrders); |
|
150 req.setDefinitionRestrictions(definitionRestrictions); |
|
151 executeRequest(&req, error); |
|
152 return req.contacts(); |
|
153 } |
|
154 |
|
155 QList<QContact> CntSymbianSimEngine::contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, const QStringList& definitionRestrictions, QContactManager::Error& error) const |
|
156 { |
127 { |
157 QContactFetchRequest req; |
128 QContactFetchRequest req; |
158 req.setFilter(filter); |
129 req.setFilter(filter); |
159 req.setSorting(sortOrders); |
130 req.setSorting(sortOrders); |
160 req.setDefinitionRestrictions(definitionRestrictions); |
131 req.setFetchHint(fetchHint); |
161 executeRequest(&req, error); |
132 executeRequest(&req, error); |
162 return req.contacts(); |
133 return req.contacts(); |
163 } |
134 } |
164 |
135 |
165 /*! |
136 /*! |
169 * \param definitionRestrictions Definition restrictions. |
140 * \param definitionRestrictions Definition restrictions. |
170 * \param error Qt error code. |
141 * \param error Qt error code. |
171 * \return A QContact for the requested QContactLocalId value or 0 if the read |
142 * \return A QContact for the requested QContactLocalId value or 0 if the read |
172 * operation was unsuccessful (e.g. contact not found). |
143 * operation was unsuccessful (e.g. contact not found). |
173 */ |
144 */ |
174 QContact CntSymbianSimEngine::contact(const QContactLocalId& contactId, const QStringList& definitionRestrictions, QContactManager::Error& error) const |
145 QContact CntSymbianSimEngine::contact(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error) const |
175 { |
146 { |
176 QContactFetchRequest req; |
147 QContactFetchRequest req; |
177 QContactLocalIdFilter filter; |
148 QContactLocalIdFilter filter; |
178 filter.setIds(QList<QContactLocalId>() << contactId); |
149 filter.setIds(QList<QContactLocalId>() << contactId); |
179 req.setFilter(filter); |
150 req.setFilter(filter); |
180 req.setDefinitionRestrictions(definitionRestrictions); |
151 req.setFetchHint(fetchHint); |
181 executeRequest(&req, error); |
152 executeRequest(&req, error); |
182 if (req.contacts().count() == 0) |
153 if (req.contacts().count() == 0) |
183 return QContact(); |
154 return QContact(); |
184 return req.contacts().at(0); |
155 return req.contacts().at(0); |
185 } |
156 } |
186 |
157 |
187 QString CntSymbianSimEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error& error) const |
158 QString CntSymbianSimEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error* error) const |
188 { |
159 { |
189 Q_UNUSED(error); |
160 Q_UNUSED(error); |
190 |
161 |
191 QContactName name = contact.detail(QContactName::DefinitionName); |
162 QContactName name = contact.detail(QContactName::DefinitionName); |
192 if(!name.customLabel().isEmpty()) { |
163 if(!name.customLabel().isEmpty()) { |
196 return QString("Unnamed"); |
167 return QString("Unnamed"); |
197 } |
168 } |
198 } |
169 } |
199 |
170 |
200 /*! |
171 /*! |
201 * Saves the contact to the Etel store. Only part of the contact's details |
172 * Saves the contacts to the Etel store. Only part of the contact's details |
202 * can be saved, and some fields may be trimmed to fit to the SIM card. |
173 * can be saved, and some fields may be trimmed to fit to the SIM card. |
203 * |
174 * |
204 * \param contact Contact to be saved. |
175 * \param contacts Contact to be saved. |
205 * \param qtError Qt error code. |
176 * \param qtError Qt error code. |
206 * \return Error status. |
177 * \return Error status. |
207 */ |
178 */ |
208 bool CntSymbianSimEngine::saveContact(QContact* contact, QContactManager::Error& error) |
179 bool CntSymbianSimEngine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error) |
209 { |
|
210 if (!contact) { |
|
211 error = QContactManager::BadArgumentError; |
|
212 return false; |
|
213 } |
|
214 |
|
215 QContactSaveRequest req; |
|
216 req.setContacts(QList<QContact>() << *contact); |
|
217 executeRequest(&req, error); |
|
218 if (req.contacts().count()) |
|
219 *contact = req.contacts().at(0); |
|
220 return (error == QContactManager::NoError); |
|
221 } |
|
222 |
|
223 bool CntSymbianSimEngine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error& error) |
|
224 { |
180 { |
225 if (!contacts) { |
181 if (!contacts) { |
226 error = QContactManager::BadArgumentError; |
182 *error = QContactManager::BadArgumentError; |
227 return false; |
183 return false; |
228 } |
184 } |
229 |
185 |
230 QContactSaveRequest req; |
186 QContactSaveRequest req; |
231 req.setContacts(*contacts); |
187 req.setContacts(*contacts); |
232 executeRequest(&req, error); |
188 executeRequest(&req, error); |
233 if (errorMap) |
189 if (errorMap) |
234 *errorMap = req.errorMap(); |
190 *errorMap = req.errorMap(); |
235 *contacts = req.contacts(); |
191 *contacts = req.contacts(); |
236 return (error == QContactManager::NoError ); |
192 return (*error == QContactManager::NoError ); |
237 } |
193 } |
238 |
194 |
239 /*! |
195 /*! |
240 * Removes the specified contact object from the Etel store. |
196 * Removes the specified contact object from the Etel store. |
241 * |
197 * |
242 * \param contactId Id of the contact to be removed. |
198 * \param contactId Id of the contact to be removed. |
243 * \param qtError Qt error code. |
199 * \param qtError Qt error code. |
244 * \return Error status. |
200 * \return Error status. |
245 */ |
201 */ |
246 bool CntSymbianSimEngine::removeContact(const QContactLocalId& contactId, QContactManager::Error& error) |
202 bool CntSymbianSimEngine::removeContacts(const QList<QContactLocalId>& contactIds, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error) |
247 { |
203 { |
248 QContactRemoveRequest req; |
204 QContactRemoveRequest req; |
249 req.setContactIds(QList<QContactLocalId>() << contactId); |
205 req.setContactIds(contactIds); |
250 return executeRequest(&req, error); |
|
251 } |
|
252 |
|
253 bool CntSymbianSimEngine::removeContacts(QList<QContactLocalId>* contactIds, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error& error) |
|
254 { |
|
255 if (!contactIds) { |
|
256 error = QContactManager::BadArgumentError; |
|
257 return false; |
|
258 } |
|
259 QContactRemoveRequest req; |
|
260 req.setContactIds(*contactIds); |
|
261 executeRequest(&req, error); |
206 executeRequest(&req, error); |
262 if (errorMap) |
207 if (errorMap) |
263 *errorMap = req.errorMap(); |
208 *errorMap = req.errorMap(); |
264 return (error == QContactManager::NoError); |
209 return (*error == QContactManager::NoError); |
265 } |
210 } |
266 |
211 |
267 /*! |
212 /*! |
268 * Returns a map of identifier to detail definition which are valid for contacts whose type is the given \a contactType |
213 * Returns a map of identifier to detail definition which are valid for contacts whose type is the given \a contactType |
269 * which are valid for the contacts in this store |
214 * which are valid for the contacts in this store |
270 */ |
215 */ |
271 QMap<QString, QContactDetailDefinition> CntSymbianSimEngine::detailDefinitions(const QString& contactType, QContactManager::Error& error) const |
216 QMap<QString, QContactDetailDefinition> CntSymbianSimEngine::detailDefinitions(const QString& contactType, QContactManager::Error* error) const |
272 { |
217 { |
273 if (!supportedContactTypes().contains(contactType)) { |
218 if (!supportedContactTypes().contains(contactType)) { |
274 // Should never happen |
219 // Should never happen |
275 error = QContactManager::NotSupportedError; |
220 *error = QContactManager::NotSupportedError; |
276 return QMap<QString, QContactDetailDefinition>(); |
221 return QMap<QString, QContactDetailDefinition>(); |
277 } |
222 } |
278 |
223 |
279 // Get store information |
224 // Get store information |
280 RMobilePhoneBookStore::TMobilePhoneBookInfoV5 storeInfo = d->m_simStore->storeInfo(); |
225 TSimStoreInfo storeInfo = d->m_simStore->storeInfo(); |
281 |
226 |
282 // the map we will eventually return |
227 // the map we will eventually return |
283 QMap<QString, QContactDetailDefinition> retn; |
228 QMap<QString, QContactDetailDefinition> retn; |
284 |
229 |
285 // local variables for reuse |
230 // local variables for reuse |
338 def.setFields(fields); |
283 def.setFields(fields); |
339 def.setUnique(true); |
284 def.setUnique(true); |
340 retn.insert(def.name(), def); |
285 retn.insert(def.name(), def); |
341 |
286 |
342 // email support needs to be checked run-time, because it is SIM specific |
287 // email support needs to be checked run-time, because it is SIM specific |
|
288 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1 |
343 if (storeInfo.iMaxEmailAddr > 0) { |
289 if (storeInfo.iMaxEmailAddr > 0) { |
344 def.setName(QContactEmailAddress::DefinitionName); |
290 def.setName(QContactEmailAddress::DefinitionName); |
345 fields.clear(); |
291 fields.clear(); |
346 f.setDataType(QVariant::String); |
292 f.setDataType(QVariant::String); |
347 f.setAllowableValues(QVariantList()); |
293 f.setAllowableValues(QVariantList()); |
348 fields.insert(QContactEmailAddress::FieldEmailAddress, f); |
294 fields.insert(QContactEmailAddress::FieldEmailAddress, f); |
349 def.setFields(fields); |
295 def.setFields(fields); |
350 def.setUnique(true); |
296 def.setUnique(true); |
351 retn.insert(def.name(), def); |
297 retn.insert(def.name(), def); |
352 } |
298 } |
|
299 #endif |
353 |
300 |
354 // phone number |
301 // phone number |
355 def.setName(QContactPhoneNumber::DefinitionName); |
302 def.setName(QContactPhoneNumber::DefinitionName); |
356 fields.clear(); |
303 fields.clear(); |
357 f.setDataType(QVariant::String); |
304 f.setDataType(QVariant::String); |
358 f.setAllowableValues(QVariantList()); |
305 f.setAllowableValues(QVariantList()); |
359 fields.insert(QContactPhoneNumber::FieldNumber, f); |
306 fields.insert(QContactPhoneNumber::FieldNumber, f); |
360 // TODO: subtypes supported in case a sim contact can have multiple phone numbers? |
307 // TODO: subtypes supported in case a sim contact can have multiple phone numbers? |
361 def.setFields(fields); |
308 def.setFields(fields); |
|
309 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1 |
362 if (storeInfo.iMaxAdditionalNumbers > 0) { |
310 if (storeInfo.iMaxAdditionalNumbers > 0) { |
363 // multiple numbers supported |
311 // multiple numbers supported |
364 def.setUnique(false); |
312 def.setUnique(false); |
365 } else { |
313 } else { |
366 // only one phone number allowed |
314 // only one phone number allowed |
367 def.setUnique(true); |
315 def.setUnique(true); |
368 } |
316 } |
|
317 #else |
|
318 // only one phone number allowed |
|
319 def.setUnique(true); |
|
320 #endif |
369 retn.insert(def.name(), def); |
321 retn.insert(def.name(), def); |
370 |
322 |
371 // nickname support needs to be checked run-time, because it is SIM specific |
323 // nickname support needs to be checked run-time, because it is SIM specific |
|
324 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1 |
372 if (storeInfo.iMaxSecondNames > 0) { |
325 if (storeInfo.iMaxSecondNames > 0) { |
373 def.setName(QContactNickname::DefinitionName); |
326 def.setName(QContactNickname::DefinitionName); |
374 fields.clear(); |
327 fields.clear(); |
375 f.setDataType(QVariant::String); |
328 f.setDataType(QVariant::String); |
376 f.setAllowableValues(QVariantList()); |
329 f.setAllowableValues(QVariantList()); |
377 fields.insert(QContactNickname::FieldNickname, f); |
330 fields.insert(QContactNickname::FieldNickname, f); |
378 def.setFields(fields); |
331 def.setFields(fields); |
379 def.setUnique(true); |
332 def.setUnique(true); |
380 retn.insert(def.name(), def); |
333 retn.insert(def.name(), def); |
381 } |
334 } |
|
335 #endif |
382 |
336 |
383 // name |
337 // name |
384 def.setName(QContactName::DefinitionName); |
338 def.setName(QContactName::DefinitionName); |
385 fields.clear(); |
339 fields.clear(); |
386 f.setDataType(QVariant::String); |
340 f.setDataType(QVariant::String); |
539 * |
498 * |
540 * \param req Request to be run. |
499 * \param req Request to be run. |
541 * \param qtError Qt error code. |
500 * \param qtError Qt error code. |
542 * \return true if succesfull, false if unsuccesfull. |
501 * \return true if succesfull, false if unsuccesfull. |
543 */ |
502 */ |
544 bool CntSymbianSimEngine::executeRequest(QContactAbstractRequest *req, QContactManager::Error& qtError) const |
503 bool CntSymbianSimEngine::executeRequest(QContactAbstractRequest *req, QContactManager::Error* qtError) const |
545 { |
504 { |
|
505 *qtError = QContactManager::NoError; |
|
506 |
546 // TODO: |
507 // TODO: |
547 // Remove this code when threads-branch is merged to master. Then this code |
508 // Remove this code when threads-branch is merged to master. Then this code |
548 // should not be needed because the default implementation at QContactManager |
509 // should not be needed because the default implementation at QContactManager |
549 // is using the asynchronous requests in a similar manner to implement |
510 // is using the asynchronous requests in a similar manner to implement |
550 // the synchronous functions. |
511 // the synchronous functions. |
551 |
512 |
552 // Create a copy engine to workaround this functions const qualifier |
513 // Create a copy engine to workaround this functions const qualifier |
553 CntSymbianSimEngine engine(*this); |
514 CntSymbianSimEngine engine(*this); |
554 |
515 |
555 // Mimic the way how async requests are normally run |
516 // Mimic the way how async requests are normally run |
556 if (engine.startRequest(req)) |
517 if (!engine.startRequest(req)) { |
557 engine.waitForRequestFinished(req, 0); // should we have a timeout? |
518 *qtError = QContactManager::LockedError; |
|
519 } else { |
|
520 if (!engine.waitForRequestFinished(req, KRequestTimeout)) |
|
521 *qtError = QContactManager::UnspecifiedError; // timeout occurred |
|
522 } |
558 engine.requestDestroyed(req); |
523 engine.requestDestroyed(req); |
559 |
524 |
560 qtError = req->error(); |
525 if (req->error()) |
561 return (qtError == QContactManager::NoError); |
526 *qtError = req->error(); |
562 } |
527 |
563 |
528 return (*qtError == QContactManager::NoError); |
564 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error& error) |
529 } |
|
530 |
|
531 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error) |
565 { |
532 { |
566 CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error); |
533 CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error); |
567 if(error != QContactManager::NoError) { |
534 if(*error != QContactManager::NoError) { |
568 delete engine; |
535 delete engine; |
569 return 0; |
536 return 0; |
570 } |
537 } |
571 return engine; |
538 return engine; |
572 } |
539 } |