|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 @released |
|
20 */ |
|
21 #include "cntpplviewmanager.h" |
|
22 #include "dbsqlconstants.h" |
|
23 #include "cntpersistenceutility.h" |
|
24 #include <cntfldst.h> |
|
25 |
|
26 const TInt KCachedPrepareTimeOut = 1000000; //1 second |
|
27 |
|
28 /** |
|
29 Object factory method. |
|
30 */ |
|
31 CCntPplViewSession* CCntPplViewSession::NewL(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, const CContactTextDef& aTextDef, const TContactViewPreferences aViewPrefs) |
|
32 { |
|
33 CCntPplViewSession* viewSession = new (ELeave) CCntPplViewSession(aContactsFile, aContactProperties, aSelectAllFields, aViewId, aViewPrefs); |
|
34 CleanupStack::PushL(viewSession); |
|
35 viewSession->ConstructL(aTextDef); |
|
36 CleanupStack::Pop(viewSession); |
|
37 return viewSession; |
|
38 } |
|
39 |
|
40 |
|
41 /** |
|
42 CCntPplViewSession first phase constructor. |
|
43 */ |
|
44 CCntPplViewSession::CCntPplViewSession(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, TContactViewPreferences aViewPrefs) |
|
45 : CTimer(CActive::EPriorityIdle), |
|
46 iViewId(aViewId), |
|
47 iContactProperties(aContactProperties), |
|
48 iContactsFile(aContactsFile), |
|
49 iSqlSmtSelectAllFieldsById(aSelectAllFields), |
|
50 iViewPrefs(aViewPrefs), |
|
51 iRSqlStatementReady(EFalse), |
|
52 iCachedSqlStatementReady(EFalse) |
|
53 { |
|
54 CActiveScheduler::Add(this); |
|
55 } |
|
56 |
|
57 |
|
58 /** |
|
59 CCntPplViewSession destructor. |
|
60 */ |
|
61 CCntPplViewSession::~CCntPplViewSession() |
|
62 { |
|
63 Deque(); |
|
64 iContactsFile.RemoveSqlDBObserverL( *this ); |
|
65 if ( iRSqlStatementReady ) |
|
66 { |
|
67 iRSqlStatement.Close(); |
|
68 iRSqlStatementReady = EFalse; |
|
69 } |
|
70 |
|
71 if ( iCachedSqlStatementReady ) |
|
72 { |
|
73 iCachedSqlStatement.Close(); |
|
74 iCachedSqlStatementReady = EFalse; |
|
75 } |
|
76 |
|
77 delete iCntSqlStatement; |
|
78 delete iTextDef; |
|
79 } |
|
80 |
|
81 |
|
82 /** |
|
83 CCntPplViewSession second phase constructor. |
|
84 */ |
|
85 void CCntPplViewSession::ConstructL(const CContactTextDef& aTextDef) |
|
86 { |
|
87 //Constructing iCntSqlStatement, iTextDef, and iIsFastAccessFieldsOnly |
|
88 //by simply call ChangeSortOrderL |
|
89 CTimer::ConstructL(); |
|
90 iContactsFile.AddSqlDBObserverL( *this ); |
|
91 ChangeSortOrderL( aTextDef ); |
|
92 } |
|
93 |
|
94 |
|
95 /** |
|
96 Change the sorting order/text definition. It should be always called when |
|
97 there is not an iteration started in persistence layer. |
|
98 |
|
99 @param aTextDef the new text definition to be used in the view session. |
|
100 */ |
|
101 void CCntPplViewSession::ChangeSortOrderL(const CContactTextDef& aTextDef) |
|
102 { |
|
103 //Cleanup the cached Prepare statement as the sort order will be changed |
|
104 Cancel(); |
|
105 CleanupCachedPrepareStatement(); |
|
106 |
|
107 //Copy the text definition |
|
108 CContactTextDef* textDef = CContactTextDef::NewLC(); |
|
109 const TInt KTextDefCount = aTextDef.Count(); |
|
110 for (TInt index = 0; index < KTextDefCount; ++index) |
|
111 { |
|
112 textDef->AppendL(TContactTextDefItem(aTextDef.At(index).iFieldType)); |
|
113 } |
|
114 |
|
115 // Create select statement on contact table |
|
116 TCntSqlStatementType statementType(ESelect, KSqlContactTableName()); |
|
117 CCntSqlStatement* sqlSmt = TSqlProvider::GetSqlStatementL(statementType); |
|
118 CleanupStack::PushL(sqlSmt); |
|
119 |
|
120 // Always select id, type flags. |
|
121 sqlSmt->SetParamL(KContactId(), KSpace()); |
|
122 sqlSmt->SetParamL(KContactTypeFlags(), KSpace()); |
|
123 |
|
124 //Go through text definition to construct select statement. |
|
125 TBool isFastAccessOnly = ETrue; |
|
126 for(TInt ii = 0; ii < KTextDefCount; ++ii) |
|
127 { |
|
128 const TDesC& KColunmName = TCntPersistenceUtility::GetFastAccessColumnNameById(aTextDef.At(ii).iFieldType.iUid); |
|
129 if(KColunmName.Length() > 0) |
|
130 { |
|
131 sqlSmt->SetParamL(KColunmName, KSpace()); |
|
132 } |
|
133 else |
|
134 { |
|
135 isFastAccessOnly = EFalse; |
|
136 } |
|
137 } |
|
138 |
|
139 if(!isFastAccessOnly) |
|
140 { |
|
141 //Fields in text blob are needed, add text fields header and |
|
142 //text blob columns in the select statement. |
|
143 sqlSmt->SetParamL(KContactTextFieldHeader(), KSpace()); |
|
144 sqlSmt->SetParamL(KContactTextFields(), KSpace()); |
|
145 } |
|
146 |
|
147 CleanupStack::Pop(2, textDef); // sqlSmt, textDef. |
|
148 |
|
149 delete iCntSqlStatement; |
|
150 iCntSqlStatement = sqlSmt; |
|
151 |
|
152 delete iTextDef; |
|
153 iTextDef = textDef; |
|
154 |
|
155 iIsFastAccessFieldsOnly = isFastAccessOnly; |
|
156 } |
|
157 |
|
158 |
|
159 /** |
|
160 Preparing sql statement for the coming iteration requests from upper layer. |
|
161 Caller has the responsibilty of controling the lifecycle of the iteration |
|
162 session -- when it starts and stop. |
|
163 */ |
|
164 void CCntPplViewSession::BeginIterateL() |
|
165 { |
|
166 if (! iContactsFile.IsOpened()) |
|
167 { |
|
168 User::Leave(KErrInUse); |
|
169 } |
|
170 |
|
171 if ( iRSqlStatementReady ) |
|
172 { |
|
173 iRSqlStatement.Close(); |
|
174 iRSqlStatementReady = EFalse; |
|
175 } |
|
176 |
|
177 // we don't need condition for iterating database. |
|
178 iCntSqlStatement->ClearCondition(); |
|
179 |
|
180 iRSqlStatement.PrepareL(iContactsFile.NamedDatabase(), iCntSqlStatement->SqlStringL()); |
|
181 iRSqlStatementReady = ETrue; |
|
182 } |
|
183 |
|
184 |
|
185 /** |
|
186 Stop iteration by releasing iteration sql statement. |
|
187 */ |
|
188 void CCntPplViewSession::EndIterate() |
|
189 { |
|
190 if ( iRSqlStatementReady ) |
|
191 { |
|
192 iRSqlStatement.Close(); |
|
193 iRSqlStatementReady = EFalse; |
|
194 } |
|
195 } |
|
196 |
|
197 |
|
198 /** |
|
199 Get next view contact object from iterating sql statement. |
|
200 |
|
201 @return CViewContact object or NULL if iteration reachs end of rows. |
|
202 */ |
|
203 CViewContact* CCntPplViewSession::NextItemL(TContactViewPreferences aViewPrefs) |
|
204 { |
|
205 if(!iRSqlStatementReady) |
|
206 { |
|
207 //Iteration has not started |
|
208 BeginIterateL(); |
|
209 } |
|
210 |
|
211 return CreateViewItemL(iRSqlStatement, *iCntSqlStatement, aViewPrefs); |
|
212 } |
|
213 |
|
214 |
|
215 /** |
|
216 Get view contact object based on given contact id. |
|
217 |
|
218 @return CViewContact object or NULL if there is not such a contact. |
|
219 */ |
|
220 CViewContact* CCntPplViewSession::ItemAtL(TContactItemId aContactId) |
|
221 { |
|
222 //Cancel the timer so that the cached Prepare statement would not be deleted. |
|
223 Cancel(); |
|
224 |
|
225 CViewContact* viewContact = NULL; |
|
226 |
|
227 TRAPD(err, viewContact = doItemAtL(aContactId)); |
|
228 if(err != KErrNone) |
|
229 { |
|
230 CleanupCachedPrepareStatement(); |
|
231 User::Leave(err); |
|
232 } |
|
233 |
|
234 //Reset the timer |
|
235 After(KCachedPrepareTimeOut); |
|
236 return viewContact; |
|
237 } |
|
238 |
|
239 |
|
240 /** |
|
241 The method to do the real work of get view contact object based on given contact id. |
|
242 |
|
243 @return CViewContact object or NULL if there is not such a contact. |
|
244 */ |
|
245 CViewContact* CCntPplViewSession::doItemAtL(TContactItemId aContactId) |
|
246 { |
|
247 if (! iContactsFile.IsOpened()) |
|
248 { |
|
249 User::Leave(KErrInUse); |
|
250 } |
|
251 |
|
252 if ( !iCachedSqlStatementReady ) |
|
253 { |
|
254 //iCacheSqlStatement is just for ItemAt while iRSqlStatement is used for iteration |
|
255 //and maintained by BeginIterateL and EndIterateL. |
|
256 iCntSqlStatement->SetConditionL(KSelectCondition_SearchForContactId()); |
|
257 |
|
258 //Create a new sqlstatment and cache its Prepare statement. |
|
259 iCachedSqlStatement.PrepareL(iContactsFile.NamedDatabase(), iCntSqlStatement->SqlStringL()); |
|
260 iCachedSqlStatementReady = ETrue; |
|
261 } |
|
262 |
|
263 User::LeaveIfError(iCachedSqlStatement.BindInt(KFirstIndex, aContactId)); //Bind item id into the condition. |
|
264 |
|
265 CViewContact* viewContact = CreateViewItemL(iCachedSqlStatement, *iCntSqlStatement, iViewPrefs); |
|
266 |
|
267 // Adding this to the cleanup stack, because coverity recons that "iCachedSqlStatement->Reset();" can leave, and it's probably right |
|
268 CleanupStack::PushL(viewContact); |
|
269 iCachedSqlStatement.Reset(); |
|
270 |
|
271 // Pop it back off the cleanup stack, and hand over ownership |
|
272 CleanupStack::Pop(viewContact); |
|
273 return viewContact; |
|
274 } |
|
275 |
|
276 |
|
277 /** |
|
278 Clean up the cached prepare statement. |
|
279 */ |
|
280 void CCntPplViewSession::CleanupCachedPrepareStatement() |
|
281 { |
|
282 if ( iCachedSqlStatementReady ) |
|
283 { |
|
284 iCachedSqlStatement.Close(); |
|
285 iCachedSqlStatementReady = EFalse; |
|
286 } |
|
287 } |
|
288 |
|
289 /** |
|
290 CTimer callback funtion, the cached Prepare statement would be de-cached if ItemAtL is not called |
|
291 during the time interval defined by KCachedPrepareTimeOut. |
|
292 */ |
|
293 void CCntPplViewSession::RunL() |
|
294 { |
|
295 CleanupCachedPrepareStatement(); |
|
296 } |
|
297 |
|
298 |
|
299 /** |
|
300 Create view contact object based on given sql statement. |
|
301 |
|
302 @return CViewContact object or NULL the contact is not found. |
|
303 */ |
|
304 CViewContact* CCntPplViewSession::CreateViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs) |
|
305 { |
|
306 if (! iContactsFile.IsOpened()) |
|
307 { |
|
308 User::Leave(KErrInUse); |
|
309 } |
|
310 |
|
311 CViewContact* viewContact = InitialiseViewItemL(aSqlStmt, aCntSqlStmt, aViewPrefs); |
|
312 if(!viewContact) |
|
313 { |
|
314 //Couldn't find the contact. |
|
315 return NULL; |
|
316 } |
|
317 |
|
318 CleanupStack::PushL(viewContact); |
|
319 if(viewContact->ContactType() == CViewContact::EContactItem) |
|
320 { |
|
321 FillViewItemL(*viewContact, aSqlStmt, aViewPrefs); |
|
322 } |
|
323 |
|
324 TUid typeUid = GetContactFieldMatchUid(*viewContact, aViewPrefs); |
|
325 if(typeUid != KUidContactFieldNone) |
|
326 { |
|
327 RSqlStatement contactSqlStmt; |
|
328 CleanupClosePushL(contactSqlStmt); |
|
329 |
|
330 /* we have to reload the row from SQL database to cache in text header and text blob */ |
|
331 contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(), iSqlSmtSelectAllFieldsById.SqlStringL()); |
|
332 User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, viewContact->Id())); //Bind item id into the condition. |
|
333 |
|
334 TInt err = contactSqlStmt.Next(); |
|
335 if(err == KSqlAtEnd) |
|
336 { |
|
337 //Should never be here, we found it in InitialiseViewItemL |
|
338 //but couldn't find the same contact in same database. |
|
339 CleanupStack::PopAndDestroy(viewContact); |
|
340 return NULL; |
|
341 } |
|
342 |
|
343 User::LeaveIfError(err); |
|
344 |
|
345 /* set first field with possible content for group or unsorted contact */ |
|
346 CContactDatabase::TTextFieldMinimal buf; |
|
347 TextFieldL(contactSqlStmt, iSqlSmtSelectAllFieldsById, iContactProperties.SystemTemplateL(), typeUid, buf); |
|
348 viewContact->SetFirstFieldForBlankContactL(buf); |
|
349 CleanupStack::PopAndDestroy(&contactSqlStmt); |
|
350 } //if(typeUid != 0) |
|
351 |
|
352 CleanupStack::Pop(viewContact); |
|
353 return viewContact; |
|
354 } |
|
355 |
|
356 |
|
357 /** |
|
358 Filling content for the given view contact object. |
|
359 |
|
360 @param aViewContact reference to the view contact object to be filled |
|
361 @param aSqlStmt the sql statement which contains the retrieved content for the view object. |
|
362 */ |
|
363 void CCntPplViewSession::FillViewItemL(CViewContact& aViewContact, RSqlStatement& aSqlStmt, const TContactViewPreferences& aViewPrefs) |
|
364 { |
|
365 if(iIsFastAccessFieldsOnly) |
|
366 { |
|
367 //The view gets fields only from fast access columns |
|
368 const TInt KTextDefCount = iTextDef->Count(); |
|
369 for(TInt index = 0; index < KTextDefCount; ++index) |
|
370 { |
|
371 const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(iTextDef->At(index).iFieldType.iUid); |
|
372 ASSERT(KColumnName.Length() > 0); |
|
373 |
|
374 TPtrC fieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName)); |
|
375 AddFieldInViewContactL(aViewContact, fieldPtrC, aViewPrefs); |
|
376 } //for |
|
377 } |
|
378 else |
|
379 { |
|
380 TBool searchFastAccessFields = EFalse; |
|
381 |
|
382 // iTextDef contains the fields that should be included in the view. |
|
383 // The array of all the field objects in a contact item is returned from |
|
384 // the Contacts table. |
|
385 RPointerArray<CContactItemField> fields; |
|
386 CleanupStack::PushL(TCleanupItem(TCntPersistenceUtility::ResetAndDestroyRPointerArray, &fields)); |
|
387 |
|
388 TPtrC8 textHeader; |
|
389 aSqlStmt.ColumnBinary(iCntSqlStatement->ParameterIndex(KContactTextFieldHeader()), textHeader); |
|
390 RDesReadStream textHeaderStream(textHeader); |
|
391 CleanupClosePushL(textHeaderStream); |
|
392 CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream); |
|
393 |
|
394 RStoreReadStream textHeaderStoreStream; |
|
395 textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root()); |
|
396 |
|
397 TPtrC textFieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KContactTextFields())); |
|
398 HBufC* textFieldsBuf = textFieldPtrC.AllocLC(); |
|
399 |
|
400 TCntPersistenceUtility::ReadTextBlobL(textHeaderStoreStream, textFieldsBuf, *iTextDef, iContactProperties.SystemTemplateL(), fields, searchFastAccessFields); |
|
401 CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf |
|
402 |
|
403 // Loop through fields, checking for fields from fast access fields, and add |
|
404 // the fields to the view contact object. |
|
405 const TInt KFieldsNumMax = fields.Count(); |
|
406 for(TInt fieldsIndex = 0; fieldsIndex < KFieldsNumMax; ++fieldsIndex) |
|
407 { |
|
408 // this doesn't own the instance stored in fields array. |
|
409 CContactItemField* itemField = fields[fieldsIndex]; |
|
410 |
|
411 if(itemField == NULL) |
|
412 { |
|
413 aViewContact.AddFieldL(KNullDesC); |
|
414 continue; |
|
415 } |
|
416 |
|
417 // The array of fields retrieved from the text fields blob does not |
|
418 // contain the text data Fast Access fields. If the searchFastAccessFields |
|
419 // flags have been set then get the data from Fast Access columns |
|
420 // before adding the data to the view. |
|
421 TPtrC fieldText; |
|
422 if(searchFastAccessFields && itemField->ContentType().FieldTypeCount() > 0) |
|
423 { |
|
424 //Check the field name of the first field type(key field type) |
|
425 //in the field's field types array |
|
426 const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(itemField->ContentType().FieldType(0).iUid); |
|
427 if(KColumnName.Length() > 0) |
|
428 { |
|
429 //this is a fast access field. |
|
430 fieldText.Set(aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName))); |
|
431 } |
|
432 else |
|
433 { |
|
434 fieldText.Set(itemField->TextStorage()->Text()); |
|
435 } |
|
436 } |
|
437 else |
|
438 { |
|
439 fieldText.Set(itemField->TextStorage()->Text()); |
|
440 } |
|
441 |
|
442 AddFieldInViewContactL(aViewContact, fieldText, aViewPrefs); |
|
443 } |
|
444 |
|
445 CleanupStack::PopAndDestroy(&fields); |
|
446 } |
|
447 } |
|
448 |
|
449 |
|
450 /** |
|
451 Initialise requested view contact object based on given parameters: |
|
452 1. search the contact in contact table. |
|
453 2. fill in contact type and hint to the view contact object. |
|
454 |
|
455 @param aSqlStmt reference to a RSqlStatement to be read in data |
|
456 @return initialized CViewContact object or NULL if reached end of rows. |
|
457 */ |
|
458 CViewContact* CCntPplViewSession::InitialiseViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs) |
|
459 { |
|
460 CViewContact* viewContact = NULL; |
|
461 |
|
462 while(viewContact == NULL) |
|
463 { |
|
464 TInt err = aSqlStmt.Next(); |
|
465 |
|
466 if(err == KSqlAtEnd) |
|
467 { |
|
468 return NULL; |
|
469 } |
|
470 |
|
471 User::LeaveIfError(err); |
|
472 |
|
473 TInt typeFlags = aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactTypeFlags())); |
|
474 TUid contactTypeUid = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
475 |
|
476 if(!ContactCorrectType(contactTypeUid, aViewPrefs)) |
|
477 { |
|
478 //The contact type doesn't match the view prefreference |
|
479 continue; |
|
480 } |
|
481 |
|
482 viewContact = CViewContact::NewLC(KNullContactId); |
|
483 |
|
484 /* Got a row and add common fields for both Groups and Contact view items. */ |
|
485 viewContact->SetId(aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactId()))); |
|
486 viewContact->SetContactHint(TCntPersistenceUtility::TypeFlagsToHint(typeFlags)); |
|
487 viewContact->SetContactTypeUid(contactTypeUid); |
|
488 |
|
489 |
|
490 if(contactTypeUid == KUidContactGroup) |
|
491 { |
|
492 // Groups don't require all the field types to be set. |
|
493 viewContact->SetContactType(CViewContact::EGroup); |
|
494 } |
|
495 else |
|
496 { |
|
497 // All other contact types do require field types to be set. |
|
498 viewContact->SetContactType(CViewContact::EContactItem); |
|
499 } |
|
500 |
|
501 CleanupStack::Pop(viewContact); |
|
502 } |
|
503 |
|
504 return viewContact; |
|
505 } |
|
506 |
|
507 |
|
508 /** |
|
509 Check if the retrieved view contact is group or unsorted contact, if so return suitable field |
|
510 match uid in order to fill in a possible text for the contact: |
|
511 For group contact -- find template label. |
|
512 For unsorted contact -- find first not none field. |
|
513 |
|
514 @param aViewContact reference to the retrieved view contact object. |
|
515 @param aViewPreferences the view preferences made by client. |
|
516 |
|
517 @return suitable match uid or KUidContactFieldNone if it's not group or unsorted contact. |
|
518 */ |
|
519 TUid CCntPplViewSession::GetContactFieldMatchUid(const CViewContact& aViewContact, const TContactViewPreferences& aViewPreferences) |
|
520 { |
|
521 TUid typeUid = KUidContactFieldNone; |
|
522 if(aViewContact.ContactType() == CViewContact::EGroup && (aViewPreferences & (EGroupsOnly | EContactAndGroups))) |
|
523 { |
|
524 // Check for group view contact type. This type of view contact uses the |
|
525 // template label field to populate the first view contact field. |
|
526 typeUid = KUidContactFieldTemplateLabel; |
|
527 } |
|
528 else if(!aViewContact.IsSortable() && (aViewPreferences & (EIgnoreUnSorted | EUnSortedAtBeginning | EUnSortedAtEnd)) == 0) |
|
529 { |
|
530 // None of the sort fields contained any data. We want this contact to |
|
531 // be sorted by the first bit of text we find so we need to retrieve the |
|
532 // first text available from the contact and use this to populate the |
|
533 // first view contact field. |
|
534 typeUid = KUidContactFieldMatchAll; |
|
535 } |
|
536 return typeUid; |
|
537 } |
|
538 |
|
539 |
|
540 /** |
|
541 Refine the field content and add the refined content to the given view contact object. |
|
542 |
|
543 @param aViewContact reference to the retrieved view contact object. |
|
544 @param aFieldPtrC The actual field content read from database. |
|
545 @param aViewPreferences The view preferences for how to format the content. |
|
546 */ |
|
547 void CCntPplViewSession::AddFieldInViewContactL(CViewContact& aViewContact, TPtrC& aFieldPtrC, const TContactViewPreferences& aViewPreferences) |
|
548 { |
|
549 _LIT(KBlank," "); |
|
550 |
|
551 // Truncate to 64 if necessary. |
|
552 TPtr ptr(const_cast<TUint16*>(aFieldPtrC.Ptr()), KTextFieldMinimalLength); |
|
553 if(aFieldPtrC.Length() > KTextFieldMinimalLength) |
|
554 { |
|
555 ptr.SetLength(KTextFieldMinimalLength); |
|
556 } |
|
557 else |
|
558 { |
|
559 ptr.SetLength(aFieldPtrC.Length()); |
|
560 } |
|
561 |
|
562 // Add the field to the view. |
|
563 if((ptr.Length() == 0) || |
|
564 (ptr.Length() == 1 && (aViewPreferences & ESingleWhiteSpaceIsEmptyField) && ptr.Compare(KBlank)==KErrNone)) |
|
565 { |
|
566 /* empty field */ |
|
567 aViewContact.AddFieldL(KNullDesC); |
|
568 } |
|
569 else |
|
570 { |
|
571 aViewContact.AddFieldL(ptr); |
|
572 } |
|
573 } |
|
574 |
|
575 /** |
|
576 Retrieve the field text for the given field type and contact item ID. |
|
577 |
|
578 The behaviour differs when a specific field type is not given i.e. when |
|
579 aFieldType is KUidContactFieldMatchAll: |
|
580 |
|
581 - First tries to find an email for the given contact item ID. |
|
582 - If there is no email then it retrieves the first entry in Fast Access fields |
|
583 for the given contact item ID. |
|
584 - If there is no Fast Access fields then it retrieves the first entry in the |
|
585 text fields blob for the given contact item ID. |
|
586 |
|
587 Text for all other field types are retrieved from the text fields blob. |
|
588 |
|
589 The caller must determine that the given contact item ID exists before calling |
|
590 this method. |
|
591 */ |
|
592 void CCntPplViewSession::TextFieldL(RSqlStatement& aSqlStatement, const CCntSqlStatement& aCntSqlStmt, const CContactTemplate& aSystemTemplate, TFieldType aFieldType, TDes& aText) |
|
593 { |
|
594 TPtrC8 textHeader; |
|
595 aSqlStatement.ColumnBinary(aCntSqlStmt.ParameterIndex(KContactTextFieldHeader()), textHeader); |
|
596 RDesReadStream textHeaderStream(textHeader); |
|
597 CleanupClosePushL(textHeaderStream); |
|
598 CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream); |
|
599 |
|
600 RStoreReadStream textHeaderStoreStream; |
|
601 textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root()); |
|
602 |
|
603 TPtrC textFieldPtrC = aSqlStatement.ColumnTextL(aCntSqlStmt.ParameterIndex(KContactTextFields())); |
|
604 HBufC* textFieldsBuf = textFieldPtrC.AllocLC(); |
|
605 |
|
606 if(aFieldType == KUidContactFieldMatchAll) |
|
607 { |
|
608 if (TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText) == EFalse) |
|
609 { |
|
610 CContactDatabase::TTextFieldMinimal fastAccessText; |
|
611 if (HasTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, fastAccessText)) |
|
612 { |
|
613 aText.Copy(fastAccessText); |
|
614 } |
|
615 } |
|
616 } |
|
617 else |
|
618 { |
|
619 if (SpecificTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, aFieldType, aText) == EFalse) |
|
620 { |
|
621 TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText); |
|
622 } |
|
623 } |
|
624 |
|
625 CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf |
|
626 } |
|
627 |
|
628 |
|
629 /** |
|
630 The first text field in the Fast Access fields is found and returned via the |
|
631 parameter aText. |
|
632 |
|
633 @param aCntItemId The contact ID for which the first text field is required. |
|
634 @param aText On return contains the text for the field of the first Identity |
|
635 text field. |
|
636 |
|
637 @return ETrue if a Fast Access text field was found, EFalse otherwise. |
|
638 */ |
|
639 TBool CCntPplViewSession::HasTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, TDes& aText) |
|
640 { |
|
641 for(TInt ii = EGivenName; ii <= ECompanyNamePrn; ++ii) |
|
642 { |
|
643 const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(KFastAccessFieldUids[ii]); |
|
644 TPtrC identText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName)); |
|
645 if(identText.Length() > 0) |
|
646 { |
|
647 TCntPersistenceUtility::CopyMinFieldText(identText, aText); |
|
648 return ETrue; |
|
649 } |
|
650 } |
|
651 return EFalse; |
|
652 } |
|
653 |
|
654 |
|
655 /** |
|
656 Checks if the given field type is in the Fast Access fields and if so the field text |
|
657 is returned via the parameter aText. |
|
658 |
|
659 @param aCntItemId The contact ID for which the specific text field is required. |
|
660 @param aText On return contains the field text for the first Fast Access fields |
|
661 with field type aFieldType. |
|
662 @param aFieldType The specific field requested. |
|
663 |
|
664 @return ETrue if the specific fast access text field was found, EFalse otherwise. |
|
665 */ |
|
666 TBool CCntPplViewSession::SpecificTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, const TFieldType aFieldType, TDes& aText) |
|
667 { |
|
668 const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(aFieldType.iUid); |
|
669 if(KColumnName.Length() > 0) |
|
670 { |
|
671 // This is a fast access field. |
|
672 TPtrC fastAccessText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName)); |
|
673 TCntPersistenceUtility::CopyMinFieldText(fastAccessText, aText); |
|
674 return ETrue; |
|
675 } |
|
676 return EFalse; |
|
677 } |
|
678 |
|
679 |
|
680 /** |
|
681 Get view session id |
|
682 |
|
683 @return the view session id assigned to the session. |
|
684 */ |
|
685 TInt CCntPplViewSession::ViewId() const |
|
686 { |
|
687 return iViewId; |
|
688 } |
|
689 |
|
690 |
|
691 TBool CCntPplViewSession::ContactCorrectType(TUid aContactTypeUid, TContactViewPreferences aTypeToInclude) |
|
692 { |
|
693 TBool correctType = EFalse; |
|
694 |
|
695 if (aContactTypeUid == KUidContactCard) |
|
696 { |
|
697 if (!(aTypeToInclude & (EGroupsOnly | EICCEntriesOnly))) |
|
698 { |
|
699 correctType = ETrue; |
|
700 } |
|
701 } |
|
702 else if (aContactTypeUid == KUidContactOwnCard) |
|
703 { |
|
704 if (!(aTypeToInclude & (EGroupsOnly | EICCEntriesOnly | EContactCardsOnly))) |
|
705 { |
|
706 correctType = ETrue; |
|
707 } |
|
708 } |
|
709 else if (aContactTypeUid == KUidContactGroup) |
|
710 { |
|
711 if (aTypeToInclude & (EGroupsOnly | EContactAndGroups)) |
|
712 { |
|
713 correctType = ETrue; |
|
714 } |
|
715 } |
|
716 else if (aContactTypeUid == KUidContactICCEntry) |
|
717 { |
|
718 if (aTypeToInclude & (EICCEntriesOnly | EICCEntriesAndContacts)) |
|
719 { |
|
720 correctType = ETrue; |
|
721 } |
|
722 } |
|
723 |
|
724 return correctType; |
|
725 } |
|
726 |
|
727 |
|
728 /** |
|
729 * Close the resource which is running and depends on RSqlDatabase |
|
730 * that will be closed in CPplContactsFile. |
|
731 */ |
|
732 void CCntPplViewSession::OnCloseL() |
|
733 { |
|
734 |
|
735 if ( iRSqlStatementReady ) |
|
736 { |
|
737 iRSqlStatement.Close(); |
|
738 iRSqlStatementReady = EFalse; |
|
739 } |
|
740 |
|
741 if ( iCachedSqlStatementReady ) |
|
742 { |
|
743 iCachedSqlStatement.Close(); |
|
744 iCachedSqlStatementReady = EFalse; |
|
745 } |
|
746 |
|
747 } |
|
748 |
|
749 |