ipsservices/ipssossettings/src/ipssetuifinder.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 22:37:30 +0200
branchRCL_3
changeset 8 e1b6206813b4
parent 1 12c456ceeff2
permissions -rw-r--r--
Revision: 201003 Kit: 201007

/*
* Copyright (c) 2007 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 class for tree structure searching.
*
*/



#include "emailtrace.h"
#include <e32base.h>

#include "ipssetutilsconsts.h"
#include "ipssetuiitemlink.h"

#include "ipssetuifinder.h"

// ============================ MEMBER FUNCTIONS ===============================

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::CIpsSetUiFinder()
// ----------------------------------------------------------------------------
CIpsSetUiFinder::CIpsSetUiFinder(
    MIpsSetUiFinder& aObserver )
    :
    iObserver( aObserver ),
    iSubArrays( NULL ),
    iTempItem( NULL ),
    iSearchItem( 0 ),
    iCurrentItem( 0 ),
    iFinderArray( NULL )
    {
    FUNC_LOG;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::ConstructL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::ConstructL()
    {
    FUNC_LOG;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::~CIpsSetUiFinder()
// ----------------------------------------------------------------------------
//
CIpsSetUiFinder::~CIpsSetUiFinder()
    {
    FUNC_LOG;
    // Shouldn't exist but remove anyway
    if ( iSubArrays )
        {
        iSubArrays->Reset();
        }

    delete iSubArrays;
    iSubArrays = NULL;

    iTempItem = NULL;

    // Clean and remove the array
    if ( iFinderArray )
        {
        iFinderArray->Reset();
        }

    delete iFinderArray;
    iFinderArray = NULL;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::NewL()
// ----------------------------------------------------------------------------
//
CIpsSetUiFinder* CIpsSetUiFinder::NewL(
    MIpsSetUiFinder& aObserver )
    {
    FUNC_LOG;
    CIpsSetUiFinder* self = NewLC( aObserver );
    CleanupStack::Pop( self );

    return self;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::NewLC()
// ----------------------------------------------------------------------------
//
CIpsSetUiFinder* CIpsSetUiFinder::NewLC(
    MIpsSetUiFinder& aObserver )
    {
    FUNC_LOG;
    CIpsSetUiFinder* self =
        new ( ELeave ) CIpsSetUiFinder( aObserver );

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

    return self;
    }


// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SetSearchFlags()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::SetSearchFlags(
    const TUint64& aSearchFlags )
    {
    FUNC_LOG;
    iSearchFlags = aSearchFlags;
    }


// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SearchFlags()
// ----------------------------------------------------------------------------
//
TUint64 CIpsSetUiFinder::SearchFlags() const
    {
    FUNC_LOG;
    return iSearchFlags;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::StartSearchL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::StartSearchL(
    CIpsSetUiBaseItemArray& aItemArray,
    const TUid& aId )
    {
    FUNC_LOG;
    InitializeSearchL( KErrUnknown );
    SearchIdFromTreeL( aItemArray, aId );
    FinalizeSearchL();
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::StartSearchL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::StartSearchL(
    CIpsSetUiBaseItemArray& aItemArray,
    const TInt aNth )
    {
    FUNC_LOG;
    InitializeSearchL( aNth );
    SearchIndexFromTreeL( aItemArray );
    FinalizeSearchL();
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::InitializeSearchL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::InitializeSearchL(
    const TInt aItem )
    {
    FUNC_LOG;
    iSearchItem = aItem;
    iTempItem = NULL;

    // Clear flags
    iSearchFlags &= ~EFinderItemFound;
    iSearchFlags &= ~EFinderItemFindError;
    iSearchFlags &= ~EFinderExit;

    iSubArrays =
        new ( ELeave ) CIpsSetUiBaseItemArray( KIpsSetUiArrayGranularity );

    // Create arrays
    if ( !iFinderArray )
        {
        iFinderArray =
            new ( ELeave ) CIpsSetUiFinderArray( KIpsSetUiArrayGranularity );
        }
    // Clean and remove the array
    else if ( !( iSearchFlags & EFinderKeepLastResult ) )
        {
        iFinderArray->Reset();
        }
    else
        {
        // make lint to keep quiet
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::FinalizeSearchL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::FinalizeSearchL()
    {
    FUNC_LOG;
    if ( iSubArrays )
        {
        iSubArrays->Reset();
        }

    delete iSubArrays;
    iSubArrays = NULL;

    iTempItem = NULL;

    // Clear flags
    iSearchFlags &= ~( EFinderItemFound | EFinderItemFindError | EFinderExit );

    iSearchItem = 0;
    iCurrentItem = 0;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::ContinueSearch()
// ----------------------------------------------------------------------------
//
TBool CIpsSetUiFinder::ContinueSearch(
    const TInt aCurrentItem,
    const TInt aMaxItems )
    {
    FUNC_LOG;
    // First check if the search should be cancelled
    if ( iSearchFlags & EFinderExit )
        {
        return EFalse;
        }

    // Check if the item is found, and that it's enough
    if ( iSearchFlags & EFinderItemFound &&
         !( iSearchFlags & EFinderSearchAll ) &&
         !( iSearchFlags & EFinderResourceSearch ) )
        {
        return EFalse;
        }

    // Set the current item
    iCurrentItem = aCurrentItem;

    // Check if the last item is in progress
    if ( iCurrentItem >= aMaxItems )
        {
        if ( !( iSearchFlags & EFinderItemFound ) )
            {
            iSearchFlags |= EFinderItemFindError;
            }

        iSearchFlags |= EFinderExit;
        return EFalse;
        }

    // Do custom checks if needed
    if ( iSearchFlags & EFinderCustomCheck &&
         !iObserver.SearchDoContinuationCheck( *iTempItem, iCurrentItem ) )
        {
        iSearchFlags |= EFinderExit;
        return EFalse;
        }

    // New round is about to start, clear the item found flag
    iSearchFlags &= ~EFinderItemFound;

    // All checks done, continue searching
    return ETrue;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SearchingItem()
// ----------------------------------------------------------------------------
//
TBool CIpsSetUiFinder::SearchingItem()
    {
    FUNC_LOG;
    TBool result = EFalse;

    // If resource search, compare against resource id of the
    // current item
    if ( iSearchFlags & EFinderResourceSearch )
        {
        result = ( iTempItem->iItemResourceId == iSearchItem );
        }
    // When going through all items in the list, set found
    // item as true
    else if ( iSearchFlags & EFinderSearchAll )
        {
        result = ETrue;
        }
    // Index search is on, compare against the item index
    else
        {
        result = !iSearchItem--;
        }

    // Turn the flag according the search mode
    result ^= iSearchFlags & EFinderExlusiveSearch;

    return result;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::ItemToArrayL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::ItemToArrayL()
    {
    FUNC_LOG;
    TIpsSetFinderItem item;

    item.iIndex = iCurrentItem;
    item.iItem = iTempItem;
    iFinderArray->AppendL( item );
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::ItemCheck()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::ItemCheckL( const TUid& aId )
    {
    FUNC_LOG;
    // Make custom check for item, EXIT search
    if ( iSearchFlags & EFinderCustomCheck &&
         !iObserver.SearchDoItemCheck( *iTempItem ) )
        {
        return;
        }

    // If user has chosen to ingore rest of the checks, CONTINUE the search
    if ( iSearchFlags & EFinderOverrideChecks )
        {
        // Remove flags
        iSearchFlags &= ~EFinderItemFound;
        iSearchFlags &= ~EFinderExit;

        return;
        }

    // Id check
    if ( iTempItem->iItemId == aId )
        {
        // Id's of both items matches, so quit the search
        iSearchFlags |= EFinderItemFound;
        ItemToArrayL();
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::ItemCheckL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::ItemCheckL()
    {
    FUNC_LOG;
    // Make custom check for item, EXIT search
    if ( iSearchFlags & EFinderCustomCheck &&
         !iObserver.SearchDoItemCheck( *iTempItem ) )
        {
        // It's decided that item has matched, add to array
        iSearchFlags |= EFinderItemFound;
        ItemToArrayL();
        return;
        }

    // If user has chosen to ingore rest of the checks, CONTINUE the search
    if ( iSearchFlags & EFinderOverrideChecks )
        {
        // Remove flags
        iSearchFlags &= ~EFinderItemFound;
        iSearchFlags &= ~EFinderExit;
        iSearchFlags &= ~EFinderOverrideChecks;

        return;
        }

    // Make hidden item check
    // If EFinderDoHideCheck is turned on, hidden items are not allowed
    // to be included into the search. When off, hidden items, except
    // permanently hidden items, are included into search
    // The item is found, when iSearchItem reaches zero.
    if ( !IsHidden() && SearchingItem() )
        {
        // Id's of both items matches, so quit the search
        iSearchFlags |= EFinderItemFound;
        ItemToArrayL();
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::ItemSubArrayCheck()
// ----------------------------------------------------------------------------
//
TBool CIpsSetUiFinder::ItemSubArrayCheck()
    {
    FUNC_LOG;
    // Check if item quit is issued. The search shouldn't be cancelled even
    // if the item is found
    if ( iSearchFlags & EFinderExit )
        {
        return EFalse;
        }

    // Check if the subfolders need to be searched
    if ( !( iSearchFlags & EFinderSearchSubFolders ) )
        {
        return EFalse;
        }

    // Check if the item is subarray item
    if ( iTempItem->iItemType != EIpsSetUiMenuArray &&
         iTempItem->iItemType != EIpsSetUiRadioButtonArray &&
         iTempItem->iItemType != EIpsSetUiCheckBoxArray &&
         iTempItem->iItemType != EIpsSetUiItemMultiLine )
        {
        return EFalse;
        }

    return ETrue;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::ContinueSubSearch()
// ----------------------------------------------------------------------------
//
TBool CIpsSetUiFinder::ContinueSubSearch()
    {
    FUNC_LOG;
    // If search is finished, don't continue the search
    if ( iSearchFlags & EFinderExit )
        {
        return EFalse;
        }

    // If items left in subarray list
    return iSubArrays->Count() > 0;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::IsHidden()
// ----------------------------------------------------------------------------
//
TInt CIpsSetUiFinder::IsHidden()
    {
    FUNC_LOG;
    // Permanently hidden items are shown only, if the ownership of the
    // array is moved to client. As then the client will get full access
    // to items in the array
    TInt hidden = iObserver.IsHidden( *iTempItem );
    if ( hidden == KErrNotSupported && 
        !( ( iSearchFlags & EFinderMoveOwnership ) == EFinderMoveOwnership ) && 
        ( ( iSearchFlags & EFinderDoHideCheck ) == EFinderDoHideCheck ) )
        {
        return KErrNotSupported;
        }
    // Hidden items are available only, if flag EFinderDoHideCheck
    // is turned off.
    else if ( ( iSearchFlags & EFinderDoHideCheck ) && hidden == KErrNotFound )
        {
        return KErrNotFound;
        }
    // The item is included into the search
    else
        {
        return KErrNone;
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::DoIndexSearchL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::DoIndexSearchL(
    CIpsSetUiBaseItemArray& aItemArray )
    {
    FUNC_LOG;
    // Search for the item in the current array before moving inside
    // the subarrays
    TInt currentItem = 0;
    TInt max = aItemArray.Count();
    for ( ; ContinueSearch( currentItem, max ); currentItem++ )
        {
        // Store the item in array to member
        iTempItem = aItemArray[currentItem];

        // Check if the item matches and set quit flag if the id of the item
        // matches with the one that is searched
        ItemCheckL();

        // If the item wasn't the searched one, check if it contains subarray
        // and append it to stack, for later searching
        if ( ItemSubArrayCheck() )
            {
            iSubArrays->AppendL( iTempItem );
            }
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::DoIdSearchL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::DoIdSearchL(
    CIpsSetUiBaseItemArray& aItemArray,
    const TUid& aId )
    {
    FUNC_LOG;
    // Search for the item in the current array before moving inside
    // the subarrays
    TInt currentItem = 0;
    TInt max = aItemArray.Count();
    for ( ; ContinueSearch( currentItem, max ); currentItem++ )
        {
        // Store the item in array to member
        iTempItem = aItemArray[iCurrentItem];

        // Check if the item matches and set quit flag if the id of the item
        // matches with the one that is searched
        ItemCheckL( aId );

        // If the item wasn't the searched one, check if it contains subarray
        // and append it to stack, for later searching
        if ( ItemSubArrayCheck() )
            {
            iSubArrays->AppendL( iTempItem );
            }
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SearchSubArraysL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::DoIdSearchSubArraysL(
    const TUid& aId )
    {
    FUNC_LOG;
    // If the correct item couldn't be found from the array,
    // search from the subarrays
    while ( ContinueSubSearch() )
        {
        // Get the first item in the array and remove it from there
        CIpsSetUiItemLink* item =
            static_cast<CIpsSetUiItemLink*>( iSubArrays->At( 0 ) );
        iSubArrays->Delete( 0 );

        // Search through the new tree
        if ( item->HasLinkArray() )
            {            
            SearchIdFromTreeL( *item->iItemLinkArray, aId );
            }
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SearchSubArraysL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::DoIndexSearchSubArraysL()
    {
    FUNC_LOG;
    // If the correct item couldn't be found from the array,
    // search from the subarrays
    while ( ContinueSubSearch() )
        {
        // Get the first item in the array and remove it from there
        CIpsSetUiItemLink* item =
            static_cast<CIpsSetUiItemLink*>( iSubArrays->At( 0 ) );
        iSubArrays->Delete( 0 );

        // Search through the new tree
        if ( item->HasLinkArray() )
            {            
            SearchIndexFromTreeL( *item->iItemLinkArray );
            }
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SearchIdFromTreeL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::SearchIdFromTreeL(
    CIpsSetUiBaseItemArray& aItemArray,
    const TUid& aId )
    {
    FUNC_LOG;
    // The search is made in following pattern:
    // First: The given array is searched through until EFinderExit flag is
    //        set or the end has been reached. The flag is set when given
    //        item(s) is (are) found. Each matching item and its index will
    //        be stored into array.
    //        Each item is checked for subarrays (during the first search).
    //        If the item has subarray, the item will be stored for
    //        searching.
    // Second: After the given array has been searched, each subarray will
    //         be searched, until conditions mentioned above have met, or
    //         each of the subarray's has been searched through.
    // The function is recursive

    // Search for the item in the current array
    DoIdSearchL( aItemArray, aId );

    // Before searching subarrays, check if subarray search is actually
    // need at all
    SearchShouldStop();

    // Search through the subarrays, if any exists
    DoIdSearchSubArraysL( aId );
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SearchIndexFromTreeL()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::SearchIndexFromTreeL(
    CIpsSetUiBaseItemArray& aItemArray )
    {
    FUNC_LOG;
    // Search for the index from the existing array
    DoIndexSearchL( aItemArray );

    // Before searching subarrays, check if subarray search is actually
    // need at all
    SearchShouldStop();

    // Check the subarrays for the existing index
    DoIndexSearchSubArraysL();
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::SearchShouldStop()
// ----------------------------------------------------------------------------
//
void CIpsSetUiFinder::SearchShouldStop()
    {
    FUNC_LOG;
    // Check if searching has been issued to be stopped
    if ( iSearchFlags & EFinderExit )
        {
        // Store flags to variables to keep things readable
        TBool found = iSearchFlags & EFinderItemFound;
        TBool seekAll =
            iSearchFlags & EFinderResourceSearch ||
            iSearchFlags & EFinderSearchAll;

        // If item has been found and only single item is searched
        // allow quitting, otherwise the search must continue
        if ( found && !seekAll )
            {
            iSearchFlags |= EFinderExit;
            }
        else
            {
            iSearchFlags &= ~EFinderExit;
            }
        }
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::FinderArray()
// ----------------------------------------------------------------------------
//
CIpsSetUiFinderArray* CIpsSetUiFinder::FinderArray() const
    {
    FUNC_LOG;
    return iFinderArray;
    }

// ----------------------------------------------------------------------------
// CIpsSetUiFinder::CopyFinderArrayLC()
// ----------------------------------------------------------------------------
//
CIpsSetUiFinderArray* CIpsSetUiFinder::FinderArrayLC() const
    {
    FUNC_LOG;
    // Create new array object
    CIpsSetUiFinderArray* finderArray = 
        new ( ELeave ) CIpsSetUiFinderArray( KIpsSetUiArrayGranularity );
    CleanupStack::PushL( finderArray );

    // Duplicate the array
    TInt items = iFinderArray->Count();
    for ( TInt item = 0; item < items; item++ )
        {
        finderArray->AppendL( iFinderArray->At( item ) );
        }

    return finderArray;
    }



//  End of File