--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/viewframework/views/listview/src/glxpreviewthumbnailbinding.cpp Wed Sep 01 12:33:26 2010 +0100
@@ -0,0 +1,456 @@
+/*
+* 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;
+ ScaleBitmapToListSizeL(value->iBitmap, bitmap);
+ GLX_LOG_INFO1("iObserver.PreviewTNReadyL() iTrialCount=%d", iTrialCount);
+ iObserver.PreviewTNReadyL(bitmap, NULL);
+ }
+ 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);
+ }