photosgallery/viewframework/views/listview/src/glxpreviewthumbnailbinding.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 14 Sep 2010 21:19:17 +0300
branchRCL_3
changeset 64 34937ec34dac
parent 60 5b3385a43d68
child 75 01504893d9cb
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c) 2008-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 : Class defination for preview thumbnail in list view
*
*/


#include <mglxmedialist.h>
#include <glxthumbnailcontext.h>
#include <glxfilterfactory.h>                         // For TGlxFilterFactory
#include <glxthumbnailattributeinfo.h>
#include <glxuiutility.h>                               // For UiUtility instance
#include <glxtracer.h>
#include <glxlog.h>
#include <glxerrormanager.h>             // For CGlxErrormanager
#include <glxuistd.h>                    // Fetch context priority def'ns
#include <mglxcache.h> 
#include <ganes/HgDoubleGraphicList.h>

#include "glxpreviewthumbnailbinding.h"
#include "glxgeneraluiutilities.h"

const TInt KThumbnailsTimeTimeDelay(50000);
const TInt KWaitCount(30);
const TInt KPreviewThumbnailFetchCount(1);


// ----------------------------------------------------------------------------
// NewL
// ----------------------------------------------------------------------------
//
CGlxPreviewThumbnailBinding* CGlxPreviewThumbnailBinding::NewL(
        MPreviewTNObserver& aObserver)
	{
	TRACER("CGlxPreviewThumbnailBinding::NewL");
	CGlxPreviewThumbnailBinding* self = CGlxPreviewThumbnailBinding::NewLC(aObserver);
	CleanupStack::Pop(self);
	return self;	
	}

// ----------------------------------------------------------------------------
// NewLC
// ----------------------------------------------------------------------------
//
CGlxPreviewThumbnailBinding* CGlxPreviewThumbnailBinding::NewLC(
        MPreviewTNObserver& aObserver)
	{
	TRACER("CGlxPreviewThumbnailBinding::NewLC");
	CGlxPreviewThumbnailBinding* self = new(ELeave)CGlxPreviewThumbnailBinding(aObserver);
	CleanupStack::PushL(self);
    self->ConstructL();
	return self;
	}

// ----------------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------------
//
CGlxPreviewThumbnailBinding::CGlxPreviewThumbnailBinding(
        MPreviewTNObserver& aObserver)
: iObserver(aObserver)
	{
	}

// ----------------------------------------------------------------------------
// ConstructL
// ----------------------------------------------------------------------------
//
void CGlxPreviewThumbnailBinding::ConstructL()
    {
    TRACER("CGlxPreviewThumbnailBinding::ConstructL");
    iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
    CGlxUiUtility* uiUtility = CGlxUiUtility::UtilityL();
    CleanupClosePushL(*uiUtility);
    iGridIconSize = uiUtility->GetGridIconSize();
    CleanupStack::PopAndDestroy(uiUtility);
    
    // Filter that filters out any GIF, corrupted images     
    iPreviewFilter = TGlxFilterFactory::CreatePreviewTNFilterL();
    iThumbnailIterator.SetRange(KPreviewThumbnailFetchCount);
    iThumbnailContext = new (ELeave) CGlxAttributeContext(&iThumbnailIterator); 
    TMPXAttribute tnAttr( KGlxMediaIdThumbnail,
                        GlxFullThumbnailAttributeId(ETrue,
                            iGridIconSize.iWidth,iGridIconSize.iHeight) );
    iThumbnailContext->SetDefaultSpec(iGridIconSize.iWidth,
                                                iGridIconSize.iHeight);
    iThumbnailContext->AddAttributeL(tnAttr);
    }

// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
CGlxPreviewThumbnailBinding::~CGlxPreviewThumbnailBinding()
	{
	TRACER("CGlxPreviewThumbnailBinding::~CGlxPreviewThumbnailBinding");
    // close any medialist that exist
	if( iMediaList )
		{
        iMediaList->RemoveMediaListObserver( this );
        iMediaList->RemoveContext(iThumbnailContext);
        iMediaList->Close();
        iMediaList = NULL;
		}
    delete iThumbnailContext;
    delete iPreviewFilter;
	// cancel any outstanding request of the timer
	if(iTimer->IsActive())
	    {
	    iTimer->Cancel();
	    }
	delete iTimer;
	iTimer = NULL;	
	}

// ----------------------------------------------------------------------------
// TimerTickedL: we need to update only when required i.e, when the thumbnail count 
// has not reached till the max limit to be shown
// ----------------------------------------------------------------------------
//
void CGlxPreviewThumbnailBinding::TimerTickedL()
    {
    TRACER("CGlxPreviewThumbnailBinding::TimerTickedL");

    if (!iMediaList)
        {
        GLX_LOG_INFO("TimerTickedL() iMediaList == NULL!");
        return;
        }

    if (iMediaList->IsPopulated())
        {
        if (iMediaList->Count())
            {
            const TGlxMedia& item = iMediaList->Item(0);
            TMPXAttribute thumbnailAttribute(KGlxMediaIdThumbnail,
                    GlxFullThumbnailAttributeId(ETrue, iGridIconSize.iWidth,
                            iGridIconSize.iHeight));

            const CGlxThumbnailAttribute* value = item.ThumbnailAttribute(
                    thumbnailAttribute);
            if (value)
                {
                CFbsBitmap* bitmap = new (ELeave) CFbsBitmap;
                CleanupStack::PushL(bitmap);
                ScaleBitmapToListSizeL(value->iBitmap, bitmap);
                GLX_LOG_INFO1("iObserver.PreviewTNReadyL() iTrialCount=%d", iTrialCount);
                iObserver.PreviewTNReadyL(bitmap, NULL);
                CleanupStack::Pop(bitmap);
                }
            else
                {
                TInt tnError = GlxErrorManager::HasAttributeErrorL(
                        item.Properties(), KGlxMediaIdThumbnail);
                if (tnError != KErrNone || iTrialCount == KWaitCount)
                    {
                    GLX_LOG_INFO1("TimerTickedL() tnError(%d) / Max Trialcount reached", tnError);
                    iObserver.PreviewTNReadyL(NULL, NULL);
                    iTrialCount = 0;
                    return;
                    }
                iTrialCount++;
                }
            }
        else
            {
            // Media count is zero, 
            // Notify immedialtely to jump to the next item in the list 
            GLX_LOG_INFO("TimerTickedL() iMediaList->Count() = 0");
            iObserver.PreviewTNReadyL(NULL, NULL);
            }
        }
    }

// ----------------------------------------------------------------------------
// IsTimeL callback function invoked when timer expires
// ----------------------------------------------------------------------------
//    
TInt CGlxPreviewThumbnailBinding::IsTimeL( TAny* aSelf )
    {
    TRACER("CGlxPreviewThumbnailBinding::IsTimeL");
    if (aSelf)
        {
        TRACER("CGlxPreviewThumbnailBinding::IsTimeL");
        CGlxPreviewThumbnailBinding* self = static_cast<CGlxPreviewThumbnailBinding*>(aSelf);
        if(self)
            {
            self->TimerTickedL();
           }
        }
    return KErrNone;        
    }


// ----------------------------------------------------------------------------
// HandleItemChangedL
// This function basically closes the old medialist if any for ex. Tags, 
// Captured.. and then opens a new medialist with teh required filter.
// ----------------------------------------------------------------------------
//    
void CGlxPreviewThumbnailBinding::HandleItemChangedL(const CMPXCollectionPath& aPath,
        TBool  aIsRefreshNeeded, TBool aBackwardNavigation)
    {
    TRACER("CGlxPreviewThumbnailBinding::HandleItemChangedL");
    GLX_LOG_INFO("CGlxPreviewThumbnailBinding::HandleItemChangedL()");
    
    iTimerTicked = EFalse;
    iIsRefreshNeeded = aIsRefreshNeeded;

    // remove and close old medialist   
    if( iMediaList )
	    {
	    // Reset the trialCount to 0 while deleting the medialist 
	    iTrialCount = 0;
	    iMediaList->RemoveMediaListObserver( this );
        iMediaList->RemoveContext(iThumbnailContext);
        iMediaList->Close();
        iMediaList = NULL;
	    }
	    
    iMediaList = MGlxMediaList::InstanceL(aPath, KGlxIdNone, iPreviewFilter);
    iMediaList->AddContextL(iThumbnailContext, KGlxFetchContextPriorityNormal);
	// adding the medialist to observ any changes or updates done
	iMediaList->AddMediaListObserverL(this);

	if(aBackwardNavigation)
	    {
	    //On backward navigation start the timer manually, since we do not  
        //get the attribute callback.
        StartTimer();        
        }
    }

// ----------------------------------------------------------------------------
// StartTimer - Starts the timer based on the flag populateListTN's
// where the flag will be true, when initially the first thumbnails in the list
// are populated.
// ----------------------------------------------------------------------------
//    
void CGlxPreviewThumbnailBinding::StartTimer()
    {
    TRACER("CGlxPreviewThumbnailBinding::StartTimer");
    
    if (iTimer)
        {
        iTimer->Cancel();
        }
        
    iTimer->Start(KThumbnailsTimeTimeDelay, KThumbnailsTimeTimeDelay,
            TCallBack(IsTimeL, this));
    }

// ----------------------------------------------------------------------------
// StopTimer - Stop the timer
// ----------------------------------------------------------------------------
//    
void CGlxPreviewThumbnailBinding::StopTimer()
    {
    TRACER("CGlxPreviewThumbnailBinding::StopTimer");
        
    if (iTimer && iTimer->IsActive())
        {
        iTimer->Cancel();
        }
    }

// ----------------------------------------------------------------------------
// HandleItemAddedL
// ----------------------------------------------------------------------------
// 
void CGlxPreviewThumbnailBinding::HandleItemAddedL( TInt /*aStartIndex*/, TInt 
    /*aEndIndex*/, MGlxMediaList* /*aList*/ )
    {
    }

// ----------------------------------------------------------------------------
// HandleItemRemoved
// ----------------------------------------------------------------------------
//  
void CGlxPreviewThumbnailBinding::HandleItemRemovedL( TInt /*aStartIndex*/, TInt 
    /*aEndIndex*/, MGlxMediaList* /*aList*/ )
    {

    }

// ----------------------------------------------------------------------------
// HandleAttributesAvailableL
// Inside this function we are going to append the index for which we have valid 
// thumbnails and when the number of available thumbnails become equal to the 
// number of slots where thumbnail to be shown we go for updating them to visual
// item.
// ----------------------------------------------------------------------------
//  
void CGlxPreviewThumbnailBinding::HandleAttributesAvailableL( TInt aItemIndex, 
    const RArray<TMPXAttribute>& aAttributes, MGlxMediaList* /*aList*/ )
    {
    TRACER("CGlxPreviewThumbnailBinding::HandleAttributesAvailableL");

    TMPXAttribute thumbnailAttribute(KGlxMediaIdThumbnail, 
        GlxFullThumbnailAttributeId( ETrue,  iGridIconSize.iWidth, 
                iGridIconSize.iHeight ) );
                                                         
    TIdentityRelation< TMPXAttribute > match ( &TMPXAttribute::Match );
    
    if (KErrNotFound != aAttributes.Find( thumbnailAttribute, match ))
    	{
		const TGlxMedia& item = iMediaList->Item( aItemIndex );
        const CGlxThumbnailAttribute* value = item.ThumbnailAttribute( 
                thumbnailAttribute );
        if (value)
	        {
	        GLX_LOG_INFO("CGlxPreviewThumbnailBinding::HandleAttributesAvailableL()");
           	StartTimer();
            }
        }
    }
    
// ----------------------------------------------------------------------------
// HandleFocusChangedL
// ----------------------------------------------------------------------------
//  
void CGlxPreviewThumbnailBinding::HandleFocusChangedL( NGlxListDefs::
    TFocusChangeType /*aType*/, TInt /*aNewIndex*/, TInt /*aOldIndex*/, 
    MGlxMediaList* /*aList*/ )
    {
    
    }

// ----------   ------------------------------------------------------------------
// HandleItemSelected
// ----------------------------------------------------------------------------
//  
void CGlxPreviewThumbnailBinding::HandleItemSelectedL(TInt /*aIndex*/, 
    TBool /*aSelected*/, MGlxMediaList* /*aList*/ )
    {

    }

// ----------------------------------------------------------------------------
// HandleMessageL
// ----------------------------------------------------------------------------
//    
 void CGlxPreviewThumbnailBinding::HandleMessageL( const CMPXMessage& /*aMessage*/, 
    MGlxMediaList* /*aList*/ )
    {
    
    }
  
// ----------------------------------------------------------------------------
// HandleError
// ----------------------------------------------------------------------------
//
void CGlxPreviewThumbnailBinding::HandleError( TInt /*aError*/ ) 
    {
    
    }
  
// ----------------------------------------------------------------------------
// HandleCommandCompleteL
// ----------------------------------------------------------------------------
//  
void CGlxPreviewThumbnailBinding::HandleCommandCompleteL( CMPXCommand* 
        /*aCommandResult*/, 
    TInt /*aError*/, MGlxMediaList* /*aList*/ )
    {
    
    }
  
// ----------------------------------------------------------------------------
// HandleMediaL
// ----------------------------------------------------------------------------
//  
void CGlxPreviewThumbnailBinding::HandleMediaL( TInt /*aListIndex*/, 
        MGlxMediaList* /*aList*/ )
    {
    
    }
  
// ----------------------------------------------------------------------------
// HandleItemModifiedL
// ----------------------------------------------------------------------------
//  
void CGlxPreviewThumbnailBinding::HandleItemModifiedL( const RArray<TInt>& 
        /*aItemIndexes*/,
    MGlxMediaList* /*aList*/ )
    {
    
    }

// ----------------------------------------------------------------------------
// HandlePopulatedL
// ----------------------------------------------------------------------------
//
void CGlxPreviewThumbnailBinding::HandlePopulatedL( MGlxMediaList* /*aList*/ )
    {
	TRACER("CGlxPreviewThumbnailBinding::HandlePopulatedL()");
    GLX_LOG_INFO("CGlxPreviewThumbnailBinding::HandlePopulatedL()");

	// Do cache cleanup. If iIsRefreshNeeded is set,
	// then clean up the item at 0th index 
	if (iIsRefreshNeeded)
		{
		if (iMediaList && iMediaList->Count() > 0)
			{
			GLX_LOG_INFO("**** Cache Cleanup ****");
			MGlxCache* cacheManager = MGlxCache::InstanceL();
			cacheManager->ForceCleanupMedia(iMediaList->IdSpaceId(0),
					iMediaList->Item(0).Id());
			cacheManager->Close();
			}
		}
	//Start the timer
	StartTimer();
	}

// ----------------------------------------------------------------------------
// ScaleBitmapToListSizeL
// ----------------------------------------------------------------------------
//
void CGlxPreviewThumbnailBinding::ScaleBitmapToListSizeL(
        CFbsBitmap* aSrcBitmap, CFbsBitmap* aDestBitmap)
    {
    TRACER("CGlxPreviewThumbnailBinding::ScaleBitmapToListSizeL()");
    TSize destSize = CHgDoubleGraphicList::PreferredImageSize();
    TSize srcSize = aSrcBitmap->SizeInPixels();
    if (destSize.iHeight * srcSize.iWidth < destSize.iWidth * srcSize.iHeight)
        {
        // Source has taller aspect than target so reduce target width
        destSize.iWidth = ((destSize.iHeight * srcSize.iWidth)
                / (srcSize.iHeight));
        }
    else
        {
        // Source has wider aspect than target so reduce target height
        destSize.iHeight = (destSize.iWidth * srcSize.iHeight)
                / srcSize.iWidth;
        }
    aDestBitmap->Create(destSize, aSrcBitmap->DisplayMode());
    CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(aDestBitmap);
    CleanupStack::PushL(bitmapDevice);
    CFbsBitGc* bitmapGc = CFbsBitGc::NewL();
    CleanupStack::PushL(bitmapGc);
    bitmapGc->Activate(bitmapDevice);
    bitmapGc->DrawBitmap(TRect(destSize), aSrcBitmap);
    CleanupStack::PopAndDestroy(bitmapGc);
    CleanupStack::PopAndDestroy(bitmapDevice);
    }