browserui/browser/FeedsSrc/FeedsClientUtilities.cpp
branchRCL_3
changeset 48 8e6fa1719340
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browserui/browser/FeedsSrc/FeedsClientUtilities.cpp	Wed Sep 01 12:31:04 2010 +0100
@@ -0,0 +1,1873 @@
+/*
+* 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 the License "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:  Manages the feed related views and implements the FeedsViewBridge.
+*
+*/
+
+#include <AknView.h>
+#include <AknViewAppUi.h>
+#include <BaUtils.h>
+#include <BaDesca.h>
+#include <brctlinterface.h>
+#include <GulIcon.h>
+#include <data_caging_path_literals.hrh>
+#include <eikmenup.h>
+#include <StringLoader.h>
+
+#include <BrowserNG.rsg>
+#include <brctldialogsprovider.h>
+#include <browserdialogsprovider.h>
+#include <brctldefs.h>
+#include <internetconnectionmanager.h>
+#include <FeatMgr.h>
+#include <Uri16.h>
+
+#include "Browser.hrh"
+#include "BrowserAppUi.h"
+#include "CommonConstants.h"
+#include "BrowserWindow.h"
+#include "BrowserWindowManager.h"
+#include "BrowserUIVariant.hrh"
+#include "Preferences.h"
+#include "BrowserGotoPane.h"
+#include "BrowserAdaptiveListPopup.h"
+#include "FeedsFeedView.h"
+#include "FeedsFolderView.h"
+#include "BrowserDialogs.h"
+#include "FeedsTopicView.h"
+#include "BrowserUtil.h"
+#include "BrowserSpecialLoadObserver.h"
+
+#include "FeedsClientUtilities.h"
+
+#include "BrowserBmOTABinSender.h"
+
+// CONSTANTS
+_LIT(KSupportedMimeTypes, "application/rss+xml;application/atom+xml;text/xml;application/xml");
+const TInt KLastUpdateGranularity = 10;
+
+const TInt KWmlSettingsAutomaticUpdatingNotSet = 32767;
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::NewL
+//
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CFeedsClientUtilities* CFeedsClientUtilities::NewL(CAknViewAppUi& aAppUI, MApiProvider& aApiProvider)
+    {
+    CFeedsClientUtilities* self = new (ELeave) CFeedsClientUtilities(aAppUI, aApiProvider);
+    
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::CFeedsClientUtilities
+//
+// C++ default constructor.
+// -----------------------------------------------------------------------------
+//
+CFeedsClientUtilities::CFeedsClientUtilities(CAknViewAppUi& aAppUI, MApiProvider& aApiProvider):
+		iAppUI(aAppUI), iApiProvider(aApiProvider), iIsUpdatingFeed(EFalse), iWaitDialog(0),
+		iEnteredURL(0), iFolderView(0), iTopicView(0), iFeedView(0), 
+        iIsConnected(EFalse), iItemIds(20), iItemStatus(20), iMimeTypes(0),
+        iFeedUpdateTimeIds(KLastUpdateGranularity), iFeedUpdateTimeTimestamps(KLastUpdateGranularity),
+        iPendingFolderItemTitle(NULL), iPendingFolderItemUrl(NULL), iExportFileName(NULL),
+	    iSearchAgent(NULL),
+    	iSearchOptList(NULL),
+    	iFeedImportRequested(EFalse),
+    	iRequestCanceled(EFalse),
+        iIsWaitDialogDisplayed(EFalse), 
+        iFeedsInterface(*this,0),
+        iCanceledRequest(CTransaction::ENone)
+	{
+	}
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ConstructL
+//
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ConstructL()
+    {
+	iApiProvider.Preferences().AddObserverL( this );
+	
+	// Set up MimeTypes
+	iMimeTypes = HBufC::NewL( KSupportedMimeTypes().Length() + 1 );
+    TPtr ptr( iMimeTypes->Des() );
+    ptr.Append( KSupportedMimeTypes() );
+    ptr.ZeroTerminate();
+	      
+    iWaitDialog = CFeedsWaitDialog::NewL(*this);
+    }
+
+// -----------------------------------------------------------------------------
+// CFolderItem::Search
+//
+// Searches for a FolderItem with the given name.  If "this"
+// isn't a folder it only checks whether or not it matches
+// the given name.  If "this" is a folder it also checks 
+// all embedded items.
+// -----------------------------------------------------------------------------
+//
+const CFeedsEntity* CFeedsClientUtilities::Search(const TDesC& aName,const CFeedsEntity& aFolder) const
+    {
+    TPtrC title;
+    if (aFolder.GetType() == EFolder)
+        {
+        aFolder.GetStringValue(EFolderAttributeTitle,title);	
+        }
+    else
+        {
+        aFolder.GetStringValue(EFeedAttributeTitle,title);	
+        }
+    if (aName.CompareF(title) == 0)
+        {
+    	return &aFolder;
+        }
+    if (aFolder.GetType() == EFolder)
+        {
+    	for(TInt i=0;i<aFolder.GetChildren().Count();i++)
+    	    {
+    		const CFeedsEntity *item;
+    		CFeedsEntity *child = aFolder.GetChildren()[i];
+    		if((item = Search(aName,*child)) != NULL)
+    		    {
+    			return item;
+    		    }
+    	    }
+        }
+
+    // Otherwise no match was found.
+    return NULL;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFolderItem::Search
+//
+// Searches for a FolderItem with the given id.  If "this"
+// isn't a folder it only checks whether or not it matches
+// the given id.  If "this" is a folder it also checks 
+// all embedded items.
+// -----------------------------------------------------------------------------
+//
+const CFeedsEntity* CFeedsClientUtilities::Search(TInt aFolderItemId,const CFeedsEntity& aFolder) const
+    {
+    if (aFolderItemId == aFolder.GetId())
+        {
+    	return &aFolder;
+        }
+    if (aFolder.GetType() == EFolder)
+        {
+    	for(TInt i=0;i<aFolder.GetChildren().Count();i++)
+    	    {
+    		const CFeedsEntity *item;
+    		CFeedsEntity *child = aFolder.GetChildren()[i];
+    		if ((item = Search(aFolderItemId,*child)) != NULL)
+    		    {
+    			return item;
+    		    }
+    	    }
+        }
+
+    // Otherwise no match was found.
+    return NULL;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::~CFeedsClientUtilities
+//
+// Deconstructor.
+// -----------------------------------------------------------------------------
+//
+CFeedsClientUtilities::~CFeedsClientUtilities()
+    {
+    DisconnectFromServer();
+    
+    iApiProvider.Preferences().RemoveObserver( this );
+    
+    delete iWaitDialog;   
+    delete iMimeTypes;
+    
+    iFeedUpdateTimeIds.Close();
+    iFeedUpdateTimeTimestamps.Close(); 
+    
+    delete iPendingFolderItemTitle;
+    delete iPendingFolderItemUrl;
+    delete iExportFileName;
+    delete iEnteredURL;
+    delete iSearchAgent;
+    
+    iItemIds.Close();
+    iItemStatus.Close();
+    iItemStatusOrig.Close();    
+
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::RequestCompleted()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::RequestCompleted(CTransaction* aTrans,TInt /*aEvent*/)
+{
+TInt status = aTrans->GetStatusCode();
+
+switch (aTrans->Type())
+    {
+    	case CTransaction::EFetchRootFolderItem:
+   	        FolderItemRequestCompleted(status, CTransaction::EFetchRootFolderItem);
+
+    	    break;
+    	
+    	case CTransaction::EWatchForChanges:
+    	    break;
+        
+    	case CTransaction::EExportOPML:
+    	case CTransaction::EImportOPML:
+    	    FolderItemRequestCompleted(status, aTrans->Type());
+    	    break;
+    	    
+        case CTransaction::EAddFolderItem:
+        case CTransaction::EDeleteFolderItem:
+        case CTransaction::EChangeFolderItem:
+        case CTransaction::EMoveFolderItem:
+        case CTransaction::EMoveFolderItemTo:
+        case CTransaction::EUpdateFolderItem:
+    	    FolderItemRequestCompleted(status, aTrans->Type());
+    	    break;
+
+        case CTransaction::EChangeSettings:
+            break;
+
+    	case CTransaction::EFetchFeed:
+   	        FeedRequestCompleted(status);
+    	    break;
+    	case CTransaction::EUpdateItemStatus:
+            break;
+        
+        default:
+            FolderItemRequestCompleted(status, aTrans->Type());
+            break;
+    }
+}
+    
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::NetworkConnectionNeededL()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::NetworkConnectionNeededL(
+        TInt* aConnectionPtr, TInt& aSockSvrHandle,
+        TBool& aNewConn, TApBearerType& aBearerType )
+    {
+    iApiProvider.SpecialLoadObserver().NetworkConnectionNeededL(
+        aConnectionPtr, &aSockSvrHandle, &aNewConn, &aBearerType );
+     //Wait dialog is shown only in the case of a new connection.
+     if ( aNewConn )
+         {
+         iWaitDialog->ShowWaitDialogL(R_FEEDS_UPDATING_FEED);
+         iIsWaitDialogDisplayed = ETrue;
+         }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::HandlePreferencesChangeL()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::HandlePreferencesChangeL(
+        const TPreferencesEvent aEvent,
+        TPreferencesValues& aValues,
+        TBrCtlDefs::TBrCtlSettings aSettingType )
+    {
+    // no specific TBrCtlDefs::TBrCtlSettings are defined for FeedsSettings
+    // so we trigger for an Unknown setting
+    if(   (EPreferencesItemChange == aEvent || EPreferencesDeactivate == aEvent)  &&
+          (TBrCtlDefs::ESettingsUnknown == aSettingType ) )
+        {
+        SetPreferencesToFeedL( aValues );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SetPreferencesToFeedL()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::SetPreferencesToFeedL( const TPreferencesValues& aValues )
+    {
+    if ( iIsWaitDialogDisplayed )
+        {
+    	return;
+        }    
+    TFeedsServerSetting setting;
+
+    // always set to 32767 in the case of feed level auto updating.
+    //setting.iAutoUpdate = KWmlSettingsAutomaticUpdatingNotSet;
+    setting.iAutoUpdate = EFalse;
+    setting.iAutoUpdateFreq = KWmlSettingsAutomaticUpdatingNotSet;
+  setting.iAutoUpdateWhileRoaming = aValues.iAutomaticUpdatingWhileRoaming;
+    
+    TUint32 autoUpdatingAP( 0 );
+#ifndef __WINSCW__
+    if (aValues.iAutomaticUpdatingAP != KWmlNoDefaultAccessPoint)
+        {
+        autoUpdatingAP = Util::IapIdFromWapIdL( iApiProvider, aValues.iAutomaticUpdatingAP );
+        }
+#endif //__WINSCW__
+	setting.iAutoUpdateAP = autoUpdatingAP;
+
+    SetFeedsServerSettingsL( setting );
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::DisconnectManualUpdateConnectionL()
+//
+// Disconnect connection provided by client for manual update.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::DisconnectManualUpdateConnectionL()
+    {
+    if ( iIsConnected )
+        {
+        // Ensure that the connection is available.
+        ConnectToServerL(EFalse);
+
+        // Pass the updated settings to the server.
+        iFeedsInterface.DisconnectManualUpdateConnectionL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::DisconnectFeedsViewL()
+//
+// Disconnect connection used by FeedsView.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::DisconnectFeedsViewL()
+    {
+    if( iFeedView )
+        {
+        iFeedView->DisconnectL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::LoadUrlL()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::LoadUrlL( const TDesC& aUrl )
+    {
+        
+    if( iApiProvider.IsPageLoaded() &&
+		iApiProvider.Preferences().UiLocalFeatureSupported( KBrowserMultipleWindows ) &&
+    	!iApiProvider.Preferences().UiLocalFeatureSupported( KBrowserMinimalMultipleWindows ))
+	    {	    
+	    // there is already a window, so create a new one if not over the max number of windows allowed
+	    if(iApiProvider.WindowMgr().WindowCount() == iApiProvider.WindowMgr().MaxWindowCount())
+	    	{
+	    	// Show warning to user
+            TBrowserDialogs::ErrorNoteL( R_BROWSER_NOTE_MAX_WINDOWS );
+		  	return;
+	    	}
+
+	    if(iApiProvider.WindowMgr().WindowCount() < iApiProvider.WindowMgr().MaxWindowCount())
+	    	{
+		    CBrowserWindow *win = iApiProvider.WindowMgr().CreateWindowL( 0, &KNullDesC );
+		    if (win != NULL)
+    		    {
+    		    CleanupStack::PushL( win );
+    		    iApiProvider.WindowMgr().SwitchWindowL( win->WindowId() );
+    		    CleanupStack::Pop();  // win		        
+    		    }
+	    	}
+	    }
+	
+	iApiProvider.WindowMgr().CurrentWindow()->SetHasFeedsContent(ETrue);
+	iApiProvider.FetchL( aUrl );
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ShowFolderViewL
+//
+// Shows the folder view, loading the folder list from the FeedsServer if need be.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ShowFolderViewL(TUid aCalledFromView /*= KUidBrowserBookmarksViewId*/)
+    {
+    
+    if ( iIsWaitDialogDisplayed )
+        {
+    	return;
+        }
+   	// Record the view from which feeds was launched.
+   	// If this function is not called with an argument,
+   	// its default value "KUidBrowserBookmarksViewId" is used.
+   	// This is specified in the header FeedsClientUtilities.h 
+   	SetCalledFromView(aCalledFromView);    	 
+
+    // Ensure that "this" is ready for uses.
+    LazyInitL(EFalse);
+
+    // Show wait dialog.
+    iWaitDialog->ShowWaitDialogL(R_FEEDS_OPENING_FEED);
+    iIsWaitDialogDisplayed = ETrue;
+    
+    // Set the view to show once the folder is ready.
+    iNextViewId = KUidBrowserFeedsFolderViewId;
+    iIsUpdatingFeed = EFalse;   
+
+    // Get the root folder.
+    FetchRootFolderL();
+    iCurrentRequest = CTransaction::EFetchRootFolderItem;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ShowTopicViewL
+//
+// Shows the topic view, loading the given feed associated with the given folder item.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ShowTopicViewL(const CFeedsEntity& aFolderItem)
+    {
+    TTime timestamp;
+    
+    if ( iIsWaitDialogDisplayed )
+        {
+    	return;
+        }    
+        
+    // Ensure that "this" is ready for uses.
+    LazyInitL(EFalse);
+
+    // Show wait dialog.
+    timestamp = aFolderItem.GetTimeValue(EFeedAttributeTimestamp,timestamp);
+    if ( timestamp.Int64() == 0 )
+        {
+    	if ( iApiProvider.Connection().Connected() )
+        	{
+    		iWaitDialog->ShowWaitDialogL(R_FEEDS_UPDATING_FEED);
+        	}
+        }
+    else
+        {
+    	iWaitDialog->ShowWaitDialogL(R_FEEDS_OPENING_FEED);
+        }
+    iIsWaitDialogDisplayed = ETrue;   
+    
+    // Set the view to show once the feed is ready.
+    iNextViewId = KUidBrowserFeedsTopicViewId;
+    iIsUpdatingFeed = EFalse;
+    
+    // Fetch the feed.
+    FetchFeedL(aFolderItem);
+    iCurrentRequest = CTransaction::EFetchFeed;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SupportedMimeTypesL
+//
+// Returns the feed related mime-types supported by the bridge.  This makes 
+// for a clean way to pass downloaded feeds content from the client to the FeedsServer 
+// (via CFeedsClientUtilities::HandleFeedL).
+// -----------------------------------------------------------------------------
+//
+TPtrC CFeedsClientUtilities::SupportedMimeTypesL()
+    {
+    return iMimeTypes->Des();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SubscribeToL
+//
+// Shows the folder view and subscribes to the given feed.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::SubscribeToL(const TDesC& aTitle, const TDesC& aUrl)
+    {  
+   	SetCalledFromView(KUidBrowserContentViewId); 
+
+    // If the root folder is available then Add the feed.
+    if (iFeedsInterface.RootFolder() != NULL)
+        {        
+        // Ensure that "this" is ready for uses.  
+        LazyInitL( EFalse );
+		CFeedsMap* temp = CFeedsMap::NewL();
+		temp->SetStringAttribute(EFeedAttributeTitle,aTitle);
+        temp->SetStringAttribute(EFeedAttributeLink,aUrl);
+        temp->SetIntegerAttribute(EFeedAttributeAutoUpdateFreq,0);
+        
+        // Set the next view to show after the new add folder item is added.
+        iNextViewId = KUidBrowserFeedsFolderViewId; 
+        
+        iFeedsInterface.AddL(EFeed,*temp, *(iFeedsInterface.RootFolder()));
+
+		delete temp;
+        // Ensure the Folder View shows the root-folder when AddFolderItemL completes.
+        iFolderView->SetCurrentFolder(*(iFeedsInterface.RootFolder()), ETrue);
+        }
+        
+    // Otherwise queue the folder item until the root folder is fetched (see above).
+    else
+        {
+        // Ensure that "this" is ready for uses.  ETrue is passed to ensure that
+        // the root folder will be fetched if it isn't already available.
+        LazyInitL( ETrue );
+
+        delete iPendingFolderItemTitle;
+        iPendingFolderItemTitle = NULL;
+        delete iPendingFolderItemUrl;
+        iPendingFolderItemUrl = NULL;
+        
+        iPendingFolderItemTitle = aTitle.AllocL();
+        TRAPD(err, iPendingFolderItemUrl = aUrl.AllocL());
+        if (err != KErrNone)
+            {
+            delete iPendingFolderItemTitle;
+            iPendingFolderItemTitle = NULL;
+            
+            User::Leave(err);
+            }
+        }
+    }
+
+
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FeedsServerSettings
+//
+// Returns Feeds Server related settings.
+// -----------------------------------------------------------------------------
+//
+TInt CFeedsClientUtilities::FeedsServerSettingsL(TFeedsServerSetting& aSetting)
+    {
+    // Ensure that the connection is available.
+    ConnectToServerL(EFalse);
+
+    return iFeedsInterface.GetSettingsL(aSetting);
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SetFeedsServerSettings
+//
+// Sets Feeds Server related settings.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::SetFeedsServerSettingsL(const TFeedsServerSetting& aNewSetting)
+    {
+    // Ensure that the connection is available.
+    ConnectToServerL(EFalse);
+
+    // Pass the updated settings to the server.
+    iFeedsInterface.SetSettingsL(aNewSetting);
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SetBrowserControlSettingL
+//
+// Sets a Browser Control related settings.  These settings are directly passed to all 
+// Browser Control instances used by the CFeedsViewBridge.  As such see the Browser
+// Control documentation for infomation about the settings.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::SetBrowserControlSettingL(TUint aSetting, TUint aValue)
+    {
+    // Pass the setting to the Feed View's Browser Control.
+    iApiProvider.BrCtlInterface().SetBrowserSettingL(aSetting, aValue);
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FolderItemRequestCompleted
+//
+// Called by RequestHandlerCompleted when the root FolderItem is either ready 
+// or an error occured.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::FolderItemRequestCompleted(TInt aStatus, CTransaction::TTransactionType aTransType/*=ENone*/)
+    {
+	TRAP_IGNORE( FolderItemRequestCompletedL(aStatus, aTransType) );
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FolderItemRequestCompletedL
+//
+// Called by FolderItemRequestCompleted.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::FolderItemRequestCompletedL(TInt aStatus, CTransaction::TTransactionType aTransType/*=ENone*/)
+    {
+    if (aTransType == iCanceledRequest)
+        {
+        iCanceledRequest = CTransaction::ENone;
+        return;
+        }
+
+    iWaitDialog->Close();
+ 
+    iIsWaitDialogDisplayed = EFalse;
+    	
+    // Show the view if everything went ok.
+    if (aStatus == KErrNone)
+        {
+        switch(aTransType)
+        	{
+        	case CTransaction::EExportOPML:
+	        	//launch send ui
+	        	SendOPMLFileL();
+				break;
+
+       		case CTransaction::EImportOPML:
+				// Delete temp file here if it exists
+				if(iTempOPMLImportFilePath.Length() > 0)
+					{
+					RFs tempRFs;
+					if (tempRFs.Connect() != KErrNone)
+						{
+						break;
+						}
+					CleanupClosePushL(tempRFs);
+					tempRFs.Delete( iTempOPMLImportFilePath );
+					tempRFs.Close();
+					CleanupStack::PopAndDestroy(); // cleanup tempRFs and reset temp file import path
+					iTempOPMLImportFilePath = _L("");
+					}
+									
+		        // Again show folder view to trigger a redraw
+				ShowFolderViewL();	
+				break;
+
+        	default:
+        		// if an import OPML was requested, do that now
+        	    if(iFeedImportRequested)
+        			{
+        			// clear flag
+        			iFeedImportRequested = EFalse;
+
+        			// show wait dialog
+					iWaitDialog->ShowWaitDialogL(R_FEEDS_WAIT_IMPORTING_FEEDS);
+				    iIsWaitDialogDisplayed = ETrue;
+					
+        	
+					if(iTempOPMLImportFilePath.Length())
+						{
+						iFeedsInterface.ImportOPMLL( iTempOPMLImportFilePath );
+						}
+            iCurrentRequest = CTransaction::EImportOPML;
+        			}       	
+        	
+		        // Set the updated folder
+		        iFolderView->RootFolderChangedL(*(iFeedsInterface.RootFolder()));
+		        
+		        // Show it.
+		        if (iNextViewId == KUidBrowserFeedsFolderViewId)
+		            {            
+		            ShowFolderViewLocalL();
+		            }
+		        
+		        // If the user tried to subscribe to a feed before it was connected
+		        // to the server then add the item now.
+		        if (iPendingFolderItemTitle != NULL)
+		            {
+		            TRAPD(err, SubscribeToL(*iPendingFolderItemTitle, *iPendingFolderItemUrl));
+		            if (err == KErrNone)
+		                {
+		                delete iPendingFolderItemTitle;
+		                iPendingFolderItemTitle = NULL;
+		                delete iPendingFolderItemUrl;
+		                iPendingFolderItemUrl = NULL;                
+		                }
+		            // Don't reset next-view; iNextViewId is EFolderViewId after above SubscribeToL() call
+		                
+		            // Otherwise try to add the folder item next time.
+		            }
+		        else if(iNextViewId == KUidBrowserFeedsFolderViewId)
+		            {
+		            // Reset next-view.
+		            iNextViewId = KUidBrowserNullViewId;
+		            }
+
+		        // Reset the "last updated" cache now that a new folder list is available.
+		        ResetFeedUpdateTime();        
+        	}
+        }
+    // Otherwise show an error.
+    else
+        {
+        // If the server terminated, reconnect to it.
+        if (aStatus == KErrServerTerminated)
+            {
+            DisconnectFromServer();
+            ConnectToServerL();
+           
+            }
+        
+        ShowServerError(aStatus, aTransType);
+        
+        // This happens when user subscribe to a feed from content view
+        // If it failed, we want to show the content view.
+        if (aStatus == KErrAlreadyExists)
+            {
+            // Set content view as the last view id.
+            iApiProvider.SetLastActiveViewId( KUidBrowserContentViewId );
+    
+            // Show the view.
+            // We already started switching to the feeds folder view and shut off full screen
+            // This will force the DoActivate on the ContentView and set back to full screen
+            iApiProvider.SetViewToBeActivatedIfNeededL( KUidBrowserFeedsFolderViewId );
+            iApiProvider.SetViewToBeActivatedIfNeededL( KUidBrowserContentViewId );
+            }
+
+        // Reset next-view.
+        iNextViewId = KUidBrowserNullViewId;
+        }        
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FeedRequestCompleted
+//
+// Called when the asynchronous request is complete.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::FeedRequestCompleted(TInt aEvent)
+    {
+    TRAP_IGNORE( FeedRequestCompletedL(aEvent) );
+    }
+    
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FeedRequestCompletedL
+//
+// Called when the asynchronous request is complete.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::FeedRequestCompletedL(TInt aStatus)
+    {
+    if (CTransaction::EFetchFeed == iCanceledRequest)
+        {
+        iCanceledRequest = CTransaction::ENone;
+        return;
+        }    
+    // Close the wait dialog.
+    iWaitDialog->Close();
+    iIsWaitDialogDisplayed = EFalse;
+
+    // Show the view if everything went ok.
+    if (aStatus == KErrNone)
+        {
+        // Extract out the intial item status -- later on, iItemStatusOrig is 
+        // used to determine which item status' change.
+        RArray<TInt>  ignore(20);
+        
+        iItemIds.Reset();
+        iItemStatus.Reset();
+        iItemStatusOrig.Reset();
+        
+        CleanupClosePushL(ignore);
+        ItemStatusL(iItemIds, iItemStatus, *(iFeedsInterface.Feed()));
+        ItemStatusL(ignore, iItemStatusOrig, *(iFeedsInterface.Feed()));
+        CleanupStack::PopAndDestroy(/*ignore*/);
+        
+        // update folder view for unread count
+        TInt unreadCount = 0;
+        for (TInt i = 0; i < iItemStatus.Count(); i++)
+            {
+            if ( iItemStatus[i] == EItemStatusUnread || iItemStatus[i] == EItemStatusNew )
+                {
+                unreadCount++;
+                }
+            }
+        iFolderView->SetUnreadCountL( unreadCount );               
+
+        // The method was called because of a updated feed.  In general, update
+        // the current view to reflect the updated feed.
+        if (iIsUpdatingFeed)
+            {
+            if (iApiProvider.LastActiveViewId() == KUidBrowserFeedsTopicViewId)
+            	{
+				iTopicView->SetCurrentFeedL(*(CurrentFeed()), 0);            	
+                }
+            }
+        
+        // Otherwise, this is a newly requested feed, so show the next
+        // view now that it is available.
+        else
+            {            
+            if (iNextViewId == KUidBrowserFeedsFeedViewId)
+                {
+                ShowFeedViewLocalL(0);
+                }
+            else if (iNextViewId == KUidBrowserFeedsTopicViewId)
+            	{
+            	ShowTopicViewLocalL(0);
+                }
+            }
+            
+        // Update the feed's "last updated" value in the cache.
+        UpdateFeedUpdatedTimeL(*(iFeedsInterface.Feed()));
+        }
+    
+    // Otherwise show an error.
+    else
+        {
+        // If the server terminated, reconnect to it.
+        if (aStatus == KErrServerTerminated)
+            {
+            DisconnectFromServer();
+            ConnectToServerL();
+            
+            }
+            
+        ShowServerError(aStatus);
+        }
+
+    // Reset updating feed.
+    iIsUpdatingFeed = EFalse;
+
+    // Reset next-view.
+    iNextViewId = KUidBrowserNullViewId;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::DialogDismissedL
+//
+// Called when the user presses the cancel button.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::DialogDismissedL()
+    {
+    // Cancel all activities that can be cancelled.
+    iIsWaitDialogDisplayed = EFalse;
+
+    
+    // If there is an ongoing search by the search agent, make sure
+    // it's cancelled and search agent destroyed  
+    if(iSearchAgent != NULL)
+        {
+        iSearchAgent->CancelSearch();
+        delete(iSearchAgent);
+        iSearchAgent = NULL;
+        }
+    else
+        {
+        iCanceledRequest = iCurrentRequest;
+        iFeedsInterface.CancelAllL();
+        }    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FetchRootFolderL
+//
+// Get the root folder from the Feeds server.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::FetchRootFolderL()
+    {
+    iFeedsInterface.GetRootFolderL();
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::AddFolderItemL
+//
+// Add a new folder item.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::AddFolderItemL(const TDesC& aTitle, const TDesC& aUrl,
+        TBool aIsFolder, const CFeedsEntity& aParent, TInt aFreq)
+    {
+    
+		CFeedsMap* temp = CFeedsMap::NewL();
+		
+		temp->SetStringAttribute(EFeedAttributeTitle,aTitle);
+		temp->SetStringAttribute(EFeedAttributeLink,aUrl);	
+        temp->SetIntegerAttribute(EFeedAttributeAutoUpdateFreq,aFreq);
+
+        // Set the next view to show after the new add folder item is added.
+        iNextViewId = KUidBrowserFeedsFolderViewId;
+    	
+        iFeedsInterface.AddL(aIsFolder?EFolder:EFeed,*temp, aParent);
+
+		delete temp;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ChangeFolderItemL
+//
+// Change the folder item.  If this is a folder then KNullDesC should be passed 
+// to the aUrl argument.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ChangeFolderItemL(CFeedsEntity& aFolderItem, 
+                const TDesC& aTitle, const TDesC& aUrl,TInt aFreq)
+    {
+	CFeedsMap* temp = CFeedsMap::NewL();
+	temp->SetStringAttribute(EFeedAttributeTitle,aTitle);
+    temp->SetStringAttribute(EFeedAttributeLink,aUrl);
+    temp->SetIntegerAttribute(EFeedAttributeAutoUpdateFreq,aFreq);
+    // Set the next view to show after the new add folder item is added.
+    iNextViewId = KUidBrowserFeedsFolderViewId;
+    	
+    aFolderItem.ChangeValueL(*temp);
+    delete temp;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::DeleteFolderItemsL
+//
+// Delete the folder items. 
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::DeleteFolderItemsL(RPointerArray<const CFeedsEntity>& aFolderItems)
+    {
+    iFeedsInterface.DeleteL(aFolderItems);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::MoveFolderItemsToL
+//
+// Move the folder items to a different parent. 
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::MoveFolderItemsToL(RPointerArray<const CFeedsEntity>& aFolderItems,
+        const CFeedsEntity& aParent)
+    {
+    iFeedsInterface.MoveToFolderL(aFolderItems, aParent);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::MoveFolderItemsL
+//
+// Move the folder item to a different index. 
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::MoveFolderItemsL(RPointerArray<const CFeedsEntity>& aFolderItems,
+        TInt aIndex)
+    {
+    iFeedsInterface.MoveL(aFolderItems, aIndex);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FetchFeedL
+//
+// Get the given feed from the Feeds server.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::FetchFeedL(const CFeedsEntity& aFeedEntity, TBool aForceUpdate, 
+        TBool aNoCache)
+    {
+    // Fetch the new feed.
+    iFeedsInterface.FetchL(aFeedEntity, aForceUpdate, aNoCache);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::UpdateFeedL
+//
+// Updates the feed with the given id.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::UpdateFeedL(const CFeedsEntity& aFeedEntity)
+    {
+    if(iIsWaitDialogDisplayed)
+    {
+    	return;
+    }
+    // Show wait dialog iff connection is already established.
+    if(iApiProvider.Connection().Connected())
+    {
+        iWaitDialog->ShowWaitDialogL(R_FEEDS_UPDATING_FEED);
+        iIsWaitDialogDisplayed = ETrue;
+    }    
+    
+    iIsUpdatingFeed = ETrue;
+
+    // Fetch the feed.
+    FetchFeedL(aFeedEntity, ETrue);
+    iCurrentRequest = CTransaction::EFetchFeed;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::UpdateFolderItemsL
+//
+// Updates the given feeds in the background.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::UpdateFolderItemsL(const RPointerArray<const CFeedsEntity>& 
+        aFolderItems)
+    {
+    if (iIsWaitDialogDisplayed)
+        {
+    	return;
+        }    
+    // Show wait dialog iff connection is already established.
+    if (iApiProvider.Connection().Connected())
+        {
+        iWaitDialog->ShowWaitDialogL(R_FEEDS_UPDATING_FEED);
+        iIsWaitDialogDisplayed = ETrue;
+        }    
+
+    // Fetch the feeds.
+    iFeedsInterface.UpdateL(aFolderItems);
+    iCurrentRequest = CTransaction::EUpdateFolderItem;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::UpdateFolderItemsL
+//
+// Updates all of feeds in the background.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::UpdateFolderItemsL()
+    {
+    if (iIsWaitDialogDisplayed)
+        {
+    	return;
+        } 
+       
+    // Show wait dialog iff connection is already established.
+    if (iApiProvider.Connection().Connected())
+        {
+        iWaitDialog->ShowWaitDialogL(R_FEEDS_UPDATING_ALL_WAIT_DIALOG);
+        iIsWaitDialogDisplayed = ETrue;
+        }    
+
+    // Fetch the feeds.
+    RPointerArray<const CFeedsEntity> aFolderItem;
+    aFolderItem.Append((iFeedsInterface.RootFolder()));
+    
+    iFeedsInterface.UpdateL(aFolderItem);
+    iCurrentRequest = CTransaction::EUpdateFolderItem;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ImportFeeds
+//
+// Import feeds from OPML file
+// -----------------------------------------------------------------------------
+//
+
+void CFeedsClientUtilities::ImportFeedsL()
+	{
+    if (iIsWaitDialogDisplayed)
+        {
+    	return;
+        }    
+	
+	// construct search agent
+	if(NULL != iSearchAgent)
+		{
+		delete(iSearchAgent);
+		iSearchAgent = NULL;
+		}
+	iSearchAgent = CFeedsFileSearchAgent::NewL(*this);
+
+    iWaitDialog->ShowWaitDialogL(R_FEEDS_WAIT_SEARCHING_FOR_FEEDS);
+    iIsWaitDialogDisplayed = ETrue;
+
+	// Start search
+	if(NULL != iSearchAgent)
+		{
+		iSearchAgent->StartSearchingL();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FeedsFileSearchCompleteL
+//
+// Implemented from the MFeedsFileSearchAgentCallback mixin, this
+// callback is called when the search for files in the filesystem has completed
+// -----------------------------------------------------------------------------
+//
+
+void CFeedsClientUtilities::FeedsFileSearchCompleteL(TInt aCount)
+	{
+	TFileEntry * fileEntry;
+	TInt i;
+
+	iWaitDialog->Close();
+	iIsWaitDialogDisplayed = EFalse;
+	
+	// If nothing is found, indicate that, cleanup and quit
+	if(aCount == 0)
+		{
+	    HBufC* note = StringLoader::LoadLC(R_FEEDS_NO_FEEDS_FOUND_ON_DEVICE);
+        iApiProvider.DialogsProvider().DialogAlertL(_L(""),*note);       
+        CleanupStack::PopAndDestroy( note );
+		}
+	else
+		{
+		//
+		// construct results dialog box to show search results
+		//
+		if(NULL != iSearchOptList)
+			{
+			delete(iSearchOptList);
+			iSearchOptList = NULL;
+			}
+		
+		iSearchOptList = new( ELeave ) CArrayFixFlat<TBrCtlSelectOptionData>(aCount);
+                
+	    HBufC* title = StringLoader::LoadLC(R_FEEDS_POPUP_TITLE_FEEDS_FILES_FOUND);	    
+
+		// loop through the search results
+        for(i = 0; i < aCount; i++)
+	        {
+	        if(iSearchAgent)
+	        	{
+					// grab file found from the search agent results and add it 
+					// as an option
+	        		fileEntry = iSearchAgent->GetFileEntry(i);
+	        		if(NULL != fileEntry)
+	        			{ 
+			            TBrCtlSelectOptionData t(fileEntry->iEntry.iName, EFalse, EFalse, EFalse);
+        		    	iSearchOptList->AppendL(t);
+    	       			}
+	        	}
+	        }
+	    
+        TBool ret(iApiProvider.DialogsProvider().DialogSelectOptionL( *title,
+        	ESelectTypeNone, *iSearchOptList));
+        	
+		CleanupStack::PopAndDestroy(title);
+		
+		//
+		// If the user selects an option, import it
+		//		
+    	if ( ret )
+        	{
+       		for( i = 0; i < aCount; i++)
+            	{
+            	if( (*iSearchOptList)[i].IsSelected() )
+                	{
+	                if(iSearchAgent)
+			        	{
+	        			fileEntry = iSearchAgent->GetFileEntry(i);
+	        			if(NULL != fileEntry)
+	        				{
+	        				BeginImportOPMLFeedsFileL(fileEntry->iPath);
+	        				}
+			        	}
+			        	break;
+                	}
+            	}
+        	}
+	
+		}
+
+		// destroy the search agent
+		delete(iSearchAgent);
+		iSearchAgent = NULL;
+	}
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::BeginImportOPMLFeedsFileL
+//
+// Given a path, save it in the class, show the root folder view and set
+// a flag to indicate we're importing. When the root folder is done opening,
+// then begin the actual import
+// -----------------------------------------------------------------------------
+//
+
+void CFeedsClientUtilities::BeginImportOPMLFeedsFileL( TFileName& aFilepath )
+	{
+		// save path
+		iTempOPMLImportFilePath = aFilepath;
+
+		// Switch to feeds view, setting the flag will import 
+		// from the tempOPMLImportFilePath when the view is ready
+		iFeedImportRequested = ETrue;		
+		ShowFolderViewL();	
+	
+	}
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ExportFeeds
+//
+// Export feeds to OPML file
+// -----------------------------------------------------------------------------
+//
+
+void CFeedsClientUtilities::ExportFeedsL(RPointerArray<const CFeedsEntity>& aFolderItems, const TDesC &aExportFileName)
+	{
+    if (iIsWaitDialogDisplayed)
+        {
+    	return;
+        }    
+
+	iWaitDialog->ShowWaitDialogL(R_FEEDS_WAIT_PROCESSING);
+	iIsWaitDialogDisplayed = ETrue;
+	
+	if (iExportFileName)
+		{
+    	delete iExportFileName;
+    	iExportFileName = NULL;
+		}
+	
+	iExportFileName = aExportFileName.AllocL();
+    iFeedsInterface.ExportFoldersL(aFolderItems, aExportFileName);
+    iCurrentRequest = CTransaction::EExportOPML;
+	}
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ShowFolderViewLocalL
+//
+// Shows the folder view.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ShowFolderViewLocalL()
+    {
+    // Set this as the last view id -- this is used in ShowLastViewL.
+    iApiProvider.SetLastActiveViewId(KUidBrowserFeedsFolderViewId);
+    
+    // Show the view.
+    iApiProvider.SetViewToBeActivatedIfNeededL(KUidBrowserFeedsFolderViewId);    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ShowTopicViewLocalL
+//
+// Shows the topic view.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ShowTopicViewLocalL(TInt aInitialItem)
+    {
+    // Set this as the last view id -- this is used in ShowLastViewL.
+    iApiProvider.SetLastActiveViewId(KUidBrowserFeedsTopicViewId);
+    
+    // Set the inital item.
+    if (iTopicView == NULL)
+		{
+		TRect rect(iAppUI.ClientRect());
+		iTopicView = CFeedsTopicView::NewL( iApiProvider, rect );
+		iAppUI.AddViewL( iTopicView ); // transfer ownership to CAknViewAppUi
+		}
+
+    iTopicView->SetInitialItem(aInitialItem);
+
+    // Show the view.
+    iApiProvider.SetViewToBeActivatedIfNeededL(KUidBrowserFeedsTopicViewId);    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ShowFeedViewLocalL
+//
+// Shows the feed view.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ShowFeedViewLocalL(TInt aInitialItem)
+    {
+    // Set this as the last view id -- this is used in ShowLastViewL.
+    iApiProvider.SetLastActiveViewId(KUidBrowserFeedsFeedViewId);
+    
+    // Set the inital item.
+    if (iFeedView == NULL)
+		{
+		TRect rect(iAppUI.ClientRect());
+		iFeedView = CFeedsFeedView::NewL( iApiProvider, rect );
+		iAppUI.AddViewL( iFeedView ); // transfer ownership to CAknViewAppUi
+		}
+
+    iFeedView->SetInitialItem(aInitialItem);
+
+    // Show the view.
+    iApiProvider.SetViewToBeActivatedIfNeededL(KUidBrowserFeedsFeedViewId);    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::CurrentRootFolder
+//
+// Returns the current root folder.
+// -----------------------------------------------------------------------------
+//
+const CFeedsEntity* CFeedsClientUtilities::CurrentRootFolder() 
+    {
+    return iFeedsInterface.RootFolder();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::CurrentFeed
+//
+// Returns the current feed.
+// -----------------------------------------------------------------------------
+//
+CFeedsEntity* CFeedsClientUtilities::CurrentFeed() 
+    {
+    return iFeedsInterface.Feed();
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::AddItemL
+//
+// Add a menu item to the given menu.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::AddItemL(CEikMenuPane& aMenuPane, TInt aCommand, 
+        TInt aTitleId)
+    {
+    CEikMenuPaneItem::SData  item;
+    HBufC*                   buf = NULL;
+    
+    buf = StringLoader::LoadLC(aTitleId);    
+    item.iText.Copy(*buf);
+    CleanupStack::PopAndDestroy(buf);
+    buf = NULL;
+    
+    item.iCommandId = aCommand;
+    item.iFlags = 0;
+    item.iCascadeId = 0;
+    aMenuPane.AddMenuItemL(item);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::AddCascadeL
+//
+// Add a sub-menu to the given menu.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::AddCascadeL(CEikMenuPane& aMenuPane, TInt aCommand, 
+        TInt aTitleId, TInt aCascade)
+    {
+    CEikMenuPaneItem::SData  item;
+    HBufC*                   buf = NULL;
+    
+    buf = StringLoader::LoadLC(aTitleId);    
+    item.iText.Copy(*buf);
+    CleanupStack::PopAndDestroy(buf);
+    buf = NULL;
+    
+    item.iCommandId = aCommand;
+    item.iFlags = 0;
+    item.iCascadeId = aCascade;
+    aMenuPane.AddMenuItemL(item);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SetItemStatus
+//
+// Sets the item's status (read/unread/new).
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::SetItemStatusL(CFeedsEntity* aItem, TFeedItemStatus aStatus)
+    {
+    TInt	ret;
+	CFeedsMap* temp = CFeedsMap::NewL();
+	temp->SetIntegerAttribute(EItemAttributeStatus,aStatus);
+    ret = aItem->ChangeValueL(*temp);
+	delete temp;
+
+    if (ret != KErrNone)
+        {
+        ShowServerError(ret);
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ItemStatus
+//
+// Returns the item's status (read/unread/new).
+// -----------------------------------------------------------------------------
+//
+TFeedItemStatus CFeedsClientUtilities::ItemStatus(TInt aItemId)
+    {
+    TInt         pos;
+    TFeedItemStatus  status = EItemStatusUndefined;
+    
+    if ((pos = iItemIds.Find(aItemId)) != KErrNotFound)
+        {        
+        status = iItemStatus[pos];
+        }
+    else
+        {
+        // TODO: panic
+        }
+        
+    return status;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ItemStatusWriteToServerL
+//
+// Writes the item status out to the server.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ItemStatusWriteToServerL()
+    {
+    RArray<TInt>         ids(20);
+    RArray<TFeedItemStatus>  status(20);
+    TInt     unreadCountDelta = 0;
+    TInt     unreadCount = 0;
+    
+    if (iItemStatus.Count() == 0)
+        {
+        return;
+        }
+        
+    CleanupClosePushL(ids);
+    CleanupClosePushL(status);
+    
+    // Build new status arrays that only contains items that changed.
+    for (TInt i = 0; i < iItemStatus.Count(); i++)
+        {
+        if (iItemStatus[i] != iItemStatusOrig[i])
+            {
+            // update orig, since the old orig doesn't hold true any more
+            // important to do so: 
+            // because this method will be called whenever deactivateView of FeedsView is called
+            iItemStatusOrig[i] = iItemStatus[i];
+
+            ids.AppendL(iItemIds[i]);
+            status.AppendL(iItemStatus[i]);
+
+            // In current UI, status can only change from New -> Read, or Unread -> Read
+            if ( iItemStatus[i] == EItemStatusRead )
+                {
+                unreadCountDelta--;
+                }
+            }
+        }    
+
+    // update folder view
+    unreadCount = iFolderView->UnreadCountChangedL( unreadCountDelta );
+
+    // Write the item status out to the server.
+    iFeedsInterface.UpdateFeedItemStatusL(ids, status, unreadCount);
+    CleanupStack::PopAndDestroy(/*status*/);
+    CleanupStack::PopAndDestroy(/*ids*/);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FaviconL
+//
+// Returns the Favicon to the given url or NULL if one isn't found.
+// -----------------------------------------------------------------------------
+//
+CGulIcon* CFeedsClientUtilities::FaviconL(const TDesC& aUrl)
+    {
+    CGulIcon*    icon = NULL;
+    
+    // TODO: Do this if access to the database is too slow.
+        // First search the local cache.
+        
+        // If not found extract it from the Feeds View's Browser Control and add
+        // it to the local cache.
+
+    // Get the favicon from the Browser Control.
+	icon = iApiProvider.WindowMgr().CurrentWindow()->BrCtlInterface().GetBitmapData(aUrl, TBrCtlDefs::EBitmapFavicon);    
+    if (icon != NULL)
+        {
+        icon->SetMask(NULL);
+        }
+    
+    return icon;
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::LazyInitL
+//
+// Ensures that the views and the connection to the FeedsServer are ready.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::LazyInitL(TBool aGetRootFolder)
+    {   
+    // Create Views
+	if(iFolderView == NULL)
+		{
+	    TRect rect(iAppUI.ClientRect());
+	    iFolderView = CFeedsFolderView::NewL( iApiProvider, rect );
+	    iAppUI.AddViewL( iFolderView ); // transfer ownership to CAknViewAppUi
+		}
+		
+
+    
+    // Connect to the server.
+    ConnectToServerL(aGetRootFolder);
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ShowServerError
+//
+// Show a server error.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ShowServerError(TInt aStatus, CTransaction::TTransactionType aRequestType/*=ENone*/)
+    {
+    TInt labelId;
+
+    // Determine which label to use.
+    switch(aStatus)
+        {
+        case KErrNoMemory:
+            labelId = R_FEEDS_OUT_OF_MEMORY;
+            break;
+		// Few errors wont be shown as pop up dialog as they will appear in list box main pane
+        case KErrCorrupt:
+            // A pop up error note should be displayed if import is requested,
+            // else error will be displayed in main pane itself
+            if (aRequestType == CTransaction::EImportOPML) 
+                {
+                labelId = R_FEEDS_MALFORMED_FEED_ERROR;
+                break;	
+                }
+		case KErrNotSupported:
+		case KErrTimedOut:
+	   	case  KErrBadName:
+        	return;
+			
+        case -KErrNotSupported:
+            // Show the special http not supported on WINSCW error
+            TRAP_IGNORE(TBrowserDialogs::InfoNoteL(R_BROWSER_INFO_NOTE, R_FEEDS_HTTP_UNSUPPORTED_WINSCW));
+            return;
+
+		case KErrAlreadyExists:
+            labelId = R_FEEDS_NAME_ALREADY_IN_USE;
+			break;			
+
+        	
+        case KErrArgument:
+            // A pop up error note should be displayed if import is requested,
+            // else error will be displayed in main pane itself
+            if (aRequestType == CTransaction::EImportOPML)
+                {
+               	labelId = R_FEEDS_MALFORMED_FEED_ERROR;
+                break;
+                }
+
+        case KErrNotFound:
+            // A pop up error note should be displayed if import is requested,
+            // else will be handled in default case.
+            if (aRequestType == CTransaction::EImportOPML)
+                {
+                labelId = R_FEEDS_FILE_NOT_FOUND_ERROR;
+                break;
+                }
+        default:
+			if (aStatus > 0) // All network errors
+                {
+                // Error will shown in listbox main pane
+                return;
+                }
+
+            // Otherwise.
+            else
+                {
+                labelId = R_FEEDS_GENERAL_ERROR;
+                }
+            break;
+        }
+
+    // Show the error dialog.
+	if (aStatus != KErrCancel)
+		{
+		TRAP_IGNORE(TBrowserDialogs::InfoNoteL(R_BROWSER_INFO_NOTE, labelId));
+		}
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ConnectToServerL
+//
+// Connect to the server.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ConnectToServerL(TBool aGetRootFolder)
+    {
+    if (!iIsConnected)
+        {
+        User::LeaveIfError(iFeedsInterface.Connect());
+        iIsConnected = ETrue;
+        }        
+    
+    if (aGetRootFolder)
+        {
+        // Set this to no-view so the folder view isn't shown after it's fetched.
+        iNextViewId = KUidBrowserNullViewId;
+        
+        FetchRootFolderL();
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::DisconnectFromServer
+//
+// Disconnect from the server.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::DisconnectFromServer()
+    {
+    if( !iIsConnected )
+        {
+        //Nothing connected, return, this is causing crash.
+        return; 
+        }
+    iFeedsInterface.Close();
+
+    iIsConnected = EFalse;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::FeedUpdatedTime
+//
+// Since the folder list isn't updated after it is fetched the FeedsClientUtilities 
+// tracks the last update times for feeds the user visits in the current session.
+// This method returns the "last updated" timestamp of the given item.
+// -----------------------------------------------------------------------------
+//
+TTime CFeedsClientUtilities::FeedUpdatedTime(const CFeedsEntity& aItem)
+    {
+    TTime  timestamp;
+    TInt   pos;
+    
+    
+    // Search the cache for the feed's url.
+    if ((pos = iFeedUpdateTimeIds.Find(aItem.GetId())) != KErrNotFound)
+        {
+        timestamp = iFeedUpdateTimeTimestamps[pos];
+        }
+        
+    // Otherwise return the item's timestamp.
+    else
+        {
+        aItem.GetTimeValue(EFeedAttributeTimestamp,timestamp);
+        }
+        
+    // Return the cached value.
+    return timestamp;
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ResetFeedUpdateTime
+//
+// Resets the "last updated" cache.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ResetFeedUpdateTime()
+    {
+    // Reset the arrays.
+    iFeedUpdateTimeIds.Reset();
+    iFeedUpdateTimeTimestamps.Reset();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::UpdateFeedUpdatedTimeL
+//
+// Update the feed's "last updated" value in the cache.
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::UpdateFeedUpdatedTimeL(const CFeedsEntity& aFeed)
+    {    
+    TInt  pos;
+    TInt  err;
+    
+    // TODO: Use the feed's id instead of the url.  This would require the
+    //       packed folder to store the feed id as well.
+    
+    // Search the cache for the feed's url and if found then update the timestamp.
+    if ((pos = iFeedUpdateTimeIds.Find(aFeed.GetId())) != KErrNotFound)
+        {
+        	TTime time;
+        	aFeed.GetTimeValue(EFeedAttributeTimestamp,time);
+        	iFeedUpdateTimeTimestamps[pos] = time;
+        }
+
+    // Otherwise add a new slot.  
+    else
+        {
+        User::LeaveIfError(iFeedUpdateTimeIds.Append(aFeed.GetId()));
+       	TTime time;
+       	aFeed.GetTimeValue(EFeedAttributeTimestamp,time);
+
+        err = iFeedUpdateTimeTimestamps.Append(time);
+        
+        // Ensure the arrays don't get out of sync if the second append fails.
+        if (err != KErrNone)
+            {
+            iFeedUpdateTimeIds.Remove(iFeedUpdateTimeIds.Count() - 1);
+            User::LeaveIfError(err);
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::InitMenuItemL()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::InitMenuItemL( CEikMenuPane* aMenuPane,
+                                             TInt aCommandId,
+                                             TInt aResourceId, 
+                                             TInt aCascadeId,
+                                             TInt aFlags )
+    {
+    CEikMenuPaneItem::SData item;
+    item.iCommandId = aCommandId;
+    item.iFlags = aFlags;
+    item.iCascadeId = aCascadeId;
+    HBufC* buf = StringLoader::LoadLC( aResourceId );
+    item.iText.Copy( *buf );
+    CleanupStack::PopAndDestroy( buf );	// buf
+    buf = NULL;
+
+    aMenuPane->AddMenuItemL( item );    
+    }
+    
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SendOPMLFileL()
+// -----------------------------------------------------------------------------
+//    
+void CFeedsClientUtilities::SendOPMLFileL( )
+    {
+    RFs                 rfs;
+    
+    _LIT(KPath, "C:\\system\\temp\\");
+    TBuf<KMaxFileName>  path(KPath);
+    
+	User::LeaveIfError(rfs.Connect());
+	CleanupClosePushL(rfs);
+
+	path.Append(*iExportFileName);
+	
+	MBmOTABinSender& sender = iApiProvider.BmOTABinSenderL();
+
+	sender.ResetAndDestroy();
+    sender.SendOPMLFileL(path);
+    
+    CleanupStack::PopAndDestroy(/*rfs*/);
+    }
+    
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::HandleCommandL()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::HandleCommandL( TUid aViewId, TInt aCommand )
+    {
+     switch (aCommand)
+        {           
+        case EWmlCmdBackToPage:
+            {
+            iApiProvider.SetViewToReturnOnClose( aViewId );
+            iApiProvider.SetViewToBeActivatedIfNeededL( KUidBrowserContentViewId );
+            break;
+            }
+
+        case EFeedsImport:
+        	ImportFeedsL();
+        	break;
+        
+        default:
+		    // pass common commands to app ui
+		    iAppUI.HandleCommandL( aCommand );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::DynInitMenuPaneL()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::DynInitMenuPaneL(
+        TInt aResourceId,
+        CEikMenuPane* aMenuPane )
+    {
+    
+    // Option menu items common to all three feeds views
+    if ((aResourceId == R_FEEDS_FOLDER_VIEW_MENU) ||
+        (aResourceId == R_FEEDS_FEED_VIEW_MENU) ||
+        (aResourceId == R_FEEDS_TOPIC_VIEW_MENU))
+        {      
+        // browser prefs
+        InitMenuItemL( aMenuPane, EWmlCmdPreferences, R_WMLBROWSER_SETTINGS_TITLE );
+        
+        // Help
+	InitMenuItemL( aMenuPane, EAknCmdHelp, R_BROWSER_MENU_ITEM_HELP, R_FEEDS_HELP_SUBMENU );
+
+        // exit
+        InitMenuItemL( aMenuPane, EWmlCmdUserExit, R_BROWSER_MENU_ITEM_EXIT );
+        }
+   }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::SetCalledFromView()
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::SetCalledFromView(TUid aViewId)
+    {
+    iCalledFromView = aViewId;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::CalledFromView()
+// -----------------------------------------------------------------------------
+//
+TUid CFeedsClientUtilities::CalledFromView()
+    {
+    return iCalledFromView;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeedsClientUtilities::ItemStatusL
+//
+// Returns the INITIAL status of each of the items in the feed.
+// The caller can then modify the values and call UpdateFeedItemStatusL
+// to request the feeds server to update the feed's item status. 
+// -----------------------------------------------------------------------------
+//
+void CFeedsClientUtilities::ItemStatusL(RArray<TInt>& aItemIds, 
+                RArray<TFeedItemStatus>& aItemStatus, const CFeedsEntity& aFeed) const
+    {
+    TInt status;
+
+    aItemIds.Reset();
+    aItemStatus.Reset();
+
+    for(TInt index=0 ; index< aFeed.GetChildren().Count() ; index++)
+        {
+        CFeedsEntity *feedEntity = aFeed.GetChildren()[index];
+
+        feedEntity->GetIntegerValue(EItemAttributeStatus,status);
+
+        User::LeaveIfError(aItemIds.Append(feedEntity->GetId()));
+        User::LeaveIfError(aItemStatus.Append((TFeedItemStatus)status));
+        }
+    }