browserui/browser/FavouritesSrc/BrowserFavouritesModel.cpp
changeset 0 84ad3b177aa3
child 24 868cceedabd3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browserui/browser/FavouritesSrc/BrowserFavouritesModel.cpp	Mon Mar 30 12:49:49 2009 +0300
@@ -0,0 +1,1084 @@
+/*
+* Copyright (c) 2002-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: 
+*      Implementation of CBrowserFavouritesModel.
+*      
+*
+*/
+
+
+// INCLUDE FILES
+#include <StringLoader.h>
+#include <aknviewappui.h>
+#include <Avkon.hrh>
+#include <AknForm.h>    // This contains CAknDialog
+#include <AknQueryDialog.h>
+#include <FavouritesDb.h>
+#include <FavouritesItem.h>
+#include <FavouritesItemList.h>
+#include <FavouritesLimits.h>
+#include <ActiveFavouritesDbNotifier.h>
+#include <BrowserNG.rsg>
+
+#include "BrowserFavouritesModel.h"
+#include "BrowserFavouritesModelObserver.h"
+#include "BrowserUtil.h"
+#include "BrowserDialogs.h"
+#include "BrowserDialogsProvider.h"
+#include "BrowserFavouritesView.h"
+
+#include "Browser.hrh"
+
+#include <FeatMgr.h>
+#include <collate.h>         // TCollateMethod
+#include "CommonConstants.h"
+
+
+// MACROS
+
+/// Cosmetic purpose macro (resource names are overly too long).
+#define _R(str) R_BROWSER_FAVOURITES_ ## str
+
+/// Time to wait before retry database OpenL() or BeginL() (==0.2 secs).
+#ifdef KRetryWait
+#undef KRetryWait
+#endif
+#define KRetryWait 200 /*TTimeIntervalMicroSeconds32*/
+
+// CONSTANTS
+
+/// Granularity of observer array.
+LOCAL_C const TInt KGranularityObservers = 4;
+
+/// Number of attempts to retry after unsuccesful database OpenL() or BeginL().
+LOCAL_C const TInt KLocalRetryCount = 2;
+
+/**
+* Estimated number of bytes in FFS for one writing operation. This amount
+* is checked to be available before each transaction which places write-lock.
+* Exact size is not known (because what happens in a transaction is unknown).
+* A typical bookmark is estimated to be less than ~200 bytes; so assuming the
+* typical operation of adding one bookmark (with database transaction
+* overhead and safety) is estimated to be 400 bytes. This should be a safe
+* guess.
+*/
+LOCAL_C const TInt KEstimatedFfsUsage = 400;
+
+// ==================== LOCAL FUNCTIONS ====================
+
+/**
+* Comparison function for two items.
+* Comparison rule:
+*   - Start Page is smaller than anything else;
+*   - otherwise, Homepage is smaller than anything else;
+*   - otherwise, Last Visited is smaller than anything else;
+*   - otherwise, any item is smaller than any folder;
+*   - otherwise, Root Folder is smaller than any other;
+*   - otherwise compare by name.
+* @param aLeft item to compare to aRight.
+* @param aRight Item to compare to aLeft.
+* @return
+*   - negative value, if aLeft is less than aRight;
+*   - 0,              if aLeft equals to aRight;
+*   - positive value, if aLeft is greater than aRight.
+*/
+LOCAL_C TInt CompareItemsL
+( const CFavouritesItem& aLeft, const CFavouritesItem& aRight )
+    {
+    // Start Page is smaller than anything else;
+    if ( aLeft.Uid() == KFavouritesStartPageUid )
+        {
+        return -1;
+        }
+    if ( aRight.Uid() == KFavouritesStartPageUid )
+        {
+        return 1;
+        }
+    // otherwise, Adaptive Bookmarks is smaller than anything else;
+    if ( aLeft.Uid() == KFavouritesAdaptiveItemsFolderUid )
+        {
+        return -1;
+        }
+    if ( aRight.Uid() == KFavouritesAdaptiveItemsFolderUid )
+        {
+        return 1;
+        }
+    // otherwise, Homepage is smaller than anything else;
+    if ( aLeft.Uid() == KFavouritesHomepageUid )
+        {
+        return -1;
+        }
+    if ( aRight.Uid() == KFavouritesHomepageUid )
+        {
+        return 1;
+        }
+    // otherwise, Last Visited is smaller than anything else;
+    if ( aLeft.Uid() == KFavouritesLastVisitedUid )
+        {
+        return -1;
+        }
+    if ( aRight.Uid() == KFavouritesLastVisitedUid )
+        {
+        return 1;
+        }
+    // otherwise, any item is smaller than any folder;
+    if ( aLeft.IsItem() && aRight.IsFolder() )
+        {
+        return -1;
+        }
+    if ( aRight.IsItem() && aLeft.IsFolder() )
+        {
+        return 1;
+        }
+    // otherwise, Root Folder is smaller than any other;
+    if ( aLeft.Uid() == KFavouritesRootUid )
+        {
+        return -1;
+        }
+	// otherwise, Null ContextId is smaller than any ContextId;
+	if ( aLeft.ContextId() == KFavouritesNullContextId && aRight.ContextId() != KFavouritesNullContextId )
+		{
+		return -1;
+		}
+	if ( aRight.ContextId() == KFavouritesNullContextId && aLeft.ContextId() != KFavouritesNullContextId )
+		{
+		return 1;
+		}
+    // otherwise compare by name.
+    return aLeft.Name().CompareC( aRight.Name() );
+    }
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::~CBrowserFavouritesModel
+// ---------------------------------------------------------
+//
+CBrowserFavouritesModel::~CBrowserFavouritesModel()
+	{
+    delete iNotifier;
+    iNotifier = NULL;
+    delete iObservers;
+    CloseDb();
+    iFavouritesSess.Close(); 
+	}
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::SetNameToDefaultL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::SetNameToDefaultL
+( CFavouritesItem& aItem ) const
+    {
+    HBufC* name = CCoeEnv::Static()->AllocReadResourceLC
+        ( StringResourceId( aItem, EDefaultName ) );
+    aItem.SetNameL( *name );
+    CleanupStack::PopAndDestroy();  // name
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::OpenDbL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::OpenDbL( TBool aDbErrorNote /*=ETrue*/ )
+    {
+    TInt err = KErrNone;
+
+    switch ( iState )
+        {
+        case EOpen:
+            {
+            // Already open.
+            break;
+            }
+
+        case ECorrupt:
+            {
+            // Useless.
+            err = KErrNotReady;
+            break;
+            }
+
+        case EClosed:
+            {
+            // Try to open now.
+            err = TimedOpenDbL();
+            if ( err )
+                {
+                // Failed to open.
+                if ( aDbErrorNote )
+                    {
+                    TBrowserDialogs::ErrorNoteL
+                        ( _R(TEXT_CANNOT_ACCESS_DB) );
+                    }
+                }
+            else
+                {
+                // Success opening.
+                iState = EOpen;
+                iNotifier->Start();
+                }
+            break;
+            }
+
+        default:
+            {
+            break;
+            }
+        }
+
+    return err;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::CloseDb
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::CloseDb()
+	{
+    if ( iNotifier )
+        {
+        // Need to check existence - ConstructL can leave half the way!
+        iNotifier->Cancel();
+        }
+    if ( iState == EOpen )
+        {
+        iDb.Close();
+        }
+    iState = EClosed;
+	}
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::BeginL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::BeginL
+( TBool aWrite, TBool aDbErrorNote, TBool aLffsCheck /*=ETrue*/ )
+    {
+    TInt err;
+
+    // Before attempting db modification, check if we would go below Critical
+    // Level in FFS (disk). The value used for checking is an estimate.
+    // Reading the db also allocates some bytes (transaction log), but
+    // this is not estimated and not checked, because it should be small
+    // enough, and would slow down operation. (Typical use is to read a lot
+    // and write much less.)
+    if (
+            aLffsCheck &&
+            aWrite &&
+            Util::FFSSpaceBelowCriticalLevelL
+                ( /*aShowErrorNote=*/aDbErrorNote, KEstimatedFfsUsage )
+       )
+        {
+        err = KErrDiskFull;
+        return err;
+        }
+
+    // Open database.
+    err = OpenDbL( /*aDbErrorNote=*/EFalse ); // Error note (if any) is here.
+    // Start a transaction.
+    if ( !err )
+        {
+        err = TimedBeginL( aWrite );
+        }
+
+    if ( err && aDbErrorNote )
+        {
+        TBrowserDialogs::ErrorNoteL( _R(TEXT_CANNOT_ACCESS_DB) );
+        }
+
+    return err;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::CommitL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::CommitL()
+    {
+    iDb.Commit();
+    CleanupStack::Pop();  // DO NOT remove this hack.
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::AddObserverL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::AddObserverL
+( MBrowserFavouritesModelObserver& aObserver )
+    {
+    iObservers->AppendL( &aObserver );
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::RemoveObserver
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::RemoveObserver
+( MBrowserFavouritesModelObserver& aObserver )
+    {
+    TInt i;
+    TInt count = iObservers->Count();
+    for ( i = 0; i < count; i++ )
+        {
+        if ( iObservers->At( i ) == &aObserver )
+            {
+            iObservers->Delete( i );
+            return;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::AddL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::AddL
+        (
+        CFavouritesItem& aItem,
+        TBool aDbErrorNote,
+        CBrowserFavouritesModel::TRenameMode aRenameMode /*=EAskIfRename*/
+        )
+    {
+    return AddUpdateL( aItem, KFavouritesNullUid, aDbErrorNote, aRenameMode );
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::UpdateL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::UpdateL
+        (
+        CFavouritesItem& aItem,
+        TInt aUid,
+        TBool aDbErrorNote,
+        CBrowserFavouritesModel::TRenameMode aRenameMode /*=EAskIfRename*/
+        )
+    {
+    return AddUpdateL( aItem, aUid, aDbErrorNote, aRenameMode );
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::SetHomepageL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::SetHomepageL
+        (
+        CFavouritesItem& aItem,
+        TBool aDbErrorNote,
+        CBrowserFavouritesModel::TRenameMode aRenameMode /*=EAskIfRename*/
+        )
+    {
+    return AddUpdateL
+        ( aItem, KFavouritesHomepageUid, aDbErrorNote, aRenameMode );
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::SetLastVisitedL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::SetLastVisitedL
+        (
+        CFavouritesItem& aItem,
+        TBool aDbErrorNote,
+        CBrowserFavouritesModel::TRenameMode aRenameMode /*=EAskIfRename*/
+        )
+    {
+    return AddUpdateL
+        ( aItem, KFavouritesLastVisitedUid, aDbErrorNote, aRenameMode );
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::AnyFoldersL
+// ---------------------------------------------------------
+//
+CBrowserFavouritesModel::TDbQuery CBrowserFavouritesModel::AnyFoldersL()
+    {
+    TDbQuery ret = EError;
+    if ( BeginL( /*aWrite=*/EFalse, /*aDbErrorNote=*/ETrue ) == KErrNone )
+        {
+        TInt count = 0;
+        if ( iDb.Count( count, KFavouritesRootUid, CFavouritesItem::EFolder )
+                                                                == KErrNone )
+            {
+            ret = count ? EYes : ENo;
+            }
+        CommitL();
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::AnyNonEmptyFoldersL
+// ---------------------------------------------------------
+//
+CBrowserFavouritesModel::TDbQuery
+CBrowserFavouritesModel::AnyNonEmptyFoldersL( CArrayFix<TInt>& aUids )
+    {
+    TDbQuery ret = EError;
+    if ( BeginL( /*aWrite=*/EFalse, /*aDbErrorNote=*/ETrue ) == KErrNone )
+        {
+        ret = ENo;
+        TInt itemCount;
+        TInt i;
+        TInt uidCount = aUids.Count();
+        for ( i = 0; i < uidCount; i++ )
+            {
+            if ( iDb.Count( itemCount, aUids.At( i ) ) == KErrNone )
+                {
+                if ( itemCount )
+                    {
+                    // We have a non-empty folder.
+                    ret = EYes;
+                    break;
+                    }
+                }
+            else
+                {
+                // Error querying; quit.
+                ret = EError;
+                break;
+                }
+            }
+        CommitL();
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::FolderInfoL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::FolderInfoL
+( TInt aFolder, TInt& aFolderCount, TInt& aFolderIndex )
+    {
+    TInt err = KErrNotFound;
+    
+    if(iApiProvider.CalledFromAnotherApp())
+        {
+        err = KErrNone;
+        aFolderIndex = 0;
+        aFolderCount = 1;
+        return err;
+        }
+    
+    CFavouritesItemList* folders = GetFoldersSortedLC();
+    // Iterate until we find the folder.
+    TInt i;
+    TInt actualCount = 0;
+    aFolderCount = actualCount = folders->Count();
+    for ( i = 0; i < actualCount; i++ )
+        {
+        if(folders->At( i )->IsHidden())
+            {
+                aFolderCount--;
+            }
+        if ( folders->At( i )->Uid() == aFolder )
+            {
+            aFolderIndex = i;
+            err = KErrNone;
+            }
+        }
+    if(aFolderIndex > aFolderCount)
+        {
+            aFolderIndex += (aFolderCount - actualCount);
+        }
+    CleanupStack::PopAndDestroy();  // folders
+    return err;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::NextFolderL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::NextFolderL( TInt aFolder, TBool aForward )
+    {
+    if ( AknLayoutUtils::LayoutMirrored() )
+        {
+        aForward = !aForward;
+        }
+    TInt folder = KFavouritesNullUid;
+    
+    if(iApiProvider.CalledFromAnotherApp())
+        {
+        return folder;
+        }
+    
+    CFavouritesItemList* folders = GetFoldersSortedLC();
+    // Iterate until we find the folder.
+    TInt i;
+    TInt count = folders->Count();
+    for ( i = 0; i < count; i++ )
+        {
+        if ( folders->At( i )->Uid() == aFolder )
+            {
+            i += aForward ? 1 : -1;
+            if ( i >= 0 && i < count )
+                {
+                // Have the neighbour.
+                folder = folders->At( i )->Uid();
+                
+                while(folders->At( i )->IsHidden())
+                    {
+                    i += aForward ? 1 : -1;
+                    if ( i < 0 || i >= count )
+                        {
+                        folder = KFavouritesNullUid;
+                        break;
+                        }
+                     else
+                        {
+                        // Have the neighbour.
+                        folder = folders->At( i )->Uid();
+                        }
+                    }
+                }
+            break;
+            }
+        }
+    CleanupStack::PopAndDestroy();  // folders
+    return folder;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::RenameQueryL
+// ---------------------------------------------------------
+//
+TBool CBrowserFavouritesModel::RenameQueryL( CFavouritesItem& aItem, TBool aNewItem )
+    {
+    TBool ret = EFalse;
+    TBuf<KFavouritesMaxName> buf = aItem.Name();
+    CAknTextQueryDialog* dialog = CAknTextQueryDialog::NewL( buf );
+    dialog->PrepareLC( _R(NAME_QUERY_OK_CANCEL) );
+    dialog->SetPredictiveTextInputPermitted(ETrue);
+    HBufC* prompt;
+    if ( aNewItem )
+        {
+        prompt =
+            StringLoader::LoadLC( StringResourceId( aItem, ENewPrompt ) );
+        }
+    else
+        {
+        prompt =
+            StringLoader::LoadLC( StringResourceId( aItem, ERenamePrompt ) );
+        }
+    dialog->SetPromptL( *prompt );
+    CleanupStack::PopAndDestroy();  // prompt
+    TInt button = dialog->RunLD();
+    if ( button )
+        {
+        aItem.SetNameL( buf.Left(KFavouritesMaxName) );
+        ret = ETrue;
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::SortL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::SortL( CFavouritesItemList& aList )
+    {
+    TBuf<KFavouritesMaxName> name;
+    TInt i;
+    TInt count = aList.Count();
+
+    TInt resId = 0;
+
+    for ( i = 0; i < count; i++ )
+        {
+        resId = CBrowserFavouritesView::GetSeamlessFolderResourceID( 
+        			aList.At(i)->ContextId() );
+        
+        if(resId) // a seamless link folder. Get the localised name.
+            {
+            HBufC* seamlessLinkName = CCoeEnv::Static()->AllocReadResourceLC( resId );
+            name = seamlessLinkName->Des();
+            CleanupStack::PopAndDestroy(); // seamlessLinkName
+			aList.At( i )->SetNameL( name );
+            }
+		}
+
+    aList.SortL( &CompareItemsL );
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::MakeUniqueNameL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::MakeUniqueNameL
+( CFavouritesItem& aItem )
+    {
+    TInt err = BeginL( /*aWrite=*/EFalse, /*aDbErrorNote=*/ETrue );
+    if ( !err )
+        {
+        err = iDb.MakeUniqueName( aItem );
+        CommitL();
+        }
+    return err;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::HandleFavouritesDbEventL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::HandleFavouritesDbEventL
+( RDbNotifier::TEvent aEvent )
+    {
+    switch ( aEvent )
+        {
+        case RDbNotifier::ECommit:
+            {
+            // Database has changed, notify observers.
+            NotifyObserversL();
+            break;
+            }
+
+        case RDbNotifier::ERollback:
+            {
+            // Database corrupted, close now and wait until everyone closes it.
+            iState = ECorrupt;
+            iDb.Close();
+            // But keep the notifier alive.
+            break;
+            }
+
+        case RDbNotifier::EClose:
+            {
+            // Database is closed by all clients.
+            if ( iState == ECorrupt )
+                {
+                // Database was closed by the model (by damage), not the user.
+                // Try to reopen it now; that will recover it.
+                iState = EClosed;
+                iNotifier->Cancel();
+                if ( OpenDbL( /*aDbErrorNote=*/EFalse ) == KErrNone )
+                    {
+                    // Succesfully reopened. Data may have changed.
+                    NotifyObserversL();
+                    }
+                }
+            break;
+            }
+
+		default:
+            {
+			break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::CBrowserFavouritesModel
+// ---------------------------------------------------------
+//
+CBrowserFavouritesModel::CBrowserFavouritesModel( MApiProvider& aApiProvider )
+	:
+	iApiProvider( aApiProvider )
+	{
+    iState = EClosed;
+	}
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::ConstructL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::ConstructL()
+	{
+    iObservers = new (ELeave) CArrayPtrFlat<MBrowserFavouritesModelObserver>
+        ( KGranularityObservers );
+    iNotifier = new (ELeave) CActiveFavouritesDbNotifier( iDb, *this );
+    User::LeaveIfError( iFavouritesSess.Connect() );
+	}
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::TimedOpenDbL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::TimedOpenDbL()
+    {
+    TInt retriesLeft = KLocalRetryCount;
+    TInt err = ( iDb.Open( iFavouritesSess, GetDBName() ));
+    while ( err && retriesLeft-- )
+        {        
+        User::After( KRetryWait );
+        err = ( iDb.Open( iFavouritesSess, GetDBName() ));
+        }
+    return err;
+    }
+    
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::GetDBName
+// ---------------------------------------------------------
+//
+const TDesC& CBrowserFavouritesModel::GetDBName()
+    {
+    //should be overridden by bookmarks model
+    return KBrowserSavedPages; //default value
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::TimedBeginL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::TimedBeginL( TBool /*aWrite*/ )
+    {
+    TInt retriesLeft = KLocalRetryCount;
+    TInt err =  iDb.Begin();
+    if ( err == KErrNone )
+        {
+        iDb.CleanupRollbackPushL();  
+        }
+    while ( err && retriesLeft-- )
+        {
+        err = iDb.Begin() ;
+        if ( err == KErrNone )
+            {
+            iDb.CleanupRollbackPushL();  
+            }
+        }
+    return err;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::AddUpdateL
+// ---------------------------------------------------------
+//
+TInt CBrowserFavouritesModel::AddUpdateL
+        (
+        CFavouritesItem& aItem,
+        TInt aUid,
+        TBool aDbErrorNote,
+        TRenameMode aRenameMode
+        )
+    {
+    TBool done = EFalse;
+    TInt err = KErrNone;
+
+    while ( !done )
+        {
+        err = BeginL( /*aWrite=*/ETrue, aDbErrorNote );
+        if ( err )
+            {
+            // Database error.
+            done = ETrue;
+            }
+        else
+            {
+            // Database OK, try to add/update item...
+            switch ( aUid )
+                {
+                    {
+                case KFavouritesHomepageUid:
+                    // Homepage update.
+                    err = iDb.SetHomepage( aItem );
+                    break;
+                    }
+
+                case KFavouritesLastVisitedUid:
+                    {
+                    // Last Visited update.
+                    err = iDb.SetLastVisited( aItem );
+                    break;
+                    }
+
+                case KFavouritesNullUid:
+                    {
+                    // Check first if the item added has the same name as any of the special folders
+                    
+                    TBool itemExists = EFalse;
+                    if (aItem.Type() == CFavouritesItem::EFolder)
+                        {   
+                        #ifdef __RSS_FEEDS
+                        HBufC* webFeedsBuf = StringLoader::LoadLC( R_BROWSER_APPS_FEEDS_LIST );
+                        TPtrC webFeeds = webFeedsBuf->Des();
+                        if(CompareIgnoreCase(aItem.Name(),webFeeds))
+                            {
+                            itemExists = ETrue;
+                            }
+                        CleanupStack::PopAndDestroy(); 
+                        #endif
+                        
+               		    if ( ( ADAPTIVEBOOKMARKS ) &&
+                            ( iApiProvider.Preferences().AdaptiveBookmarks() ==
+                                            EWmlSettingsAdaptiveBookmarksOn ))
+               		        {
+               		        HBufC* recentUrlsBuf = StringLoader::LoadLC( R_BROWSER_ADAPTIVE_BOOKMARKS_FOLDER);
+                            TPtrC recentUrls = recentUrlsBuf->Des();
+                            if(CompareIgnoreCase(aItem.Name(),recentUrls))
+                                {
+                                itemExists = ETrue;
+                                }
+                            CleanupStack::PopAndDestroy(); 
+               		        }
+                        }
+                    
+                      if (( itemExists ) && (aItem.Type() == CFavouritesItem::EFolder))
+                        {
+                        err = KErrAlreadyExists;
+                        }
+                    else
+                        {
+                        // New item addition.
+                        err = iDb.Add( aItem, aRenameMode == EAutoRename );                        
+                        }
+                    break;
+                    }
+
+                default:
+                    {
+                    // Existing item update.
+                    err = iDb.Update( aItem, aUid, aRenameMode == EAutoRename );
+                    break;
+                    }
+                }
+            CommitL();
+            
+            // ...and see the outcome.
+            switch( err )
+                {
+                case KErrNone:
+                    {
+                    // All is well.
+                    done = ETrue;
+                    break;
+                    }
+                case KErrAlreadyExists:
+                    {
+                    // The name is conflicting.
+                    switch ( aRenameMode )
+                        {
+                        case EAutoRename:
+                            {
+                            // We should never get here;
+                            // this is handled by the Engine's AutoRename.
+                            __ASSERT_DEBUG( EFalse, Util::Panic\
+                                ( Util::EFavouritesInternal ) );
+                            done = ETrue;
+                            break;
+                            }
+                        case EDontRename:
+                            {
+                            // No rename is needed.
+                            // Return with KErrAlreadyExists.
+                            done = ETrue;
+                            break;
+                            }
+                        case EAskIfRename:
+                        default:
+                            {
+                            // Prompt the user for new name.
+                            // Retry with new name, or return if Cancelled.
+							TBrowserDialogs::InfoNoteL
+											(
+											R_BROWSER_INFO_NOTE,
+											_R(TEXT_FLDR_NAME_ALREADY_USED),
+											aItem.Name()
+											);
+                            done = !RenameQueryL( aItem, EFalse );
+                            break;
+                            }
+                        }
+                    break;
+                    }
+                case KErrPathNotFound:
+                    {
+                    // The name is conflicting.
+                    switch ( aRenameMode )
+                        {
+                        case EAutoRename:
+                            {
+                            // We should never get here;
+                            // this is handled by the Engine's AutoRename.
+                            __ASSERT_DEBUG( EFalse, Util::Panic\
+                                ( Util::EFavouritesInternal ) );
+                            done = ETrue;
+                            break;
+                            }
+                        case EDontRename:
+                            {
+                            // No rename is needed.
+                            // Return with KErrAlreadyExists.
+                            done = ETrue;
+                            break;
+                            }
+                        case EAskIfRename:
+                        default:
+                            {
+                            // Prompt the user for new name.
+                            // Retry with new name, or return if Cancelled.
+							TBrowserDialogs::InfoNoteL
+												(
+												R_BROWSER_INFO_NOTE,
+												_R( TEXT_PRMPT_ILLEGAL_CHAR ),
+												aItem.Name()
+												);							
+                            done = !RenameQueryL( aItem, EFalse );
+                            break;
+                            }
+                        }
+                    break;
+					}
+                    
+                case KErrNotFound:
+                    {
+                    // Update leaved with KErrNotFound meaning someone deleted entry while it was edited
+                    // Add entry as new item instead.
+                    if (aUid != KFavouritesNullUid)
+                        {
+                        aUid = KFavouritesNullUid;
+                        }
+                    break;
+                    }
+                    
+                default:
+                    {
+                    // Some error; quit.
+                    done = ETrue;
+                    break;
+                    }
+                }
+            }
+        }
+    return err;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::GetFoldersSortedLC
+// ---------------------------------------------------------
+//
+CFavouritesItemList* CBrowserFavouritesModel::GetFoldersSortedLC()
+    {
+    CFavouritesItemList* folders = new (ELeave) CFavouritesItemList();
+    CleanupStack::PushL( folders );
+    // Get all folders.
+    iDb.GetAll( *folders, KFavouritesRootUid, CFavouritesItem::EFolder );
+     // Sort folders,
+    folders->SortL( &CompareItemsL );
+    return folders;
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::NotifyObserversL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::NotifyObserversL()
+    {
+    TInt i;
+    TInt count = iObservers->Count();
+    for ( i = 0; i < count; i++ )
+        {
+        iObservers->At( i )->HandleFavouritesModelChangeL();
+        }
+    }
+
+// ---------------------------------------------------------
+// CBrowserBookmarksModel::ManualSortL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::ManualSortL(TInt aFolder, CBrowserBookmarksOrder* aBMOrder, CArrayFixFlat<TInt>* aOrderArray, CFavouritesItemList* aItems)
+    {
+    if ( Database().GetData( aFolder ,*aBMOrder ) == KErrNone)
+        {
+        if( aOrderArray->Count() )
+            {
+            TInt swapTo = 0;
+            CFavouritesItem* swappedItem = CFavouritesItem::NewL();
+            CleanupStack::PushL(swappedItem);
+            for ( TInt i=0; i<aOrderArray->Count();i++ )    
+                {
+                TInt swapFrom = aItems->UidToIndex( ( *aOrderArray )[i] );
+                if (swapFrom != KErrNotFound)
+                    {
+                    if ((swapFrom != swapTo) && (swapTo < aItems->Count() ) )
+                        {
+                        (*swappedItem) = *( *aItems )[swapFrom];
+                        *( *aItems )[swapFrom] = *( *aItems )[swapTo];
+                        *( *aItems )[swapTo] = (*swappedItem);
+                        }
+                    swapTo++;
+                    }
+                }
+            CleanupStack::PopAndDestroy(swappedItem);
+            }
+        else
+            {
+              SortL(*aItems);
+            }
+        }
+    else
+        {
+        SortL(*aItems);
+        }
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::AddUidToLastPlaceL
+// ---------------------------------------------------------
+//
+void CBrowserFavouritesModel::AddUidToLastPlaceL(
+        TInt aUid,
+        CArrayFixFlat<TInt>* aOrderArray,
+        CBrowserBookmarksOrder* aCurrentOrder )
+    {
+    if( aCurrentOrder )
+        {
+        TInt index(0);
+        if( aOrderArray->Count() )
+            {
+           	index = aOrderArray->Count();
+            }
+        aOrderArray->InsertL( index , aUid );
+        }
+    }
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::OpenFavouritesFile
+// ---------------------------------------------------------
+//
+
+TInt CBrowserFavouritesModel::OpenFavouritesFile ( RFavouritesFile & aFavFile, TInt aUid )
+{
+return aFavFile.Open( iDb, aUid );
+}
+
+// ---------------------------------------------------------
+// CBrowserFavouritesModel::ReplaceFavouritesFile
+// ---------------------------------------------------------
+//
+
+TInt CBrowserFavouritesModel::ReplaceFavouritesFile ( RFavouritesFile & aFavFile, TInt aUid )
+{
+return aFavFile.Replace( iDb, aUid );
+}
+
+// ---------------------------------------------------------------------------
+// CBrowserFavouritesModel::CompareIgnoreCase
+// Compare two descriptors
+// ---------------------------------------------------------------------------
+//
+TBool CBrowserFavouritesModel::CompareIgnoreCase( const TDesC& aFirst, 
+                                      const TDesC& aSecond )
+    {
+    // Get the standard method
+    TCollationMethod meth = *Mem::CollationMethodByIndex( 0 );
+    meth.iFlags |= TCollationMethod::EFoldCase;
+    meth.iFlags |= TCollationMethod::EIgnoreNone;
+
+    // Magic: Collation level 3 is used
+    return aFirst.CompareC( aSecond, 3, &meth ) == 0;
+    }
+
+
+// End of File