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