|
S60 3rd Edition SDK for Symbian OS Example Applications Guide |
00001 /* 00002 * ============================================================================== 00003 * Name : LandmarksContainer.cpp 00004 * Part of : Landmark Reference Application 00005 * Interface : - 00006 * Description : Implements the CLandmarksContainer class 00007 * Version : 1.0 00008 * 00009 * Copyright (c) 2004-2006 Nokia Corporation. 00010 * This material, including documentation and any related 00011 * computer programs, is protected by copyright controlled by 00012 * Nokia Corporation. 00013 * ============================================================================== 00014 */ 00015 00016 // INCLUDE FILES 00017 #include <aknsfld.h> 00018 #include <aknnavi.h> 00019 #include <eikclbd.h> 00020 #include <AknView.h> 00021 #include <AknQueryDialog.h> 00022 00023 #include "LmRefApp.hrh" 00024 #include <LmRefApp.rsg> 00025 #include "LandmarksContainer.h" 00026 #include "LandmarksCommonData.h" 00027 #include "LandmarksListBoxModel.h" 00028 #include "LandmarksModel.h" 00029 #include "LandmarksEditDialog.h" 00030 #include "LandmarksApplicationEngine.h" 00031 #include "LandmarksListBox.h" 00032 00033 // ============================= LOCAL FUNCTIONS =============================== 00034 00035 // ----------------------------------------------------------------------------- 00036 // ResetAndDestroyLandmarks resets and destroys all landmarks owned by the 00037 // supplied landmark array. 00038 // Param: aAny: an instance of CArrayPtr<CPosLandmark>* to reset and destroy 00039 // ----------------------------------------------------------------------------- 00040 // 00041 void ResetAndDestroyLandmarks(TAny* aAny) 00042 { 00043 CArrayPtr<CPosLandmark>* landmarks = 00044 reinterpret_cast <CArrayPtr<CPosLandmark>*> (aAny); 00045 landmarks->ResetAndDestroy(); 00046 } 00047 00048 // ============================ MEMBER FUNCTIONS =============================== 00049 00050 // ----------------------------------------------------------------------------- 00051 // CLandmarksContainer::CLandmarksContainer 00052 // C++ constructor can NOT contain any code, that 00053 // might leave. 00054 // ----------------------------------------------------------------------------- 00055 // 00056 CLandmarksContainer::CLandmarksContainer( 00057 CAknView& aView, 00058 CLandmarksApplicationEngine& aEngine, 00059 CAknNavigationDecorator* aNaviDecorator) 00060 : CLandmarksContainerBase(aView, aEngine), 00061 iNaviDecorator(aNaviDecorator) 00062 { 00063 } 00064 00065 // ----------------------------------------------------------------------------- 00066 // CLandmarksContainer::ConstructL 00067 // Symbian 2nd phase constructor can leave. 00068 // ----------------------------------------------------------------------------- 00069 // 00070 void CLandmarksContainer::ConstructL( 00071 const TRect& aRect) 00072 { 00073 // Create listbox and findbox. 00074 CLandmarksContainerBase::ConstructL(aRect); 00075 00076 // Start observer db events. 00077 iEngine.AddDbObserverL(this); 00078 00079 // Create data model. 00080 iModel = CLandmarksModel::NewL(); 00081 00082 // Create a descriptor array that will contain the landmark names and 00083 // icon indeces. 00084 CLandmarksListBoxModel* model = iListBox->Model(); 00085 model->SetItemTextArray(iModel->ItemList()); 00086 model->SetOwnershipType(ELbmDoesNotOwnItemArray); 00087 00088 // Create an icon array that will be displayed in the listbox. 00089 00090 CIconList* icons = iModel->CreateIconListL(); 00091 iListBox->ItemDrawer()->ColumnData()->SetIconArray(icons); 00092 00093 // Observe listbox for state changes. 00094 iListBox->SetObserver(this); 00095 00096 // Observe findbox for state changes. 00097 iFindBox->SetObserver(this); 00098 00099 // Populate listbox with landmarks and icons. 00100 StartUpdateListBoxL(); 00101 } 00102 00103 // Destructor 00104 CLandmarksContainer::~CLandmarksContainer() 00105 { 00106 delete iModel; 00107 delete iCurrentName; 00108 } 00109 00110 // ----------------------------------------------------------------------------- 00111 // CLandmarksContainer::MakeNaviPaneVisibleL 00112 // 00113 // (other items were commented in a header). 00114 // ----------------------------------------------------------------------------- 00115 // 00116 void CLandmarksContainer::MakeNaviPaneVisibleL(TBool aVisible) 00117 { 00118 CEikStatusPane* statusPane = iAvkonAppUi->StatusPane(); 00119 CAknNavigationControlContainer* naviPane = 00120 (CAknNavigationControlContainer*) statusPane-> 00121 ControlL(TUid::Uid(EEikStatusPaneUidNavi)); 00122 00123 if (!aVisible) 00124 { 00125 // Remove tabs from this view's navi pane 00126 naviPane->Pop(iNaviDecorator); 00127 } 00128 else 00129 { 00130 // Recreate tabs to this view's navi pane 00131 naviPane->PushL(*iNaviDecorator); 00132 } 00133 } 00134 00135 // ----------------------------------------------------------------------------- 00136 // CLandmarksContainer::CurrentLandmark 00137 // 00138 // (other items were commented in a header). 00139 // ----------------------------------------------------------------------------- 00140 // 00141 TPosLmItemId CLandmarksContainer::CurrentLandmark() 00142 { 00143 return iModel->CurrentItemId(); 00144 } 00145 00146 // ----------------------------------------------------------------------------- 00147 // CLandmarksContainer::DeleteLandmarkL 00148 // 00149 // (other items were commented in a header). 00150 // ----------------------------------------------------------------------------- 00151 // 00152 void CLandmarksContainer::DeleteLandmarkL() 00153 { 00154 // Extract landmark name 00155 TPtrC name; 00156 CPosLandmark* currentLandmark = 00157 iEngine.LandmarkLC(iModel->CurrentItemId()); 00158 currentLandmark->GetLandmarkName(name); 00159 00160 // Format query 00161 HBufC* queryFormat = 00162 iCoeEnv->AllocReadResourceAsDes16LC(R_LMREFAPP_DELETE_LANDMARK); 00163 HBufC* queryBuf = HBufC::NewLC(name.Length() + queryFormat->Length()); 00164 TPtr query = queryBuf->Des(); 00165 query.Format(*queryFormat, &name); 00166 00167 // Launch dialog 00168 CAknQueryDialog* queryDialog = CAknQueryDialog::NewL(); 00169 if (queryDialog->ExecuteLD(R_LMREFAPP_GENERAL_QUERY, query)) 00170 { 00171 iEngine.DeleteLandmarkL(currentLandmark->LandmarkId()); 00172 } 00173 00174 CleanupStack::PopAndDestroy(3, currentLandmark); 00175 } 00176 00177 // ----------------------------------------------------------------------------- 00178 // CLandmarksContainer::OfferKeyEventL 00179 // 00180 // (other items were commented in a header). 00181 // ----------------------------------------------------------------------------- 00182 // 00183 TKeyResponse CLandmarksContainer::OfferKeyEventL( 00184 const TKeyEvent& aKeyEvent, TEventCode aType) 00185 { 00186 TKeyResponse response = EKeyWasNotConsumed; 00187 00188 switch (aKeyEvent.iCode) 00189 { 00190 case EKeyUpArrow: 00191 case EKeyDownArrow: 00192 // Scrolling the list box. Forward to iListBox. 00193 response = iListBox->OfferKeyEventL(aKeyEvent, aType); 00194 break; 00195 00196 case EKeyDevice3: 00197 // Select key pressed. Edit landmark. 00198 iView.ProcessCommandL(ELandmarksOpen); 00199 response = EKeyWasConsumed; 00200 break; 00201 00202 case EKeyBackspace: 00203 if ((iFindBox->TextLength() == 0) && IsItemSelected()) 00204 { 00205 // If search field is empty backspace deletes a landmark. 00206 DeleteLandmarkL(); 00207 response = EKeyWasConsumed; 00208 break; 00209 } 00210 // remove letter in find box 00211 default: 00212 // Forward key events to find box. 00213 response = iFindBox->OfferKeyEventL(aKeyEvent, aType); 00214 break; 00215 } 00216 00217 return response; 00218 } 00219 00220 // ----------------------------------------------------------------------------- 00221 // CLandmarksContainer::NotifyOperationProgressL 00222 // 00223 // (other items were commented in a header). 00224 // ----------------------------------------------------------------------------- 00225 // 00226 void CLandmarksContainer::NotifyOperationProgressL( 00227 TOperation aOperation, 00228 TInt aProgress, 00229 TInt aErrorCode) 00230 { 00231 switch (aOperation) 00232 { 00233 case ELandmarkSearch: 00234 HandleSearchReadyL(aErrorCode); 00235 break; 00236 00237 case ELandmarkRead: 00238 HandleReadReadyL(aErrorCode, aProgress == KOperationReady); 00239 break; 00240 00241 default: 00242 break; 00243 } 00244 } 00245 00246 // ----------------------------------------------------------------------------- 00247 // CLandmarksContainer::NotifyDbEventL 00248 // 00249 // (other items were commented in a header). 00250 // ----------------------------------------------------------------------------- 00251 // 00252 void CLandmarksContainer::NotifyDbEventL( 00253 TPosLmEvent& aEvent, 00254 TInt aErrorCode) 00255 { 00256 if (aErrorCode == KErrNone) 00257 { 00258 switch (aEvent.iEventType) 00259 { 00260 case EPosLmEventUnknownChanges: 00261 case EPosLmEventLandmarkUnknownChanges: 00262 case EPosLmEventCategoryUnknownChanges: 00263 case EPosLmEventLandmarkCreated: 00264 case EPosLmEventLandmarkDeleted: 00265 StartUpdateListBoxL(); 00266 break; 00267 // Any of the 3 events below might have cancelled an ongoing 00268 // landmark search/read operation => must restart refreshing list 00269 case EPosLmEventCategoryCreated: 00270 case EPosLmEventCategoryDeleted: 00271 case EPosLmEventCategoryUpdated: 00272 if (iIsActive) 00273 { 00274 StartUpdateListBoxL(); 00275 } 00276 break; 00277 case EPosLmEventLandmarkUpdated: 00278 if (IsRefreshNeededL(aEvent.iLandmarkItemId)) 00279 { 00280 StartUpdateListBoxL(); 00281 } 00282 break; 00283 case EPosLmEventNewDefaultDatabaseLocation: 00284 // Not supported by this application 00285 break; 00286 case EPosLmEventMediaRemoved: 00287 // Not supported by this application 00288 break; 00289 default: 00290 // Ignore other category events 00291 break; 00292 } 00293 } 00294 } 00295 00296 // ----------------------------------------------------------------------------- 00297 // CLandmarksContainer::HandleControlEventL 00298 // 00299 // (other items were commented in a header). 00300 // ----------------------------------------------------------------------------- 00301 // 00302 void CLandmarksContainer::HandleControlEventL( 00303 CCoeControl* aControl, 00304 TCoeEvent aEventType) 00305 { 00306 if (aEventType == EEventStateChanged && aControl == iListBox) 00307 { 00308 // Take the index of the current item in the list 00309 TInt itemIndex = iListBox->CurrentItemIndex(); 00310 00311 // Set the current item in the model object regarding to the list box. 00312 iModel->SetCurrentItem(itemIndex); 00313 00314 // Store the name of the current landmark 00315 StoreCurrentLandmarkNameL(); 00316 } 00317 00318 if (aEventType == EEventStateChanged && aControl == iFindBox) 00319 { 00320 // Fetch filter from search field 00321 TInt searchTextLength = iFindBox->TextLength(); 00322 HBufC* filterBuf = HBufC::NewLC(searchTextLength); 00323 TPtr filter = filterBuf->Des(); 00324 iFindBox->GetSearchText(filter); 00325 00326 // If filter has changed repopulate list box. (It is necessary to check 00327 // if filter has changed since each filter change generates several 00328 // EEventStateChanged events for find box) 00329 if (filter != *iOldFilter) 00330 { 00331 // Filter has changed. Start filtering. 00332 StartUpdateListBoxL(); 00333 } 00334 00335 CleanupStack::PopAndDestroy(filterBuf); 00336 } 00337 } 00338 00339 // ----------------------------------------------------------------------------- 00340 // CLandmarksContainer::StartUpdateListBoxL 00341 // 00342 // (other items were commented in a header). 00343 // ----------------------------------------------------------------------------- 00344 // 00345 void CLandmarksContainer::StartUpdateListBoxL() 00346 { 00347 // Fetch filter from find box 00348 TInt searchTextLength = iFindBox->TextLength(); 00349 const TInt KExtraChars = 2; // 2 chars wildcards 00350 HBufC* filterBuf = HBufC::NewLC(searchTextLength + KExtraChars); 00351 TPtr filter = filterBuf->Des(); 00352 iFindBox->GetSearchText(filter); 00353 00354 // Find out if there is any prevoius result to limit the search to 00355 TInt oldFilterLength = iOldFilter->Length(); 00356 TBool searchOnlyInPreviousMatches = 00357 // If previous filter is empty there is no search results 00358 oldFilterLength > 0 && 00359 00360 // If chars have been removed from filter we abandon previous results 00361 filter.Length() > oldFilterLength && 00362 00363 // There must exist at least one previous match 00364 IsItemSelected(); 00365 00366 // old filter used - now we can update it 00367 delete iOldFilter; 00368 iOldFilter = NULL; 00369 iOldFilter = filter.AllocL(); 00370 00371 // Start to asynchronously populate the listbox model according to filter 00372 if (searchTextLength == 0) 00373 { 00374 iEngine.StartSearchingLandmarksL(this); 00375 } 00376 else 00377 { 00378 filter.Insert(0, KWildCard); 00379 filter.Append(KWildCard); 00380 iEngine.StartSearchingLandmarksL( 00381 filter, searchOnlyInPreviousMatches, this); 00382 } 00383 00384 // Indicate we are active 00385 iIsActive = ETrue; 00386 00387 CleanupStack::PopAndDestroy(filterBuf); 00388 } 00389 00390 // ----------------------------------------------------------------------------- 00391 // CLandmarksContainer::HandleSearchReadyL 00392 // 00393 // (other items were commented in a header). 00394 // ----------------------------------------------------------------------------- 00395 // 00396 void CLandmarksContainer::HandleSearchReadyL(TInt aErrorCode) 00397 { 00398 00399 // Delete old icon array and add new 00400 CColumnListBoxData* columnData = iListBox->ItemDrawer()->ColumnData(); 00401 CArrayPtr<CGulIcon>* iconList = columnData->IconArray(); 00402 iconList->ResetAndDestroy(); 00403 delete iconList; 00404 columnData->SetIconArray(iModel->CreateIconListL()); 00405 00406 if (aErrorCode == KErrNone) 00407 { 00408 // Update model 00409 iModel->SetItemIds(iEngine.FetchLandmarkSearchResult()); 00410 iListBox->HandleItemRemovalL(); 00411 00412 iEngine.StartReadingLandmarksL(KNrOfItemsDisplayed, this); 00413 iReadingFirstPage = ETrue; 00414 } 00415 else if (aErrorCode == KErrNotFound) 00416 { 00417 // Updating list ready 00418 iIsActive = EFalse; 00419 00420 // Update model (indicate no item is selected) 00421 iModel->SetItemIds(NULL); 00422 iModel->SetCurrentItem(iListBox->CurrentItemIndex()); 00423 00424 // Update the view 00425 iListBox->HandleItemRemovalL(); 00426 iListBox->DrawDeferred(); 00427 } 00428 } 00429 00430 // ----------------------------------------------------------------------------- 00431 // CLandmarksContainer::HandleReadReadyL 00432 // 00433 // (other items were commented in a header). 00434 // ----------------------------------------------------------------------------- 00435 // 00436 void CLandmarksContainer::HandleReadReadyL(TInt aErrorCode, TBool aFinished) 00437 { 00438 // Update model with new landmarks 00439 CArrayPtr<CPosLandmark>* landmarks = iEngine.FetchLandmarksLC(); 00440 CleanupStack::PushL(TCleanupItem(ResetAndDestroyLandmarks, landmarks)); 00441 iModel->RepopulateModelL(landmarks); 00442 CleanupStack::PopAndDestroy(2, landmarks); 00443 00444 if (aErrorCode == KErrNone) 00445 { 00446 if (aFinished) 00447 { 00448 // Updating list ready 00449 iIsActive = EFalse; 00450 } 00451 if (iReadingFirstPage) 00452 { 00453 // First page ready 00454 iReadingFirstPage = EFalse; 00455 00456 // Add the first page 00457 iListBox->HandleItemAdditionL(); 00458 00459 // Set the first item selected by default. We must do this since 00460 // HandleItemRemovalL in HandleSearchReadyL resets the listbox. 00461 iModel->SetCurrentItem(0); 00462 iListBox->SetCurrentItemIndex(0); 00463 StoreCurrentLandmarkNameL(); 00464 } 00465 else 00466 { 00467 iListBox->HandleItemAdditionL(); 00468 } 00469 } 00470 } 00471 00472 // ----------------------------------------------------------------------------- 00473 // CLandmarksContainer::IsRefreshNeededL 00474 // 00475 // (other items were commented in a header). 00476 // ----------------------------------------------------------------------------- 00477 // 00478 TBool CLandmarksContainer::IsRefreshNeededL(TPosLmItemId& aModifiedLandmark) 00479 { 00480 if (iIsActive) 00481 { 00482 return ETrue; 00483 } 00484 else 00485 { 00486 if (aModifiedLandmark == iModel->CurrentItemId()) 00487 { 00488 // Investigate if we need to refresh. Compare name. 00489 CPosLandmark* landmark = iEngine.LandmarkLC(aModifiedLandmark); 00490 TPtrC name; 00491 landmark->GetLandmarkName(name); 00492 TBool isNameDifferent = 00493 iCurrentName && *iCurrentName != name || 00494 !iCurrentName && name != KNullDesC; 00495 CleanupStack::PopAndDestroy(landmark); 00496 00497 // If name is different the list needs to be re-sorted. Otherwise 00498 // some other field has been modified and the list is not affected. 00499 return isNameDifferent; 00500 } 00501 else 00502 { 00503 // Some other process than this has modified a landmark 00504 return ETrue; 00505 } 00506 } 00507 } 00508 00509 // ----------------------------------------------------------------------------- 00510 // CLandmarksContainer::StoreCurrentLandmarkNameL 00511 // 00512 // (other items were commented in a header). 00513 // ----------------------------------------------------------------------------- 00514 // 00515 void CLandmarksContainer::StoreCurrentLandmarkNameL() 00516 { 00517 CPosLandmark* landmark = iEngine.LandmarkLC(iModel->CurrentItemId()); 00518 TPtrC name; 00519 landmark->GetLandmarkName(name); 00520 delete iCurrentName; 00521 iCurrentName = NULL; 00522 iCurrentName = name.AllocL(); 00523 CleanupStack::PopAndDestroy(landmark); 00524 } 00525 00526 // End of File 00527
|
© Nokia 2006 |