landmarksui/engine/src/CLmkSearchedLmListProvider.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:31:27 +0100
branchRCL_3
changeset 18 870918037e16
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
 * Copyright (c) 2002-2010 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>
#include "Debug.h"

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

#if defined(_DEBUG)
/// 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()
    {
    DEBUG( CLmkSearchedLmListProvider::PrepareListL start );
    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();
    DEBUG( CLmkSearchedLmListProvider::PrepareListL End );
    }

// -----------------------------------------------------------------------------
// CLmkSearchedLmListProvider::PrepareListL
// -----------------------------------------------------------------------------
//
TBool CLmkSearchedLmListProvider::PrepareListL(const TDesC& aSearchPattern,
        TBool aSearchOnlyInPreviousMatches)
    {
    iCount = 0;
    iRequestFromFindBox = ETrue;
    iOperationNotInUse = ETrue;
    iIsSecondSearchStarted = EFalse;
    DEBUG1( CLmkSearchedLmListProvider::PrepareListL 2 start with aSearchPattern = %d,aSearchPattern.Length());

    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();
    DEBUG( CLmkSearchedLmListProvider::PrepareListL 2 End );
    return ETrue;
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::StartSecondSearchL
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::StartSecondSearchL()
    {
    DEBUG( CLmkSearchedLmListProvider::StartSecondSearchL start );

    iIsSecondSearchStarted = ETrue;

    // 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

    iSearchAO->StartOperation();
    DEBUG( CLmkSearchedLmListProvider::StartSecondSearchL End );
    }

// ---------------------------------------------------------
// CLmkSearchedLmListProvider::HandleOperationL
// ---------------------------------------------------------
//
void CLmkSearchedLmListProvider::HandleOperationL(TOperationTypes aType,
        TReal32 aProgress, TInt aStatus)
    {
    DEBUG1( CLmkSearchedLmListProvider::HandleOperationL start aType=%d,aType);
    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;

            DEBUG2( CLmkSearchedLmListProvider::HandleOperationL iRequestFromFindBox=%d iIsSecondSearchStarted=%d
                    ,iRequestFromFindBox,iIsSecondSearchStarted);

            if (iRequestFromFindBox && iIsSecondSearchStarted == EFalse)
                {
                DEBUG( CLmkSearchedLmListProvider::HandleOperationL start secondsearch );
                StartSecondSearchL();
                return;
                }

            DEBUG( CLmkSearchedLmListProvider::HandleOperationL refresh list );

            iIsSecondSearchStarted = EFalse;

            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);
                    }
                }
            iRequestFromFindBox = EFalse;
            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