|
1 /* |
|
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description : Class defination for preview thumbnail in list view |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <mglxmedialist.h> |
|
20 #include <glxthumbnailcontext.h> |
|
21 #include <glxfilterfactory.h> // For TGlxFilterFactory |
|
22 #include <glxthumbnailattributeinfo.h> |
|
23 #include <glxuiutility.h> // For UiUtility instance |
|
24 #include <glxtracer.h> |
|
25 #include <glxlog.h> |
|
26 #include <glxerrormanager.h> // For CGlxErrormanager |
|
27 #include <glxuistd.h> // Fetch context priority def'ns |
|
28 #include <mglxcache.h> |
|
29 #include <ganes/HgDoubleGraphicList.h> |
|
30 |
|
31 #include "glxpreviewthumbnailbinding.h" |
|
32 #include "glxgeneraluiutilities.h" |
|
33 |
|
34 const TInt KThumbnailsTimeTimeDelay(50000); |
|
35 const TInt KWaitCount(30); |
|
36 const TInt KPreviewThumbnailFetchCount(1); |
|
37 |
|
38 |
|
39 // ---------------------------------------------------------------------------- |
|
40 // NewL |
|
41 // ---------------------------------------------------------------------------- |
|
42 // |
|
43 CGlxPreviewThumbnailBinding* CGlxPreviewThumbnailBinding::NewL( |
|
44 MPreviewTNObserver& aObserver) |
|
45 { |
|
46 TRACER("CGlxPreviewThumbnailBinding::NewL"); |
|
47 CGlxPreviewThumbnailBinding* self = CGlxPreviewThumbnailBinding::NewLC(aObserver); |
|
48 CleanupStack::Pop(self); |
|
49 return self; |
|
50 } |
|
51 |
|
52 // ---------------------------------------------------------------------------- |
|
53 // NewLC |
|
54 // ---------------------------------------------------------------------------- |
|
55 // |
|
56 CGlxPreviewThumbnailBinding* CGlxPreviewThumbnailBinding::NewLC( |
|
57 MPreviewTNObserver& aObserver) |
|
58 { |
|
59 TRACER("CGlxPreviewThumbnailBinding::NewLC"); |
|
60 CGlxPreviewThumbnailBinding* self = new(ELeave)CGlxPreviewThumbnailBinding(aObserver); |
|
61 CleanupStack::PushL(self); |
|
62 self->ConstructL(); |
|
63 return self; |
|
64 } |
|
65 |
|
66 // ---------------------------------------------------------------------------- |
|
67 // Constructor |
|
68 // ---------------------------------------------------------------------------- |
|
69 // |
|
70 CGlxPreviewThumbnailBinding::CGlxPreviewThumbnailBinding( |
|
71 MPreviewTNObserver& aObserver) |
|
72 : iObserver(aObserver) |
|
73 { |
|
74 } |
|
75 |
|
76 // ---------------------------------------------------------------------------- |
|
77 // ConstructL |
|
78 // ---------------------------------------------------------------------------- |
|
79 // |
|
80 void CGlxPreviewThumbnailBinding::ConstructL() |
|
81 { |
|
82 TRACER("CGlxPreviewThumbnailBinding::ConstructL"); |
|
83 iTimer = CPeriodic::NewL( CActive::EPriorityStandard ); |
|
84 CGlxUiUtility* uiUtility = CGlxUiUtility::UtilityL(); |
|
85 CleanupClosePushL(*uiUtility); |
|
86 iGridIconSize = uiUtility->GetGridIconSize(); |
|
87 CleanupStack::PopAndDestroy(uiUtility); |
|
88 |
|
89 // Filter that filters out any GIF, corrupted images |
|
90 iPreviewFilter = TGlxFilterFactory::CreatePreviewTNFilterL(); |
|
91 iThumbnailIterator.SetRange(KPreviewThumbnailFetchCount); |
|
92 iThumbnailContext = new (ELeave) CGlxAttributeContext(&iThumbnailIterator); |
|
93 TMPXAttribute tnAttr( KGlxMediaIdThumbnail, |
|
94 GlxFullThumbnailAttributeId(ETrue, |
|
95 iGridIconSize.iWidth,iGridIconSize.iHeight) ); |
|
96 iThumbnailContext->SetDefaultSpec(iGridIconSize.iWidth, |
|
97 iGridIconSize.iHeight); |
|
98 iThumbnailContext->AddAttributeL(tnAttr); |
|
99 } |
|
100 |
|
101 // ---------------------------------------------------------------------------- |
|
102 // Destructor |
|
103 // ---------------------------------------------------------------------------- |
|
104 // |
|
105 CGlxPreviewThumbnailBinding::~CGlxPreviewThumbnailBinding() |
|
106 { |
|
107 TRACER("CGlxPreviewThumbnailBinding::~CGlxPreviewThumbnailBinding"); |
|
108 // close any medialist that exist |
|
109 if( iMediaList ) |
|
110 { |
|
111 iMediaList->RemoveMediaListObserver( this ); |
|
112 iMediaList->RemoveContext(iThumbnailContext); |
|
113 iMediaList->Close(); |
|
114 iMediaList = NULL; |
|
115 } |
|
116 delete iThumbnailContext; |
|
117 delete iPreviewFilter; |
|
118 // cancel any outstanding request of the timer |
|
119 if(iTimer->IsActive()) |
|
120 { |
|
121 iTimer->Cancel(); |
|
122 } |
|
123 delete iTimer; |
|
124 iTimer = NULL; |
|
125 } |
|
126 |
|
127 // ---------------------------------------------------------------------------- |
|
128 // TimerTickedL: we need to update only when required i.e, when the thumbnail count |
|
129 // has not reached till the max limit to be shown |
|
130 // ---------------------------------------------------------------------------- |
|
131 // |
|
132 void CGlxPreviewThumbnailBinding::TimerTickedL() |
|
133 { |
|
134 TRACER("CGlxPreviewThumbnailBinding::TimerTickedL"); |
|
135 |
|
136 if (!iMediaList) |
|
137 { |
|
138 GLX_LOG_INFO("TimerTickedL() iMediaList == NULL!"); |
|
139 return; |
|
140 } |
|
141 |
|
142 if (iMediaList->IsPopulated()) |
|
143 { |
|
144 if (iMediaList->Count()) |
|
145 { |
|
146 const TGlxMedia& item = iMediaList->Item(0); |
|
147 TMPXAttribute thumbnailAttribute(KGlxMediaIdThumbnail, |
|
148 GlxFullThumbnailAttributeId(ETrue, iGridIconSize.iWidth, |
|
149 iGridIconSize.iHeight)); |
|
150 |
|
151 const CGlxThumbnailAttribute* value = item.ThumbnailAttribute( |
|
152 thumbnailAttribute); |
|
153 if (value) |
|
154 { |
|
155 CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; |
|
156 ScaleBitmapToListSizeL(value->iBitmap, bitmap); |
|
157 GLX_LOG_INFO1("iObserver.PreviewTNReadyL() iTrialCount=%d", iTrialCount); |
|
158 iObserver.PreviewTNReadyL(bitmap, NULL); |
|
159 } |
|
160 else |
|
161 { |
|
162 TInt tnError = GlxErrorManager::HasAttributeErrorL( |
|
163 item.Properties(), KGlxMediaIdThumbnail); |
|
164 if (tnError != KErrNone || iTrialCount == KWaitCount) |
|
165 { |
|
166 GLX_LOG_INFO1("TimerTickedL() tnError(%d) / Max Trialcount reached", tnError); |
|
167 iObserver.PreviewTNReadyL(NULL, NULL); |
|
168 iTrialCount = 0; |
|
169 return; |
|
170 } |
|
171 iTrialCount++; |
|
172 } |
|
173 } |
|
174 else |
|
175 { |
|
176 // Media count is zero, |
|
177 // Notify immedialtely to jump to the next item in the list |
|
178 GLX_LOG_INFO("TimerTickedL() iMediaList->Count() = 0"); |
|
179 iObserver.PreviewTNReadyL(NULL, NULL); |
|
180 } |
|
181 } |
|
182 } |
|
183 |
|
184 // ---------------------------------------------------------------------------- |
|
185 // IsTimeL callback function invoked when timer expires |
|
186 // ---------------------------------------------------------------------------- |
|
187 // |
|
188 TInt CGlxPreviewThumbnailBinding::IsTimeL( TAny* aSelf ) |
|
189 { |
|
190 TRACER("CGlxPreviewThumbnailBinding::IsTimeL"); |
|
191 if (aSelf) |
|
192 { |
|
193 TRACER("CGlxPreviewThumbnailBinding::IsTimeL"); |
|
194 CGlxPreviewThumbnailBinding* self = static_cast<CGlxPreviewThumbnailBinding*>(aSelf); |
|
195 if(self) |
|
196 { |
|
197 self->TimerTickedL(); |
|
198 } |
|
199 } |
|
200 return KErrNone; |
|
201 } |
|
202 |
|
203 |
|
204 // ---------------------------------------------------------------------------- |
|
205 // HandleItemChangedL |
|
206 // This function basically closes the old medialist if any for ex. Tags, |
|
207 // Captured.. and then opens a new medialist with teh required filter. |
|
208 // ---------------------------------------------------------------------------- |
|
209 // |
|
210 void CGlxPreviewThumbnailBinding::HandleItemChangedL(const CMPXCollectionPath& aPath, |
|
211 TBool aIsRefreshNeeded, TBool aBackwardNavigation) |
|
212 { |
|
213 TRACER("CGlxPreviewThumbnailBinding::HandleItemChangedL"); |
|
214 GLX_LOG_INFO("CGlxPreviewThumbnailBinding::HandleItemChangedL()"); |
|
215 |
|
216 iTimerTicked = EFalse; |
|
217 iIsRefreshNeeded = aIsRefreshNeeded; |
|
218 |
|
219 // remove and close old medialist |
|
220 if( iMediaList ) |
|
221 { |
|
222 // Reset the trialCount to 0 while deleting the medialist |
|
223 iTrialCount = 0; |
|
224 iMediaList->RemoveMediaListObserver( this ); |
|
225 iMediaList->RemoveContext(iThumbnailContext); |
|
226 iMediaList->Close(); |
|
227 iMediaList = NULL; |
|
228 } |
|
229 |
|
230 iMediaList = MGlxMediaList::InstanceL(aPath, KGlxIdNone, iPreviewFilter); |
|
231 iMediaList->AddContextL(iThumbnailContext, KGlxFetchContextPriorityNormal); |
|
232 // adding the medialist to observ any changes or updates done |
|
233 iMediaList->AddMediaListObserverL(this); |
|
234 |
|
235 if(aBackwardNavigation) |
|
236 { |
|
237 //On backward navigation start the timer manually, since we do not |
|
238 //get the attribute callback. |
|
239 StartTimer(); |
|
240 } |
|
241 } |
|
242 |
|
243 // ---------------------------------------------------------------------------- |
|
244 // StartTimer - Starts the timer based on the flag populateListTN's |
|
245 // where the flag will be true, when initially the first thumbnails in the list |
|
246 // are populated. |
|
247 // ---------------------------------------------------------------------------- |
|
248 // |
|
249 void CGlxPreviewThumbnailBinding::StartTimer() |
|
250 { |
|
251 TRACER("CGlxPreviewThumbnailBinding::StartTimer"); |
|
252 |
|
253 if (iTimer) |
|
254 { |
|
255 iTimer->Cancel(); |
|
256 } |
|
257 |
|
258 iTimer->Start(KThumbnailsTimeTimeDelay, KThumbnailsTimeTimeDelay, |
|
259 TCallBack(IsTimeL, this)); |
|
260 } |
|
261 |
|
262 // ---------------------------------------------------------------------------- |
|
263 // StopTimer - Stop the timer |
|
264 // ---------------------------------------------------------------------------- |
|
265 // |
|
266 void CGlxPreviewThumbnailBinding::StopTimer() |
|
267 { |
|
268 TRACER("CGlxPreviewThumbnailBinding::StopTimer"); |
|
269 |
|
270 if (iTimer && iTimer->IsActive()) |
|
271 { |
|
272 iTimer->Cancel(); |
|
273 } |
|
274 } |
|
275 |
|
276 // ---------------------------------------------------------------------------- |
|
277 // HandleItemAddedL |
|
278 // ---------------------------------------------------------------------------- |
|
279 // |
|
280 void CGlxPreviewThumbnailBinding::HandleItemAddedL( TInt /*aStartIndex*/, TInt |
|
281 /*aEndIndex*/, MGlxMediaList* /*aList*/ ) |
|
282 { |
|
283 } |
|
284 |
|
285 // ---------------------------------------------------------------------------- |
|
286 // HandleItemRemoved |
|
287 // ---------------------------------------------------------------------------- |
|
288 // |
|
289 void CGlxPreviewThumbnailBinding::HandleItemRemovedL( TInt /*aStartIndex*/, TInt |
|
290 /*aEndIndex*/, MGlxMediaList* /*aList*/ ) |
|
291 { |
|
292 |
|
293 } |
|
294 |
|
295 // ---------------------------------------------------------------------------- |
|
296 // HandleAttributesAvailableL |
|
297 // Inside this function we are going to append the index for which we have valid |
|
298 // thumbnails and when the number of available thumbnails become equal to the |
|
299 // number of slots where thumbnail to be shown we go for updating them to visual |
|
300 // item. |
|
301 // ---------------------------------------------------------------------------- |
|
302 // |
|
303 void CGlxPreviewThumbnailBinding::HandleAttributesAvailableL( TInt aItemIndex, |
|
304 const RArray<TMPXAttribute>& aAttributes, MGlxMediaList* /*aList*/ ) |
|
305 { |
|
306 TRACER("CGlxPreviewThumbnailBinding::HandleAttributesAvailableL"); |
|
307 |
|
308 TMPXAttribute thumbnailAttribute(KGlxMediaIdThumbnail, |
|
309 GlxFullThumbnailAttributeId( ETrue, iGridIconSize.iWidth, |
|
310 iGridIconSize.iHeight ) ); |
|
311 |
|
312 TIdentityRelation< TMPXAttribute > match ( &TMPXAttribute::Match ); |
|
313 |
|
314 if (KErrNotFound != aAttributes.Find( thumbnailAttribute, match )) |
|
315 { |
|
316 const TGlxMedia& item = iMediaList->Item( aItemIndex ); |
|
317 const CGlxThumbnailAttribute* value = item.ThumbnailAttribute( |
|
318 thumbnailAttribute ); |
|
319 if (value) |
|
320 { |
|
321 GLX_LOG_INFO("CGlxPreviewThumbnailBinding::HandleAttributesAvailableL()"); |
|
322 StartTimer(); |
|
323 } |
|
324 } |
|
325 } |
|
326 |
|
327 // ---------------------------------------------------------------------------- |
|
328 // HandleFocusChangedL |
|
329 // ---------------------------------------------------------------------------- |
|
330 // |
|
331 void CGlxPreviewThumbnailBinding::HandleFocusChangedL( NGlxListDefs:: |
|
332 TFocusChangeType /*aType*/, TInt /*aNewIndex*/, TInt /*aOldIndex*/, |
|
333 MGlxMediaList* /*aList*/ ) |
|
334 { |
|
335 |
|
336 } |
|
337 |
|
338 // ---------- ------------------------------------------------------------------ |
|
339 // HandleItemSelected |
|
340 // ---------------------------------------------------------------------------- |
|
341 // |
|
342 void CGlxPreviewThumbnailBinding::HandleItemSelectedL(TInt /*aIndex*/, |
|
343 TBool /*aSelected*/, MGlxMediaList* /*aList*/ ) |
|
344 { |
|
345 |
|
346 } |
|
347 |
|
348 // ---------------------------------------------------------------------------- |
|
349 // HandleMessageL |
|
350 // ---------------------------------------------------------------------------- |
|
351 // |
|
352 void CGlxPreviewThumbnailBinding::HandleMessageL( const CMPXMessage& /*aMessage*/, |
|
353 MGlxMediaList* /*aList*/ ) |
|
354 { |
|
355 |
|
356 } |
|
357 |
|
358 // ---------------------------------------------------------------------------- |
|
359 // HandleError |
|
360 // ---------------------------------------------------------------------------- |
|
361 // |
|
362 void CGlxPreviewThumbnailBinding::HandleError( TInt /*aError*/ ) |
|
363 { |
|
364 |
|
365 } |
|
366 |
|
367 // ---------------------------------------------------------------------------- |
|
368 // HandleCommandCompleteL |
|
369 // ---------------------------------------------------------------------------- |
|
370 // |
|
371 void CGlxPreviewThumbnailBinding::HandleCommandCompleteL( CMPXCommand* |
|
372 /*aCommandResult*/, |
|
373 TInt /*aError*/, MGlxMediaList* /*aList*/ ) |
|
374 { |
|
375 |
|
376 } |
|
377 |
|
378 // ---------------------------------------------------------------------------- |
|
379 // HandleMediaL |
|
380 // ---------------------------------------------------------------------------- |
|
381 // |
|
382 void CGlxPreviewThumbnailBinding::HandleMediaL( TInt /*aListIndex*/, |
|
383 MGlxMediaList* /*aList*/ ) |
|
384 { |
|
385 |
|
386 } |
|
387 |
|
388 // ---------------------------------------------------------------------------- |
|
389 // HandleItemModifiedL |
|
390 // ---------------------------------------------------------------------------- |
|
391 // |
|
392 void CGlxPreviewThumbnailBinding::HandleItemModifiedL( const RArray<TInt>& |
|
393 /*aItemIndexes*/, |
|
394 MGlxMediaList* /*aList*/ ) |
|
395 { |
|
396 |
|
397 } |
|
398 |
|
399 // ---------------------------------------------------------------------------- |
|
400 // HandlePopulatedL |
|
401 // ---------------------------------------------------------------------------- |
|
402 // |
|
403 void CGlxPreviewThumbnailBinding::HandlePopulatedL( MGlxMediaList* /*aList*/ ) |
|
404 { |
|
405 TRACER("CGlxPreviewThumbnailBinding::HandlePopulatedL()"); |
|
406 GLX_LOG_INFO("CGlxPreviewThumbnailBinding::HandlePopulatedL()"); |
|
407 |
|
408 // Do cache cleanup. If iIsRefreshNeeded is set, |
|
409 // then clean up the item at 0th index |
|
410 if (iIsRefreshNeeded) |
|
411 { |
|
412 if (iMediaList && iMediaList->Count() > 0) |
|
413 { |
|
414 GLX_LOG_INFO("**** Cache Cleanup ****"); |
|
415 MGlxCache* cacheManager = MGlxCache::InstanceL(); |
|
416 cacheManager->ForceCleanupMedia(iMediaList->IdSpaceId(0), |
|
417 iMediaList->Item(0).Id()); |
|
418 cacheManager->Close(); |
|
419 } |
|
420 } |
|
421 //Start the timer |
|
422 StartTimer(); |
|
423 } |
|
424 |
|
425 // ---------------------------------------------------------------------------- |
|
426 // ScaleBitmapToListSizeL |
|
427 // ---------------------------------------------------------------------------- |
|
428 // |
|
429 void CGlxPreviewThumbnailBinding::ScaleBitmapToListSizeL( |
|
430 CFbsBitmap* aSrcBitmap, CFbsBitmap* aDestBitmap) |
|
431 { |
|
432 TRACER("CGlxPreviewThumbnailBinding::ScaleBitmapToListSizeL()"); |
|
433 TSize destSize = CHgDoubleGraphicList::PreferredImageSize(); |
|
434 TSize srcSize = aSrcBitmap->SizeInPixels(); |
|
435 if (destSize.iHeight * srcSize.iWidth < destSize.iWidth * srcSize.iHeight) |
|
436 { |
|
437 // Source has taller aspect than target so reduce target width |
|
438 destSize.iWidth = ((destSize.iHeight * srcSize.iWidth) |
|
439 / (srcSize.iHeight)); |
|
440 } |
|
441 else |
|
442 { |
|
443 // Source has wider aspect than target so reduce target height |
|
444 destSize.iHeight = (destSize.iWidth * srcSize.iHeight) |
|
445 / srcSize.iWidth; |
|
446 } |
|
447 aDestBitmap->Create(destSize, aSrcBitmap->DisplayMode()); |
|
448 CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(aDestBitmap); |
|
449 CleanupStack::PushL(bitmapDevice); |
|
450 CFbsBitGc* bitmapGc = CFbsBitGc::NewL(); |
|
451 CleanupStack::PushL(bitmapGc); |
|
452 bitmapGc->Activate(bitmapDevice); |
|
453 bitmapGc->DrawBitmap(TRect(destSize), aSrcBitmap); |
|
454 CleanupStack::PopAndDestroy(bitmapGc); |
|
455 CleanupStack::PopAndDestroy(bitmapDevice); |
|
456 } |