|
1 /* |
|
2 * Copyright (c) 2005-2007 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: Content renderer implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 // System includes |
|
19 #include <e32hashtab.h> |
|
20 #include <utf.h> |
|
21 #include <gulicon.h> |
|
22 |
|
23 // User includes |
|
24 |
|
25 #include "contentrenderer.h" |
|
26 #include "appui.h" |
|
27 #include "activetransactionstack.h" |
|
28 #include "transactionfactoryimpl.h" |
|
29 #include "mtransaction.h" |
|
30 #include "mtransactionelement.h" |
|
31 #include "aixmluiutils.h" |
|
32 #include "xmluicontroller.h" |
|
33 #include "xmlnodeidgenerator.h" |
|
34 #include "aixmluiconstants.h" |
|
35 #include "aifweventhandler.h" |
|
36 #include "databuffertransactionelement.h" |
|
37 #include "newstickercallbackhandler.h" |
|
38 #include "newstickertransactionelement.h" |
|
39 #include "csspropertymap.h" |
|
40 #include "policyevaluator.h" |
|
41 #include "debug.h" |
|
42 #include "xnuiengineappif.h" |
|
43 #include "xnnodeappif.h" |
|
44 #include "xnproperty.h" |
|
45 #include "mxncomponentinterface.h" |
|
46 #include "xntext.h" |
|
47 #include "xnbitmap.h" |
|
48 #include "xntype.h" |
|
49 #include "xnmenuadapter.h" |
|
50 #include "xnlistquerydialogadapter.h" |
|
51 #include "mxncomponentinterface.h" |
|
52 #include "aistrcnv.h" |
|
53 #include "contentprioritymap.h" |
|
54 #include "ainativeuiplugins.h" |
|
55 |
|
56 using namespace AiXmlUiController; |
|
57 using namespace AiUiDef::xml; |
|
58 using namespace XnTextInterface; |
|
59 using namespace XnImageInterface; |
|
60 |
|
61 namespace |
|
62 { |
|
63 typedef RPointerArray<CXnNodeAppIf> RXnNodeArray; |
|
64 |
|
65 /** |
|
66 * Gets content item iterator. |
|
67 * |
|
68 * @param aPlugin plugin to fetch the iterator |
|
69 * @param aContentType type of iterator (content/resource/event) |
|
70 * @return the iterator |
|
71 * @leave KErrNotSupported if plugin does not provide iterator |
|
72 */ |
|
73 static MAiContentItemIterator& ContentItemIteratorL( MAiPropertyExtension& aPlugin, |
|
74 TInt aContentType ) |
|
75 { |
|
76 MAiContentItemIterator* iter = |
|
77 static_cast< MAiContentItemIterator* >( aPlugin.GetPropertyL( aContentType ) ); |
|
78 |
|
79 if ( !iter ) |
|
80 { |
|
81 User::Leave( KErrNotSupported ); |
|
82 } |
|
83 |
|
84 return *iter; |
|
85 } |
|
86 |
|
87 /** |
|
88 * Gets the content priority associated in the property element. |
|
89 * |
|
90 * @param aPropertyElement the property element |
|
91 * @return priority value or KErrNotFound for non-prioritized element |
|
92 */ |
|
93 TInt GetContentPriority( CXnNodeAppIf& aPropertyElement ) |
|
94 { |
|
95 TInt32 priority( KErrNotFound ); |
|
96 |
|
97 const TDesC8* name = PropertyValue( aPropertyElement, |
|
98 property::KName ); |
|
99 |
|
100 |
|
101 if ( name && *name == name::KPriority ) |
|
102 { |
|
103 const TDesC8* value = PropertyValue( aPropertyElement, |
|
104 property::KValue ); |
|
105 if ( value ) |
|
106 { |
|
107 AiUtility::ParseInt( priority, *value ); |
|
108 } |
|
109 } |
|
110 |
|
111 return priority; |
|
112 } |
|
113 |
|
114 /** |
|
115 * Remove elements from array which do not contain priority or priority is not lower than |
|
116 * the given value. |
|
117 * |
|
118 * @param aElements array of elements |
|
119 * @param aLastPriority upper bound of priority value (excluded from the array) |
|
120 */ |
|
121 void RemoveNonPriorityElements( RPointerArray< CXnNodeAppIf>& aElements, |
|
122 TInt aLastPriority ) |
|
123 { |
|
124 // Remove non priority elements and higher priority elements |
|
125 |
|
126 TInt elementCount = aElements.Count(); |
|
127 for ( TInt i = 0; i < elementCount; ) |
|
128 { |
|
129 CXnNodeAppIf* current = aElements[i]; |
|
130 |
|
131 // Check name attribute |
|
132 const TDesC8* name = PropertyValue( *current, property::KName ); |
|
133 |
|
134 if ( !name || *name != name::KPriority ) |
|
135 { |
|
136 // Remove current |
|
137 aElements.Remove( i ); |
|
138 --elementCount; |
|
139 } |
|
140 else |
|
141 { |
|
142 // Check current priority |
|
143 const TDesC8* value = PropertyValue( *current, property::KValue ); |
|
144 |
|
145 if ( !value ) // value not present |
|
146 { |
|
147 aElements.Remove( i ); |
|
148 --elementCount; |
|
149 continue; |
|
150 } |
|
151 |
|
152 TInt32 currentPriority( KErrNotFound ); |
|
153 if ( AiUtility::ParseInt( currentPriority, *value ) != KErrNone ) |
|
154 { |
|
155 // value is not integer |
|
156 aElements.Remove( i ); |
|
157 --elementCount; |
|
158 continue; |
|
159 } |
|
160 |
|
161 if ( currentPriority < aLastPriority ) |
|
162 { |
|
163 // Keep element and iterate further |
|
164 ++i; |
|
165 } |
|
166 else |
|
167 { |
|
168 // priority is too high |
|
169 aElements.Remove( i ); |
|
170 --elementCount; |
|
171 } |
|
172 } |
|
173 } |
|
174 } |
|
175 |
|
176 /** |
|
177 * Descending priority order for prioritized content selectors. |
|
178 * |
|
179 * @param aNode1 First node to compare |
|
180 * @param aNode2 Second node to compare |
|
181 * @return 0 nodes have equal priority |
|
182 * @return >0 aNode1 has lower priority |
|
183 * @return <0 aNode2 has lower priority |
|
184 */ |
|
185 TInt DescendingPriorityOrder( const CXnNodeAppIf& aNode1, |
|
186 const CXnNodeAppIf& aNode2 ) |
|
187 { |
|
188 // Array content has been validated, so no checks are needed |
|
189 const TDesC8* value1 = PropertyValue( aNode1, |
|
190 property::KValue ); |
|
191 |
|
192 const TDesC8* value2 = PropertyValue( aNode2, |
|
193 property::KValue ); |
|
194 |
|
195 TInt32 priority1( KErrNotFound ); |
|
196 AiUtility::ParseInt( priority1, *value1 ); |
|
197 |
|
198 TInt32 priority2( KErrNotFound ); |
|
199 AiUtility::ParseInt( priority2, *value2 ); |
|
200 |
|
201 if ( priority1 == priority2 ) |
|
202 { |
|
203 return 0; |
|
204 } |
|
205 |
|
206 return ( priority1 < priority2 ) ? 1 : -1; |
|
207 } |
|
208 |
|
209 /** |
|
210 * Removes duplicate entries in content change array |
|
211 */ |
|
212 void RemoveDuplicateContentChangesL( RAiPolicyElementArray& aArray ) |
|
213 { |
|
214 for ( TInt i = 0; i < aArray.Count(); ++i ) |
|
215 { |
|
216 HBufC* id = PropertyValueL( aArray[i].Target(), |
|
217 AiUiDef::xml::property::KId ); |
|
218 if ( id ) |
|
219 { |
|
220 CleanupStack::PushL( id ); |
|
221 for ( TInt j = i; j < aArray.Count(); ++j ) |
|
222 { |
|
223 HBufC* id2 = PropertyValueL( aArray[j].Target(), |
|
224 AiUiDef::xml::property::KId ); |
|
225 if ( id2) |
|
226 { |
|
227 CleanupStack::PushL( id2 ); |
|
228 // Same id and same policy |
|
229 if ( i != j && |
|
230 id->Compare( *id2 ) == 0 && |
|
231 ( aArray[i].Policy().Compare( aArray[j].Policy()) == 0) |
|
232 ) |
|
233 { |
|
234 aArray.Remove( j ); |
|
235 --j; |
|
236 } |
|
237 } |
|
238 CleanupStack::PopAndDestroy( id2 ); |
|
239 |
|
240 } |
|
241 CleanupStack::PopAndDestroy( id ); |
|
242 } |
|
243 } |
|
244 } |
|
245 /** |
|
246 * Cleanup item for cleanup of TPtrHashMapIter |
|
247 */ |
|
248 class TMapCleanupItem |
|
249 { |
|
250 public: |
|
251 |
|
252 TMapCleanupItem( TPtrHashMapIter< TDesC, TInt >& aIterator ); |
|
253 |
|
254 /** |
|
255 * Removes the pointers in the map and deletes the objects |
|
256 * referenced by the pointers. |
|
257 */ |
|
258 void Release(); |
|
259 |
|
260 private: |
|
261 |
|
262 TPtrHashMapIter< TDesC, TInt > iIterator; |
|
263 |
|
264 }; |
|
265 |
|
266 /** |
|
267 * Helper to handle cleanup of map iterator |
|
268 * @param aMapCleanupItem |
|
269 */ |
|
270 void CleanupRelease( TAny* aMapCleanupItem ) |
|
271 { |
|
272 if ( aMapCleanupItem ) |
|
273 { |
|
274 static_cast< TMapCleanupItem* >( aMapCleanupItem )->Release(); |
|
275 } |
|
276 } |
|
277 |
|
278 /** |
|
279 * Helper to push map iterator into cleanup stack. |
|
280 * |
|
281 * @param aCleanupItem item to push into cleanup stack |
|
282 **/ |
|
283 void CleanupReleasePushL( TMapCleanupItem& aCleanupItem ) |
|
284 { |
|
285 CleanupStack::PushL( TCleanupItem( CleanupRelease, |
|
286 &aCleanupItem ) ); |
|
287 } |
|
288 |
|
289 |
|
290 } |
|
291 |
|
292 TMapCleanupItem::TMapCleanupItem( TPtrHashMapIter< TDesC, TInt >& aIterator ) |
|
293 : iIterator( aIterator ) |
|
294 { |
|
295 } |
|
296 |
|
297 void TMapCleanupItem::Release() |
|
298 { |
|
299 // Delete current key and value |
|
300 const TDesC* key = iIterator.CurrentKey(); |
|
301 const TInt* value = iIterator.CurrentValue(); |
|
302 |
|
303 delete key; |
|
304 delete value; |
|
305 |
|
306 // Remove mapping from the map. |
|
307 iIterator.RemoveCurrent(); |
|
308 } |
|
309 |
|
310 |
|
311 |
|
312 // ============================ MEMBER FUNCTIONS =============================== |
|
313 |
|
314 CContentRenderer::CContentRenderer( CAppUi& aAppUi ) |
|
315 : iAppUi( aAppUi ) |
|
316 { |
|
317 } |
|
318 |
|
319 void CContentRenderer::ConstructL() |
|
320 { |
|
321 iContentPriorityMap = AiUtility::CContentPriorityMap::NewL(); |
|
322 iPropertyMap = CCssPropertyMap::NewL(); |
|
323 iFactory = CTransactionFactoryImpl::NewL(*iContentPriorityMap, |
|
324 *iPropertyMap); |
|
325 iStack = CActiveTransactionStack::NewL(); |
|
326 iNodeIdGenerator = CXmlNodeIdGenerator::NewL(); |
|
327 iTimer = CPeriodic::NewL( CActive::EPriorityStandard ); |
|
328 iPolicyEvaluator = CPolicyEvaluator::NewL(); |
|
329 } |
|
330 |
|
331 CContentRenderer* CContentRenderer::NewL( CAppUi& aAppUi ) |
|
332 { |
|
333 CContentRenderer* self = new( ELeave ) CContentRenderer( aAppUi ); |
|
334 |
|
335 CleanupStack::PushL( self ); |
|
336 self->ConstructL(); |
|
337 CleanupStack::Pop(); |
|
338 |
|
339 return self; |
|
340 } |
|
341 |
|
342 CContentRenderer::~CContentRenderer() |
|
343 { |
|
344 delete iPolicyEvaluator; |
|
345 |
|
346 if ( iTimer ) |
|
347 { |
|
348 iTimer->Cancel(); |
|
349 delete iTimer; |
|
350 } |
|
351 |
|
352 delete iNodeIdGenerator; |
|
353 |
|
354 if ( iStack ) |
|
355 { |
|
356 while ( !iStack->IsEmpty() ) |
|
357 { |
|
358 MTransaction* tr = iStack->Pop(); |
|
359 iFactory->ReleaseTransaction( tr ); |
|
360 } |
|
361 |
|
362 delete iStack; |
|
363 } |
|
364 |
|
365 delete iFactory; |
|
366 |
|
367 iRefreshableUiElements.ResetAndDestroy(); |
|
368 |
|
369 delete iNTClass; |
|
370 |
|
371 delete iPropertyMap; |
|
372 |
|
373 delete iContentPriorityMap; |
|
374 delete iCallbackHandler; |
|
375 } |
|
376 |
|
377 void CContentRenderer::SetEventHandler( MAiFwEventHandler& aFwEventHandler ) |
|
378 { |
|
379 iFwEventHandler = &aFwEventHandler; |
|
380 } |
|
381 |
|
382 void CContentRenderer::Reset() |
|
383 { |
|
384 iContentPriorityMap->Reset(); |
|
385 iPropertyMap->Reset(); |
|
386 } |
|
387 |
|
388 void CContentRenderer::CleanPluginFromUi( MAiPropertyExtension& aPlugin ) |
|
389 { |
|
390 // Create transaction to clean UI |
|
391 TInt txId = reinterpret_cast< TInt >( &aPlugin ); |
|
392 |
|
393 TBool txCreated = ( StartTransaction( txId ) == KErrNone ); |
|
394 |
|
395 // Clean plugin |
|
396 TRAPD( cleanError, CleanPluginFromUiL( aPlugin ) ); |
|
397 |
|
398 // Commit transaction |
|
399 if ( txCreated ) |
|
400 { |
|
401 if (cleanError ) |
|
402 { |
|
403 CancelTransaction( txId ); |
|
404 } |
|
405 else |
|
406 { |
|
407 Commit( txId ); |
|
408 } |
|
409 } |
|
410 } |
|
411 |
|
412 TInt CContentRenderer::StartTransaction( TInt aTxId ) |
|
413 { |
|
414 __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Start transaction id=%d"), aTxId); |
|
415 __HEAP("XML UI: Start transaction"); |
|
416 __TICK("XML UI: Start transaction"); |
|
417 TRAPD( error, DoStartTransactionL( aTxId ) ); |
|
418 |
|
419 if ( error ) |
|
420 { |
|
421 SetImmediateMode( ETrue ); |
|
422 } |
|
423 |
|
424 return error; |
|
425 } |
|
426 |
|
427 TInt CContentRenderer::Commit( TInt aTxId ) |
|
428 { |
|
429 // Remove transaction with aTxId from stack |
|
430 MTransaction* tr = iStack->Remove( aTxId ); |
|
431 |
|
432 if ( tr ) |
|
433 { |
|
434 // Commit transaction |
|
435 RPropertyHashMap propertyHashMap; |
|
436 |
|
437 TBool layoutChanged( EFalse ); |
|
438 |
|
439 TRAPD( error, tr->CommitL( layoutChanged, propertyHashMap ) ); |
|
440 if( error == KErrNone ) |
|
441 { |
|
442 TRAP_IGNORE( SetPropertyArraysL( propertyHashMap ) ); |
|
443 } |
|
444 propertyHashMap.Close(); |
|
445 |
|
446 __TICK("XML UI: Commit transaction"); |
|
447 __HEAP("XML UI: Commit transaction"); |
|
448 __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Commit transaction id=%d"), aTxId); |
|
449 |
|
450 StartContentRefresh(); |
|
451 |
|
452 TRAP_IGNORE |
|
453 ( |
|
454 iAppUi.UiEngineL()->RenderUIL(); //jtm+++ |
|
455 ProcessContentChangesL( *tr ); |
|
456 ); |
|
457 |
|
458 |
|
459 iFactory->ReleaseTransaction( tr ); |
|
460 |
|
461 return error; |
|
462 } |
|
463 |
|
464 return KErrNotSupported; |
|
465 } |
|
466 |
|
467 void CContentRenderer::ProcessContentChangesL( MTransaction& aTr ) |
|
468 { |
|
469 TDblQueIter<CTransactionElement> iter = aTr.ElementIter(); |
|
470 RAiPolicyElementArray contentChangedArray; |
|
471 CleanupClosePushL( contentChangedArray ); |
|
472 |
|
473 while ( iter ) |
|
474 { |
|
475 CTransactionElement* element = iter++; |
|
476 CXnNodeAppIf& target = element->Target(); |
|
477 |
|
478 // Find own and parents policy/ContentChanged nodes |
|
479 iPolicyEvaluator->EvaluateContentChangedPolicyL( target, |
|
480 contentChangedArray); |
|
481 |
|
482 iPolicyEvaluator->EvaluateContentChangedPolicyL( *(target.ParentL()), |
|
483 contentChangedArray); |
|
484 } |
|
485 |
|
486 ::RemoveDuplicateContentChangesL( contentChangedArray ); |
|
487 |
|
488 for ( TInt i = 0; i < contentChangedArray.Count(); ++i ) |
|
489 { |
|
490 ProcessContentChangeL( contentChangedArray[i] ); |
|
491 } |
|
492 CleanupStack::PopAndDestroy(); |
|
493 } |
|
494 |
|
495 void CContentRenderer::ProcessContentChangeL( TAiPolicyElement& aElement ) |
|
496 { |
|
497 const TDesC8* id = PropertyValue( aElement.Target(), |
|
498 AiUiDef::xml::property::KId ); |
|
499 if ( id ) |
|
500 { |
|
501 CXnNodeAppIf* targetNode = FindNodeByIdL( *id, aElement.Target().Namespace() ); |
|
502 if ( targetNode ) |
|
503 { |
|
504 if ( aElement.Policy() == AiUiDef::xml::value::KShowTooltips ) |
|
505 { |
|
506 targetNode->ShowTooltipsL(); |
|
507 } |
|
508 } |
|
509 } |
|
510 } |
|
511 |
|
512 TInt CContentRenderer::CancelTransaction( TInt aTxId ) |
|
513 { |
|
514 // Remove transaction with aTxId from stack |
|
515 MTransaction* tr = iStack->Remove( aTxId ); |
|
516 |
|
517 if ( tr ) |
|
518 { |
|
519 // Release transaction to factory |
|
520 __TICK("XML UI: Cancel transaction"); |
|
521 __HEAP("XML UI: Cancel transaction"); |
|
522 __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Cancel transaction id=%d"), aTxId); |
|
523 |
|
524 iFactory->ReleaseTransaction( tr ); |
|
525 |
|
526 return KErrNone; |
|
527 } |
|
528 |
|
529 return KErrNotSupported; |
|
530 } |
|
531 |
|
532 TBool CContentRenderer::CanPublish( MAiPropertyExtension& aPlugin, |
|
533 TInt aContent, |
|
534 TInt aIndex ) |
|
535 { |
|
536 TInt error( KErrNone ); |
|
537 TInt retval( KErrNone ); |
|
538 __PRINTS("*** UC: Init - Content Validation ***"); |
|
539 __TIME("UC: Content Validation", |
|
540 TRAP( error, retval = CanPublishL( aPlugin, aContent, aIndex ) ); |
|
541 ); |
|
542 __HEAP("UC: Content Validation"); |
|
543 __PRINTS("*** UC: Done - Content Validation ***"); |
|
544 |
|
545 return ( error == KErrNone && retval == KErrNone ); |
|
546 } |
|
547 |
|
548 TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin, |
|
549 TInt aContent, |
|
550 TInt aResource, |
|
551 TInt aIndex ) |
|
552 { |
|
553 TInt error( KErrNone ); |
|
554 TInt retval( KErrNone ); |
|
555 __PRINTS("*** UC: Init - Content Publishing (Resource) ***"); |
|
556 __TIME("UC: Content Publishing (Resource)", |
|
557 TRAP( error, retval = DoPublishL( aPlugin, aContent, aResource, aIndex ) ); |
|
558 ); |
|
559 __HEAP("UC: Content Publishing (Resource)"); |
|
560 __PRINTS("*** UC: Done - Content Publishing (Resource) ***"); |
|
561 |
|
562 if( !error && retval ) |
|
563 { |
|
564 error = retval; |
|
565 } |
|
566 |
|
567 return error; |
|
568 } |
|
569 |
|
570 TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin, |
|
571 TInt aContent, |
|
572 const TDesC16& aText, |
|
573 TInt aIndex ) |
|
574 { |
|
575 TInt error( KErrNone ); |
|
576 TInt retval( KErrNone ); |
|
577 |
|
578 __PRINTS("*** UC: Init - Content Publishing (Value-Text) ***"); |
|
579 __TIME("UC: Content Publishing (Value-Text)", |
|
580 TRAP( error, retval = DoPublishL( aPlugin, aContent, aText, aIndex ) ); |
|
581 ); |
|
582 __HEAP("UC: Content Publishing (Value-Text)"); |
|
583 __PRINTS("*** UC: Done - Content Publishing (Value-Text) ***"); |
|
584 |
|
585 if( !error && retval ) |
|
586 { |
|
587 error = retval; |
|
588 } |
|
589 |
|
590 return error; |
|
591 } |
|
592 |
|
593 TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin, |
|
594 TInt aContent, |
|
595 const TDesC8& aBuf, |
|
596 TInt aIndex ) |
|
597 { |
|
598 TInt error( KErrNone ); |
|
599 TInt retval( KErrNone ); |
|
600 |
|
601 __PRINTS("*** UC: Init - Content Publishing (Value-Buf) ***"); |
|
602 __TIME("UC: Content Publishing (Value-Buf)", |
|
603 TRAP( error, retval = DoPublishL( aPlugin, aContent, aBuf, aIndex ) ); |
|
604 ) |
|
605 __HEAP("UC: Content Publishing (Value-Buf)"); |
|
606 __PRINTS("*** UC: Done - Content Publishing (Value-Buf) ***"); |
|
607 |
|
608 if( !error && retval ) |
|
609 { |
|
610 error = retval; |
|
611 } |
|
612 |
|
613 return error; |
|
614 } |
|
615 |
|
616 TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin, |
|
617 TInt aContent, |
|
618 RFile& aFile, |
|
619 TInt aIndex ) |
|
620 { |
|
621 TInt error( KErrNone ); |
|
622 TInt retval( KErrNone ); |
|
623 |
|
624 __PRINTS("*** UC: Init - Content Publishing (Value-RFile) ***"); |
|
625 __TIME("UC: Content Publishing (Value-RFile)", |
|
626 TRAP( error, retval = DoPublishL( aPlugin, aContent, aFile, aIndex ) ); |
|
627 ); |
|
628 __HEAP("UC: Content Publishing (Value-RFile)"); |
|
629 __PRINTS("*** UC: Done - Content Publishing (Value-RFile) ***"); |
|
630 |
|
631 if( !error && retval ) |
|
632 { |
|
633 error = retval; |
|
634 } |
|
635 |
|
636 return error; |
|
637 } |
|
638 |
|
639 TInt CContentRenderer::Clean( MAiPropertyExtension& aPlugin, TInt aContent, TInt aIndex ) |
|
640 { |
|
641 TInt error( KErrNone ); |
|
642 TInt retval( KErrNone ); |
|
643 |
|
644 __PRINTS("*** UC: Init - Content Publishing (Clean) ***"); |
|
645 __TIME("UC: Content Publishing (Clean)", |
|
646 TRAP( error, retval = DoCleanL( aPlugin, aContent, aIndex ) ); |
|
647 ); |
|
648 __HEAP("UC: Content Publishing (Clean)"); |
|
649 __PRINTS("*** UC: Done - Content Publishing (Clean) ***"); |
|
650 |
|
651 if( !error && retval ) |
|
652 { |
|
653 error = retval; |
|
654 } |
|
655 |
|
656 return error; |
|
657 } |
|
658 |
|
659 TAny* CContentRenderer::Extension( TUid /*aUid*/ ) |
|
660 { |
|
661 // No extensions supported |
|
662 return NULL; |
|
663 } |
|
664 |
|
665 TBool CContentRenderer::RequiresSubscription( |
|
666 const TAiPublisherInfo& aPublisherInfo ) const |
|
667 { |
|
668 if ( aPublisherInfo.iNamespace == KNativeUiNamespace ) |
|
669 { |
|
670 // Not targeted to this content renderer |
|
671 return EFalse; |
|
672 } |
|
673 |
|
674 return ETrue; |
|
675 } |
|
676 |
|
677 void CContentRenderer::DoStartTransactionL( TInt aTxId ) |
|
678 { |
|
679 MTransaction* tr = iFactory->CreateTransactionL( aTxId ); |
|
680 iStack->Push(tr); |
|
681 SetImmediateMode(EFalse); |
|
682 } |
|
683 |
|
684 TInt CContentRenderer::CanPublishL( MAiPropertyExtension& aPlugin, |
|
685 TInt aContent, |
|
686 TInt aIndex ) |
|
687 { |
|
688 // Get content item for aContent |
|
689 MAiContentItemIterator& iter( |
|
690 ContentItemIteratorL( aPlugin, EAiPublisherContent ) ); |
|
691 |
|
692 const TAiContentItem& item( iter.ItemL( aContent ) ); |
|
693 |
|
694 // Lookup ui element |
|
695 const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) ); |
|
696 |
|
697 CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, |
|
698 aPlugin.PublisherInfoL()->iNamespace ) ); |
|
699 |
|
700 if( !property ) |
|
701 { |
|
702 return KErrNotFound; |
|
703 } |
|
704 |
|
705 // Check content priority |
|
706 TInt priority( GetContentPriority( *property ) ); |
|
707 |
|
708 CXnNodeAppIf* target( property->ParentL() ); |
|
709 |
|
710 if( !target ) |
|
711 { |
|
712 return KErrNotSupported; |
|
713 } |
|
714 |
|
715 if ( !AllowPublishByPriority( *target, priority ) ) |
|
716 { |
|
717 return KErrAccessDenied; |
|
718 } |
|
719 |
|
720 // Check if content type is supported by target |
|
721 const TDesC8& contentType( ContentType( item ) ); |
|
722 |
|
723 if ( !iFactory->IsSupported( *target, contentType ) && |
|
724 target->Type()->Type() != XnPropertyNames::listquerydialog::KListQueryDialog ) |
|
725 { |
|
726 return KErrNotSupported; |
|
727 } |
|
728 |
|
729 return KErrNone; |
|
730 } |
|
731 |
|
732 TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin, |
|
733 TInt aContent, |
|
734 TInt aResource, |
|
735 TInt aIndex ) |
|
736 { |
|
737 TAiPublisherInfo *info = static_cast<TAiPublisherInfo*>(aPlugin.GetPropertyL( EAiPublisherInfo )); |
|
738 if (!info) |
|
739 { |
|
740 return KErrNotFound; |
|
741 } |
|
742 // Read ref value. |
|
743 MAiContentItemIterator& refIter( ContentItemIteratorL( aPlugin, EAiPublisherResources ) ); |
|
744 const TAiContentItem& ref( refIter.ItemL( aResource ) ); |
|
745 |
|
746 const TDesC8& refType( ContentType( ref ) ); |
|
747 |
|
748 // Resolve source node |
|
749 const TDesC& nodeId = iNodeIdGenerator->ResourceNodeIdL(aPlugin, ref); |
|
750 HBufC8* nodeId8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(nodeId); |
|
751 CleanupStack::PushL(nodeId8); |
|
752 CXnNodeAppIf* source = NULL; |
|
753 __TIME_MARK(xmlOverhead); |
|
754 source = FindNodeByIdL( *nodeId8, info->iNamespace ); |
|
755 __TIME_ENDMARK("XML UI: Lookup node by id", xmlOverhead); |
|
756 __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Lookup node by id=%S"), &nodeId); |
|
757 |
|
758 CleanupStack::PopAndDestroy(nodeId8); |
|
759 |
|
760 // Fetch content id |
|
761 MAiContentItemIterator& iter = ContentItemIteratorL( aPlugin, EAiPublisherContent ); |
|
762 const TAiContentItem& item = iter.ItemL( aContent ); |
|
763 |
|
764 const TDesC& targetId = iNodeIdGenerator->ContentNodeIdL(aPlugin, item); |
|
765 |
|
766 TInt retval( KErrNotSupported ); |
|
767 |
|
768 // Check types |
|
769 if ( refType == KContentTypeText ) |
|
770 { |
|
771 // Fetch text |
|
772 const TDesC8& text = source->GetPCData(); |
|
773 |
|
774 // Delegate to data publishing function |
|
775 retval = PublishDataL( aPlugin, |
|
776 targetId, |
|
777 text, |
|
778 refType, |
|
779 aIndex, |
|
780 source ); |
|
781 } |
|
782 else if ( refType.Find( KContentTypeImage ) != KErrNotFound ) |
|
783 { |
|
784 // Fetch icon |
|
785 CGulIcon* icon = LoadIconLC( *source ); |
|
786 |
|
787 // Delegate to icon publishing function |
|
788 retval = PublishIconL( aPlugin, |
|
789 targetId, |
|
790 icon, |
|
791 aIndex, |
|
792 source ); |
|
793 |
|
794 CleanupStack::Pop( icon ); |
|
795 } |
|
796 |
|
797 return retval; |
|
798 } |
|
799 |
|
800 TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin, |
|
801 TInt aContent, |
|
802 const TDesC16& aText, |
|
803 TInt aIndex ) |
|
804 { |
|
805 // Resolve content item |
|
806 MAiContentItemIterator& iter( |
|
807 ContentItemIteratorL( aPlugin, EAiPublisherContent ) ); |
|
808 |
|
809 const TAiContentItem& item( iter.ItemL( aContent ) ); |
|
810 |
|
811 const TDesC8& type( ContentType( item ) ); |
|
812 |
|
813 if ( type == KContentTypeText ) |
|
814 { |
|
815 // Find ui element |
|
816 const TDesC& nodeId = iNodeIdGenerator->ContentNodeIdL( aPlugin, item ); |
|
817 |
|
818 __TIME_MARK(xmlOverhead); |
|
819 |
|
820 CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, |
|
821 aPlugin.PublisherInfoL()->iNamespace ) ); |
|
822 |
|
823 if( !property ) |
|
824 { |
|
825 return KErrNotFound; |
|
826 } |
|
827 |
|
828 TInt priority( GetContentPriority( *property ) ); |
|
829 |
|
830 __TIME_ENDMARK("XML UI: Lookup node by class", xmlOverhead); |
|
831 __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Lookup node by class=%S"), &nodeId); |
|
832 |
|
833 //Navigate to parent |
|
834 CXnNodeAppIf* target( property->ParentL() ); |
|
835 |
|
836 if( !target ) |
|
837 { |
|
838 return KErrNotSupported; |
|
839 } |
|
840 |
|
841 // Check priority |
|
842 if ( AllowPublishByPriority( *target, priority ) ) |
|
843 { |
|
844 // Check if target is newsticker |
|
845 MTransactionElement* element( NULL ); |
|
846 |
|
847 if ( IsParentNewsticker( *target ) ) |
|
848 { |
|
849 // Register callback interface for newsticker |
|
850 CXnNodeAppIf *parent( target->ParentL() ); |
|
851 |
|
852 if( !parent ) |
|
853 { |
|
854 return KErrNotFound; |
|
855 } |
|
856 |
|
857 RegisterNewstickerCallbackInterfaceL( *parent ); |
|
858 |
|
859 const TAiPublisherInfo* info( aPlugin.PublisherInfoL() ); |
|
860 |
|
861 if ( info ) |
|
862 { |
|
863 iNTPublisher.Set( info->iName ); |
|
864 iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId ); |
|
865 } |
|
866 |
|
867 element = iFactory->CreateNewsTickerTransactionElementL( *target, |
|
868 aText, |
|
869 priority, |
|
870 aIndex ); |
|
871 } |
|
872 else if( target->Type()->Type() == |
|
873 XnListQueryDialogInterface::MXnListQueryDialogInterface::Type()) |
|
874 { |
|
875 // Get the data interface for dialog and publish data |
|
876 XnListQueryDialogInterface::MXnListQueryDialogInterface* listQuery( NULL ); |
|
877 XnComponentInterface::MakeInterfaceL( listQuery, *target ); |
|
878 LeaveIfNull( listQuery, KErrNotSupported ); |
|
879 listQuery->ReplaceItemL( aText, aIndex -1 );// plugins publish ordinals not indexes |
|
880 return KErrNone; |
|
881 } |
|
882 else |
|
883 { |
|
884 // Create transaction element for text |
|
885 // Not put to cleanupstack, because element is from our pool! |
|
886 element = iFactory->CreateTextTransactionElementL( *target, |
|
887 aText, |
|
888 priority ); |
|
889 } |
|
890 |
|
891 iPolicyEvaluator->EvaluateContentPolicyL( *target, |
|
892 element->PolicyArray() ); |
|
893 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
894 element->PolicyArray() ); |
|
895 |
|
896 ProcessTransactionElementL( element ); |
|
897 } |
|
898 else |
|
899 { |
|
900 return KErrAccessDenied; |
|
901 } |
|
902 } |
|
903 else |
|
904 { |
|
905 return KErrNotSupported; |
|
906 } |
|
907 |
|
908 return KErrNone; |
|
909 } |
|
910 |
|
911 TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin, |
|
912 TInt aContent, |
|
913 const TDesC8& aBuf, |
|
914 TInt aIndex ) |
|
915 { |
|
916 // resolve content item |
|
917 MAiContentItemIterator& iter( |
|
918 ContentItemIteratorL( aPlugin, EAiPublisherContent ) ); |
|
919 |
|
920 const TAiContentItem& item( iter.ItemL( aContent ) ); |
|
921 |
|
922 const TDesC8& type( ContentType( item ) ); |
|
923 |
|
924 TInt retval( KErrNotSupported ); |
|
925 |
|
926 if( type == KContentTypeBitmap ) |
|
927 { |
|
928 // Unpack icon from pointer |
|
929 CGulIcon* icon( LeaveIfNull( UnpackPtr<CGulIcon>( aBuf ), KErrArgument ) ); |
|
930 |
|
931 const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) ); |
|
932 |
|
933 // Publish icon |
|
934 retval = PublishIconL( aPlugin, nodeId, icon, aIndex ); |
|
935 } |
|
936 else if ( type == KContentTypeImageSvg ) |
|
937 { |
|
938 // Get node id |
|
939 const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) ); |
|
940 |
|
941 // Publish SVG data |
|
942 retval = PublishDataL( aPlugin, nodeId, aBuf, KContentTypeImageSvg, aIndex ); |
|
943 } |
|
944 |
|
945 return retval; |
|
946 } |
|
947 |
|
948 TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin, |
|
949 TInt aContent, |
|
950 RFile& aFile, |
|
951 TInt aIndex) |
|
952 { |
|
953 //Resolve content item |
|
954 MAiContentItemIterator& iter( |
|
955 ContentItemIteratorL( aPlugin, EAiPublisherContent ) ); |
|
956 |
|
957 const TAiContentItem& item( iter.ItemL( aContent ) ); |
|
958 |
|
959 const TDesC8& type( ContentType( item ) ); |
|
960 |
|
961 // Image support |
|
962 if ( type.Find( KContentTypeImage ) != KErrNotFound ) |
|
963 { |
|
964 // Find ui element |
|
965 const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) ); |
|
966 |
|
967 CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, |
|
968 aPlugin.PublisherInfoL()->iNamespace ) ); |
|
969 |
|
970 if( !property ) |
|
971 { |
|
972 return KErrNotFound; |
|
973 } |
|
974 |
|
975 // Check priority |
|
976 TInt priority( GetContentPriority( *property ) ); |
|
977 |
|
978 CXnNodeAppIf* target( property->ParentL() ); |
|
979 |
|
980 if( !target ) |
|
981 { |
|
982 return KErrNotSupported; |
|
983 } |
|
984 |
|
985 if ( AllowPublishByPriority( *target, priority ) ) |
|
986 { |
|
987 // Check if target is newsticker |
|
988 if ( IsParentNewsticker( *target ) ) |
|
989 { |
|
990 // Register callback interface |
|
991 CXnNodeAppIf *parent( target->ParentL() ); |
|
992 |
|
993 if( !parent ) |
|
994 { |
|
995 return KErrNotFound; |
|
996 } |
|
997 |
|
998 RegisterNewstickerCallbackInterfaceL( *parent ); |
|
999 |
|
1000 const TAiPublisherInfo* info( aPlugin.PublisherInfoL() ); |
|
1001 |
|
1002 if( info ) |
|
1003 { |
|
1004 iNTPublisher.Set( info->iName ); |
|
1005 iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId ); |
|
1006 } |
|
1007 } |
|
1008 |
|
1009 // Create transaction element for file |
|
1010 MTransactionElement* element = |
|
1011 iFactory->CreateImageTransactionElementL( *target, |
|
1012 aFile, |
|
1013 priority ); |
|
1014 |
|
1015 iPolicyEvaluator->EvaluateContentPolicyL( *target, |
|
1016 element->PolicyArray() ); |
|
1017 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
1018 element->PolicyArray() ); |
|
1019 |
|
1020 ProcessTransactionElementL( element ); |
|
1021 } |
|
1022 else |
|
1023 { |
|
1024 return KErrAccessDenied; |
|
1025 } |
|
1026 } |
|
1027 else |
|
1028 { |
|
1029 return KErrNotSupported; |
|
1030 } |
|
1031 |
|
1032 return KErrNone; |
|
1033 } |
|
1034 |
|
1035 TInt CContentRenderer::DoCleanL( MAiPropertyExtension& aPlugin, |
|
1036 TInt aContent, |
|
1037 TInt aIndex ) |
|
1038 { |
|
1039 // Resolve content item |
|
1040 MAiContentItemIterator& iter( |
|
1041 ContentItemIteratorL( aPlugin, EAiPublisherContent ) ); |
|
1042 |
|
1043 const TAiContentItem& item( iter.ItemL( aContent ) ); |
|
1044 |
|
1045 const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) ); |
|
1046 |
|
1047 CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, |
|
1048 aPlugin.PublisherInfoL()->iNamespace ) ); |
|
1049 |
|
1050 if( !property ) |
|
1051 { |
|
1052 return KErrNotFound; |
|
1053 } |
|
1054 |
|
1055 TInt priority( GetContentPriority( *property ) ); |
|
1056 |
|
1057 // Navigate to parent |
|
1058 CXnNodeAppIf* target( property->ParentL() ); |
|
1059 |
|
1060 if( !target ) |
|
1061 { |
|
1062 return KErrNotSupported; |
|
1063 } |
|
1064 |
|
1065 if ( !AllowPublishByPriority( *target, priority ) ) |
|
1066 { |
|
1067 return KErrAccessDenied; |
|
1068 } |
|
1069 |
|
1070 if ( IsParentNewsticker( *target ) ) |
|
1071 { |
|
1072 CXnNodeAppIf *parent( target->ParentL() ); |
|
1073 |
|
1074 if( !parent ) |
|
1075 { |
|
1076 return KErrNotFound; |
|
1077 } |
|
1078 |
|
1079 RegisterNewstickerCallbackInterfaceL( *parent ); |
|
1080 |
|
1081 const TAiPublisherInfo* info( aPlugin.PublisherInfoL() ); |
|
1082 |
|
1083 if( info ) |
|
1084 { |
|
1085 iNTPublisher.Set( info->iName ); |
|
1086 iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId ); |
|
1087 } |
|
1088 } |
|
1089 if( target->Type()->Type() == |
|
1090 XnListQueryDialogInterface::MXnListQueryDialogInterface::Type()) |
|
1091 { |
|
1092 // Get the data interface for dialog and delete data |
|
1093 XnListQueryDialogInterface::MXnListQueryDialogInterface* listQuery( NULL ); |
|
1094 XnComponentInterface::MakeInterfaceL( listQuery, *target ); |
|
1095 LeaveIfNull( listQuery, KErrNotSupported ); |
|
1096 listQuery->DeleteItem( aIndex -1 );// plugins publish ordinals not indexes |
|
1097 return KErrNone; |
|
1098 } |
|
1099 |
|
1100 // Create transaction element for empty content |
|
1101 MTransactionElement* element = |
|
1102 iFactory->CreateEmptyContentTransactionElementL( *target, aIndex ); |
|
1103 |
|
1104 iPolicyEvaluator->EvaluateEmptyContentPolicyL( *target, |
|
1105 element->PolicyArray() ); |
|
1106 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
1107 element->PolicyArray() ); |
|
1108 |
|
1109 ProcessTransactionElementL( element ); |
|
1110 |
|
1111 if ( priority > KErrNotFound ) // Only for prioritized elements |
|
1112 { |
|
1113 // Add current ui element into content refresh map |
|
1114 HBufC* uiElementId = PropertyValueL( *target, |
|
1115 XnPropertyNames::common::KId ); |
|
1116 return RefreshContentL( uiElementId, priority ); |
|
1117 } |
|
1118 |
|
1119 return KErrNone; |
|
1120 } |
|
1121 |
|
1122 void CContentRenderer::SetImmediateMode( TBool aImmediateMode ) |
|
1123 { |
|
1124 iImmediateMode = aImmediateMode; |
|
1125 } |
|
1126 |
|
1127 TBool CContentRenderer::IsImmediateMode() const |
|
1128 { |
|
1129 return iImmediateMode; |
|
1130 } |
|
1131 |
|
1132 void CContentRenderer::ProcessTransactionElementL( MTransactionElement* aElement ) |
|
1133 { |
|
1134 LeaveIfNull( aElement, KErrArgument ); |
|
1135 |
|
1136 if ( IsImmediateMode() || iStack->IsEmpty() ) |
|
1137 { |
|
1138 // No transaction. Commit element immediately |
|
1139 TBool layoutChanged = EFalse; |
|
1140 |
|
1141 RPropertyHashMap propertyHashMap; |
|
1142 aElement->CommitL(layoutChanged, propertyHashMap); |
|
1143 SetPropertyArraysL( propertyHashMap ); |
|
1144 propertyHashMap.Close(); |
|
1145 |
|
1146 iFactory->ReleaseTransactionElement( aElement ); |
|
1147 StartContentRefresh(); |
|
1148 |
|
1149 // Re-layout |
|
1150 iAppUi.UiEngineL()->RenderUIL(); |
|
1151 } |
|
1152 else |
|
1153 { |
|
1154 // Append transaction element to transaction |
|
1155 MTransaction* tr = iStack->Top(); |
|
1156 tr->Append( *aElement ); |
|
1157 } |
|
1158 } |
|
1159 |
|
1160 CXnNodeAppIf* CContentRenderer::FindNodeByClassL( const TDesC& aCid, |
|
1161 TInt aIndex, |
|
1162 const TDesC8& aNs ) |
|
1163 { |
|
1164 // Find node |
|
1165 HBufC8* classId = CnvUtfConverter::ConvertFromUnicodeToUtf8L(aCid); |
|
1166 CleanupStack::PushL(classId); |
|
1167 |
|
1168 RPointerArray<CXnNodeAppIf> nodes = iAppUi.UiEngineL()->FindNodeByClassL( *classId, aNs ); |
|
1169 |
|
1170 CleanupStack::PopAndDestroy(classId); |
|
1171 |
|
1172 CleanupClosePushL( nodes ); |
|
1173 |
|
1174 for ( TInt i = 0; i < nodes.Count(); ++i ) |
|
1175 { |
|
1176 CXnNodeAppIf* node = nodes[i]; |
|
1177 |
|
1178 const TDesC8* name = |
|
1179 PropertyValue( *node, AiUiDef::xml::property::KName ); |
|
1180 |
|
1181 if ( name && ( *name == AiUiDef::xml::name::KOrdinal ) ) |
|
1182 { |
|
1183 const TDesC8* value = |
|
1184 PropertyValue( *node, AiUiDef::xml::property::KValue ); |
|
1185 |
|
1186 if ( value ) |
|
1187 { |
|
1188 // Try to parse index from string either |
|
1189 |
|
1190 TInt32 index( 0 ); |
|
1191 User::LeaveIfError( AiUtility::ParseInt( index, *value ) ); |
|
1192 |
|
1193 if ( index == aIndex ) |
|
1194 { |
|
1195 CleanupStack::PopAndDestroy(&nodes); |
|
1196 return node; |
|
1197 } |
|
1198 } |
|
1199 } |
|
1200 else if ( name && ( *name == AiUiDef::xml::name::KTarget ) ) |
|
1201 { |
|
1202 const TDesC8* target = |
|
1203 PropertyValue( *node, AiUiDef::xml::property::KValue ); |
|
1204 |
|
1205 CXnNodeAppIf* targetNode = FindNodeByIdL( *target, node->Namespace() ); |
|
1206 if ( targetNode ) |
|
1207 { |
|
1208 CleanupStack::PopAndDestroy( &nodes ); |
|
1209 return targetNode; |
|
1210 } |
|
1211 } |
|
1212 else if ( nodes.Count() == 1 ) // Only one node in class |
|
1213 { |
|
1214 // No ordinal specified |
|
1215 node = nodes[ 0 ]; |
|
1216 CleanupStack::PopAndDestroy(&nodes); |
|
1217 return node; |
|
1218 } |
|
1219 } |
|
1220 |
|
1221 CleanupStack::PopAndDestroy( &nodes ); |
|
1222 |
|
1223 return NULL; // Never reached. Needed to omit compiler warning |
|
1224 } |
|
1225 |
|
1226 CXnNodeAppIf* CContentRenderer::FindNodeByIdL( const TDesC& aCid, const TDesC& aNs ) |
|
1227 { |
|
1228 // Find node |
|
1229 return LeaveIfNull( iAppUi.UiEngineL()->FindNodeByIdL( aCid, aNs ), |
|
1230 KErrNotFound ); |
|
1231 } |
|
1232 |
|
1233 CXnNodeAppIf* CContentRenderer::FindNodeByIdL( const TDesC8& aCid, const TDesC8& aNs ) |
|
1234 { |
|
1235 // Find node |
|
1236 return LeaveIfNull( iAppUi.UiEngineL()->FindNodeByIdL( aCid, aNs ), |
|
1237 KErrNotFound ); |
|
1238 } |
|
1239 |
|
1240 TInt CContentRenderer::PublishIconL( MAiPropertyExtension& aPlugin, |
|
1241 const TDesC& aCid, |
|
1242 CGulIcon* aIcon, |
|
1243 TInt aIndex, |
|
1244 CXnNodeAppIf* aResource ) |
|
1245 { |
|
1246 // Find proiperty element by class |
|
1247 CXnNodeAppIf* property( FindNodeByClassL( aCid, aIndex, |
|
1248 aPlugin.PublisherInfoL()->iNamespace ) ); |
|
1249 |
|
1250 if( !property ) |
|
1251 { |
|
1252 return KErrNotFound; |
|
1253 } |
|
1254 |
|
1255 // Get priority information |
|
1256 TInt priority( GetContentPriority( *property ) ); |
|
1257 |
|
1258 // Navigate to parent |
|
1259 CXnNodeAppIf* target( property->ParentL() ); |
|
1260 |
|
1261 if( !target ) |
|
1262 { |
|
1263 return KErrNotFound; |
|
1264 } |
|
1265 |
|
1266 // Check priority |
|
1267 if ( !AllowPublishByPriority( *target, priority ) ) |
|
1268 { |
|
1269 return KErrAccessDenied; |
|
1270 } |
|
1271 |
|
1272 // Special handling of newsticker |
|
1273 if ( IsParentNewsticker( *target ) ) |
|
1274 { |
|
1275 // Register callback interface |
|
1276 CXnNodeAppIf *parent( target->ParentL() ); |
|
1277 |
|
1278 if( !parent ) |
|
1279 { |
|
1280 return KErrNotFound; |
|
1281 } |
|
1282 |
|
1283 RegisterNewstickerCallbackInterfaceL( *parent ); |
|
1284 |
|
1285 const TAiPublisherInfo* info( aPlugin.PublisherInfoL() ); |
|
1286 |
|
1287 if( info ) |
|
1288 { |
|
1289 iNTPublisher.Set( info->iName ); |
|
1290 iNTClass = AiUtility::CopyToBufferL( iNTClass, aCid ); |
|
1291 } |
|
1292 } |
|
1293 |
|
1294 MTransactionElement* element = |
|
1295 iFactory->CreateImageTransactionElementL( *target, |
|
1296 aIcon, |
|
1297 priority ); |
|
1298 |
|
1299 if ( aResource ) |
|
1300 { |
|
1301 iPolicyEvaluator->EvaluateResourcePolicyL( *target, |
|
1302 *aResource, |
|
1303 element->PolicyArray() ); |
|
1304 iPolicyEvaluator->EvaluateContentPolicyL( *target, |
|
1305 element->PolicyArray() ); |
|
1306 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
1307 element->PolicyArray() ); |
|
1308 } |
|
1309 |
|
1310 else |
|
1311 { |
|
1312 iPolicyEvaluator->EvaluateContentPolicyL( *target, |
|
1313 element->PolicyArray() ); |
|
1314 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
1315 element->PolicyArray() ); |
|
1316 } |
|
1317 |
|
1318 ProcessTransactionElementL( element ); |
|
1319 |
|
1320 return KErrNone; |
|
1321 } |
|
1322 |
|
1323 TInt CContentRenderer::PublishDataL( MAiPropertyExtension& aPlugin, |
|
1324 const TDesC& aCid, |
|
1325 const TDesC8& aData, |
|
1326 const TDesC8& aContentType, |
|
1327 TInt aIndex, |
|
1328 CXnNodeAppIf* aResource ) |
|
1329 { |
|
1330 CXnNodeAppIf* property( FindNodeByClassL( aCid, aIndex, |
|
1331 aPlugin.PublisherInfoL()->iNamespace ) ); |
|
1332 |
|
1333 if( !property ) |
|
1334 { |
|
1335 return KErrNotFound; |
|
1336 } |
|
1337 |
|
1338 TInt priority( GetContentPriority( *property ) ); |
|
1339 |
|
1340 // Navigate to parent |
|
1341 CXnNodeAppIf* target( property->ParentL() ); |
|
1342 |
|
1343 if( !target ) |
|
1344 { |
|
1345 return KErrNotFound; |
|
1346 } |
|
1347 |
|
1348 if ( !AllowPublishByPriority( *target, priority ) ) |
|
1349 { |
|
1350 return KErrAccessDenied; |
|
1351 } |
|
1352 |
|
1353 if ( !CDataBufferTransactionElement::IsSupported( *target, aContentType ) ) |
|
1354 { |
|
1355 return KErrNotSupported; |
|
1356 } |
|
1357 |
|
1358 // Handle newsticker |
|
1359 if ( IsParentNewsticker( *target ) ) |
|
1360 { |
|
1361 CXnNodeAppIf *parent( target->ParentL() ); |
|
1362 |
|
1363 if( !parent ) |
|
1364 { |
|
1365 return KErrNotFound; |
|
1366 } |
|
1367 |
|
1368 RegisterNewstickerCallbackInterfaceL( *parent ); |
|
1369 |
|
1370 const TAiPublisherInfo* info( aPlugin.PublisherInfoL() ); |
|
1371 |
|
1372 if( info ) |
|
1373 { |
|
1374 iNTPublisher.Set( info->iName ); |
|
1375 iNTClass = AiUtility::CopyToBufferL( iNTClass, aCid ); |
|
1376 } |
|
1377 } |
|
1378 |
|
1379 MTransactionElement* element = |
|
1380 iFactory->CreateDataBufferTransactionElementL( *target, |
|
1381 aData, |
|
1382 priority ); |
|
1383 |
|
1384 if ( aResource ) |
|
1385 { |
|
1386 iPolicyEvaluator->EvaluateResourcePolicyL( *target, |
|
1387 *aResource, |
|
1388 element->PolicyArray() ); |
|
1389 iPolicyEvaluator->EvaluateContentPolicyL( *target, |
|
1390 element->PolicyArray() ); |
|
1391 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
1392 element->PolicyArray() ); |
|
1393 } |
|
1394 else |
|
1395 { |
|
1396 iPolicyEvaluator->EvaluateContentPolicyL( *target, |
|
1397 element->PolicyArray() ); |
|
1398 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
1399 element->PolicyArray() ); |
|
1400 } |
|
1401 |
|
1402 ProcessTransactionElementL( element ); |
|
1403 |
|
1404 return KErrNone; |
|
1405 } |
|
1406 |
|
1407 TBool CContentRenderer::AllowPublishByPriority( CXnNodeAppIf& aUiElement, |
|
1408 TInt aPriority ) const |
|
1409 { |
|
1410 // Get ui element id |
|
1411 const TDesC8* uiElementId = PropertyValue( aUiElement, |
|
1412 XnPropertyNames::common::KId ); |
|
1413 |
|
1414 if ( uiElementId ) |
|
1415 { |
|
1416 // compare given priority with the current value of ui element |
|
1417 return iContentPriorityMap->OverrideContent( *uiElementId, aPriority ); |
|
1418 } |
|
1419 |
|
1420 return EFalse; // priority cannot be used, because ui element does not have id |
|
1421 } |
|
1422 |
|
1423 void CContentRenderer::StartContentRefresh() |
|
1424 { |
|
1425 // Cancel ongoing refresh |
|
1426 iTimer->Cancel(); |
|
1427 |
|
1428 if ( iRefreshableUiElements.Count() > 0 ) |
|
1429 { |
|
1430 // Refreshable elements exist. Start timer to make refresh asynchronous |
|
1431 iTimer->Start( TTimeIntervalMicroSeconds32( 0 ), |
|
1432 TTimeIntervalMicroSeconds32( 0 ), |
|
1433 TCallBack( RefreshContentCallback, this ) ); |
|
1434 } |
|
1435 } |
|
1436 |
|
1437 /** |
|
1438 * Adds ui element to list of refreshable elements |
|
1439 * |
|
1440 * @param aUiElementId ui element id |
|
1441 * @param aOldPriority old priority value |
|
1442 */ |
|
1443 TInt CContentRenderer::RefreshContentL( HBufC* aUiElementId, |
|
1444 TInt aOldPriority ) |
|
1445 { |
|
1446 if( !aUiElementId ) |
|
1447 { |
|
1448 return KErrArgument; |
|
1449 } |
|
1450 |
|
1451 // Take ownership of aUiElementId |
|
1452 CleanupStack::PushL( aUiElementId ); |
|
1453 |
|
1454 if ( !iFwEventHandler ) |
|
1455 { |
|
1456 // Content refresh event cannot be sent |
|
1457 CleanupStack::PopAndDestroy( aUiElementId ); |
|
1458 return KErrNotReady; |
|
1459 } |
|
1460 |
|
1461 // Find current mapping |
|
1462 TInt* oldPriority = iRefreshableUiElements.Find( *aUiElementId ); |
|
1463 |
|
1464 if ( oldPriority ) |
|
1465 { |
|
1466 // Update mapping |
|
1467 *oldPriority = aOldPriority; |
|
1468 CleanupStack::PopAndDestroy( aUiElementId ); |
|
1469 } |
|
1470 else |
|
1471 { |
|
1472 // Create new mapping |
|
1473 oldPriority = new( ELeave ) TInt( aOldPriority ); |
|
1474 CleanupStack::PushL( oldPriority ); |
|
1475 |
|
1476 User::LeaveIfError( iRefreshableUiElements.Insert( aUiElementId, |
|
1477 oldPriority ) ); |
|
1478 |
|
1479 CleanupStack::Pop( 2, aUiElementId ); |
|
1480 } |
|
1481 |
|
1482 return KErrNone; |
|
1483 } |
|
1484 |
|
1485 /** |
|
1486 * Callback function to make content refreshing asynchronous |
|
1487 */ |
|
1488 TInt CContentRenderer::RefreshContentCallback( TAny* aContentRenderer ) |
|
1489 { |
|
1490 if ( !aContentRenderer ) |
|
1491 { |
|
1492 return KErrArgument; |
|
1493 } |
|
1494 |
|
1495 CContentRenderer* renderer = static_cast< CContentRenderer* >( aContentRenderer ); |
|
1496 TRAP_IGNORE( renderer->SendRefreshContentEventL() ); |
|
1497 return KErrNone; |
|
1498 } |
|
1499 |
|
1500 /** |
|
1501 * Sends Refresh content event to framework. |
|
1502 * Event is sent for content selectors with lower priority than the |
|
1503 * last content which has been cleaned from ui element. |
|
1504 */ |
|
1505 void CContentRenderer::SendRefreshContentEventL() |
|
1506 { |
|
1507 // Cancel periodic timer. |
|
1508 iTimer->Cancel(); |
|
1509 |
|
1510 // Get ui element id and old content priority |
|
1511 TPtrHashMapIter< TDesC, TInt> iter( iRefreshableUiElements ); |
|
1512 iter.Reset(); |
|
1513 |
|
1514 const TDesC* uiElementId = iter.NextKey(); // Never NULL |
|
1515 TInt priority = *( iter.CurrentValue() ); |
|
1516 |
|
1517 // Cleanup item for iterator |
|
1518 TMapCleanupItem cleanup( iter ); |
|
1519 CleanupReleasePushL( cleanup ); |
|
1520 |
|
1521 // Lookup ui element |
|
1522 CXnNodeAppIf* uiElement = FindNodeByIdL( *uiElementId ); |
|
1523 |
|
1524 // Remove current ui element from the map |
|
1525 CleanupStack::PopAndDestroy( &cleanup ); |
|
1526 |
|
1527 // Find lower priority content elements associated to this ui element |
|
1528 RPointerArray< CXnNodeAppIf > children = uiElement->ChildrenL(); |
|
1529 |
|
1530 // Remove higher priority content elements |
|
1531 RemoveNonPriorityElements( children, priority ); |
|
1532 |
|
1533 // Sort array to descending order |
|
1534 children.Sort( TLinearOrder< CXnNodeAppIf >( DescendingPriorityOrder ) ); |
|
1535 |
|
1536 // Send event for content selectors in descending priority order. |
|
1537 // Continue until first content gets published or array exhausts. |
|
1538 for ( TInt i = 0; i < children.Count(); ++i ) |
|
1539 { |
|
1540 CXnNodeAppIf* current = children[ i ]; |
|
1541 |
|
1542 // Get content selector |
|
1543 const HBufC* contentSelector = PropertyValueL( *current, |
|
1544 XnPropertyNames::common::KClass ); |
|
1545 |
|
1546 if ( contentSelector && iFwEventHandler->RefreshContent( *contentSelector )) |
|
1547 { |
|
1548 break; |
|
1549 } |
|
1550 } |
|
1551 |
|
1552 // Free content selector array |
|
1553 children.Reset(); |
|
1554 |
|
1555 // Continue content refresh for next ui element. |
|
1556 StartContentRefresh(); |
|
1557 } |
|
1558 |
|
1559 void CContentRenderer::TitleScrolled( TInt aTitleIndex ) |
|
1560 { |
|
1561 if ( iCallbackHandler ) |
|
1562 { |
|
1563 TRAP_IGNORE( iCallbackHandler->TitleScrolledL( iNTPublisher, |
|
1564 *iNTClass, |
|
1565 aTitleIndex ) ); |
|
1566 } |
|
1567 } |
|
1568 |
|
1569 void CContentRenderer::TitleToScroll( TInt aTitleIndex ) |
|
1570 { |
|
1571 if ( iCallbackHandler ) |
|
1572 { |
|
1573 TRAP_IGNORE( iCallbackHandler->TitleToScrollL( iNTPublisher, |
|
1574 *iNTClass, |
|
1575 aTitleIndex ) ); |
|
1576 } |
|
1577 } |
|
1578 |
|
1579 TBool CContentRenderer::IsParentNewsticker( CXnNodeAppIf& aTarget ) |
|
1580 { |
|
1581 CXnNodeAppIf* parent = NULL; |
|
1582 TRAP_IGNORE( parent = aTarget.ParentL() ); |
|
1583 if ( !parent ) |
|
1584 { |
|
1585 return EFalse; |
|
1586 } |
|
1587 CXnType* typeInfo = parent->Type(); |
|
1588 |
|
1589 if ( !typeInfo ) |
|
1590 { |
|
1591 return EFalse; |
|
1592 } |
|
1593 |
|
1594 return ( typeInfo->Type() == XnNewstickerInterface::MXnNewstickerInterface::Type()); |
|
1595 } |
|
1596 |
|
1597 void CContentRenderer::RegisterNewstickerCallbackInterfaceL( CXnNodeAppIf& aTarget ) |
|
1598 { |
|
1599 if ( !iCallbackHandler ) |
|
1600 { |
|
1601 // Instantiate callback handler |
|
1602 CNewstickerCallbackHandler* handler = CNewstickerCallbackHandler::NewLC( *iFwEventHandler ); |
|
1603 |
|
1604 // Set callback handler |
|
1605 iCallbackHandler = handler; |
|
1606 CleanupStack::Pop( handler ); |
|
1607 } |
|
1608 // Obtain newsticker component interface |
|
1609 XnNewstickerInterface::MXnNewstickerInterface* newsticker = NULL; |
|
1610 XnComponentInterface::MakeInterfaceL( newsticker, aTarget ); |
|
1611 |
|
1612 LeaveIfNull( newsticker, KErrGeneral ); |
|
1613 |
|
1614 // Set callback interface |
|
1615 newsticker->SetCallbackInterfaceL( this ); |
|
1616 } |
|
1617 |
|
1618 void CContentRenderer::CleanPluginFromUiL( MAiPropertyExtension& aPlugin ) |
|
1619 { |
|
1620 TInt itemCount = 0; |
|
1621 |
|
1622 // Resolve content items |
|
1623 MAiContentItemIterator& iter = ContentItemIteratorL( aPlugin, EAiPublisherContent ); |
|
1624 iter.Reset(); |
|
1625 |
|
1626 // Clean all content items |
|
1627 while ( iter.HasNext() ) |
|
1628 { |
|
1629 const TAiContentItem& item = iter.NextL(); |
|
1630 |
|
1631 const TDesC& nodeId = iNodeIdGenerator->ContentNodeIdL( aPlugin, item ); |
|
1632 |
|
1633 // Find nodes |
|
1634 HBufC8* nodeId8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(nodeId); |
|
1635 CleanupStack::PushL(nodeId8); |
|
1636 |
|
1637 RPointerArray<CXnNodeAppIf> nodes = iAppUi.UiEngineL()->FindNodeByClassL( |
|
1638 *nodeId8, aPlugin.PublisherInfoL()->iNamespace ); |
|
1639 |
|
1640 CleanupStack::PopAndDestroy(nodeId8); |
|
1641 |
|
1642 itemCount += nodes.Count(); |
|
1643 |
|
1644 CleanupClosePushL( nodes ); |
|
1645 |
|
1646 for ( TInt i = 0; i < nodes.Count(); ++i ) |
|
1647 { |
|
1648 CXnNodeAppIf* property = nodes[i]; |
|
1649 |
|
1650 TInt priority = GetContentPriority( *property ); |
|
1651 |
|
1652 // Navigate to parent |
|
1653 CXnNodeAppIf* target = LeaveIfNull( property->ParentL(), KErrNotFound ); |
|
1654 |
|
1655 if ( AllowPublishByPriority( *target, priority ) ) |
|
1656 { |
|
1657 // Create transaction element for empty content |
|
1658 MTransactionElement* element = |
|
1659 iFactory->CreateEmptyContentTransactionElementL( *target, 0 ); |
|
1660 |
|
1661 iPolicyEvaluator->EvaluateEmptyContentPolicyL( *target, |
|
1662 element->PolicyArray() ); |
|
1663 iPolicyEvaluator->EvaluateVisibilityPolicyL( *target, |
|
1664 element->PolicyArray() ); |
|
1665 |
|
1666 ProcessTransactionElementL( element ); |
|
1667 |
|
1668 if ( priority > KErrNotFound ) // Only for prioritized elements |
|
1669 { |
|
1670 // Add current ui element into content refresh map |
|
1671 HBufC* uiElementId = PropertyValueL( *target, |
|
1672 XnPropertyNames::common::KId ); |
|
1673 RefreshContentL( uiElementId, priority ); |
|
1674 } |
|
1675 } |
|
1676 } |
|
1677 |
|
1678 CleanupStack::PopAndDestroy(&nodes); |
|
1679 } |
|
1680 |
|
1681 if ( itemCount == 0 ) |
|
1682 { |
|
1683 //Nothing to clean from UI. Cancel transaction outside current trap harness |
|
1684 User::Leave( KErrNotFound ); |
|
1685 } |
|
1686 } |
|
1687 |
|
1688 // End of File |