diff -r 1fc85118c3ae -r 870918037e16 locationlandmarksrefappfors60/Src/LandmarksContainer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locationlandmarksrefappfors60/Src/LandmarksContainer.cpp Wed Sep 01 12:31:27 2010 +0100 @@ -0,0 +1,482 @@ +/* +* Copyright (c) 2004-2005 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implements the CLandmarksContainer class +* +*/ + + + +#include +#include +#include +#include +#include + +#include "LmRefApp.hrh" +#include +#include "LandmarksContainer.h" +#include "LandmarksCommonData.h" +#include "LandmarksListBoxModel.h" +#include "LandmarksModel.h" +#include "LandmarksApplicationEngine.h" +#include "LandmarksListbox.h" + +// ============================= LOCAL FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// ResetAndDestroyLandmarks resets and destroys all landmarks owned by the +// supplied landmark array. +// Param: aAny: an instance of CArrayPtr* to reset and destroy +// ----------------------------------------------------------------------------- +// +void ResetAndDestroyLandmarks(TAny* aAny) + { + CArrayPtr* landmarks = + reinterpret_cast *> (aAny); + landmarks->ResetAndDestroy(); + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +CLandmarksContainer::CLandmarksContainer( + CAknView& aView, + CLandmarksApplicationEngine& aEngine, + CAknNavigationDecorator* aNaviDecorator) +: CLandmarksContainerBase(aView, aEngine), + iNaviDecorator(aNaviDecorator) + { + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::ConstructL( + const TRect& aRect) + { + // Create listbox and findbox. + CLandmarksContainerBase::ConstructL(aRect); + + // Start observer db events. + iEngine.AddDbObserverL(this); + + // Create data model. + iModel = CLandmarksModel::NewL(); + + // Create a descriptor array that will contain the landmark names and + // icon indeces. + CLandmarksListBoxModel* model = iListBox->Model(); + model->SetItemTextArray(iModel->ItemList()); + model->SetOwnershipType(ELbmDoesNotOwnItemArray); + + // Create an icon array that will be displayed in the listbox. + + CIconList* icons = iModel->CreateIconListL(); + iListBox->ItemDrawer()->ColumnData()->SetIconArray(icons); + + // Observe listbox for state changes. + iListBox->SetObserver(this); + + // Observe findbox for state changes. + iFindBox->SetObserver(this); + + // Populate listbox with landmarks and icons. + StartUpdateListBoxL(); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +CLandmarksContainer::~CLandmarksContainer() + { + delete iModel; + delete iCurrentName; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TPosLmItemId CLandmarksContainer::CurrentLandmark() + { + return iModel->CurrentItemId(); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::DeleteLandmarkL() + { + // Extract landmark name + TPtrC name; + CPosLandmark* currentLandmark = + iEngine.LandmarkLC(iModel->CurrentItemId()); + currentLandmark->GetLandmarkName(name); + + // Format query + HBufC* queryFormat = + iCoeEnv->AllocReadResourceAsDes16LC(R_LMREFAPP_DELETE_LANDMARK); + HBufC* queryBuf = HBufC::NewLC(name.Length() + queryFormat->Length()); + TPtr query = queryBuf->Des(); + query.Format(*queryFormat, &name); + + // Launch dialog + CAknQueryDialog* queryDialog = CAknQueryDialog::NewL(); + if (queryDialog->ExecuteLD(R_LMREFAPP_GENERAL_QUERY, query)) + { + iEngine.DeleteLandmarkL(currentLandmark->LandmarkId()); + } + + CleanupStack::PopAndDestroy(3, currentLandmark); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::GetSelectedLandmarksL( RArray& aItemIds ) + { + iModel->GetItemIdsL( *(iListBox->SelectionIndexes()), aItemIds ); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TKeyResponse CLandmarksContainer::OfferKeyEventL( + const TKeyEvent& aKeyEvent, TEventCode aType) + { + TKeyResponse response = EKeyWasNotConsumed; + + switch (aKeyEvent.iCode) + { + case EKeyUpArrow: + case EKeyDownArrow: + // Scrolling the list box. Forward to iListBox. + response = iListBox->OfferKeyEventL(aKeyEvent, aType); + break; + + case EKeyDevice3: + if ( aKeyEvent.iModifiers & EModifierShift ) + { + iListBox->View()->ToggleItemL( iListBox->CurrentItemIndex() ); + } + else + { + // Select key pressed. Edit landmark. + iView.ProcessCommandL(ELandmarksOpen); + response = EKeyWasConsumed; + } + break; + + case EKeyBackspace: + if ((iFindBox->TextLength() == 0) && IsItemSelected()) + { + // If search field is empty backspace deletes a landmark. + DeleteLandmarkL(); + response = EKeyWasConsumed; + break; + } + // remove letter in find box + default: + // Forward key events to find box. + response = iFindBox->OfferKeyEventL(aKeyEvent, aType); + break; + } + + return response; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::NotifyOperationProgressL( + TOperation aOperation, + TInt aProgress, + TInt aErrorCode) + { + switch (aOperation) + { + case ELandmarkSearch: + HandleSearchReadyL(aErrorCode); + break; + + case ELandmarkRead: + HandleReadReadyL(aErrorCode, aProgress == KOperationReady); + break; + + default: + break; + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::NotifyDbEventL( + TPosLmEvent& aEvent, + TInt aErrorCode) + { + if (aErrorCode == KErrNone) + { + switch (aEvent.iEventType) + { + case EPosLmEventUnknownChanges: + case EPosLmEventLandmarkUnknownChanges: + case EPosLmEventCategoryUnknownChanges: + case EPosLmEventLandmarkCreated: + case EPosLmEventLandmarkDeleted: + StartUpdateListBoxL(); + break; + // Any of the 3 events below might have cancelled an ongoing + // landmark search/read operation => must restart refreshing list + case EPosLmEventCategoryCreated: + case EPosLmEventCategoryDeleted: + case EPosLmEventCategoryUpdated: + if (iIsActive) + { + StartUpdateListBoxL(); + } + break; + case EPosLmEventLandmarkUpdated: + if (IsRefreshNeededL(aEvent.iLandmarkItemId)) + { + StartUpdateListBoxL(); + } + break; + case EPosLmEventNewDefaultDatabaseLocation: + // Not supported by this application + break; + case EPosLmEventMediaRemoved: + // Not supported by this application + break; + default: + // Ignore other category events + break; + } + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::HandleControlEventL( + CCoeControl* aControl, + TCoeEvent aEventType) + { + if (aEventType == EEventStateChanged && aControl == iListBox) + { + // Take the index of the current item in the list + TInt itemIndex = iListBox->CurrentItemIndex(); + + // Set the current item in the model object regarding to the list box. + iModel->SetCurrentItem(itemIndex); + + // Store the name of the current landmark + StoreCurrentLandmarkNameL(); + } + + if (aEventType == EEventStateChanged && aControl == iFindBox) + { + // Fetch filter from search field + TInt searchTextLength = iFindBox->TextLength(); + HBufC* filterBuf = HBufC::NewLC(searchTextLength); + TPtr filter = filterBuf->Des(); + iFindBox->GetSearchText(filter); + + // If filter has changed repopulate list box. (It is necessary to check + // if filter has changed since each filter change generates several + // EEventStateChanged events for find box) + if (filter != *iOldFilter) + { + // Filter has changed. Start filtering. + StartUpdateListBoxL(); + } + + CleanupStack::PopAndDestroy(filterBuf); + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::StartUpdateListBoxL() + { + // Fetch filter from find box + TInt searchTextLength = iFindBox->TextLength(); + const TInt KExtraChars = 2; // 2 chars wildcards + HBufC* filterBuf = HBufC::NewLC(searchTextLength + KExtraChars); + TPtr filter = filterBuf->Des(); + iFindBox->GetSearchText(filter); + + // Find out if there is any prevoius result to limit the search to + TInt oldFilterLength = iOldFilter->Length(); + TBool searchOnlyInPreviousMatches = + // If previous filter is empty there is no search results + oldFilterLength > 0 && + + // If chars have been removed from filter we abandon previous results + filter.Length() > oldFilterLength && + + // There must exist at least one previous match + IsItemSelected(); + + // old filter used - now we can update it + delete iOldFilter; + iOldFilter = NULL; + iOldFilter = filter.AllocL(); + + // Start to asynchronously populate the listbox model according to filter + if (searchTextLength == 0) + { + iEngine.StartSearchingLandmarksL(this); + } + else + { + filter.Insert(0, KWildCard); + filter.Append(KWildCard); + iEngine.StartSearchingLandmarksL( + filter, searchOnlyInPreviousMatches, this); + } + + // Indicate we are active + iIsActive = ETrue; + + CleanupStack::PopAndDestroy(filterBuf); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::HandleSearchReadyL(TInt aErrorCode) + { + + // Delete old icon array and add new + CColumnListBoxData* columnData = iListBox->ItemDrawer()->ColumnData(); + CArrayPtr* iconList = columnData->IconArray(); + iconList->ResetAndDestroy(); + delete iconList; + columnData->SetIconArray(iModel->CreateIconListL()); + + if (aErrorCode == KErrNone) + { + // Update model + iModel->SetItemIds(iEngine.FetchLandmarkSearchResult()); + iListBox->HandleItemRemovalL(); + + iEngine.StartReadingLandmarksL(KNrOfItemsDisplayed, this); + iReadingFirstPage = ETrue; + } + else if (aErrorCode == KErrNotFound) + { + // Updating list ready + iIsActive = EFalse; + + // Update model (indicate no item is selected) + iModel->SetItemIds(NULL); + iModel->SetCurrentItem(iListBox->CurrentItemIndex()); + + // Update the view + iListBox->HandleItemRemovalL(); + iListBox->DrawDeferred(); + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::HandleReadReadyL(TInt aErrorCode, TBool aFinished) + { + // Update model with new landmarks + CArrayPtr* landmarks = iEngine.FetchLandmarksLC(); + CleanupStack::PushL(TCleanupItem(ResetAndDestroyLandmarks, landmarks)); + iModel->RepopulateModelL(landmarks); + CleanupStack::PopAndDestroy(2, landmarks); + + if (aErrorCode == KErrNone) + { + if (aFinished) + { + // Updating list ready + iIsActive = EFalse; + } + if (iReadingFirstPage) + { + // First page ready + iReadingFirstPage = EFalse; + + // Add the first page + iListBox->HandleItemAdditionL(); + + // Set the first item selected by default. We must do this since + // HandleItemRemovalL in HandleSearchReadyL resets the listbox. + iModel->SetCurrentItem(0); + iListBox->SetCurrentItemIndex(0); + StoreCurrentLandmarkNameL(); + } + else + { + iListBox->HandleItemAdditionL(); + } + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TBool CLandmarksContainer::IsRefreshNeededL(TPosLmItemId& aModifiedLandmark) + { + if (iIsActive) + { + return ETrue; + } + else + { + if (aModifiedLandmark == iModel->CurrentItemId()) + { + // Investigate if we need to refresh. Compare name. + CPosLandmark* landmark = iEngine.LandmarkLC(aModifiedLandmark); + TPtrC name; + landmark->GetLandmarkName(name); + TBool isNameDifferent = + iCurrentName && *iCurrentName != name || + !iCurrentName && name != KNullDesC; + CleanupStack::PopAndDestroy(landmark); + + // If name is different the list needs to be re-sorted. Otherwise + // some other field has been modified and the list is not affected. + return isNameDifferent; + } + else + { + // Some other process than this has modified a landmark + return ETrue; + } + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CLandmarksContainer::StoreCurrentLandmarkNameL() + { + CPosLandmark* landmark = iEngine.LandmarkLC(iModel->CurrentItemId()); + TPtrC name; + landmark->GetLandmarkName(name); + delete iCurrentName; + iCurrentName = NULL; + iCurrentName = name.AllocL(); + CleanupStack::PopAndDestroy(landmark); + } + +