|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "cntsymbiansimengine.h" |
|
43 #include <qtcontacts.h> |
|
44 #include <mmtsy_names.h> |
|
45 |
|
46 #include "cntsymbiansimtransformerror.h" |
|
47 #include "cntsimstore.h" |
|
48 #include "cntsimcontactfetchrequest.h" |
|
49 #include "cntsimcontactlocalidfetchrequest.h" |
|
50 #include "cntsimcontactsaverequest.h" |
|
51 #include "cntsimcontactremoverequest.h" |
|
52 #include "cntsimdetaildefinitionfetchrequest.h" |
|
53 |
|
54 #ifdef SYMBIANSIM_BACKEND_USE_ETEL_TESTSERVER |
|
55 #include <mpbutil_etel_test_server.h> |
|
56 #else |
|
57 #include <mpbutil.h> |
|
58 #endif |
|
59 |
|
60 #include <QEventLoop> |
|
61 #include <QTimer> |
|
62 |
|
63 |
|
64 |
|
65 CntSymbianSimEngineData::CntSymbianSimEngineData() |
|
66 :m_simStore(0) |
|
67 { |
|
68 |
|
69 } |
|
70 |
|
71 CntSymbianSimEngineData::~CntSymbianSimEngineData() |
|
72 { |
|
73 if (ref == 0) { |
|
74 // Remove all unfinished requests. |
|
75 // If the client has behaved itself then there should be none left. |
|
76 while (m_asyncRequests.size()) { |
|
77 QMap<QContactAbstractRequest *, CntAbstractSimRequest *>::iterator itr = m_asyncRequests.begin(); |
|
78 delete itr.value(); |
|
79 m_asyncRequests.remove(itr.key()); |
|
80 qWarning("Dangling async request!"); |
|
81 } |
|
82 } |
|
83 } |
|
84 |
|
85 CntSymbianSimEngine::CntSymbianSimEngine(const QMap<QString, QString>& parameters, QContactManager::Error& error) |
|
86 { |
|
87 error = QContactManager::NoError; |
|
88 |
|
89 d = new CntSymbianSimEngineData(); |
|
90 d->m_simStore = new CntSimStore(this, parameters.value(KParameterKeySimStoreName)); |
|
91 |
|
92 if(d->m_simStore->storeName() == KParameterValueSimStoreNameSdn) { |
|
93 // In case of SDN store we need to check if any SDN contacts exist to |
|
94 // determine if the store is supported or not |
|
95 if(d->m_simStore->storeInfo().iUsedEntries == 0) |
|
96 error = QContactManager::NotSupportedError; |
|
97 } |
|
98 } |
|
99 |
|
100 CntSymbianSimEngine::CntSymbianSimEngine(const CntSymbianSimEngine &other) |
|
101 :d(other.d) |
|
102 { |
|
103 |
|
104 } |
|
105 |
|
106 CntSymbianSimEngine::~CntSymbianSimEngine() |
|
107 { |
|
108 |
|
109 } |
|
110 |
|
111 void CntSymbianSimEngine::deref() |
|
112 { |
|
113 delete this; |
|
114 } |
|
115 |
|
116 QString CntSymbianSimEngine::managerName() const |
|
117 { |
|
118 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 } |
|
132 |
|
133 /*! |
|
134 * 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. |
|
136 */ |
|
137 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const |
|
138 { |
|
139 QContactLocalIdFetchRequest req; |
|
140 req.setFilter(filter); |
|
141 req.setSorting(sortOrders); |
|
142 executeRequest(&req, error); |
|
143 return req.ids(); |
|
144 } |
|
145 |
|
146 QList<QContact> CntSymbianSimEngine::contacts(const QList<QContactSortOrder>& sortOrders, const QStringList& definitionRestrictions, 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 { |
|
157 QContactFetchRequest req; |
|
158 req.setFilter(filter); |
|
159 req.setSorting(sortOrders); |
|
160 req.setDefinitionRestrictions(definitionRestrictions); |
|
161 executeRequest(&req, error); |
|
162 return req.contacts(); |
|
163 } |
|
164 |
|
165 /*! |
|
166 * Reads a contact from the Etel store. |
|
167 * |
|
168 * \param contactId The Id of the contact to be retrieved. |
|
169 * \param definitionRestrictions Definition restrictions. |
|
170 * \param error Qt error code. |
|
171 * \return A QContact for the requested QContactLocalId value or 0 if the read |
|
172 * operation was unsuccessful (e.g. contact not found). |
|
173 */ |
|
174 QContact CntSymbianSimEngine::contact(const QContactLocalId& contactId, const QStringList& definitionRestrictions, QContactManager::Error& error) const |
|
175 { |
|
176 QContactFetchRequest req; |
|
177 QContactLocalIdFilter filter; |
|
178 filter.setIds(QList<QContactLocalId>() << contactId); |
|
179 req.setFilter(filter); |
|
180 req.setDefinitionRestrictions(definitionRestrictions); |
|
181 executeRequest(&req, error); |
|
182 if (req.contacts().count() == 0) |
|
183 return QContact(); |
|
184 return req.contacts().at(0); |
|
185 } |
|
186 |
|
187 QString CntSymbianSimEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error& error) const |
|
188 { |
|
189 Q_UNUSED(error); |
|
190 |
|
191 QContactName name = contact.detail(QContactName::DefinitionName); |
|
192 if(!name.customLabel().isEmpty()) { |
|
193 return name.customLabel(); |
|
194 } else { |
|
195 // TODO: localize unnamed |
|
196 return QString("Unnamed"); |
|
197 } |
|
198 } |
|
199 |
|
200 /*! |
|
201 * Saves the contact 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. |
|
203 * |
|
204 * \param contact Contact to be saved. |
|
205 * \param qtError Qt error code. |
|
206 * \return Error status. |
|
207 */ |
|
208 bool CntSymbianSimEngine::saveContact(QContact* contact, 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 { |
|
225 if (!contacts) { |
|
226 error = QContactManager::BadArgumentError; |
|
227 return false; |
|
228 } |
|
229 |
|
230 QContactSaveRequest req; |
|
231 req.setContacts(*contacts); |
|
232 executeRequest(&req, error); |
|
233 if (errorMap) |
|
234 *errorMap = req.errorMap(); |
|
235 *contacts = req.contacts(); |
|
236 return (error == QContactManager::NoError ); |
|
237 } |
|
238 |
|
239 /*! |
|
240 * Removes the specified contact object from the Etel store. |
|
241 * |
|
242 * \param contactId Id of the contact to be removed. |
|
243 * \param qtError Qt error code. |
|
244 * \return Error status. |
|
245 */ |
|
246 bool CntSymbianSimEngine::removeContact(const QContactLocalId& contactId, QContactManager::Error& error) |
|
247 { |
|
248 QContactRemoveRequest req; |
|
249 req.setContactIds(QList<QContactLocalId>() << contactId); |
|
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); |
|
262 if (errorMap) |
|
263 *errorMap = req.errorMap(); |
|
264 return (error == QContactManager::NoError); |
|
265 } |
|
266 |
|
267 /*! |
|
268 * 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 |
|
270 */ |
|
271 QMap<QString, QContactDetailDefinition> CntSymbianSimEngine::detailDefinitions(const QString& contactType, QContactManager::Error& error) const |
|
272 { |
|
273 if (!supportedContactTypes().contains(contactType)) { |
|
274 // Should never happen |
|
275 error = QContactManager::NotSupportedError; |
|
276 return QMap<QString, QContactDetailDefinition>(); |
|
277 } |
|
278 |
|
279 // Get store information |
|
280 RMobilePhoneBookStore::TMobilePhoneBookInfoV5 storeInfo = d->m_simStore->storeInfo(); |
|
281 |
|
282 // the map we will eventually return |
|
283 QMap<QString, QContactDetailDefinition> retn; |
|
284 |
|
285 // local variables for reuse |
|
286 QMap<QString, QContactDetailFieldDefinition> fields; |
|
287 QContactDetailFieldDefinition f; |
|
288 QContactDetailDefinition def; |
|
289 QVariantList subTypes; |
|
290 |
|
291 // sync target |
|
292 def.setName(QContactSyncTarget::DefinitionName); |
|
293 fields.clear(); |
|
294 f.setDataType(QVariant::String); |
|
295 subTypes.clear(); |
|
296 subTypes << QString(QLatin1String(KSimSyncTarget)); |
|
297 f.setAllowableValues(subTypes); |
|
298 fields.insert(QContactSyncTarget::FieldSyncTarget, f); |
|
299 def.setFields(fields); |
|
300 def.setUnique(true); |
|
301 retn.insert(def.name(), def); |
|
302 |
|
303 // type |
|
304 def.setName(QContactType::DefinitionName); |
|
305 fields.clear(); |
|
306 f.setDataType(QVariant::String); |
|
307 subTypes.clear(); |
|
308 // groups are not supported |
|
309 subTypes << QString(QLatin1String(QContactType::TypeContact)); |
|
310 f.setAllowableValues(subTypes); |
|
311 fields.insert(QContactType::FieldType, f); // note: NO CONTEXT!! |
|
312 def.setFields(fields); |
|
313 def.setUnique(true); |
|
314 retn.insert(def.name(), def); |
|
315 |
|
316 /* TODO |
|
317 // guid |
|
318 def.setName(QContactGuid::DefinitionName); |
|
319 fields.clear(); |
|
320 f.setDataType(QVariant::String); |
|
321 f.setAllowableValues(QVariantList()); |
|
322 fields.insert(QContactGuid::FieldGuid, f); |
|
323 f.setDataType(QVariant::StringList); |
|
324 f.setAllowableValues(contexts); |
|
325 fields.insert(QContactDetail::FieldContext, f); |
|
326 def.setFields(fields); |
|
327 def.setUnique(false); |
|
328 def.setAccessConstraint(QContactDetailDefinition::CreateOnly); |
|
329 retn.insert(def.name(), def); |
|
330 */ |
|
331 |
|
332 // display label |
|
333 def.setName(QContactDisplayLabel::DefinitionName); |
|
334 fields.clear(); |
|
335 f.setDataType(QVariant::String); |
|
336 f.setAllowableValues(QVariantList()); |
|
337 fields.insert(QContactDisplayLabel::FieldLabel, f); |
|
338 def.setFields(fields); |
|
339 def.setUnique(true); |
|
340 retn.insert(def.name(), def); |
|
341 |
|
342 // email support needs to be checked run-time, because it is SIM specific |
|
343 if (storeInfo.iMaxEmailAddr > 0) { |
|
344 def.setName(QContactEmailAddress::DefinitionName); |
|
345 fields.clear(); |
|
346 f.setDataType(QVariant::String); |
|
347 f.setAllowableValues(QVariantList()); |
|
348 fields.insert(QContactEmailAddress::FieldEmailAddress, f); |
|
349 def.setFields(fields); |
|
350 def.setUnique(true); |
|
351 retn.insert(def.name(), def); |
|
352 } |
|
353 |
|
354 // phone number |
|
355 def.setName(QContactPhoneNumber::DefinitionName); |
|
356 fields.clear(); |
|
357 f.setDataType(QVariant::String); |
|
358 f.setAllowableValues(QVariantList()); |
|
359 fields.insert(QContactPhoneNumber::FieldNumber, f); |
|
360 // TODO: subtypes supported in case a sim contact can have multiple phone numbers? |
|
361 def.setFields(fields); |
|
362 if (storeInfo.iMaxAdditionalNumbers > 0) { |
|
363 // multiple numbers supported |
|
364 def.setUnique(false); |
|
365 } else { |
|
366 // only one phone number allowed |
|
367 def.setUnique(true); |
|
368 } |
|
369 retn.insert(def.name(), def); |
|
370 |
|
371 // nickname support needs to be checked run-time, because it is SIM specific |
|
372 if (storeInfo.iMaxSecondNames > 0) { |
|
373 def.setName(QContactNickname::DefinitionName); |
|
374 fields.clear(); |
|
375 f.setDataType(QVariant::String); |
|
376 f.setAllowableValues(QVariantList()); |
|
377 fields.insert(QContactNickname::FieldNickname, f); |
|
378 def.setFields(fields); |
|
379 def.setUnique(true); |
|
380 retn.insert(def.name(), def); |
|
381 } |
|
382 |
|
383 // name |
|
384 def.setName(QContactName::DefinitionName); |
|
385 fields.clear(); |
|
386 f.setDataType(QVariant::String); |
|
387 f.setAllowableValues(QVariantList()); |
|
388 fields.insert(QContactName::FieldCustomLabel, f); |
|
389 def.setFields(fields); |
|
390 def.setUnique(true); |
|
391 retn.insert(def.name(), def); |
|
392 |
|
393 return retn; |
|
394 } |
|
395 |
|
396 void CntSymbianSimEngine::requestDestroyed(QContactAbstractRequest* req) |
|
397 { |
|
398 if (d->m_asyncRequests.contains(req)) { |
|
399 delete d->m_asyncRequests.take(req); |
|
400 } |
|
401 } |
|
402 |
|
403 bool CntSymbianSimEngine::startRequest(QContactAbstractRequest* req) |
|
404 { |
|
405 // Don't allow two async requests to be active at the same time. |
|
406 // The RMobilePhoneBookStore cannot handle it. |
|
407 foreach (QContactAbstractRequest* r, d->m_asyncRequests.keys()) { |
|
408 if (r->isActive()) { |
|
409 // TODO: Should we set the error for the request also? |
|
410 return false; |
|
411 } |
|
412 } |
|
413 |
|
414 // Check for existing request and start again |
|
415 if (d->m_asyncRequests.contains(req)) { |
|
416 return d->m_asyncRequests.value(req)->start(); |
|
417 } |
|
418 |
|
419 // Existing request not found. Create a new one. |
|
420 CntAbstractSimRequest* simReq = 0; |
|
421 switch (req->type()) |
|
422 { |
|
423 case QContactAbstractRequest::ContactFetchRequest: |
|
424 { |
|
425 QContactFetchRequest* r = static_cast<QContactFetchRequest*>(req); |
|
426 simReq = new CntSimContactFetchRequest(this, r); |
|
427 } |
|
428 break; |
|
429 |
|
430 case QContactAbstractRequest::ContactLocalIdFetchRequest: |
|
431 { |
|
432 QContactLocalIdFetchRequest* r = static_cast<QContactLocalIdFetchRequest*>(req); |
|
433 simReq = new CntSimContactLocalIdFetchRequest(this, r); |
|
434 } |
|
435 break; |
|
436 |
|
437 case QContactAbstractRequest::ContactSaveRequest: |
|
438 { |
|
439 QContactSaveRequest* r = static_cast<QContactSaveRequest*>(req); |
|
440 simReq = new CntSimContactSaveRequest(this, r); |
|
441 } |
|
442 break; |
|
443 |
|
444 case QContactAbstractRequest::ContactRemoveRequest: |
|
445 { |
|
446 QContactRemoveRequest* r = static_cast<QContactRemoveRequest*>(req); |
|
447 simReq = new CntSimContactRemoveRequest(this, r); |
|
448 } |
|
449 break; |
|
450 |
|
451 case QContactAbstractRequest::DetailDefinitionFetchRequest: |
|
452 { |
|
453 QContactDetailDefinitionFetchRequest* r = static_cast<QContactDetailDefinitionFetchRequest*>(req); |
|
454 simReq = new CntSimDetailDefinitionFetchRequest(this, r); |
|
455 } |
|
456 break; |
|
457 |
|
458 case QContactAbstractRequest::DetailDefinitionSaveRequest: |
|
459 case QContactAbstractRequest::DetailDefinitionRemoveRequest: |
|
460 case QContactAbstractRequest::RelationshipFetchRequest: |
|
461 case QContactAbstractRequest::RelationshipSaveRequest: |
|
462 case QContactAbstractRequest::RelationshipRemoveRequest: |
|
463 // fall through. |
|
464 default: // unknown request type. |
|
465 break; |
|
466 } |
|
467 |
|
468 if (simReq) { |
|
469 d->m_asyncRequests.insert(req, simReq); |
|
470 return simReq->start(); |
|
471 } |
|
472 |
|
473 return false; |
|
474 } |
|
475 |
|
476 bool CntSymbianSimEngine::cancelRequest(QContactAbstractRequest* req) |
|
477 { |
|
478 if (d->m_asyncRequests.contains(req)) |
|
479 return d->m_asyncRequests.value(req)->cancel(); |
|
480 return false; |
|
481 } |
|
482 |
|
483 bool CntSymbianSimEngine::waitForRequestFinished(QContactAbstractRequest* req, int msecs) |
|
484 { |
|
485 if (!d->m_asyncRequests.contains(req)) |
|
486 return false; |
|
487 |
|
488 if (req->state() != QContactAbstractRequest::ActiveState) |
|
489 return false; |
|
490 |
|
491 QEventLoop *loop = new QEventLoop(this); |
|
492 QObject::connect(req, SIGNAL(resultsAvailable()), loop, SLOT(quit())); |
|
493 |
|
494 // NOTE: zero means wait forever |
|
495 if (msecs > 0) |
|
496 QTimer::singleShot(msecs, loop, SLOT(quit())); |
|
497 |
|
498 loop->exec(); |
|
499 loop->disconnect(); |
|
500 loop->deleteLater(); |
|
501 |
|
502 return (req->state() == QContactAbstractRequest::FinishedState); |
|
503 } |
|
504 |
|
505 /*! |
|
506 * Returns true if the given feature \a feature is supported by the manager, |
|
507 * for the specified type of contact \a contactType |
|
508 */ |
|
509 bool CntSymbianSimEngine::hasFeature(QContactManager::ManagerFeature feature, const QString& contactType) const |
|
510 { |
|
511 Q_UNUSED(feature); |
|
512 Q_UNUSED(contactType); |
|
513 // We don't support anything in the ManagerFeature |
|
514 return false; |
|
515 } |
|
516 |
|
517 /*! |
|
518 * Returns the list of data types supported by the manager |
|
519 */ |
|
520 QStringList CntSymbianSimEngine::supportedContactTypes() const |
|
521 { |
|
522 // TODO: groups supported by some USIM cards? |
|
523 return QStringList() << QContactType::TypeContact; |
|
524 } |
|
525 |
|
526 void CntSymbianSimEngine::updateDisplayLabel(QContact& contact) const |
|
527 { |
|
528 QContactManager::Error error(QContactManager::NoError); |
|
529 QString label = synthesizedDisplayLabel(contact, error); |
|
530 if(error == QContactManager::NoError) { |
|
531 contact = setContactDisplayLabel(label, contact); |
|
532 } |
|
533 } |
|
534 |
|
535 /*! |
|
536 * Executes an asynchronous request so that it will appear synchronous. This is |
|
537 * used internally in all synchronous functions. This way we only need to |
|
538 * implement the matching asynchronous request. |
|
539 * |
|
540 * \param req Request to be run. |
|
541 * \param qtError Qt error code. |
|
542 * \return true if succesfull, false if unsuccesfull. |
|
543 */ |
|
544 bool CntSymbianSimEngine::executeRequest(QContactAbstractRequest *req, QContactManager::Error& qtError) const |
|
545 { |
|
546 // TODO: |
|
547 // Remove this code when threads-branch is merged to master. Then this code |
|
548 // should not be needed because the default implementation at QContactManager |
|
549 // is using the asynchronous requests in a similar manner to implement |
|
550 // the synchronous functions. |
|
551 |
|
552 // Create a copy engine to workaround this functions const qualifier |
|
553 CntSymbianSimEngine engine(*this); |
|
554 |
|
555 // Mimic the way how async requests are normally run |
|
556 if (engine.startRequest(req)) |
|
557 engine.waitForRequestFinished(req, 0); // should we have a timeout? |
|
558 engine.requestDestroyed(req); |
|
559 |
|
560 qtError = req->error(); |
|
561 return (qtError == QContactManager::NoError); |
|
562 } |
|
563 |
|
564 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error& error) |
|
565 { |
|
566 CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error); |
|
567 if(error != QContactManager::NoError) { |
|
568 delete engine; |
|
569 return 0; |
|
570 } |
|
571 return engine; |
|
572 } |
|
573 |
|
574 QString CntSymbianSimFactory::managerName() const |
|
575 { |
|
576 return CNT_SYMBIANSIM_MANAGER_NAME; |
|
577 } |
|
578 |
|
579 Q_EXPORT_PLUGIN2(mobapicontactspluginsymbiansim, CntSymbianSimFactory); |