meetingrequest/mrgui/src/cesmrlocationpluginhandler.cpp
branchRCL_3
changeset 25 3533d4323edc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meetingrequest/mrgui/src/cesmrlocationpluginhandler.cpp	Wed Sep 01 12:28:57 2010 +0100
@@ -0,0 +1,791 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  ESMR Location plugin handler implementation
+*
+*/
+#include "emailtrace.h"
+#include "cesmrlocationpluginhandler.h"
+#include "esmrconfig.hrh"
+
+#include <calentry.h>
+#include <StringLoader.h>
+#include <AknQueryDialog.h>
+#include <esmrgui.rsg>
+//<cmail>
+#include "cesmrurlparserplugin.h"
+//</cmail>
+#include <CLmkLandmarkSelectorDlg.h>
+#include <TLmkItemIdDbCombiInfo.h>
+#include <EPos_CPosLandmark.h>
+#include <AknUtils.h>
+#include <ct/rcpointerarray.h>
+
+#ifdef RD_USE_MYLOCATIONUI
+#include <mylocationui.h>
+#endif //RD_USE_MYLOCATIONUI
+
+#include "cesmrlocationplugin.h"
+#include "esmrcommands.h"
+#include "mesmrcalentry.h"
+
+#include "cesmrdynamicitemselectionlist.h"
+#include "cesmrlocationhistorymanager.h"
+#include "mesmrlocationhistoryitem.h"
+#include "cesmrconfirmationquery.h"
+
+// Unnamed namespace for local definitions
+namespace { //codescanner::namespace
+
+_LIT(KSpace, " ");
+
+// Maximum length of the text in location field
+const TInt KMaxLocationTextLength = 255;
+
+}
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::CESMRLocationPluginHandler
+// -----------------------------------------------------------------------------
+//
+CESMRLocationPluginHandler::CESMRLocationPluginHandler( MObjectProvider& aParent )
+: iParent(&aParent)
+    {
+    FUNC_LOG;
+
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::~CESMRLocationPluginHandler
+// -----------------------------------------------------------------------------
+//
+CESMRLocationPluginHandler::~CESMRLocationPluginHandler()
+    {
+    FUNC_LOG;
+    delete iWait;
+    delete iLocationPlugin;
+    delete iLandmark;
+    delete iUrlParser;
+    delete iLocationHistoryManager;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::NewL
+// -----------------------------------------------------------------------------
+//
+CESMRLocationPluginHandler* CESMRLocationPluginHandler::NewL(
+        MObjectProvider& aParent )
+    {
+    FUNC_LOG;
+    CESMRLocationPluginHandler* self =
+        new (ELeave) CESMRLocationPluginHandler( aParent );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::ConstructL()
+    {
+    FUNC_LOG;
+    iWait = new( ELeave ) CActiveSchedulerWait;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::HandleCommandL
+// -----------------------------------------------------------------------------
+//
+TBool CESMRLocationPluginHandler::HandleCommandL( TInt aCommand,
+                                                 MESMRCalEntry& aEntry,
+                                                 TBool aIgnoreQuery )
+    {
+    FUNC_LOG;
+    iIgnoreQuery = aIgnoreQuery;
+    iEntryUpdated = EFalse;
+
+    switch ( aCommand )
+        {
+        case EESMRCmdAssignFromMap:
+            {
+            if( !(iWait->IsStarted()) )
+                {
+                CCalEntry& entry = aEntry.Entry();
+                const TDesC& location = entry.LocationL();
+
+                CCalGeoValue* geoVal = entry.GeoValueL();
+                
+                if ( geoVal )
+                    {
+                    // Launch Maps
+                    LocationPluginL().SelectFromMapL( location, geoVal );
+                    }
+                else
+                    {
+                    // Extract location URL from description
+                    TPtrC locationUrl;
+                    UrlParserL().FindLocationUrl( entry.DescriptionL(),
+                                                  locationUrl );
+    
+                    // Launch Maps
+                    LocationPluginL().SelectFromMapL( location, locationUrl );
+                    }
+                iWait->Start(); // codescanner::callActiveObjectWithoutCheckingOrStopping
+
+                // iLandmark is set in async callback SelectFromMapCompleted
+                // from Maps application.
+                if ( iLandmark )
+                    {
+                    UpdateEntryFromLandmarkL( aEntry, *iLandmark );
+                    delete iLandmark;
+                    iLandmark = NULL;
+                    }
+                }
+            }
+            break;
+        case EESMRCmdUpdateFromMap:
+            {
+            if ( !(iWait->IsStarted()) )
+                {
+                // Launch Maps and ignore existing coordinates,
+                // because location has been updated
+                LocationPluginL().SelectFromMapL( aEntry.Entry().LocationL(),
+                                                  KNullDesC );
+                iWait->Start(); // codescanner::callActiveObjectWithoutCheckingOrStopping
+
+                // iLandmark is set in async callback SelectFromMapCompleted
+                // from Maps application.
+                if ( iLandmark )
+                    {
+                    UpdateEntryFromLandmarkL( aEntry, *iLandmark );
+                    delete iLandmark;
+                    iLandmark = NULL;
+                    }
+                }
+            break;
+            }
+        case EESMRCmdSearchFromMap:
+            {
+            const TDesC& location = aEntry.Entry().LocationL();
+            LocationPluginL().SearchFromMapL( location );
+            }
+            break;
+        case EESMRCmdShowOnMap:
+            {
+            CCalGeoValue* geoVal = aEntry.Entry().GeoValueL();
+            TReal lat, lon;
+            if ( geoVal && geoVal->GetLatLong( lat, lon ) )
+                {
+                LocationPluginL().ShowOnMapL( *geoVal );
+                }
+            else
+                {
+                const TDesC& description = aEntry.Entry().DescriptionL();
+                TPtrC locationUrl;
+                TInt position = UrlParserL().FindLocationUrl( description,
+                                                              locationUrl );
+                if ( position >= 0 )
+                    {
+                    LocationPluginL().ShowOnMapL( locationUrl );
+                    }
+                }
+            break;
+            }
+        case EESMRCmdLandmarks:
+            {
+            SearchFromLandmarksL( iParent, aEntry );
+            break;
+            }
+        case EESMRCmdPreviousLocations:
+            {
+            ShowSelectPreviousLocationQueryL( aEntry );
+            break;
+            }
+        case EMRCommandMyLocations:
+            {
+#ifdef RD_USE_MYLOCATIONUI
+            CMyLocationSelectorUi* ui = CMyLocationSelectorUi::NewL();
+            CleanupStack::PushL( ui );
+            
+            CPosLandmark* landmark = ui->LaunchMyLocationSelectorUiL();
+            
+            if ( landmark )
+                {
+                CleanupStack::PushL( landmark );
+                UpdateEntryFromLandmarkL( aEntry, *landmark );
+                CleanupStack::PopAndDestroy( landmark );
+                }
+            
+            CleanupStack::PopAndDestroy( ui );
+#else // RD_USE_MYLOCATIONUI
+            ASSERT( EFalse );
+#endif //RD_USE_MYLOCATIONUI
+            break;
+            }
+            
+        default:
+            User::Leave( KErrGeneral );
+        }
+
+    return iEntryUpdated;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::IsCommandAvailableL
+// -----------------------------------------------------------------------------
+//
+TBool
+CESMRLocationPluginHandler::IsCommandAvailableL( TInt aCommand,
+                                                 const MESMRCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    TBool res( EFalse );
+
+    switch ( aCommand )
+        {
+        case EESMRCmdAssignFromMap: //fallthrough
+        case EESMRCmdUpdateFromMap:
+        case EESMRCmdSearchFromMap:
+        case EESMRCmdLandmarks:
+            {
+            res = ETrue;
+            break;
+            }
+        case EESMRCmdPreviousLocations:
+            {
+            if ( LocationHistoryManagerL().ItemCount() > 0 )
+                {
+                res = ETrue;
+                }
+            break;
+            }
+        case EESMRCmdShowOnMap:
+            {
+            // Try to fetch vCal GEO value from entry
+            CCalGeoValue* geoVal = aEntry.Entry().GeoValueL();
+            TReal lat, lon;
+            if ( geoVal && geoVal->GetLatLong( lat, lon ) )
+                {
+                res = ETrue;
+                }
+            else
+                {
+                // Check if description field has location url
+                const TDesC& description = aEntry.Entry().DescriptionL();
+                TPtrC locationUrl;
+                TInt position = UrlParserL().FindLocationUrl( description,
+                                                              locationUrl );
+                if ( position >= 0 )
+                    {
+                    res = ETrue;
+                    }
+                }
+
+            break;
+            }
+#ifdef RD_USE_MYLOCATIONUI
+        case EMRCommandMyLocations:
+            {
+            res = ETrue;
+            break;
+            }
+#endif
+        default:
+            {
+            break;
+            }
+        }
+
+    return res;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::StoreLocationToHistoryL
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::StoreLocationToHistoryL(
+        const MESMRCalEntry& aEntry  )
+    {
+    FUNC_LOG;
+    const CCalEntry& entry = aEntry.Entry();
+    const TDesC& entryLocation = entry.LocationL();
+
+    // Store location only if location field contains text.
+    if ( entryLocation.Length() > 0 )
+        {
+        const TDesC& entryDescription = entry.DescriptionL();
+
+        // Search for location url from description.
+        TPtrC locationUrl;
+        TInt position = UrlParserL().FindLocationUrl( entryDescription,
+                                                      locationUrl );
+
+        // If url was not found.
+        if ( position < 0 )
+            {
+            locationUrl.Set( KNullDesC );
+            }
+
+        // Check if history item with same location and url
+        // is already stored.
+        TInt existingHistoryItemIndex = KErrNotFound;
+        TInt itemCount = LocationHistoryManagerL().ItemCount();
+        for ( TInt i = 0; i < itemCount; ++i )
+            {
+            const MESMRLocationHistoryItem& item =
+                iLocationHistoryManager->LocationHistoryItemL( i );
+
+            if ( item.Address().Compare( entryLocation ) == 0 &&
+                 item.Url().Compare( locationUrl ) == 0 )
+                {
+                existingHistoryItemIndex = i;
+                break;
+                }
+            }
+
+        // If history item with same location and url existed
+        // update it's position in history array only.
+        if ( existingHistoryItemIndex >= 0 )
+            {
+            // Ownership is not transferred,
+            // existing item is already owned by location manager.
+            const MESMRLocationHistoryItem& item =
+                iLocationHistoryManager->LocationHistoryItemL( existingHistoryItemIndex );
+
+            iLocationHistoryManager->UpdateLocationHistoryL( &item );
+            }
+        else
+            {
+            // Create new history item.
+            MESMRLocationHistoryItem* historyItem =
+                iLocationHistoryManager->CreateLocationHistoryItemL(
+                            entryLocation,
+                            locationUrl );
+
+            // Store new item to history.
+            CleanupDeletePushL( historyItem );
+            iLocationHistoryManager->UpdateLocationHistoryL( historyItem );
+            CleanupStack::Pop( historyItem );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::UpdateEntryLocationL
+// -----------------------------------------------------------------------------
+//
+TBool CESMRLocationPluginHandler::UpdateEntryLocationL( MESMRCalEntry& aEntry,
+                                                        const TDesC& aLocation,
+                                                        TBool aIgnoreQuery,
+                                                        TBool& aLocationReplaced )
+    {
+    FUNC_LOG;
+    TBool entryUpdated = EFalse;
+
+    if ( aLocation.Length() > 0 )
+        {
+        CCalEntry& entry = aEntry.Entry();
+        const TDesC& location = entry.LocationL();
+
+        // Replace old location field content.
+        TBool replace = ETrue;
+
+        if ( !aIgnoreQuery
+             && location.Length() > 0
+             && location != aLocation )
+            {
+            // Query for replacing old location field content
+            replace = CESMRConfirmationQuery::ExecuteL( location );
+            }
+
+        // If previous location was empty or user selects to
+        // replace previous location with new one.
+        if (  location.Length() == 0 || replace )
+            {
+            entry.SetLocationL( aLocation.Left( KMaxLocationTextLength ) );
+            entryUpdated = ETrue;
+            aLocationReplaced = ETrue;
+            }
+        else
+            {
+            // Concatenate new address to existing one
+            // Create CPtrCArray for existing and new location strings
+            CPtrCArray* strings = new( ELeave ) CPtrCArray( 2 );
+            CleanupStack::PushL( strings );
+            strings->AppendL( TPtrC( location ) );
+            strings->AppendL( TPtrC( aLocation ) );
+            HBufC* newLocation =
+                StringLoader::LoadLC( R_MEET_REQ_NEW_LOCATION_FORMAT,
+                                      *strings );
+            entry.SetLocationL( newLocation->Left( KMaxLocationTextLength ) );
+            entryUpdated = ETrue;
+            CleanupStack::PopAndDestroy( 2, strings );
+            }
+        }
+
+    return entryUpdated;
+    }
+
+// -----------------------------------------------------------------------------
+// From MESMRLocationPluginObserver
+// CESMRLocationPluginHandler::SelectFromMapCompleted
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::SelectFromMapCompleted( TInt aError,
+                                                         CPosLandmark* aLandmark )
+    {
+    FUNC_LOG;
+    // Remove previous landmark if one is set.
+    if ( iLandmark )
+        {
+        delete iLandmark;
+        iLandmark = NULL;
+        }
+
+    if ( aError == KErrNone )
+        {
+        // pointer to the result of landmark fetch
+        iLandmark = aLandmark;
+        }
+
+    if ( iWait->IsStarted() )
+        {
+        iWait->AsyncStop();
+        }
+    }
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::LocationPluginL
+// -----------------------------------------------------------------------------
+//
+CESMRLocationPlugin& CESMRLocationPluginHandler::LocationPluginL()
+    {
+    FUNC_LOG;
+    if ( !iLocationPlugin )
+        {
+        // Lazy construction of Location ECom plugin
+        iLocationPlugin = CESMRLocationPlugin::NewL();
+        iLocationPlugin->SetObserver(this);
+        }
+
+    return *iLocationPlugin;
+    }
+
+// ---------------------------------------------------------------------------
+// Creates adress descriptor from a  landmark object
+// ---------------------------------------------------------------------------
+//
+HBufC* CESMRLocationPluginHandler::CreateAddressFromLandmarkL(
+                                               const CPosLandmark& aLandmark )
+    {
+    FUNC_LOG;
+    CPtrCArray* addressStrings = new( ELeave ) CPtrCArray( 2 );
+    CleanupStack::PushL( addressStrings );
+
+    TBool streetAvailable = aLandmark.IsPositionFieldAvailable( EPositionFieldStreet );
+    TBool cityAvailable = aLandmark.IsPositionFieldAvailable( EPositionFieldCity );
+
+    if ( streetAvailable )
+        {
+        TPtrC streetPtr( KNullDesC );
+        User::LeaveIfError( aLandmark.GetPositionField( EPositionFieldStreet,
+                                                         streetPtr ) );
+        if ( streetPtr.Length() > 0 )
+            {
+            addressStrings->AppendL( streetPtr );
+            }
+        }
+
+    if ( cityAvailable )
+        {
+        TPtrC cityPtr( KNullDesC );
+        User::LeaveIfError( aLandmark.GetPositionField( EPositionFieldCity,
+                                                         cityPtr ) );
+        if ( cityPtr.Length() > 0 )
+            {
+            addressStrings->AppendL( cityPtr );
+            }
+        }
+
+    HBufC* address(NULL);
+
+    if ( addressStrings->Count() == 2 )
+        {
+        //format street and city to buffer
+        address = StringLoader::LoadL( R_MEET_REQ_ADDRESS_STREET_CITY,
+                                       *addressStrings );
+        }
+    else if ( addressStrings->Count() == 1 )
+        {
+        // alloc street or city to buffer
+        address = addressStrings->At( 0 ).AllocL();
+        }
+    else if ( addressStrings->Count() == 0 )
+        {
+        TPtrC namePtr( KNullDesC );
+        User::LeaveIfError( aLandmark.GetLandmarkName( namePtr ));
+        if ( namePtr.Length() > 0)
+            {
+            address = namePtr.AllocL();
+            }
+        }
+
+    CleanupStack::PopAndDestroy( addressStrings );
+
+    //Transfer ownership of address
+    return address;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::UpdateEntryFromLandmarkL
+// Updates location information into calendar entry from aLandmark.
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::UpdateEntryFromLandmarkL(
+        MESMRCalEntry& aEntry,
+        const CPosLandmark& aLandmark )
+    {
+    FUNC_LOG;
+    //parse and add address to calendar entry
+    HBufC* streetAddress = CreateAddressFromLandmarkL( aLandmark );
+    if ( streetAddress )
+        {
+        CleanupDeletePushL( streetAddress );
+        UpdateEntryLocationL( aEntry, *streetAddress );
+        CleanupStack::PopAndDestroy( streetAddress );
+        }
+
+    CCalEntry& entry = aEntry.Entry();
+    TLocality locality;
+    if ( aLandmark.GetPosition( locality ) == KErrNone )
+        {
+        // Store GEO value to entry
+        CCalGeoValue* geoVal = CCalGeoValue::NewL();
+        CleanupStack::PushL( geoVal );
+        geoVal->SetLatLongL( locality.Latitude(), locality.Longitude() );
+        entry.SetGeoValueL( *geoVal );
+        CleanupStack::PopAndDestroy( geoVal );
+        
+        //parse and add location url to calendar entry
+        HBufC* locationUrl = UrlParserL().CreateUrlFromLandmarkL( aLandmark );
+        CleanupDeletePushL( locationUrl );
+        UpdateEntryDescriptionL( aEntry, *locationUrl );
+        CleanupStack::PopAndDestroy( locationUrl );
+        }
+    else if ( iLocationReplaced )// Location field content from this landmark
+        {
+        // Clear GEO value and location URL
+        entry.ClearGeoValueL();
+        const TDesC& description = entry.DescriptionL();
+        TPtrC url;
+        TInt pos = UrlParserL().FindLocationUrl( description, url );
+        if ( pos > KErrNotFound )
+            {
+            TPtrC desc = description.Mid( pos + url.Length() );
+            entry.SetDescriptionL( desc );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::SearchFromLandmarksL
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::SearchFromLandmarksL( MObjectProvider* aParent, MESMRCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    CLmkLandmarkSelectorDlg* landmarkDlg = CLmkLandmarkSelectorDlg::NewL();
+    CleanupStack::PushL( landmarkDlg );
+    landmarkDlg->SetMopParent( aParent );
+    TLmkItemIdDbCombiInfo selectedItem;
+
+    // Execute landmark selection dialog
+    TInt isAccepted = landmarkDlg->ExecuteLD( selectedItem );
+    CleanupStack::Pop( landmarkDlg );
+    if ( isAccepted != 0 )
+        {
+        TPosLmItemId itemId = selectedItem.GetItemId();
+        CPosLandmarkDatabase* lmDataBase = selectedItem.GetLmDb();
+        CleanupStack::PushL( lmDataBase );
+
+        // Read selected landmark from landmarks database
+        CPosLandmark* landmark = lmDataBase->ReadLandmarkLC( itemId );
+        UpdateEntryFromLandmarkL( aEntry, *landmark );
+        CleanupStack::PopAndDestroy( landmark );
+        CleanupStack::PopAndDestroy( lmDataBase );
+        ReleaseLandmarkResources();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::ShowSelectPreviousLocationQueryL
+// Shows "Previous locations" query and updates aEntry
+// according to selection.
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::ShowSelectPreviousLocationQueryL( MESMRCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    // Array for listbox items.
+    RCPointerArray<HBufC> addressArray;
+    CleanupClosePushL( addressArray );
+
+    // Populate address array.
+    TInt itemCount = LocationHistoryManagerL().ItemCount();
+    for ( TInt i = 0; i < itemCount; ++i )
+        {
+        const MESMRLocationHistoryItem& item =
+            iLocationHistoryManager->LocationHistoryItemL( i );
+        HBufC* address = item.Address().AllocLC();
+        addressArray.AppendL( address );
+        CleanupStack::Pop( address );
+        }
+
+    CESMRDynamicItemSelectionList* selectionQuery =
+            CESMRDynamicItemSelectionList::NewL();
+    CleanupStack::PushL( selectionQuery );
+
+    // Execute selection query.
+    TInt idx = selectionQuery->ExecuteL( addressArray,
+            CESMRDynamicItemSelectionList::EESMRRecentLocationList );
+
+    CleanupStack::PopAndDestroy( selectionQuery );
+
+    if ( idx >= 0 && idx < addressArray.Count() )
+        {
+        const MESMRLocationHistoryItem& item =
+            iLocationHistoryManager->LocationHistoryItemL( idx );
+
+        // Update entry location.
+        const TDesC& selectedLocation = item.Address();
+        UpdateEntryLocationL( aEntry, selectedLocation );
+
+        // Update entry description if url available.
+        const TDesC& selectedLocationUrl = item.Url();
+        if ( selectedLocationUrl.Length() > 0 )
+            {
+            UpdateEntryDescriptionL( aEntry, selectedLocationUrl );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( &addressArray );
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::UpdateEntryLocationL
+// Updates aEntry location with aLocation.
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::UpdateEntryLocationL(
+        MESMRCalEntry& aEntry, const TDesC& aLocation )
+    {
+    FUNC_LOG;
+    iEntryUpdated |= UpdateEntryLocationL( aEntry,
+                                           aLocation,
+                                           iIgnoreQuery,
+                                           iLocationReplaced );
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::UpdateEntryDescriptionL
+// Updates aEntry description with aLocationUrl.
+// -----------------------------------------------------------------------------
+//
+void CESMRLocationPluginHandler::UpdateEntryDescriptionL(
+        MESMRCalEntry& aEntry, const TDesC& aLocationUrl )
+    {
+    FUNC_LOG;
+    if ( aLocationUrl.Length() > 0 )
+        {
+        CCalEntry& entry = aEntry.Entry();
+        HBufC* description = HBufC::NewL( entry.DescriptionL().Length() +
+                             aLocationUrl.Length() + 1);
+        CleanupStack::PushL( description );
+        TPtr descriptionPointer( description->Des() );
+        TPtrC urlPointer;
+        TInt position;
+        position = UrlParserL().FindLocationUrl( entry.DescriptionL(), urlPointer);
+
+        if ( position >= KErrNone )
+            {
+            descriptionPointer.Copy( entry.DescriptionL() );
+            if ( ( position > 0 ) && ( entry.DescriptionL().Length() >
+                                        (position + aLocationUrl.Length() ) ) )
+                {
+                descriptionPointer.Delete( position, ( urlPointer.Length() + 1 ) );
+                }
+            else
+                {
+                descriptionPointer.Delete( position, urlPointer.Length() );
+                }
+            descriptionPointer.Insert( 0, aLocationUrl );
+            if ( position > 0 )
+                {
+                descriptionPointer.Insert( aLocationUrl.Length(), KSpace );
+                }
+            entry.SetDescriptionL( *description );
+            iEntryUpdated = ETrue;
+            }
+        else
+            {
+            descriptionPointer.Copy( entry.DescriptionL() );
+            descriptionPointer.Insert( 0, aLocationUrl );
+            if ( entry.DescriptionL().Length() != 0 )
+                {
+                descriptionPointer.Insert( aLocationUrl.Length(), KSpace );
+                }
+            entry.SetDescriptionL( *description );
+            iEntryUpdated = ETrue;
+            }
+        CleanupStack::PopAndDestroy( description );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::UrlParserL
+// Creates and returns location URL parser.
+// -----------------------------------------------------------------------------
+//
+CESMRUrlParserPlugin& CESMRLocationPluginHandler::UrlParserL()
+    {
+    FUNC_LOG;
+    if ( !iUrlParser )
+        {
+        iUrlParser = CESMRUrlParserPlugin::NewL();
+        }
+
+    return *iUrlParser;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRLocationPluginHandler::LocationHistoryManagerL
+// Creates and returns location history manager.
+// -----------------------------------------------------------------------------
+//
+CESMRLocationHistoryManager& CESMRLocationPluginHandler::LocationHistoryManagerL()
+    {
+    FUNC_LOG;
+    if ( !iLocationHistoryManager )
+        {
+        iLocationHistoryManager = CESMRLocationHistoryManager::NewL();
+        }
+
+    return *iLocationHistoryManager;
+    }
+
+// EOF
+