landmarksui/engine/src/CLmkSearchedLmListProvider.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 00:16:03 +0200
changeset 0 522cd55cc3d7
child 3 3c271c9e6618
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2002-2009 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:    Filtered landmarks list provider
*
*/


// SYSTEM INCLUDES
#include <EPos_CPosLmPartialReadParameters.h>
#include <EPos_CPosLandmark.h>
#include <EPos_TPosLmSortPref.h>
#include <EPos_CPosLandmarkDatabase.h>
#include <EPos_CPosLmItemIterator.h>
#include <EPos_CPosLmSearchCriteria.h>
#include <EPos_CPosLandmarkSearch.h>
#include <e32math.h>
#include <EPos_CPosLmCompositeCriteria.h>
#include <EPos_CPosLmCategoryCriteria.h>
#include <EPos_CPosLmIdListCriteria.h>
#include <EPos_CPosLmTextCriteria.h>
#include <AknWaitDialog.h>
#include <lmkui.rsg>

// USER INCLUDES
#include "CLmkSearchedLmListProvider.h"
#include "CLmkLandmarkUiItem.h"
#include "CLmkAOOperation.h"
#include "MLmkSelectorIconMgr.h"
#include <lmkerrors.h>

// CONSTANTS
_LIT(KSpaceTextCriteria,"* ");
_LIT(KDefaultTextCriteria,"*");

#if defined(_DEBUG)
// CONSTANTS
/// Unnamed namespace for local definitions
namespace {

_LIT( KPanicMsg, "CLmkSearchedLmListProvider" );

void Panic( TPanicCode aReason )
    {
    User::Panic( KPanicMsg, aReason );
    }
}  // namespace
#endif
// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CLmkSearchedLmListProvider::CLmkSearchedLmListProvider
// C++ constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CLmkSearchedLmListProvider::CLmkSearchedLmListProvider(
    CPosLandmarkDatabase& aDb,
    CPosLmSearchCriteria& aCriteria )
    : CLmkLmItemListProvider( aDb ),
      iCriteria( aCriteria ),
      iIsSecondSearchStarted(EFalse)
    {
    }

// -----------------------------------------------------------------------------
// CLmkSearchedLmListProvider::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CLmkSearchedLmListProvider::ConstructL()
    {
    // base class 2nd phase constructor
    CLmkLmItemListProvider::BaseConstructL();

    iReadParams = CPosLmPartialReadParameters::NewLC();
    CleanupStack::Pop(); // iReadParams
    iReadParams->SetRequestedAttributes( CPosLandmark::ELandmarkName |
                                         CPosLandmark::EIcon | CPosLandmark::ECategoryInfo);

    iSearch = CPosLandmarkSearch::NewL( iDb );
    }

// -----------------------------------------------------------------------------
// CLmkSearchedLmListProvider::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CLmkSearchedLmListProvider* CLmkSearchedLmListProvider::NewL(
    CPosLandmarkDatabase& aDb,
    CPosLmSearchCriteria& aCriteria )
    {
    CLmkSearchedLmListProvider* self =
        new ( ELeave ) CLmkSearchedLmListProvider( aDb, aCriteria );

    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();

    return self;
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::~CLmkSearchedLmListProvider
// ---------------------------------------------------------
//
CLmkSearchedLmListProvider::~CLmkSearchedLmListProvider()
    {
    delete iReadParams;
    delete iSearch;
    if (iSearchAO)
		{
    	iSearchAO->StopOperation();
    	}
    delete iSearchAO;
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::ItemAtL
// ---------------------------------------------------------
//
CLmkUiItemBase* CLmkSearchedLmListProvider::ItemAtL( TInt aIndex )
    {
    __ASSERT_DEBUG( iIconMgr, Panic( KLmkPanicNullMember ) );
    //landmark with updated icon, if associated with one cat.
    CPosLandmark* landmark = GetLandmarkLC(aIndex);
    TPtrC mbmFile;
    TInt iconFileIndex = -1;
    TInt iconListIndex = -1;
    TInt iconMasktIndex = -1;
    TInt result = landmark->GetIcon( mbmFile, iconFileIndex, iconMasktIndex );
    if ( result == KErrNone )
        {
        TRAPD(err, iconListIndex =
                    iIconMgr->GetIconL( mbmFile, iconFileIndex ) );
        if ( err == KErrNotFound ) // icon file not found -> fallback to default
            {
            iconListIndex = iIconMgr->GetDefaultIconL(
                MLmkSelectorIconMgr::ELandmarkDefaultIcon );
            }
        }
    else
        {
        iconListIndex = iIconMgr->GetDefaultIconL(
            MLmkSelectorIconMgr::ELandmarkDefaultIcon );
        }

    CLmkLandmarkUiItem* uiItem =
        CLmkLandmarkUiItem::NewL( landmark, iconListIndex );
    CleanupStack::Pop(); // landmark, ownership transferred
    return uiItem;
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::PrepareListL
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::PrepareListL()
    {    
    iCount = 0;

    iDb.SetPartialReadParametersL( *iReadParams );

    TPosLmSortPref sortOrder( CPosLandmark::ELandmarkName,
                              TPosLmSortPref::EAscending );
    CPosLmOperation* operation =
        iSearch->StartLandmarkSearchL( iCriteria, sortOrder );
    CleanupStack::PushL( operation );
    if (iSearchAO)
		{
    	iSearchAO->StopOperation();
	    delete iSearchAO; // cancel possibly pending operation
	    iSearchAO = NULL;
    	}
    iSearchAO = CLmkAOOperation::NewL( operation,
                                       *this,
                                       MLmkAOOperationObserver::ESearch,
                                       iOperationNotInUse );
	iOperationNotInUse = ETrue;
    CleanupStack::Pop( operation ); // ownership transferred
    iSearchAO->StartOperation();
    }

// -----------------------------------------------------------------------------
// CLmkSearchedLmListProvider::PrepareListL
// -----------------------------------------------------------------------------
//
TBool CLmkSearchedLmListProvider::PrepareListL(const TDesC& aSearchPattern,
    							TBool aSearchOnlyInPreviousMatches)
	{
    iCount = 0;
	iRequestFromFindBox = ETrue;
	iOperationNotInUse = ETrue;
    iIsSecondSearchStarted = EFalse;

	if( aSearchPattern.Compare( KDefaultTextCriteria ) == 0
			|| aSearchPattern.Length() <= 0  )
		{
		PrepareListL();
		iRequestFromFindBox = EFalse;
		return ETrue;
		}

	// We need to cancel if we are searching/reading landmarks.
 	if (iSearchAO)
	 	{
	 	iSearchAO->StopOperation();
	 	delete iSearchAO; // cancel possibly pending operation
		iSearchAO = NULL;
	 	}

	// Create the composite criterion
	CPosLmCompositeCriteria* compCrit = CPosLmCompositeCriteria::NewLC(
	    CPosLmCompositeCriteria::ECompositionOR );

	// Create the text search criterion and add it to composite
	CPosLmTextCriteria* textCrit1 = CPosLmTextCriteria::NewLC();

    const TInt KExtraChars = 3; // 2 chars wildcards
    HBufC* filterBuf = HBufC::NewLC(aSearchPattern.Length() + KExtraChars);
    TPtr filter = filterBuf->Des();
	filter.Copy(KSpaceTextCriteria);
	filter.Append(aSearchPattern);

	textCrit1->SetTextL( filter );
    textCrit1->SetAttributesToSearch(CPosLandmark::ELandmarkName);

	User::LeaveIfError( compCrit->AddArgument( textCrit1 ) );
	// Ownership of the text criterion has been passed to the composite
	CleanupStack::PopAndDestroy( filterBuf );
	CleanupStack::Pop( textCrit1 );

	// Create the text search criterion and add it to composite
	CPosLmTextCriteria* textCrit2 = CPosLmTextCriteria::NewLC();
	textCrit2->SetTextL( aSearchPattern );
    textCrit2->SetAttributesToSearch(CPosLandmark::ELandmarkName);

	User::LeaveIfError( compCrit->AddArgument( textCrit2 ) );
	// Ownership of the text criterion has been passed to the composite
	CleanupStack::Pop( textCrit2 );

    iDb.SetPartialReadParametersL( *iReadParams );

    TPosLmSortPref sortOrder( CPosLandmark::ELandmarkName,
                              TPosLmSortPref::EAscending );
	// Start the search
    // Create search operation
    CPosLmOperation* operation = iSearch->StartLandmarkSearchL(
    					*compCrit, sortOrder, aSearchOnlyInPreviousMatches );

 	CleanupStack::PopAndDestroy( compCrit );
 	CleanupStack::PushL( operation );

	iSearchAO = CLmkAOOperation::NewL( operation,
                                   *this,
                                   MLmkAOOperationObserver::ESearch,
                                   ETrue );
	CleanupStack::Pop( operation ); // ownership transferred

    iSearchAO->StartOperation();

    return ETrue;
 	}

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::StartSecondSearchL
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::StartSecondSearchL()
	{
	// Create the composite criterion
	CPosLmCompositeCriteria* compCrit = CPosLmCompositeCriteria::NewLC(
	    CPosLmCompositeCriteria::ECompositionAND );

	// Create the category search criterion and add it to composite
	CPosLmCategoryCriteria* catCrit = CPosLmCategoryCriteria::NewLC();
	catCrit->SetCategoryItemId( (static_cast<CPosLmCategoryCriteria&>(iCriteria)).CategoryItemId() );

	User::LeaveIfError( compCrit->AddArgument( catCrit ) );
	// Ownership of the category criterion has been passed to the composite
	CleanupStack::Pop( catCrit );

	// Create the text search criterion and add it to composite
	CPosLmIdListCriteria* idListCrit = CPosLmIdListCriteria::NewLC();
	idListCrit->SetLandmarkIdsL( iIdArray );

	User::LeaveIfError( compCrit->AddArgument( idListCrit ) );
	// Ownership of the text criterion has been passed to the composite
	CleanupStack::Pop( idListCrit );

    iDb.SetPartialReadParametersL( *iReadParams );

    TPosLmSortPref sortOrder( CPosLandmark::ELandmarkName,
                              TPosLmSortPref::EAscending );
	// Start the search
    // Create search operation
    CPosLmOperation* operation = iSearch->StartLandmarkSearchL( *compCrit, sortOrder );

 	CleanupStack::PopAndDestroy( compCrit );
 	CleanupStack::PushL( operation );

	iSearchAO = CLmkAOOperation::NewL( operation,
                                   *this,
                                   MLmkAOOperationObserver::ESearch,
                                   ETrue );
	CleanupStack::Pop( operation ); // ownership transferred

	iIsSecondSearchStarted = EFalse;
    iSearchAO->StartOperation();

	}

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::HandleOperationL
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::HandleOperationL(
    TOperationTypes aType,
    TReal32 aProgress,
    TInt aStatus )
    {
    if ( aType == MLmkAOOperationObserver::EDeleteLandmarks )
    	{
    	return;
    	}
    if ( aType == MLmkAOOperationObserver::ERemoveCategory )
    	{
    	return;
    	}
    if ( aType == MLmkAOOperationObserver::ESearch )
        {
   		ReadItemsToArrayL();
       	if ( aStatus == KErrNone )
	        {
	        if( iSearchAO )
	        	{
	        	iSearchAO->StopOperation();
				delete iSearchAO;
		        iSearchAO = NULL;
	        	}

			// reset operation values
	        iOperationCmd = ELmkCmdStopOperation;//temp default value
	        iCount = 0;

	        if( iIsSecondSearchStarted )
	        	{
	        	StartSecondSearchL();
	        	}

	        if(iOperationNotInUse == EFalse )
	        	{
	        	NotifyObservers( ELmkEventItemAdditionComplete );
	        	}
	        else
		        {
		        if (iRequestFromFindBox)
			        {
			        NotifyObservers( ELmkEventFindListReady );
			        }
				else
					{
		        	NotifyObservers( ELmkEventListReady );
					}
		        }

	        iOperationNotInUse = ETrue;

            if ( iCatDelete )
                {
                NotifyObservers( ELmkEventCategoryDeleted );
                iCatDelete = EFalse;
                }
            else if(iCatUpdate)
	            {
	            NotifyObservers( ELmkEventCategoryUpdated );
                iCatUpdate = EFalse;
                }

    		if(iItemsDeleted < iItemsToDelete)
    			{
    			PrepareForDeleteL();
    			}
    		else
    			{
    			if(iWaitNote)
    				{
		            iWaitNote->ProcessFinishedL();
		            iWaitNote = NULL;
    				}
    			}
	        return;
	        } // end of if ( aStatus == KErrNone )

	    if ( iCount == ELmkStepOne || iCount == ELmkStepTwo )
	        {
			if (iOperationNotInUse == EFalse )
	        	{
	        	NotifyObservers( ELmkEventItemAdditionComplete );
	        	}
	        else
		        {
		        if (iRequestFromFindBox)
			        {
			        NotifyObservers( ELmkEventFindListReady );
			        }
				else
					{
		        	NotifyObservers( ELmkEventListReady );
					}
		        }
		    iOperationNotInUse = EFalse;
	        }
        }
    else
        { // This is not this classes' operation
        CLmkLmItemListProvider::HandleOperationL( aType, aProgress, aStatus);
        }
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::HandleDatabaseEvent
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::HandleDatabaseEvent( TPosLmEvent& aEvent )
    {
    iCatDelete = EFalse;

	TBool needRefresh = ETrue;

	// check any items are selected to do operations like iconchanges or add to category.
	if( iSelectedItemsCount > 0 
		&& iOperationCmd != ELmkCmdAddToCat
		&& iOperationCmd != ERemoveFromCat )
		{
		iCount++;
		if( iSelectedItemsCount == iCount )
			{
			iSelectedItemsCount = 0;
			iCount = 0;
			}
		needRefresh = EFalse;
		}

    switch ( aEvent.iEventType )
        {
        case EPosLmEventLandmarkUpdated: 		// lm icon changes, lm renaming
        case EPosLmEventLandmarkUnknownChanges:	// lm multiple deletion, lm add to category
        case EPosLmEventUnknownChanges:
        case EPosLmEventLandmarkCreated:
        case EPosLmEventCategoryDeleted:
        case EPosLmEventCategoryUpdated:
            {
            iOperationNotInUse = EFalse;
           	if (aEvent.iEventType == EPosLmEventCategoryDeleted )
	            {
	            iCatDelete = ETrue;
	            }
	        if (aEvent.iEventType == EPosLmEventCategoryUpdated )
	            {
	            iCatUpdate = ETrue;
	            }

			if( needRefresh )
				{
		        if( iSearchAO )
		        	{
		        	iSearchAO->StopOperation();
					delete iSearchAO;
			        iSearchAO = NULL;
		        	}
	            iOperationNotInUse = EFalse;
	            TInt err = KErrNone;
	            do
	                {
	                TRAP( err, PrepareListL() );
	                }while(err == KErrLocked);
	            if ( err )
	                {
	                HandleError( err );
	                }
				}
			else
				{
				NotifyObservers( ELmkEventListReady );
				}
            break;
            }
        case EPosLmEventLandmarkDeleted:
        	{
		   	TInt index = iIdArray.Find( aEvent.iLandmarkItemId );
		   	if( index != KErrNotFound && index < iIdArray.Count())
		   		{
		   		iIdArray.Remove(index);
			   	NotifyObservers( ELmkEventListReady );
		   		}
		   	break;
        	}
        default:
            { // Not interesting event for this provider
            break;
            }
        }
    // Remember to call base class observer method too
    CLmkLmItemListProvider::HandleDatabaseEvent( aEvent );
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::ReadItemsToArrayL
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::ReadItemsToArrayL()
    {
    iIdArray.Reset();
    CPosLmItemIterator* iterator = iSearch->MatchIteratorL();
    CleanupStack::PushL( iterator );
    iCount = iterator->NumOfItemsL();
    if ( iCount > 0 )
        { // can only be called if there are some items
        iterator->GetItemIdsL( iIdArray, 0, iCount ); // array is first reseted
        }
    CleanupStack::PopAndDestroy( iterator );
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::RemoveLandmarksL
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::RemoveLandmarksL(const RArray<TPosLmItemId>& aSelectedItems )
	{
	iItemsToDelete = aSelectedItems.Count();
	iSelectedForDelete.Reset();
	for(TInt i=0;i<iItemsToDelete;i++)
		iSelectedForDelete.Append(aSelectedItems[i]);
	iItemsDeleted = 0;
	iIsRemoveLandmarks = ETrue;

	if(iWaitNote)
		{
		delete iWaitNote;
		iWaitNote = NULL;
		}
	PrepareForDeleteL();
	}

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::PrepareForDelete
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::PrepareForDeleteL()
	{
	RArray<TPosLmItemId> lmItemsChunk;
	TInt count = iItemsDeleted;
	if(iItemsToDelete > (iItemsDeleted + 10))
		{
		iItemsDeleted = iItemsDeleted + 10;
		}
	else
		{
		iItemsDeleted = iItemsDeleted + (iItemsToDelete - iItemsDeleted);
		}

	for(TInt i=count;i<iItemsDeleted;i++)
		{
		lmItemsChunk.Append(iSelectedForDelete[i]);
		}

	CPosLmOperation* operation = NULL;
	if(iType == MLmkAOOperationObserver::EDeleteLandmarks)
		{
		operation = iDb.RemoveLandmarksL( lmItemsChunk );
		}
	if(iType == MLmkAOOperationObserver::ERemoveCategory)
		{
		CPosLmCategoryManager* mgr = CPosLmCategoryManager::NewL( iDb );
		CleanupStack::PushL(mgr);
		operation = mgr->RemoveCategoryFromLandmarksL( iCategoryId, lmItemsChunk );
		CleanupStack::PopAndDestroy();//mgr
		}
	User::LeaveIfNull( operation );

	CleanupStack::PushL( operation );
	iSearchAO = CLmkAOOperation::NewL( operation,
	               *this,
	               iType,
	               EFalse );
	CleanupStack::Pop( operation ); // ownership transferred

    if( iSearchAO )
        {
        iSearchAO->StartOperation();

        if(!iWaitNote)
            {
            iWaitNote = new (ELeave) CAknWaitDialog(NULL, ETrue);
            if(!iWaitNote->ExecuteLD(R_LMK_PROCESSING_WAIT_NOTE))
                {
                iSearchAO->StopOperation();
                delete iSearchAO;
                iSearchAO = NULL;
                iWaitNote = NULL;
                }
            }
        }
	
	lmItemsChunk.Close();
	}

//  End of File