|
1 /* |
|
2 * Copyright (c) 2004-2005 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implements the CLandmarksContainer class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <aknsfld.h> |
|
21 #include <aknnavi.h> |
|
22 #include <eikclbd.h> |
|
23 #include <aknview.h> |
|
24 #include <AknQueryDialog.h> |
|
25 |
|
26 #include "LmRefApp.hrh" |
|
27 #include <LmRefApp.rsg> |
|
28 #include "LandmarksContainer.h" |
|
29 #include "LandmarksCommonData.h" |
|
30 #include "LandmarksListBoxModel.h" |
|
31 #include "LandmarksModel.h" |
|
32 #include "LandmarksApplicationEngine.h" |
|
33 #include "LandmarksListbox.h" |
|
34 |
|
35 // ============================= LOCAL FUNCTIONS =============================== |
|
36 |
|
37 // ----------------------------------------------------------------------------- |
|
38 // ResetAndDestroyLandmarks resets and destroys all landmarks owned by the |
|
39 // supplied landmark array. |
|
40 // Param: aAny: an instance of CArrayPtr<CPosLandmark>* to reset and destroy |
|
41 // ----------------------------------------------------------------------------- |
|
42 // |
|
43 void ResetAndDestroyLandmarks(TAny* aAny) |
|
44 { |
|
45 CArrayPtr<CPosLandmark>* landmarks = |
|
46 reinterpret_cast <CArrayPtr<CPosLandmark>*> (aAny); |
|
47 landmarks->ResetAndDestroy(); |
|
48 } |
|
49 |
|
50 // ============================ MEMBER FUNCTIONS =============================== |
|
51 |
|
52 // ----------------------------------------------------------------------------- |
|
53 // ----------------------------------------------------------------------------- |
|
54 // |
|
55 CLandmarksContainer::CLandmarksContainer( |
|
56 CAknView& aView, |
|
57 CLandmarksApplicationEngine& aEngine, |
|
58 CAknNavigationDecorator* aNaviDecorator) |
|
59 : CLandmarksContainerBase(aView, aEngine), |
|
60 iNaviDecorator(aNaviDecorator) |
|
61 { |
|
62 } |
|
63 |
|
64 // ----------------------------------------------------------------------------- |
|
65 // ----------------------------------------------------------------------------- |
|
66 // |
|
67 void CLandmarksContainer::ConstructL( |
|
68 const TRect& aRect) |
|
69 { |
|
70 // Create listbox and findbox. |
|
71 CLandmarksContainerBase::ConstructL(aRect); |
|
72 |
|
73 // Start observer db events. |
|
74 iEngine.AddDbObserverL(this); |
|
75 |
|
76 // Create data model. |
|
77 iModel = CLandmarksModel::NewL(); |
|
78 |
|
79 // Create a descriptor array that will contain the landmark names and |
|
80 // icon indeces. |
|
81 CLandmarksListBoxModel* model = iListBox->Model(); |
|
82 model->SetItemTextArray(iModel->ItemList()); |
|
83 model->SetOwnershipType(ELbmDoesNotOwnItemArray); |
|
84 |
|
85 // Create an icon array that will be displayed in the listbox. |
|
86 |
|
87 CIconList* icons = iModel->CreateIconListL(); |
|
88 iListBox->ItemDrawer()->ColumnData()->SetIconArray(icons); |
|
89 |
|
90 // Observe listbox for state changes. |
|
91 iListBox->SetObserver(this); |
|
92 |
|
93 // Observe findbox for state changes. |
|
94 iFindBox->SetObserver(this); |
|
95 |
|
96 // Populate listbox with landmarks and icons. |
|
97 StartUpdateListBoxL(); |
|
98 } |
|
99 |
|
100 // ----------------------------------------------------------------------------- |
|
101 // ----------------------------------------------------------------------------- |
|
102 // |
|
103 CLandmarksContainer::~CLandmarksContainer() |
|
104 { |
|
105 delete iModel; |
|
106 delete iCurrentName; |
|
107 } |
|
108 |
|
109 // ----------------------------------------------------------------------------- |
|
110 // ----------------------------------------------------------------------------- |
|
111 // |
|
112 TPosLmItemId CLandmarksContainer::CurrentLandmark() |
|
113 { |
|
114 return iModel->CurrentItemId(); |
|
115 } |
|
116 |
|
117 // ----------------------------------------------------------------------------- |
|
118 // ----------------------------------------------------------------------------- |
|
119 // |
|
120 void CLandmarksContainer::DeleteLandmarkL() |
|
121 { |
|
122 // Extract landmark name |
|
123 TPtrC name; |
|
124 CPosLandmark* currentLandmark = |
|
125 iEngine.LandmarkLC(iModel->CurrentItemId()); |
|
126 currentLandmark->GetLandmarkName(name); |
|
127 |
|
128 // Format query |
|
129 HBufC* queryFormat = |
|
130 iCoeEnv->AllocReadResourceAsDes16LC(R_LMREFAPP_DELETE_LANDMARK); |
|
131 HBufC* queryBuf = HBufC::NewLC(name.Length() + queryFormat->Length()); |
|
132 TPtr query = queryBuf->Des(); |
|
133 query.Format(*queryFormat, &name); |
|
134 |
|
135 // Launch dialog |
|
136 CAknQueryDialog* queryDialog = CAknQueryDialog::NewL(); |
|
137 if (queryDialog->ExecuteLD(R_LMREFAPP_GENERAL_QUERY, query)) |
|
138 { |
|
139 iEngine.DeleteLandmarkL(currentLandmark->LandmarkId()); |
|
140 } |
|
141 |
|
142 CleanupStack::PopAndDestroy(3, currentLandmark); |
|
143 } |
|
144 |
|
145 // ----------------------------------------------------------------------------- |
|
146 // ----------------------------------------------------------------------------- |
|
147 // |
|
148 void CLandmarksContainer::GetSelectedLandmarksL( RArray<TPosLmItemId>& aItemIds ) |
|
149 { |
|
150 iModel->GetItemIdsL( *(iListBox->SelectionIndexes()), aItemIds ); |
|
151 } |
|
152 |
|
153 // ----------------------------------------------------------------------------- |
|
154 // ----------------------------------------------------------------------------- |
|
155 // |
|
156 TKeyResponse CLandmarksContainer::OfferKeyEventL( |
|
157 const TKeyEvent& aKeyEvent, TEventCode aType) |
|
158 { |
|
159 TKeyResponse response = EKeyWasNotConsumed; |
|
160 |
|
161 switch (aKeyEvent.iCode) |
|
162 { |
|
163 case EKeyUpArrow: |
|
164 case EKeyDownArrow: |
|
165 // Scrolling the list box. Forward to iListBox. |
|
166 response = iListBox->OfferKeyEventL(aKeyEvent, aType); |
|
167 break; |
|
168 |
|
169 case EKeyDevice3: |
|
170 if ( aKeyEvent.iModifiers & EModifierShift ) |
|
171 { |
|
172 iListBox->View()->ToggleItemL( iListBox->CurrentItemIndex() ); |
|
173 } |
|
174 else |
|
175 { |
|
176 // Select key pressed. Edit landmark. |
|
177 iView.ProcessCommandL(ELandmarksOpen); |
|
178 response = EKeyWasConsumed; |
|
179 } |
|
180 break; |
|
181 |
|
182 case EKeyBackspace: |
|
183 if ((iFindBox->TextLength() == 0) && IsItemSelected()) |
|
184 { |
|
185 // If search field is empty backspace deletes a landmark. |
|
186 DeleteLandmarkL(); |
|
187 response = EKeyWasConsumed; |
|
188 break; |
|
189 } |
|
190 // remove letter in find box |
|
191 default: |
|
192 // Forward key events to find box. |
|
193 response = iFindBox->OfferKeyEventL(aKeyEvent, aType); |
|
194 break; |
|
195 } |
|
196 |
|
197 return response; |
|
198 } |
|
199 |
|
200 // ----------------------------------------------------------------------------- |
|
201 // ----------------------------------------------------------------------------- |
|
202 // |
|
203 void CLandmarksContainer::NotifyOperationProgressL( |
|
204 TOperation aOperation, |
|
205 TInt aProgress, |
|
206 TInt aErrorCode) |
|
207 { |
|
208 switch (aOperation) |
|
209 { |
|
210 case ELandmarkSearch: |
|
211 HandleSearchReadyL(aErrorCode); |
|
212 break; |
|
213 |
|
214 case ELandmarkRead: |
|
215 HandleReadReadyL(aErrorCode, aProgress == KOperationReady); |
|
216 break; |
|
217 |
|
218 default: |
|
219 break; |
|
220 } |
|
221 } |
|
222 |
|
223 // ----------------------------------------------------------------------------- |
|
224 // ----------------------------------------------------------------------------- |
|
225 // |
|
226 void CLandmarksContainer::NotifyDbEventL( |
|
227 TPosLmEvent& aEvent, |
|
228 TInt aErrorCode) |
|
229 { |
|
230 if (aErrorCode == KErrNone) |
|
231 { |
|
232 switch (aEvent.iEventType) |
|
233 { |
|
234 case EPosLmEventUnknownChanges: |
|
235 case EPosLmEventLandmarkUnknownChanges: |
|
236 case EPosLmEventCategoryUnknownChanges: |
|
237 case EPosLmEventLandmarkCreated: |
|
238 case EPosLmEventLandmarkDeleted: |
|
239 StartUpdateListBoxL(); |
|
240 break; |
|
241 // Any of the 3 events below might have cancelled an ongoing |
|
242 // landmark search/read operation => must restart refreshing list |
|
243 case EPosLmEventCategoryCreated: |
|
244 case EPosLmEventCategoryDeleted: |
|
245 case EPosLmEventCategoryUpdated: |
|
246 if (iIsActive) |
|
247 { |
|
248 StartUpdateListBoxL(); |
|
249 } |
|
250 break; |
|
251 case EPosLmEventLandmarkUpdated: |
|
252 if (IsRefreshNeededL(aEvent.iLandmarkItemId)) |
|
253 { |
|
254 StartUpdateListBoxL(); |
|
255 } |
|
256 break; |
|
257 case EPosLmEventNewDefaultDatabaseLocation: |
|
258 // Not supported by this application |
|
259 break; |
|
260 case EPosLmEventMediaRemoved: |
|
261 // Not supported by this application |
|
262 break; |
|
263 default: |
|
264 // Ignore other category events |
|
265 break; |
|
266 } |
|
267 } |
|
268 } |
|
269 |
|
270 // ----------------------------------------------------------------------------- |
|
271 // ----------------------------------------------------------------------------- |
|
272 // |
|
273 void CLandmarksContainer::HandleControlEventL( |
|
274 CCoeControl* aControl, |
|
275 TCoeEvent aEventType) |
|
276 { |
|
277 if (aEventType == EEventStateChanged && aControl == iListBox) |
|
278 { |
|
279 // Take the index of the current item in the list |
|
280 TInt itemIndex = iListBox->CurrentItemIndex(); |
|
281 |
|
282 // Set the current item in the model object regarding to the list box. |
|
283 iModel->SetCurrentItem(itemIndex); |
|
284 |
|
285 // Store the name of the current landmark |
|
286 StoreCurrentLandmarkNameL(); |
|
287 } |
|
288 |
|
289 if (aEventType == EEventStateChanged && aControl == iFindBox) |
|
290 { |
|
291 // Fetch filter from search field |
|
292 TInt searchTextLength = iFindBox->TextLength(); |
|
293 HBufC* filterBuf = HBufC::NewLC(searchTextLength); |
|
294 TPtr filter = filterBuf->Des(); |
|
295 iFindBox->GetSearchText(filter); |
|
296 |
|
297 // If filter has changed repopulate list box. (It is necessary to check |
|
298 // if filter has changed since each filter change generates several |
|
299 // EEventStateChanged events for find box) |
|
300 if (filter != *iOldFilter) |
|
301 { |
|
302 // Filter has changed. Start filtering. |
|
303 StartUpdateListBoxL(); |
|
304 } |
|
305 |
|
306 CleanupStack::PopAndDestroy(filterBuf); |
|
307 } |
|
308 } |
|
309 |
|
310 // ----------------------------------------------------------------------------- |
|
311 // ----------------------------------------------------------------------------- |
|
312 // |
|
313 void CLandmarksContainer::StartUpdateListBoxL() |
|
314 { |
|
315 // Fetch filter from find box |
|
316 TInt searchTextLength = iFindBox->TextLength(); |
|
317 const TInt KExtraChars = 2; // 2 chars wildcards |
|
318 HBufC* filterBuf = HBufC::NewLC(searchTextLength + KExtraChars); |
|
319 TPtr filter = filterBuf->Des(); |
|
320 iFindBox->GetSearchText(filter); |
|
321 |
|
322 // Find out if there is any prevoius result to limit the search to |
|
323 TInt oldFilterLength = iOldFilter->Length(); |
|
324 TBool searchOnlyInPreviousMatches = |
|
325 // If previous filter is empty there is no search results |
|
326 oldFilterLength > 0 && |
|
327 |
|
328 // If chars have been removed from filter we abandon previous results |
|
329 filter.Length() > oldFilterLength && |
|
330 |
|
331 // There must exist at least one previous match |
|
332 IsItemSelected(); |
|
333 |
|
334 // old filter used - now we can update it |
|
335 delete iOldFilter; |
|
336 iOldFilter = NULL; |
|
337 iOldFilter = filter.AllocL(); |
|
338 |
|
339 // Start to asynchronously populate the listbox model according to filter |
|
340 if (searchTextLength == 0) |
|
341 { |
|
342 iEngine.StartSearchingLandmarksL(this); |
|
343 } |
|
344 else |
|
345 { |
|
346 filter.Insert(0, KWildCard); |
|
347 filter.Append(KWildCard); |
|
348 iEngine.StartSearchingLandmarksL( |
|
349 filter, searchOnlyInPreviousMatches, this); |
|
350 } |
|
351 |
|
352 // Indicate we are active |
|
353 iIsActive = ETrue; |
|
354 |
|
355 CleanupStack::PopAndDestroy(filterBuf); |
|
356 } |
|
357 |
|
358 // ----------------------------------------------------------------------------- |
|
359 // ----------------------------------------------------------------------------- |
|
360 // |
|
361 void CLandmarksContainer::HandleSearchReadyL(TInt aErrorCode) |
|
362 { |
|
363 |
|
364 // Delete old icon array and add new |
|
365 CColumnListBoxData* columnData = iListBox->ItemDrawer()->ColumnData(); |
|
366 CArrayPtr<CGulIcon>* iconList = columnData->IconArray(); |
|
367 iconList->ResetAndDestroy(); |
|
368 delete iconList; |
|
369 columnData->SetIconArray(iModel->CreateIconListL()); |
|
370 |
|
371 if (aErrorCode == KErrNone) |
|
372 { |
|
373 // Update model |
|
374 iModel->SetItemIds(iEngine.FetchLandmarkSearchResult()); |
|
375 iListBox->HandleItemRemovalL(); |
|
376 |
|
377 iEngine.StartReadingLandmarksL(KNrOfItemsDisplayed, this); |
|
378 iReadingFirstPage = ETrue; |
|
379 } |
|
380 else if (aErrorCode == KErrNotFound) |
|
381 { |
|
382 // Updating list ready |
|
383 iIsActive = EFalse; |
|
384 |
|
385 // Update model (indicate no item is selected) |
|
386 iModel->SetItemIds(NULL); |
|
387 iModel->SetCurrentItem(iListBox->CurrentItemIndex()); |
|
388 |
|
389 // Update the view |
|
390 iListBox->HandleItemRemovalL(); |
|
391 iListBox->DrawDeferred(); |
|
392 } |
|
393 } |
|
394 |
|
395 // ----------------------------------------------------------------------------- |
|
396 // ----------------------------------------------------------------------------- |
|
397 // |
|
398 void CLandmarksContainer::HandleReadReadyL(TInt aErrorCode, TBool aFinished) |
|
399 { |
|
400 // Update model with new landmarks |
|
401 CArrayPtr<CPosLandmark>* landmarks = iEngine.FetchLandmarksLC(); |
|
402 CleanupStack::PushL(TCleanupItem(ResetAndDestroyLandmarks, landmarks)); |
|
403 iModel->RepopulateModelL(landmarks); |
|
404 CleanupStack::PopAndDestroy(2, landmarks); |
|
405 |
|
406 if (aErrorCode == KErrNone) |
|
407 { |
|
408 if (aFinished) |
|
409 { |
|
410 // Updating list ready |
|
411 iIsActive = EFalse; |
|
412 } |
|
413 if (iReadingFirstPage) |
|
414 { |
|
415 // First page ready |
|
416 iReadingFirstPage = EFalse; |
|
417 |
|
418 // Add the first page |
|
419 iListBox->HandleItemAdditionL(); |
|
420 |
|
421 // Set the first item selected by default. We must do this since |
|
422 // HandleItemRemovalL in HandleSearchReadyL resets the listbox. |
|
423 iModel->SetCurrentItem(0); |
|
424 iListBox->SetCurrentItemIndex(0); |
|
425 StoreCurrentLandmarkNameL(); |
|
426 } |
|
427 else |
|
428 { |
|
429 iListBox->HandleItemAdditionL(); |
|
430 } |
|
431 } |
|
432 } |
|
433 |
|
434 // ----------------------------------------------------------------------------- |
|
435 // ----------------------------------------------------------------------------- |
|
436 // |
|
437 TBool CLandmarksContainer::IsRefreshNeededL(TPosLmItemId& aModifiedLandmark) |
|
438 { |
|
439 if (iIsActive) |
|
440 { |
|
441 return ETrue; |
|
442 } |
|
443 else |
|
444 { |
|
445 if (aModifiedLandmark == iModel->CurrentItemId()) |
|
446 { |
|
447 // Investigate if we need to refresh. Compare name. |
|
448 CPosLandmark* landmark = iEngine.LandmarkLC(aModifiedLandmark); |
|
449 TPtrC name; |
|
450 landmark->GetLandmarkName(name); |
|
451 TBool isNameDifferent = |
|
452 iCurrentName && *iCurrentName != name || |
|
453 !iCurrentName && name != KNullDesC; |
|
454 CleanupStack::PopAndDestroy(landmark); |
|
455 |
|
456 // If name is different the list needs to be re-sorted. Otherwise |
|
457 // some other field has been modified and the list is not affected. |
|
458 return isNameDifferent; |
|
459 } |
|
460 else |
|
461 { |
|
462 // Some other process than this has modified a landmark |
|
463 return ETrue; |
|
464 } |
|
465 } |
|
466 } |
|
467 |
|
468 // ----------------------------------------------------------------------------- |
|
469 // ----------------------------------------------------------------------------- |
|
470 // |
|
471 void CLandmarksContainer::StoreCurrentLandmarkNameL() |
|
472 { |
|
473 CPosLandmark* landmark = iEngine.LandmarkLC(iModel->CurrentItemId()); |
|
474 TPtrC name; |
|
475 landmark->GetLandmarkName(name); |
|
476 delete iCurrentName; |
|
477 iCurrentName = NULL; |
|
478 iCurrentName = name.AllocL(); |
|
479 CleanupStack::PopAndDestroy(landmark); |
|
480 } |
|
481 |
|
482 |