--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/idlehomescreen/xmluicontroller/src/contentrenderer.cpp Thu Dec 17 08:40:49 2009 +0200
@@ -0,0 +1,1688 @@
+/*
+* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Content renderer implementation
+*
+*/
+
+// System includes
+#include <e32hashtab.h>
+#include <utf.h>
+#include <gulicon.h>
+
+// User includes
+
+#include "contentrenderer.h"
+#include "appui.h"
+#include "activetransactionstack.h"
+#include "transactionfactoryimpl.h"
+#include "mtransaction.h"
+#include "mtransactionelement.h"
+#include "aixmluiutils.h"
+#include "xmluicontroller.h"
+#include "xmlnodeidgenerator.h"
+#include "aixmluiconstants.h"
+#include "aifweventhandler.h"
+#include "databuffertransactionelement.h"
+#include "newstickercallbackhandler.h"
+#include "newstickertransactionelement.h"
+#include "csspropertymap.h"
+#include "policyevaluator.h"
+#include "debug.h"
+#include "xnuiengineappif.h"
+#include "xnnodeappif.h"
+#include "xnproperty.h"
+#include "mxncomponentinterface.h"
+#include "xntext.h"
+#include "xnbitmap.h"
+#include "xntype.h"
+#include "xnmenuadapter.h"
+#include "xnlistquerydialogadapter.h"
+#include "mxncomponentinterface.h"
+#include "aistrcnv.h"
+#include "contentprioritymap.h"
+#include "ainativeuiplugins.h"
+
+using namespace AiXmlUiController;
+using namespace AiUiDef::xml;
+using namespace XnTextInterface;
+using namespace XnImageInterface;
+
+namespace
+ {
+ typedef RPointerArray<CXnNodeAppIf> RXnNodeArray;
+
+ /**
+ * Gets content item iterator.
+ *
+ * @param aPlugin plugin to fetch the iterator
+ * @param aContentType type of iterator (content/resource/event)
+ * @return the iterator
+ * @leave KErrNotSupported if plugin does not provide iterator
+ */
+ static MAiContentItemIterator& ContentItemIteratorL( MAiPropertyExtension& aPlugin,
+ TInt aContentType )
+ {
+ MAiContentItemIterator* iter =
+ static_cast< MAiContentItemIterator* >( aPlugin.GetPropertyL( aContentType ) );
+
+ if ( !iter )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ return *iter;
+ }
+
+ /**
+ * Gets the content priority associated in the property element.
+ *
+ * @param aPropertyElement the property element
+ * @return priority value or KErrNotFound for non-prioritized element
+ */
+ TInt GetContentPriority( CXnNodeAppIf& aPropertyElement )
+ {
+ TInt32 priority( KErrNotFound );
+
+ const TDesC8* name = PropertyValue( aPropertyElement,
+ property::KName );
+
+
+ if ( name && *name == name::KPriority )
+ {
+ const TDesC8* value = PropertyValue( aPropertyElement,
+ property::KValue );
+ if ( value )
+ {
+ AiUtility::ParseInt( priority, *value );
+ }
+ }
+
+ return priority;
+ }
+
+ /**
+ * Remove elements from array which do not contain priority or priority is not lower than
+ * the given value.
+ *
+ * @param aElements array of elements
+ * @param aLastPriority upper bound of priority value (excluded from the array)
+ */
+ void RemoveNonPriorityElements( RPointerArray< CXnNodeAppIf>& aElements,
+ TInt aLastPriority )
+ {
+ // Remove non priority elements and higher priority elements
+
+ TInt elementCount = aElements.Count();
+ for ( TInt i = 0; i < elementCount; )
+ {
+ CXnNodeAppIf* current = aElements[i];
+
+ // Check name attribute
+ const TDesC8* name = PropertyValue( *current, property::KName );
+
+ if ( !name || *name != name::KPriority )
+ {
+ // Remove current
+ aElements.Remove( i );
+ --elementCount;
+ }
+ else
+ {
+ // Check current priority
+ const TDesC8* value = PropertyValue( *current, property::KValue );
+
+ if ( !value ) // value not present
+ {
+ aElements.Remove( i );
+ --elementCount;
+ continue;
+ }
+
+ TInt32 currentPriority( KErrNotFound );
+ if ( AiUtility::ParseInt( currentPriority, *value ) != KErrNone )
+ {
+ // value is not integer
+ aElements.Remove( i );
+ --elementCount;
+ continue;
+ }
+
+ if ( currentPriority < aLastPriority )
+ {
+ // Keep element and iterate further
+ ++i;
+ }
+ else
+ {
+ // priority is too high
+ aElements.Remove( i );
+ --elementCount;
+ }
+ }
+ }
+ }
+
+ /**
+ * Descending priority order for prioritized content selectors.
+ *
+ * @param aNode1 First node to compare
+ * @param aNode2 Second node to compare
+ * @return 0 nodes have equal priority
+ * @return >0 aNode1 has lower priority
+ * @return <0 aNode2 has lower priority
+ */
+ TInt DescendingPriorityOrder( const CXnNodeAppIf& aNode1,
+ const CXnNodeAppIf& aNode2 )
+ {
+ // Array content has been validated, so no checks are needed
+ const TDesC8* value1 = PropertyValue( aNode1,
+ property::KValue );
+
+ const TDesC8* value2 = PropertyValue( aNode2,
+ property::KValue );
+
+ TInt32 priority1( KErrNotFound );
+ AiUtility::ParseInt( priority1, *value1 );
+
+ TInt32 priority2( KErrNotFound );
+ AiUtility::ParseInt( priority2, *value2 );
+
+ if ( priority1 == priority2 )
+ {
+ return 0;
+ }
+
+ return ( priority1 < priority2 ) ? 1 : -1;
+ }
+
+ /**
+ * Removes duplicate entries in content change array
+ */
+ void RemoveDuplicateContentChangesL( RAiPolicyElementArray& aArray )
+ {
+ for ( TInt i = 0; i < aArray.Count(); ++i )
+ {
+ HBufC* id = PropertyValueL( aArray[i].Target(),
+ AiUiDef::xml::property::KId );
+ if ( id )
+ {
+ CleanupStack::PushL( id );
+ for ( TInt j = i; j < aArray.Count(); ++j )
+ {
+ HBufC* id2 = PropertyValueL( aArray[j].Target(),
+ AiUiDef::xml::property::KId );
+ if ( id2)
+ {
+ CleanupStack::PushL( id2 );
+ // Same id and same policy
+ if ( i != j &&
+ id->Compare( *id2 ) == 0 &&
+ ( aArray[i].Policy().Compare( aArray[j].Policy()) == 0)
+ )
+ {
+ aArray.Remove( j );
+ --j;
+ }
+ }
+ CleanupStack::PopAndDestroy( id2 );
+
+ }
+ CleanupStack::PopAndDestroy( id );
+ }
+ }
+ }
+ /**
+ * Cleanup item for cleanup of TPtrHashMapIter
+ */
+ class TMapCleanupItem
+ {
+ public:
+
+ TMapCleanupItem( TPtrHashMapIter< TDesC, TInt >& aIterator );
+
+ /**
+ * Removes the pointers in the map and deletes the objects
+ * referenced by the pointers.
+ */
+ void Release();
+
+ private:
+
+ TPtrHashMapIter< TDesC, TInt > iIterator;
+
+ };
+
+ /**
+ * Helper to handle cleanup of map iterator
+ * @param aMapCleanupItem
+ */
+ void CleanupRelease( TAny* aMapCleanupItem )
+ {
+ if ( aMapCleanupItem )
+ {
+ static_cast< TMapCleanupItem* >( aMapCleanupItem )->Release();
+ }
+ }
+
+ /**
+ * Helper to push map iterator into cleanup stack.
+ *
+ * @param aCleanupItem item to push into cleanup stack
+ **/
+ void CleanupReleasePushL( TMapCleanupItem& aCleanupItem )
+ {
+ CleanupStack::PushL( TCleanupItem( CleanupRelease,
+ &aCleanupItem ) );
+ }
+
+
+ }
+
+TMapCleanupItem::TMapCleanupItem( TPtrHashMapIter< TDesC, TInt >& aIterator )
+ : iIterator( aIterator )
+ {
+ }
+
+void TMapCleanupItem::Release()
+ {
+ // Delete current key and value
+ const TDesC* key = iIterator.CurrentKey();
+ const TInt* value = iIterator.CurrentValue();
+
+ delete key;
+ delete value;
+
+ // Remove mapping from the map.
+ iIterator.RemoveCurrent();
+ }
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+CContentRenderer::CContentRenderer( CAppUi& aAppUi )
+ : iAppUi( aAppUi )
+ {
+ }
+
+void CContentRenderer::ConstructL()
+ {
+ iContentPriorityMap = AiUtility::CContentPriorityMap::NewL();
+ iPropertyMap = CCssPropertyMap::NewL();
+ iFactory = CTransactionFactoryImpl::NewL(*iContentPriorityMap,
+ *iPropertyMap);
+ iStack = CActiveTransactionStack::NewL();
+ iNodeIdGenerator = CXmlNodeIdGenerator::NewL();
+ iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+ iPolicyEvaluator = CPolicyEvaluator::NewL();
+ }
+
+CContentRenderer* CContentRenderer::NewL( CAppUi& aAppUi )
+ {
+ CContentRenderer* self = new( ELeave ) CContentRenderer( aAppUi );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+CContentRenderer::~CContentRenderer()
+ {
+ delete iPolicyEvaluator;
+
+ if ( iTimer )
+ {
+ iTimer->Cancel();
+ delete iTimer;
+ }
+
+ delete iNodeIdGenerator;
+
+ if ( iStack )
+ {
+ while ( !iStack->IsEmpty() )
+ {
+ MTransaction* tr = iStack->Pop();
+ iFactory->ReleaseTransaction( tr );
+ }
+
+ delete iStack;
+ }
+
+ delete iFactory;
+
+ iRefreshableUiElements.ResetAndDestroy();
+
+ delete iNTClass;
+
+ delete iPropertyMap;
+
+ delete iContentPriorityMap;
+ delete iCallbackHandler;
+ }
+
+void CContentRenderer::SetEventHandler( MAiFwEventHandler& aFwEventHandler )
+ {
+ iFwEventHandler = &aFwEventHandler;
+ }
+
+void CContentRenderer::Reset()
+ {
+ iContentPriorityMap->Reset();
+ iPropertyMap->Reset();
+ }
+
+void CContentRenderer::CleanPluginFromUi( MAiPropertyExtension& aPlugin )
+ {
+ // Create transaction to clean UI
+ TInt txId = reinterpret_cast< TInt >( &aPlugin );
+
+ TBool txCreated = ( StartTransaction( txId ) == KErrNone );
+
+ // Clean plugin
+ TRAPD( cleanError, CleanPluginFromUiL( aPlugin ) );
+
+ // Commit transaction
+ if ( txCreated )
+ {
+ if (cleanError )
+ {
+ CancelTransaction( txId );
+ }
+ else
+ {
+ Commit( txId );
+ }
+ }
+ }
+
+TInt CContentRenderer::StartTransaction( TInt aTxId )
+ {
+ __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Start transaction id=%d"), aTxId);
+ __HEAP("XML UI: Start transaction");
+ __TICK("XML UI: Start transaction");
+ TRAPD( error, DoStartTransactionL( aTxId ) );
+
+ if ( error )
+ {
+ SetImmediateMode( ETrue );
+ }
+
+ return error;
+ }
+
+TInt CContentRenderer::Commit( TInt aTxId )
+ {
+ // Remove transaction with aTxId from stack
+ MTransaction* tr = iStack->Remove( aTxId );
+
+ if ( tr )
+ {
+ // Commit transaction
+ RPropertyHashMap propertyHashMap;
+
+ TBool layoutChanged( EFalse );
+
+ TRAPD( error, tr->CommitL( layoutChanged, propertyHashMap ) );
+ if( error == KErrNone )
+ {
+ TRAP_IGNORE( SetPropertyArraysL( propertyHashMap ) );
+ }
+ propertyHashMap.Close();
+
+ __TICK("XML UI: Commit transaction");
+ __HEAP("XML UI: Commit transaction");
+ __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Commit transaction id=%d"), aTxId);
+
+ StartContentRefresh();
+
+ TRAP_IGNORE
+ (
+ iAppUi.UiEngineL()->RenderUIL(); //jtm+++
+ ProcessContentChangesL( *tr );
+ );
+
+
+ iFactory->ReleaseTransaction( tr );
+
+ return error;
+ }
+
+ return KErrNotSupported;
+ }
+
+void CContentRenderer::ProcessContentChangesL( MTransaction& aTr )
+ {
+ TDblQueIter<CTransactionElement> iter = aTr.ElementIter();
+ RAiPolicyElementArray contentChangedArray;
+ CleanupClosePushL( contentChangedArray );
+
+ while ( iter )
+ {
+ CTransactionElement* element = iter++;
+ CXnNodeAppIf& target = element->Target();
+
+ // Find own and parents policy/ContentChanged nodes
+ iPolicyEvaluator->EvaluateContentChangedPolicyL( target,
+ contentChangedArray);
+
+ iPolicyEvaluator->EvaluateContentChangedPolicyL( *(target.ParentL()),
+ contentChangedArray);
+ }
+
+ ::RemoveDuplicateContentChangesL( contentChangedArray );
+
+ for ( TInt i = 0; i < contentChangedArray.Count(); ++i )
+ {
+ ProcessContentChangeL( contentChangedArray[i] );
+ }
+ CleanupStack::PopAndDestroy();
+ }
+
+void CContentRenderer::ProcessContentChangeL( TAiPolicyElement& aElement )
+ {
+ const TDesC8* id = PropertyValue( aElement.Target(),
+ AiUiDef::xml::property::KId );
+ if ( id )
+ {
+ CXnNodeAppIf* targetNode = FindNodeByIdL( *id, aElement.Target().Namespace() );
+ if ( targetNode )
+ {
+ if ( aElement.Policy() == AiUiDef::xml::value::KShowTooltips )
+ {
+ targetNode->ShowTooltipsL();
+ }
+ }
+ }
+ }
+
+TInt CContentRenderer::CancelTransaction( TInt aTxId )
+ {
+ // Remove transaction with aTxId from stack
+ MTransaction* tr = iStack->Remove( aTxId );
+
+ if ( tr )
+ {
+ // Release transaction to factory
+ __TICK("XML UI: Cancel transaction");
+ __HEAP("XML UI: Cancel transaction");
+ __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Cancel transaction id=%d"), aTxId);
+
+ iFactory->ReleaseTransaction( tr );
+
+ return KErrNone;
+ }
+
+ return KErrNotSupported;
+ }
+
+TBool CContentRenderer::CanPublish( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ TInt aIndex )
+ {
+ TInt error( KErrNone );
+ TInt retval( KErrNone );
+ __PRINTS("*** UC: Init - Content Validation ***");
+ __TIME("UC: Content Validation",
+ TRAP( error, retval = CanPublishL( aPlugin, aContent, aIndex ) );
+ );
+ __HEAP("UC: Content Validation");
+ __PRINTS("*** UC: Done - Content Validation ***");
+
+ return ( error == KErrNone && retval == KErrNone );
+ }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ TInt aResource,
+ TInt aIndex )
+ {
+ TInt error( KErrNone );
+ TInt retval( KErrNone );
+ __PRINTS("*** UC: Init - Content Publishing (Resource) ***");
+ __TIME("UC: Content Publishing (Resource)",
+ TRAP( error, retval = DoPublishL( aPlugin, aContent, aResource, aIndex ) );
+ );
+ __HEAP("UC: Content Publishing (Resource)");
+ __PRINTS("*** UC: Done - Content Publishing (Resource) ***");
+
+ if( !error && retval )
+ {
+ error = retval;
+ }
+
+ return error;
+ }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ const TDesC16& aText,
+ TInt aIndex )
+ {
+ TInt error( KErrNone );
+ TInt retval( KErrNone );
+
+ __PRINTS("*** UC: Init - Content Publishing (Value-Text) ***");
+ __TIME("UC: Content Publishing (Value-Text)",
+ TRAP( error, retval = DoPublishL( aPlugin, aContent, aText, aIndex ) );
+ );
+ __HEAP("UC: Content Publishing (Value-Text)");
+ __PRINTS("*** UC: Done - Content Publishing (Value-Text) ***");
+
+ if( !error && retval )
+ {
+ error = retval;
+ }
+
+ return error;
+ }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ const TDesC8& aBuf,
+ TInt aIndex )
+ {
+ TInt error( KErrNone );
+ TInt retval( KErrNone );
+
+ __PRINTS("*** UC: Init - Content Publishing (Value-Buf) ***");
+ __TIME("UC: Content Publishing (Value-Buf)",
+ TRAP( error, retval = DoPublishL( aPlugin, aContent, aBuf, aIndex ) );
+ )
+ __HEAP("UC: Content Publishing (Value-Buf)");
+ __PRINTS("*** UC: Done - Content Publishing (Value-Buf) ***");
+
+ if( !error && retval )
+ {
+ error = retval;
+ }
+
+ return error;
+ }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ RFile& aFile,
+ TInt aIndex )
+ {
+ TInt error( KErrNone );
+ TInt retval( KErrNone );
+
+ __PRINTS("*** UC: Init - Content Publishing (Value-RFile) ***");
+ __TIME("UC: Content Publishing (Value-RFile)",
+ TRAP( error, retval = DoPublishL( aPlugin, aContent, aFile, aIndex ) );
+ );
+ __HEAP("UC: Content Publishing (Value-RFile)");
+ __PRINTS("*** UC: Done - Content Publishing (Value-RFile) ***");
+
+ if( !error && retval )
+ {
+ error = retval;
+ }
+
+ return error;
+ }
+
+TInt CContentRenderer::Clean( MAiPropertyExtension& aPlugin, TInt aContent, TInt aIndex )
+ {
+ TInt error( KErrNone );
+ TInt retval( KErrNone );
+
+ __PRINTS("*** UC: Init - Content Publishing (Clean) ***");
+ __TIME("UC: Content Publishing (Clean)",
+ TRAP( error, retval = DoCleanL( aPlugin, aContent, aIndex ) );
+ );
+ __HEAP("UC: Content Publishing (Clean)");
+ __PRINTS("*** UC: Done - Content Publishing (Clean) ***");
+
+ if( !error && retval )
+ {
+ error = retval;
+ }
+
+ return error;
+ }
+
+TAny* CContentRenderer::Extension( TUid /*aUid*/ )
+ {
+ // No extensions supported
+ return NULL;
+ }
+
+TBool CContentRenderer::RequiresSubscription(
+ const TAiPublisherInfo& aPublisherInfo ) const
+ {
+ if ( aPublisherInfo.iNamespace == KNativeUiNamespace )
+ {
+ // Not targeted to this content renderer
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+void CContentRenderer::DoStartTransactionL( TInt aTxId )
+ {
+ MTransaction* tr = iFactory->CreateTransactionL( aTxId );
+ iStack->Push(tr);
+ SetImmediateMode(EFalse);
+ }
+
+TInt CContentRenderer::CanPublishL( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ TInt aIndex )
+ {
+ // Get content item for aContent
+ MAiContentItemIterator& iter(
+ ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+
+ const TAiContentItem& item( iter.ItemL( aContent ) );
+
+ // Lookup ui element
+ const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+ CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex,
+ aPlugin.PublisherInfoL()->iNamespace ) );
+
+ if( !property )
+ {
+ return KErrNotFound;
+ }
+
+ // Check content priority
+ TInt priority( GetContentPriority( *property ) );
+
+ CXnNodeAppIf* target( property->ParentL() );
+
+ if( !target )
+ {
+ return KErrNotSupported;
+ }
+
+ if ( !AllowPublishByPriority( *target, priority ) )
+ {
+ return KErrAccessDenied;
+ }
+
+ // Check if content type is supported by target
+ const TDesC8& contentType( ContentType( item ) );
+
+ if ( !iFactory->IsSupported( *target, contentType ) &&
+ target->Type()->Type() != XnPropertyNames::listquerydialog::KListQueryDialog )
+ {
+ return KErrNotSupported;
+ }
+
+ return KErrNone;
+ }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ TInt aResource,
+ TInt aIndex )
+ {
+ TAiPublisherInfo *info = static_cast<TAiPublisherInfo*>(aPlugin.GetPropertyL( EAiPublisherInfo ));
+ if (!info)
+ {
+ return KErrNotFound;
+ }
+ // Read ref value.
+ MAiContentItemIterator& refIter( ContentItemIteratorL( aPlugin, EAiPublisherResources ) );
+ const TAiContentItem& ref( refIter.ItemL( aResource ) );
+
+ const TDesC8& refType( ContentType( ref ) );
+
+ // Resolve source node
+ const TDesC& nodeId = iNodeIdGenerator->ResourceNodeIdL(aPlugin, ref);
+ HBufC8* nodeId8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(nodeId);
+ CleanupStack::PushL(nodeId8);
+ CXnNodeAppIf* source = NULL;
+ __TIME_MARK(xmlOverhead);
+ source = FindNodeByIdL( *nodeId8, info->iNamespace );
+ __TIME_ENDMARK("XML UI: Lookup node by id", xmlOverhead);
+ __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Lookup node by id=%S"), &nodeId);
+
+ CleanupStack::PopAndDestroy(nodeId8);
+
+ // Fetch content id
+ MAiContentItemIterator& iter = ContentItemIteratorL( aPlugin, EAiPublisherContent );
+ const TAiContentItem& item = iter.ItemL( aContent );
+
+ const TDesC& targetId = iNodeIdGenerator->ContentNodeIdL(aPlugin, item);
+
+ TInt retval( KErrNotSupported );
+
+ // Check types
+ if ( refType == KContentTypeText )
+ {
+ // Fetch text
+ const TDesC8& text = source->GetPCData();
+
+ // Delegate to data publishing function
+ retval = PublishDataL( aPlugin,
+ targetId,
+ text,
+ refType,
+ aIndex,
+ source );
+ }
+ else if ( refType.Find( KContentTypeImage ) != KErrNotFound )
+ {
+ // Fetch icon
+ CGulIcon* icon = LoadIconLC( *source );
+
+ // Delegate to icon publishing function
+ retval = PublishIconL( aPlugin,
+ targetId,
+ icon,
+ aIndex,
+ source );
+
+ CleanupStack::Pop( icon );
+ }
+
+ return retval;
+ }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ const TDesC16& aText,
+ TInt aIndex )
+ {
+ // Resolve content item
+ MAiContentItemIterator& iter(
+ ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+
+ const TAiContentItem& item( iter.ItemL( aContent ) );
+
+ const TDesC8& type( ContentType( item ) );
+
+ if ( type == KContentTypeText )
+ {
+ // Find ui element
+ const TDesC& nodeId = iNodeIdGenerator->ContentNodeIdL( aPlugin, item );
+
+ __TIME_MARK(xmlOverhead);
+
+ CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex,
+ aPlugin.PublisherInfoL()->iNamespace ) );
+
+ if( !property )
+ {
+ return KErrNotFound;
+ }
+
+ TInt priority( GetContentPriority( *property ) );
+
+ __TIME_ENDMARK("XML UI: Lookup node by class", xmlOverhead);
+ __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Lookup node by class=%S"), &nodeId);
+
+ //Navigate to parent
+ CXnNodeAppIf* target( property->ParentL() );
+
+ if( !target )
+ {
+ return KErrNotSupported;
+ }
+
+ // Check priority
+ if ( AllowPublishByPriority( *target, priority ) )
+ {
+ // Check if target is newsticker
+ MTransactionElement* element( NULL );
+
+ if ( IsParentNewsticker( *target ) )
+ {
+ // Register callback interface for newsticker
+ CXnNodeAppIf *parent( target->ParentL() );
+
+ if( !parent )
+ {
+ return KErrNotFound;
+ }
+
+ RegisterNewstickerCallbackInterfaceL( *parent );
+
+ const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+
+ if ( info )
+ {
+ iNTPublisher.Set( info->iName );
+ iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId );
+ }
+
+ element = iFactory->CreateNewsTickerTransactionElementL( *target,
+ aText,
+ priority,
+ aIndex );
+ }
+ else if( target->Type()->Type() ==
+ XnListQueryDialogInterface::MXnListQueryDialogInterface::Type())
+ {
+ // Get the data interface for dialog and publish data
+ XnListQueryDialogInterface::MXnListQueryDialogInterface* listQuery( NULL );
+ XnComponentInterface::MakeInterfaceL( listQuery, *target );
+ LeaveIfNull( listQuery, KErrNotSupported );
+ listQuery->ReplaceItemL( aText, aIndex -1 );// plugins publish ordinals not indexes
+ return KErrNone;
+ }
+ else
+ {
+ // Create transaction element for text
+ // Not put to cleanupstack, because element is from our pool!
+ element = iFactory->CreateTextTransactionElementL( *target,
+ aText,
+ priority );
+ }
+
+ iPolicyEvaluator->EvaluateContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+
+ ProcessTransactionElementL( element );
+ }
+ else
+ {
+ return KErrAccessDenied;
+ }
+ }
+ else
+ {
+ return KErrNotSupported;
+ }
+
+ return KErrNone;
+ }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ const TDesC8& aBuf,
+ TInt aIndex )
+ {
+ // resolve content item
+ MAiContentItemIterator& iter(
+ ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+
+ const TAiContentItem& item( iter.ItemL( aContent ) );
+
+ const TDesC8& type( ContentType( item ) );
+
+ TInt retval( KErrNotSupported );
+
+ if( type == KContentTypeBitmap )
+ {
+ // Unpack icon from pointer
+ CGulIcon* icon( LeaveIfNull( UnpackPtr<CGulIcon>( aBuf ), KErrArgument ) );
+
+ const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+ // Publish icon
+ retval = PublishIconL( aPlugin, nodeId, icon, aIndex );
+ }
+ else if ( type == KContentTypeImageSvg )
+ {
+ // Get node id
+ const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+ // Publish SVG data
+ retval = PublishDataL( aPlugin, nodeId, aBuf, KContentTypeImageSvg, aIndex );
+ }
+
+ return retval;
+ }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ RFile& aFile,
+ TInt aIndex)
+ {
+ //Resolve content item
+ MAiContentItemIterator& iter(
+ ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+
+ const TAiContentItem& item( iter.ItemL( aContent ) );
+
+ const TDesC8& type( ContentType( item ) );
+
+ // Image support
+ if ( type.Find( KContentTypeImage ) != KErrNotFound )
+ {
+ // Find ui element
+ const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+ CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex,
+ aPlugin.PublisherInfoL()->iNamespace ) );
+
+ if( !property )
+ {
+ return KErrNotFound;
+ }
+
+ // Check priority
+ TInt priority( GetContentPriority( *property ) );
+
+ CXnNodeAppIf* target( property->ParentL() );
+
+ if( !target )
+ {
+ return KErrNotSupported;
+ }
+
+ if ( AllowPublishByPriority( *target, priority ) )
+ {
+ // Check if target is newsticker
+ if ( IsParentNewsticker( *target ) )
+ {
+ // Register callback interface
+ CXnNodeAppIf *parent( target->ParentL() );
+
+ if( !parent )
+ {
+ return KErrNotFound;
+ }
+
+ RegisterNewstickerCallbackInterfaceL( *parent );
+
+ const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+
+ if( info )
+ {
+ iNTPublisher.Set( info->iName );
+ iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId );
+ }
+ }
+
+ // Create transaction element for file
+ MTransactionElement* element =
+ iFactory->CreateImageTransactionElementL( *target,
+ aFile,
+ priority );
+
+ iPolicyEvaluator->EvaluateContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+
+ ProcessTransactionElementL( element );
+ }
+ else
+ {
+ return KErrAccessDenied;
+ }
+ }
+ else
+ {
+ return KErrNotSupported;
+ }
+
+ return KErrNone;
+ }
+
+TInt CContentRenderer::DoCleanL( MAiPropertyExtension& aPlugin,
+ TInt aContent,
+ TInt aIndex )
+ {
+ // Resolve content item
+ MAiContentItemIterator& iter(
+ ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+
+ const TAiContentItem& item( iter.ItemL( aContent ) );
+
+ const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+ CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex,
+ aPlugin.PublisherInfoL()->iNamespace ) );
+
+ if( !property )
+ {
+ return KErrNotFound;
+ }
+
+ TInt priority( GetContentPriority( *property ) );
+
+ // Navigate to parent
+ CXnNodeAppIf* target( property->ParentL() );
+
+ if( !target )
+ {
+ return KErrNotSupported;
+ }
+
+ if ( !AllowPublishByPriority( *target, priority ) )
+ {
+ return KErrAccessDenied;
+ }
+
+ if ( IsParentNewsticker( *target ) )
+ {
+ CXnNodeAppIf *parent( target->ParentL() );
+
+ if( !parent )
+ {
+ return KErrNotFound;
+ }
+
+ RegisterNewstickerCallbackInterfaceL( *parent );
+
+ const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+
+ if( info )
+ {
+ iNTPublisher.Set( info->iName );
+ iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId );
+ }
+ }
+ if( target->Type()->Type() ==
+ XnListQueryDialogInterface::MXnListQueryDialogInterface::Type())
+ {
+ // Get the data interface for dialog and delete data
+ XnListQueryDialogInterface::MXnListQueryDialogInterface* listQuery( NULL );
+ XnComponentInterface::MakeInterfaceL( listQuery, *target );
+ LeaveIfNull( listQuery, KErrNotSupported );
+ listQuery->DeleteItem( aIndex -1 );// plugins publish ordinals not indexes
+ return KErrNone;
+ }
+
+ // Create transaction element for empty content
+ MTransactionElement* element =
+ iFactory->CreateEmptyContentTransactionElementL( *target, aIndex );
+
+ iPolicyEvaluator->EvaluateEmptyContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+
+ ProcessTransactionElementL( element );
+
+ if ( priority > KErrNotFound ) // Only for prioritized elements
+ {
+ // Add current ui element into content refresh map
+ HBufC* uiElementId = PropertyValueL( *target,
+ XnPropertyNames::common::KId );
+ return RefreshContentL( uiElementId, priority );
+ }
+
+ return KErrNone;
+ }
+
+void CContentRenderer::SetImmediateMode( TBool aImmediateMode )
+ {
+ iImmediateMode = aImmediateMode;
+ }
+
+TBool CContentRenderer::IsImmediateMode() const
+ {
+ return iImmediateMode;
+ }
+
+void CContentRenderer::ProcessTransactionElementL( MTransactionElement* aElement )
+ {
+ LeaveIfNull( aElement, KErrArgument );
+
+ if ( IsImmediateMode() || iStack->IsEmpty() )
+ {
+ // No transaction. Commit element immediately
+ TBool layoutChanged = EFalse;
+
+ RPropertyHashMap propertyHashMap;
+ aElement->CommitL(layoutChanged, propertyHashMap);
+ SetPropertyArraysL( propertyHashMap );
+ propertyHashMap.Close();
+
+ iFactory->ReleaseTransactionElement( aElement );
+ StartContentRefresh();
+
+ // Re-layout
+ iAppUi.UiEngineL()->RenderUIL();
+ }
+ else
+ {
+ // Append transaction element to transaction
+ MTransaction* tr = iStack->Top();
+ tr->Append( *aElement );
+ }
+ }
+
+CXnNodeAppIf* CContentRenderer::FindNodeByClassL( const TDesC& aCid,
+ TInt aIndex,
+ const TDesC8& aNs )
+ {
+ // Find node
+ HBufC8* classId = CnvUtfConverter::ConvertFromUnicodeToUtf8L(aCid);
+ CleanupStack::PushL(classId);
+
+ RPointerArray<CXnNodeAppIf> nodes = iAppUi.UiEngineL()->FindNodeByClassL( *classId, aNs );
+
+ CleanupStack::PopAndDestroy(classId);
+
+ CleanupClosePushL( nodes );
+
+ for ( TInt i = 0; i < nodes.Count(); ++i )
+ {
+ CXnNodeAppIf* node = nodes[i];
+
+ const TDesC8* name =
+ PropertyValue( *node, AiUiDef::xml::property::KName );
+
+ if ( name && ( *name == AiUiDef::xml::name::KOrdinal ) )
+ {
+ const TDesC8* value =
+ PropertyValue( *node, AiUiDef::xml::property::KValue );
+
+ if ( value )
+ {
+ // Try to parse index from string either
+
+ TInt32 index( 0 );
+ User::LeaveIfError( AiUtility::ParseInt( index, *value ) );
+
+ if ( index == aIndex )
+ {
+ CleanupStack::PopAndDestroy(&nodes);
+ return node;
+ }
+ }
+ }
+ else if ( name && ( *name == AiUiDef::xml::name::KTarget ) )
+ {
+ const TDesC8* target =
+ PropertyValue( *node, AiUiDef::xml::property::KValue );
+
+ CXnNodeAppIf* targetNode = FindNodeByIdL( *target, node->Namespace() );
+ if ( targetNode )
+ {
+ CleanupStack::PopAndDestroy( &nodes );
+ return targetNode;
+ }
+ }
+ else if ( nodes.Count() == 1 ) // Only one node in class
+ {
+ // No ordinal specified
+ node = nodes[ 0 ];
+ CleanupStack::PopAndDestroy(&nodes);
+ return node;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &nodes );
+
+ return NULL; // Never reached. Needed to omit compiler warning
+ }
+
+CXnNodeAppIf* CContentRenderer::FindNodeByIdL( const TDesC& aCid, const TDesC& aNs )
+ {
+ // Find node
+ return LeaveIfNull( iAppUi.UiEngineL()->FindNodeByIdL( aCid, aNs ),
+ KErrNotFound );
+ }
+
+CXnNodeAppIf* CContentRenderer::FindNodeByIdL( const TDesC8& aCid, const TDesC8& aNs )
+ {
+ // Find node
+ return LeaveIfNull( iAppUi.UiEngineL()->FindNodeByIdL( aCid, aNs ),
+ KErrNotFound );
+ }
+
+TInt CContentRenderer::PublishIconL( MAiPropertyExtension& aPlugin,
+ const TDesC& aCid,
+ CGulIcon* aIcon,
+ TInt aIndex,
+ CXnNodeAppIf* aResource )
+ {
+ // Find proiperty element by class
+ CXnNodeAppIf* property( FindNodeByClassL( aCid, aIndex,
+ aPlugin.PublisherInfoL()->iNamespace ) );
+
+ if( !property )
+ {
+ return KErrNotFound;
+ }
+
+ // Get priority information
+ TInt priority( GetContentPriority( *property ) );
+
+ // Navigate to parent
+ CXnNodeAppIf* target( property->ParentL() );
+
+ if( !target )
+ {
+ return KErrNotFound;
+ }
+
+ // Check priority
+ if ( !AllowPublishByPriority( *target, priority ) )
+ {
+ return KErrAccessDenied;
+ }
+
+ // Special handling of newsticker
+ if ( IsParentNewsticker( *target ) )
+ {
+ // Register callback interface
+ CXnNodeAppIf *parent( target->ParentL() );
+
+ if( !parent )
+ {
+ return KErrNotFound;
+ }
+
+ RegisterNewstickerCallbackInterfaceL( *parent );
+
+ const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+
+ if( info )
+ {
+ iNTPublisher.Set( info->iName );
+ iNTClass = AiUtility::CopyToBufferL( iNTClass, aCid );
+ }
+ }
+
+ MTransactionElement* element =
+ iFactory->CreateImageTransactionElementL( *target,
+ aIcon,
+ priority );
+
+ if ( aResource )
+ {
+ iPolicyEvaluator->EvaluateResourcePolicyL( *target,
+ *aResource,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+ }
+
+ else
+ {
+ iPolicyEvaluator->EvaluateContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+ }
+
+ ProcessTransactionElementL( element );
+
+ return KErrNone;
+ }
+
+TInt CContentRenderer::PublishDataL( MAiPropertyExtension& aPlugin,
+ const TDesC& aCid,
+ const TDesC8& aData,
+ const TDesC8& aContentType,
+ TInt aIndex,
+ CXnNodeAppIf* aResource )
+ {
+ CXnNodeAppIf* property( FindNodeByClassL( aCid, aIndex,
+ aPlugin.PublisherInfoL()->iNamespace ) );
+
+ if( !property )
+ {
+ return KErrNotFound;
+ }
+
+ TInt priority( GetContentPriority( *property ) );
+
+ // Navigate to parent
+ CXnNodeAppIf* target( property->ParentL() );
+
+ if( !target )
+ {
+ return KErrNotFound;
+ }
+
+ if ( !AllowPublishByPriority( *target, priority ) )
+ {
+ return KErrAccessDenied;
+ }
+
+ if ( !CDataBufferTransactionElement::IsSupported( *target, aContentType ) )
+ {
+ return KErrNotSupported;
+ }
+
+ // Handle newsticker
+ if ( IsParentNewsticker( *target ) )
+ {
+ CXnNodeAppIf *parent( target->ParentL() );
+
+ if( !parent )
+ {
+ return KErrNotFound;
+ }
+
+ RegisterNewstickerCallbackInterfaceL( *parent );
+
+ const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+
+ if( info )
+ {
+ iNTPublisher.Set( info->iName );
+ iNTClass = AiUtility::CopyToBufferL( iNTClass, aCid );
+ }
+ }
+
+ MTransactionElement* element =
+ iFactory->CreateDataBufferTransactionElementL( *target,
+ aData,
+ priority );
+
+ if ( aResource )
+ {
+ iPolicyEvaluator->EvaluateResourcePolicyL( *target,
+ *aResource,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+ }
+ else
+ {
+ iPolicyEvaluator->EvaluateContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+ }
+
+ ProcessTransactionElementL( element );
+
+ return KErrNone;
+ }
+
+TBool CContentRenderer::AllowPublishByPriority( CXnNodeAppIf& aUiElement,
+ TInt aPriority ) const
+ {
+ // Get ui element id
+ const TDesC8* uiElementId = PropertyValue( aUiElement,
+ XnPropertyNames::common::KId );
+
+ if ( uiElementId )
+ {
+ // compare given priority with the current value of ui element
+ return iContentPriorityMap->OverrideContent( *uiElementId, aPriority );
+ }
+
+ return EFalse; // priority cannot be used, because ui element does not have id
+ }
+
+void CContentRenderer::StartContentRefresh()
+ {
+ // Cancel ongoing refresh
+ iTimer->Cancel();
+
+ if ( iRefreshableUiElements.Count() > 0 )
+ {
+ // Refreshable elements exist. Start timer to make refresh asynchronous
+ iTimer->Start( TTimeIntervalMicroSeconds32( 0 ),
+ TTimeIntervalMicroSeconds32( 0 ),
+ TCallBack( RefreshContentCallback, this ) );
+ }
+ }
+
+/**
+ * Adds ui element to list of refreshable elements
+ *
+ * @param aUiElementId ui element id
+ * @param aOldPriority old priority value
+ */
+TInt CContentRenderer::RefreshContentL( HBufC* aUiElementId,
+ TInt aOldPriority )
+ {
+ if( !aUiElementId )
+ {
+ return KErrArgument;
+ }
+
+ // Take ownership of aUiElementId
+ CleanupStack::PushL( aUiElementId );
+
+ if ( !iFwEventHandler )
+ {
+ // Content refresh event cannot be sent
+ CleanupStack::PopAndDestroy( aUiElementId );
+ return KErrNotReady;
+ }
+
+ // Find current mapping
+ TInt* oldPriority = iRefreshableUiElements.Find( *aUiElementId );
+
+ if ( oldPriority )
+ {
+ // Update mapping
+ *oldPriority = aOldPriority;
+ CleanupStack::PopAndDestroy( aUiElementId );
+ }
+ else
+ {
+ // Create new mapping
+ oldPriority = new( ELeave ) TInt( aOldPriority );
+ CleanupStack::PushL( oldPriority );
+
+ User::LeaveIfError( iRefreshableUiElements.Insert( aUiElementId,
+ oldPriority ) );
+
+ CleanupStack::Pop( 2, aUiElementId );
+ }
+
+ return KErrNone;
+ }
+
+/**
+ * Callback function to make content refreshing asynchronous
+ */
+TInt CContentRenderer::RefreshContentCallback( TAny* aContentRenderer )
+ {
+ if ( !aContentRenderer )
+ {
+ return KErrArgument;
+ }
+
+ CContentRenderer* renderer = static_cast< CContentRenderer* >( aContentRenderer );
+ TRAP_IGNORE( renderer->SendRefreshContentEventL() );
+ return KErrNone;
+ }
+
+/**
+ * Sends Refresh content event to framework.
+ * Event is sent for content selectors with lower priority than the
+ * last content which has been cleaned from ui element.
+ */
+void CContentRenderer::SendRefreshContentEventL()
+ {
+ // Cancel periodic timer.
+ iTimer->Cancel();
+
+ // Get ui element id and old content priority
+ TPtrHashMapIter< TDesC, TInt> iter( iRefreshableUiElements );
+ iter.Reset();
+
+ const TDesC* uiElementId = iter.NextKey(); // Never NULL
+ TInt priority = *( iter.CurrentValue() );
+
+ // Cleanup item for iterator
+ TMapCleanupItem cleanup( iter );
+ CleanupReleasePushL( cleanup );
+
+ // Lookup ui element
+ CXnNodeAppIf* uiElement = FindNodeByIdL( *uiElementId );
+
+ // Remove current ui element from the map
+ CleanupStack::PopAndDestroy( &cleanup );
+
+ // Find lower priority content elements associated to this ui element
+ RPointerArray< CXnNodeAppIf > children = uiElement->ChildrenL();
+
+ // Remove higher priority content elements
+ RemoveNonPriorityElements( children, priority );
+
+ // Sort array to descending order
+ children.Sort( TLinearOrder< CXnNodeAppIf >( DescendingPriorityOrder ) );
+
+ // Send event for content selectors in descending priority order.
+ // Continue until first content gets published or array exhausts.
+ for ( TInt i = 0; i < children.Count(); ++i )
+ {
+ CXnNodeAppIf* current = children[ i ];
+
+ // Get content selector
+ const HBufC* contentSelector = PropertyValueL( *current,
+ XnPropertyNames::common::KClass );
+
+ if ( contentSelector && iFwEventHandler->RefreshContent( *contentSelector ))
+ {
+ break;
+ }
+ }
+
+ // Free content selector array
+ children.Reset();
+
+ // Continue content refresh for next ui element.
+ StartContentRefresh();
+ }
+
+void CContentRenderer::TitleScrolled( TInt aTitleIndex )
+ {
+ if ( iCallbackHandler )
+ {
+ TRAP_IGNORE( iCallbackHandler->TitleScrolledL( iNTPublisher,
+ *iNTClass,
+ aTitleIndex ) );
+ }
+ }
+
+void CContentRenderer::TitleToScroll( TInt aTitleIndex )
+ {
+ if ( iCallbackHandler )
+ {
+ TRAP_IGNORE( iCallbackHandler->TitleToScrollL( iNTPublisher,
+ *iNTClass,
+ aTitleIndex ) );
+ }
+ }
+
+TBool CContentRenderer::IsParentNewsticker( CXnNodeAppIf& aTarget )
+ {
+ CXnNodeAppIf* parent = NULL;
+ TRAP_IGNORE( parent = aTarget.ParentL() );
+ if ( !parent )
+ {
+ return EFalse;
+ }
+ CXnType* typeInfo = parent->Type();
+
+ if ( !typeInfo )
+ {
+ return EFalse;
+ }
+
+ return ( typeInfo->Type() == XnNewstickerInterface::MXnNewstickerInterface::Type());
+ }
+
+void CContentRenderer::RegisterNewstickerCallbackInterfaceL( CXnNodeAppIf& aTarget )
+ {
+ if ( !iCallbackHandler )
+ {
+ // Instantiate callback handler
+ CNewstickerCallbackHandler* handler = CNewstickerCallbackHandler::NewLC( *iFwEventHandler );
+
+ // Set callback handler
+ iCallbackHandler = handler;
+ CleanupStack::Pop( handler );
+ }
+ // Obtain newsticker component interface
+ XnNewstickerInterface::MXnNewstickerInterface* newsticker = NULL;
+ XnComponentInterface::MakeInterfaceL( newsticker, aTarget );
+
+ LeaveIfNull( newsticker, KErrGeneral );
+
+ // Set callback interface
+ newsticker->SetCallbackInterfaceL( this );
+ }
+
+void CContentRenderer::CleanPluginFromUiL( MAiPropertyExtension& aPlugin )
+ {
+ TInt itemCount = 0;
+
+ // Resolve content items
+ MAiContentItemIterator& iter = ContentItemIteratorL( aPlugin, EAiPublisherContent );
+ iter.Reset();
+
+ // Clean all content items
+ while ( iter.HasNext() )
+ {
+ const TAiContentItem& item = iter.NextL();
+
+ const TDesC& nodeId = iNodeIdGenerator->ContentNodeIdL( aPlugin, item );
+
+ // Find nodes
+ HBufC8* nodeId8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(nodeId);
+ CleanupStack::PushL(nodeId8);
+
+ RPointerArray<CXnNodeAppIf> nodes = iAppUi.UiEngineL()->FindNodeByClassL(
+ *nodeId8, aPlugin.PublisherInfoL()->iNamespace );
+
+ CleanupStack::PopAndDestroy(nodeId8);
+
+ itemCount += nodes.Count();
+
+ CleanupClosePushL( nodes );
+
+ for ( TInt i = 0; i < nodes.Count(); ++i )
+ {
+ CXnNodeAppIf* property = nodes[i];
+
+ TInt priority = GetContentPriority( *property );
+
+ // Navigate to parent
+ CXnNodeAppIf* target = LeaveIfNull( property->ParentL(), KErrNotFound );
+
+ if ( AllowPublishByPriority( *target, priority ) )
+ {
+ // Create transaction element for empty content
+ MTransactionElement* element =
+ iFactory->CreateEmptyContentTransactionElementL( *target, 0 );
+
+ iPolicyEvaluator->EvaluateEmptyContentPolicyL( *target,
+ element->PolicyArray() );
+ iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+ element->PolicyArray() );
+
+ ProcessTransactionElementL( element );
+
+ if ( priority > KErrNotFound ) // Only for prioritized elements
+ {
+ // Add current ui element into content refresh map
+ HBufC* uiElementId = PropertyValueL( *target,
+ XnPropertyNames::common::KId );
+ RefreshContentL( uiElementId, priority );
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&nodes);
+ }
+
+ if ( itemCount == 0 )
+ {
+ //Nothing to clean from UI. Cancel transaction outside current trap harness
+ User::Leave( KErrNotFound );
+ }
+ }
+
+// End of File