|
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 |
|
22 #include "cntpplviewmanager.h" |
|
23 #include "cntsqlprovider.h" |
|
24 #include "dbsqlconstants.h" |
|
25 #include "cntpersistenceutility.h" |
|
26 |
|
27 const TInt KViewSessionsGranularity = 4; |
|
28 |
|
29 |
|
30 /** |
|
31 Object factory method. |
|
32 */ |
|
33 CCntPplViewManager* CCntPplViewManager::NewL(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties) |
|
34 { |
|
35 CCntPplViewManager* manager = new (ELeave) CCntPplViewManager(aContactsFile, aContactProperties); |
|
36 CleanupStack::PushL(manager); |
|
37 manager->ConstructL(); |
|
38 CleanupStack::Pop(manager); |
|
39 return manager; |
|
40 } |
|
41 |
|
42 |
|
43 /** |
|
44 CCntPplViewManager first phase constructor. |
|
45 */ |
|
46 CCntPplViewManager::CCntPplViewManager(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties) |
|
47 : iContactsFile(aContactsFile), |
|
48 iContactProperties(aContactProperties), |
|
49 iNextViewId(KPLViewSessionIdNull + 1), |
|
50 iViewSessions(KViewSessionsGranularity) |
|
51 { |
|
52 } |
|
53 |
|
54 |
|
55 /** |
|
56 CCntPplViewManager destructor. |
|
57 */ |
|
58 CCntPplViewManager::~CCntPplViewManager() |
|
59 { |
|
60 iViewSessions.ResetAndDestroy(); |
|
61 delete iSelectFullFieldsStmt; |
|
62 } |
|
63 |
|
64 |
|
65 /** |
|
66 CCntPplViewManager second phase constructor. |
|
67 */ |
|
68 void CCntPplViewManager::ConstructL() |
|
69 { |
|
70 /* |
|
71 Construct select statement: |
|
72 "SELECT contact_id, type_flags, first_name, last_name, company_name, firstname_prn, |
|
73 lastname_prn, companyname_prn, text_fields_header, text_fields |
|
74 FROM contact WHERE contact_id == :SeekId" |
|
75 */ |
|
76 TCntSqlStatementType statementType(ESelect, KSqlContactTableName); |
|
77 iSelectFullFieldsStmt = TSqlProvider::GetSqlStatementL(statementType); |
|
78 |
|
79 // To select id, type flags, and all fast access fields. |
|
80 iSelectFullFieldsStmt->SetParamL(KContactId(), KSpace()); |
|
81 iSelectFullFieldsStmt->SetParamL(KContactTypeFlags(), KSpace()); |
|
82 iSelectFullFieldsStmt->SetParamL(KContactFirstName(), KSpace()); |
|
83 iSelectFullFieldsStmt->SetParamL(KContactLastName(), KSpace()); |
|
84 iSelectFullFieldsStmt->SetParamL(KContactCompanyName(), KSpace()); |
|
85 iSelectFullFieldsStmt->SetParamL(KContactFirstNamePrn(), KSpace()); |
|
86 iSelectFullFieldsStmt->SetParamL(KContactLastNamePrn(), KSpace()); |
|
87 iSelectFullFieldsStmt->SetParamL(KContactCompanyNamePrn(), KSpace()); |
|
88 |
|
89 // Also select text header, and text blob |
|
90 iSelectFullFieldsStmt->SetParamL(KContactTextFieldHeader(), KSpace()); |
|
91 iSelectFullFieldsStmt->SetParamL(KContactTextFields(), KSpace()); |
|
92 |
|
93 // Add selecting condition |
|
94 HBufC* condition = HBufC::NewLC(KSelectCondition_SearchForEqual().Length() + KContactId().Length()); |
|
95 TPtr ptrCondition = condition->Des(); |
|
96 ptrCondition.Format(KSelectCondition_SearchForEqual(), &KContactId); |
|
97 |
|
98 iSelectFullFieldsStmt->SetConditionL(ptrCondition); |
|
99 |
|
100 CleanupStack::PopAndDestroy(condition); |
|
101 } |
|
102 |
|
103 |
|
104 /** |
|
105 Create a new view session which is mapping to a local view. |
|
106 |
|
107 @param aTextDef the text definition for the view |
|
108 @param aViewPrefs the view preferences for the view. |
|
109 @return the view session id created for the local view. |
|
110 */ |
|
111 TInt CCntPplViewManager::OpenViewL(const CContactTextDef& aTextDef, const TContactViewPreferences aViewPrefs) |
|
112 { |
|
113 CCntPplViewSession* viewSession = CCntPplViewSession::NewL(iContactsFile, |
|
114 iContactProperties, *iSelectFullFieldsStmt, iNextViewId, aTextDef, aViewPrefs); |
|
115 CleanupStack::PushL(viewSession); |
|
116 iViewSessions.AppendL(viewSession); |
|
117 CleanupStack::Pop(viewSession); |
|
118 |
|
119 //there is no relationship between the iViewSessions index (subscript) and iNextViewId |
|
120 return iNextViewId++; |
|
121 } |
|
122 |
|
123 |
|
124 /** |
|
125 Close a view session. |
|
126 |
|
127 @param aViewId the id of the view session to be closed |
|
128 */ |
|
129 void CCntPplViewManager::CloseView(TInt aViewId) |
|
130 { |
|
131 TInt index = FindViewSessionIndexById(aViewId); |
|
132 if(index != KErrNotFound) |
|
133 { |
|
134 CCntPplViewSession* viewSession = iViewSessions[index]; |
|
135 iViewSessions.Remove(index); |
|
136 delete viewSession; |
|
137 } |
|
138 } |
|
139 |
|
140 |
|
141 /** |
|
142 Change a sort order for a view session. |
|
143 |
|
144 @param aViewId the id of the view session |
|
145 @param aTextDef the new sort order/text definition. |
|
146 */ |
|
147 void CCntPplViewManager::ChangeSortOrderL(TInt aViewId, const CContactTextDef& aTextDef) |
|
148 { |
|
149 FindViewSessionByIdL(aViewId)->ChangeSortOrderL(aTextDef); |
|
150 } |
|
151 |
|
152 |
|
153 /** |
|
154 Start iteration in a view session. |
|
155 |
|
156 @param aViewId the id of the view session |
|
157 */ |
|
158 void CCntPplViewManager::BeginIterateL(TInt aViewId) |
|
159 { |
|
160 FindViewSessionByIdL(aViewId)->BeginIterateL(); |
|
161 } |
|
162 |
|
163 |
|
164 /** |
|
165 End iteration in a view session. |
|
166 |
|
167 @param aViewId the id of the view session |
|
168 */ |
|
169 void CCntPplViewManager::EndIterateL(TInt aViewId) |
|
170 { |
|
171 FindViewSessionByIdL(aViewId)->EndIterate(); |
|
172 } |
|
173 |
|
174 |
|
175 /** |
|
176 Get next view item in a view session. |
|
177 |
|
178 @param aViewId the id of the view session |
|
179 @return the view item got from the database |
|
180 @leave KErrNotFound if iterator reachs the end of rows. |
|
181 */ |
|
182 CViewContact* CCntPplViewManager::NextItemL(TInt aViewId, TContactViewPreferences aViewPrefs) |
|
183 { |
|
184 return FindViewSessionByIdL(aViewId)->NextItemL(aViewPrefs); |
|
185 } |
|
186 |
|
187 |
|
188 /** |
|
189 Get view item by given contact id in a view session. |
|
190 |
|
191 @param aViewId the id of the view session |
|
192 @return the view item got from the database |
|
193 @leave KErrNotFound if there is not the row. |
|
194 */ |
|
195 CViewContact* CCntPplViewManager::ItemAtL(TContactItemId aContactId, TInt aViewId) |
|
196 { |
|
197 return FindViewSessionByIdL(aViewId)->ItemAtL(aContactId); |
|
198 } |
|
199 |
|
200 |
|
201 /** |
|
202 Find a view session by given view session id. |
|
203 |
|
204 @param aViewId the id of the view session |
|
205 @return the view session |
|
206 @leave KErrArgument if there is not such a view session. |
|
207 */ |
|
208 CCntPplViewSession* CCntPplViewManager::FindViewSessionByIdL(TInt aViewId) const |
|
209 { |
|
210 ASSERT(aViewId >= 0); |
|
211 TInt index = FindViewSessionIndexById(aViewId); |
|
212 if(index == KErrNotFound) |
|
213 { |
|
214 User::Leave(KErrNotFound); |
|
215 } |
|
216 |
|
217 return iViewSessions[index]; |
|
218 } |
|
219 |
|
220 |
|
221 /** |
|
222 Find a view session by given view session id. |
|
223 |
|
224 @param aViewId the id of the view session |
|
225 @return the index of view session stored in view session array |
|
226 KNotFoundIndex if there is not such a view session. |
|
227 */ |
|
228 TInt CCntPplViewManager::FindViewSessionIndexById(TInt aViewId) const |
|
229 { |
|
230 TInt index = KErrNotFound; |
|
231 TInt count = iViewSessions.Count(); |
|
232 for(TInt i = 0; i < count; ++i) |
|
233 { |
|
234 ASSERT(iViewSessions[i] != NULL); |
|
235 if(aViewId == iViewSessions[i]->ViewId()) |
|
236 { |
|
237 index = i; |
|
238 break; |
|
239 } |
|
240 } |
|
241 return index; |
|
242 } |
|
243 |
|
244 |
|
245 /** |
|
246 CContactDatabase::ReadContactTextDefL() uses a text definition - a way of |
|
247 grouping fields to form a string which represents a contact item - to |
|
248 build up a string from a contact item. |
|
249 |
|
250 When creating the string, the contact item is searched for fields whose type |
|
251 matches one of the fields specified in the text definition. |
|
252 |
|
253 The contents of the first matching field of each type found in the |
|
254 item are read into the string. |
|
255 |
|
256 These strings may be separated using a field separator, which is also specified |
|
257 in the text definition. A separator is not appended to the last field used to |
|
258 make up the string. It is only inserted when there is a following non-empty |
|
259 field. |
|
260 |
|
261 @param aContactId The contact ID for which the text definition is required. |
|
262 @param aResult The string representing the contact item. |
|
263 @param aTextDef The text definition which contains the fields that are read |
|
264 and returned in the aResult string. |
|
265 |
|
266 @return the contact type uid for the specified contact. |
|
267 */ |
|
268 TUid CCntPplViewManager::ReadContactTextDefL(TContactItemId aContactId, TDes &aResult,const CContactTextDef& aTextDef) |
|
269 { |
|
270 if (! iContactsFile.IsOpened()) |
|
271 { |
|
272 User::Leave(KErrInUse); |
|
273 } |
|
274 |
|
275 RSqlStatement contactSqlStmt; |
|
276 CleanupClosePushL(contactSqlStmt); |
|
277 |
|
278 /* we have to reload the row from SQL database to cache in text header and text blob */ |
|
279 contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(), iSelectFullFieldsStmt->SqlStringL()); |
|
280 User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, aContactId)); //Bind item id into the condition. |
|
281 |
|
282 TInt err = contactSqlStmt.Next(); |
|
283 if(err == KSqlAtEnd) |
|
284 { |
|
285 //couldn't find the contact |
|
286 err = KErrNotFound; |
|
287 } |
|
288 |
|
289 User::LeaveIfError(err); |
|
290 |
|
291 TInt typeFlags = contactSqlStmt.ColumnInt(iSelectFullFieldsStmt->ParameterIndex(KContactTypeFlags())); |
|
292 TUid contactTypeUid = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
293 TInt attr = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; |
|
294 |
|
295 if((attr & EContactAttrsFlags_Deleted) == 0) |
|
296 { |
|
297 //Only read text def for not deleted contact. |
|
298 TBuf<KMaxContactTextSeperator> nextSeperator; |
|
299 TContactTextDefItem textDefItem; |
|
300 |
|
301 // Mark the first iteration in the loop. |
|
302 TBool firstText = ETrue; |
|
303 |
|
304 TInt max = aTextDef.Count(); |
|
305 for(TInt i=0; i<max; ++i) |
|
306 { |
|
307 // Recreate the TTextFieldMinimal on each iteration. |
|
308 CContactDatabase::TTextFieldMinimal textFieldMin; |
|
309 textDefItem = aTextDef[i]; |
|
310 // Populate the TTextFieldMinimal. |
|
311 CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), textDefItem.iFieldType, textFieldMin); |
|
312 // Append the returned text. |
|
313 if (textFieldMin.Length() > 0) |
|
314 { |
|
315 // Only add a seperator after the first text has been appended. |
|
316 if ((firstText == EFalse) && (aResult.MaxLength() > aResult.Length())) |
|
317 { |
|
318 aResult.Append(nextSeperator.Left(Min(aResult.MaxLength() - aResult.Length(), nextSeperator.Length()))); |
|
319 } |
|
320 aResult.Append(textFieldMin.Left(Min(aResult.MaxLength() - aResult.Length(),textFieldMin.Length()))); |
|
321 firstText = EFalse; |
|
322 } |
|
323 nextSeperator = textDefItem.iSeperator; |
|
324 } |
|
325 |
|
326 // Add the best match if it was requested. |
|
327 if(aResult.Length() == 0 && const_cast<CContactTextDef&>(aTextDef).ExactMatchOnly() == EFalse) |
|
328 { |
|
329 CContactDatabase::TTextFieldMinimal textFieldMin; |
|
330 if (aTextDef.FallbackField() != KUidContactFieldNone) |
|
331 { |
|
332 CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), aTextDef.FallbackField(), textFieldMin); |
|
333 } |
|
334 if(textFieldMin.Length() == 0) // No results from call to TextFieldL()? |
|
335 { |
|
336 CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), KUidContactFieldMatchAll, textFieldMin); |
|
337 } |
|
338 aResult.Append(textFieldMin.Left(Min(aResult.MaxLength(),textFieldMin.Length()))); |
|
339 } |
|
340 } //if((attr & EContactAttrsFlags_Deleted) != 0) |
|
341 |
|
342 CleanupStack::PopAndDestroy(&contactSqlStmt); |
|
343 |
|
344 return contactTypeUid; |
|
345 } |
|
346 |
|
347 |
|
348 /** |
|
349 Retrieve the field text for the given field type and contact item ID. |
|
350 |
|
351 The behaviour differs when a specific field type is not given i.e. when |
|
352 aFieldType is KUidContactFieldMatchAll: |
|
353 |
|
354 - First tries to find an email for the given contact item ID. |
|
355 - If there is no email then it retrieves the first entry in Fast Access fields |
|
356 for the given contact item ID. |
|
357 - If there is no Fast Access fields then it retrieves the first entry in the |
|
358 text fields blob for the given contact item ID. |
|
359 |
|
360 Text for all other field types are retrieved from the text fields blob. |
|
361 |
|
362 The caller must determine that the given contact item ID exists before calling |
|
363 this method. |
|
364 |
|
365 @param aContactId The contact ID for which the field text is required. |
|
366 @param aFieldType the field type to determine what kind of text client required. |
|
367 @param aText the reference to the buffer of final found field text. |
|
368 */ |
|
369 void CCntPplViewManager::TextFieldL(TInt aContactId, TFieldType aFieldType, TDes& aText) |
|
370 { |
|
371 if (! iContactsFile.IsOpened()) |
|
372 { |
|
373 User::Leave(KErrInUse); |
|
374 } |
|
375 |
|
376 RSqlStatement contactSqlStmt; |
|
377 CleanupClosePushL(contactSqlStmt); |
|
378 |
|
379 /* we have to reload the row from SQL database to cache in text header and text blob */ |
|
380 contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(), iSelectFullFieldsStmt->SqlStringL()); |
|
381 User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, aContactId)); //Bind item id into the condition. |
|
382 |
|
383 TInt err = contactSqlStmt.Next(); |
|
384 if(err == KSqlAtEnd) |
|
385 { |
|
386 //couldn't find the contact |
|
387 err = KErrNotFound; |
|
388 } |
|
389 |
|
390 User::LeaveIfError(err); |
|
391 |
|
392 CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), aFieldType, aText); |
|
393 |
|
394 CleanupStack::PopAndDestroy(&contactSqlStmt); |
|
395 } |
|
396 |