clock2/clockui/uilayer/src/clockdocument.cpp
author andy simpson <andrews@symbian.org>
Thu, 02 Sep 2010 15:47:07 +0100
branchRCL_3
changeset 67 1539a383d7b6
parent 48 bf573002ff72
parent 66 bd7edf625bdd
permissions -rw-r--r--
Merge after removal of incorrect RCL_3 drop

/*
* Copyright (c) 2008 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:   This is the source file for the CClockDocument class.
*
*/

// System includes
#include <s32file.h>
#include <f32file.h>
#include <tzlocalizationdatatypes.h>
#include <tzlocalizer.h>

// User includes
#include "clockdocument.h"
#include "clockappui.h"
#include "clkuialarmmodel.h"
#include "clkcommon.h"

// Constants
const TInt KWorldClockListGranularity( 15 );
const TInt KZeroValue( 0 );

// Literals
_LIT( KFileName, "clock.dat" );

// ---------------------------------------------------------
// CClockDocument::NewL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CClockDocument* CClockDocument::NewL( CEikApplication& aApp )
    {
    CClockDocument* selfObj = new ( ELeave ) CClockDocument( aApp );
    CleanupStack::PushL( selfObj );
    
    selfObj->ConstructL();
    
    CleanupStack::Pop( selfObj );
    return selfObj;
    }

// ---------------------------------------------------------
// CClockDocument::~CClockDocument
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CClockDocument::~CClockDocument()
    {
    if( iAlarmModel )
        {
        delete iAlarmModel;
        iAlarmModel = NULL;
        }
    if( iTzLocalizer )
    	{
    	delete iTzLocalizer;
    	iTzLocalizer = NULL;
    	}
    if( iWorldClockList )
        {
        iWorldClockList->Reset();
        delete iWorldClockList;
        iWorldClockList = NULL;
        }
    }

// ---------------------------------------------------------
// CClockDocument::ReadDataL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockDocument::ReadDataL()
    {
    // The stream used to store data.
    RFileReadStream fileRStream;
    TFileName fileName;

    CleanupClosePushL( fileRStream );

    // The eikon environment.
    CEikonEnv* eikonEnv = CEikonEnv::Static();
    eikonEnv->FsSession().PrivatePath( fileName );
    
    TParse fileParse;
    fileParse.Set( KFileName, &fileName, NULL ); 

    // Open the file for reading.
    User::LeaveIfError( fileRStream.Open( Process()->FsSession(), fileParse.FullName(), EFileShareReadersOnly ) );

    TUint highInt( fileRStream.ReadUint32L() );
    TUint lowInt( fileRStream.ReadUint32L() );
    
    // Restore the previous alarm time.    
    iPrevAlarmTime = MAKE_TINT64( highInt, lowInt );
    
    // Read the cities selected by user previously.
    TUint cityCount( FALSE );
    TRAP_IGNORE( cityCount = fileRStream.ReadUint32L() );

    TCityInfo cityInfo;
    RTz tzHandle;
    // Connect to the timezone handle.
    User::LeaveIfError( tzHandle.Connect() );
    CleanupClosePushL( tzHandle );

    for( TUint index( FALSE ); index < cityCount; index++ ) 
    	{
    	cityInfo.iImagePath.Delete( KZeroValue, cityInfo.iImagePath.Length() );
    	ReadCityL( fileRStream, cityInfo, tzHandle );
    	iWorldClockList->AppendL( cityInfo, sizeof( cityInfo ) );    
    	}
    
    // Cleanup.
    CleanupStack::PopAndDestroy( &tzHandle );
    CleanupStack::PopAndDestroy( &fileRStream );
    }

// ---------------------------------------------------------
// CClockDocument::StoreDataL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockDocument::StoreDataL()
    {
    // The stream used to store data.
    RFileWriteStream fileWStream;
    TFileName fileName;

    CleanupClosePushL( fileWStream );

    // The eikon environment.
    CEikonEnv* eikonEnv = CEikonEnv::Static();

    eikonEnv->FsSession().PrivatePath( fileName );
    eikonEnv->FsSession().MkDirAll( fileName );

    TParse fileParse;
    fileParse.Set( KFileName, &fileName, NULL ); 

    // Replace the file if it already exists.
    User::LeaveIfError( fileWStream.Replace( Process()->FsSession(),fileParse.FullName(), EFileShareExclusive ) );

    // Store the previous alarm time.
    fileWStream.WriteUint32L( I64HIGH( iPrevAlarmTime ) );
    fileWStream.WriteUint32L( I64LOW( iPrevAlarmTime ) );

    // Complete the write operation.
    fileWStream.CommitL();
    
    TInt index( FALSE );
    // Check if the home city is added in world clock
    if( iHomeCityItemAdded )
        {
        // Do not store the home city data.
        // Start storing data from index 1
        index = TRUE;
        // Store the count of cities in the list without home city.
        fileWStream.WriteUint32L( iWorldClockList->Count()- 1 );
        }
    else
        {
        // Store all the cities selected in world clock view.
        // Store the count of cities in the list.
        fileWStream.WriteUint32L( iWorldClockList->Count() );
        }
		
    // Now store the cities selected in world clock view.    
    for( ; index < iWorldClockList->Count(); index++ )
    	{
    	fileWStream.WriteInt16L( ( *iWorldClockList )[ index ].iCityGroupId );
    	fileWStream.WriteInt16L( ( *iWorldClockList )[ index ].iCityOffsetInGroup );

    	TInt imagePathLength = ( *iWorldClockList )[ index ].iImagePath.Length();
    	fileWStream.WriteInt16L( imagePathLength  );
    	if( KZeroValue != imagePathLength )
            {
            fileWStream.WriteL( ( *iWorldClockList )[ index ].iImagePath, imagePathLength );
            }
    	}
    // Complete the write operation. 
    fileWStream.CommitL();
    
    // Cleanup.
    CleanupStack::PopAndDestroy( &fileWStream );
    }

// ---------------------------------------------------------
// CClockDocument::AlarmModel
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CClkUiAlarmModel* CClockDocument::AlarmModel()
    {
    return iAlarmModel;
    }

/*// ---------------------------------------------------------
// CClockDocument::GetPrevAlarmTime
// rest of the details are commented in the header
// ---------------------------------------------------------
//
TTime CClockDocument::GetPrevAlarmTime()
    {
    return TTime( iPrevAlarmTime );
    }

// ---------------------------------------------------------
// CClockDocument::SetPrevAlarmTime
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockDocument::SetPrevAlarmTime( TTime aPrevAlarmTime )
    {
    iPrevAlarmTime = aPrevAlarmTime.Int64();
    }*/

// ---------------------------------------------------------
// CClockDocument::GetWorldClockList
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CArrayPakFlat< TCityInfo >* CClockDocument::GetWorldClockList()
    {
    return iWorldClockList;
    }

// ---------------------------------------------------------
// CClockDocument::GetHomeCity
// rest of the details are commented in the header
// ---------------------------------------------------------
//
const TBuf< KHomeCityLength > CClockDocument::GetHomeCity()
    {
    return iHomeCity;
    }

// ---------------------------------------------------------
// CClockDocument::SetHomeCityL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockDocument::SetHomeCityL( TCityInfo& aCityInfo )
    {
    // First save the home city.
    iHomeCity.Copy( aCityInfo.iCity );
    
    // Now use the localizer to update the home city as a frequently used zone.
    iTzLocalizer->SetTimeZoneL( aCityInfo.iTimeZoneId );
    CTzLocalizedCity* localizedCity = iTzLocalizer->FindCityByNameL( aCityInfo.iCity, aCityInfo.iTimeZoneId );
    if( localizedCity )
        {
    	CleanupStack::PushL( localizedCity );
    	iTzLocalizer->SetFrequentlyUsedZoneL( *localizedCity, CTzLocalizedTimeZone::ECurrentZone );
    	// Cleanup.
    	CleanupStack::PopAndDestroy( localizedCity );
        }
    }

// ---------------------------------------------------------
// CClockDocument::UpdateHomeCityL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockDocument::UpdateHomeCityL()
    {
    // Connect to the timezone server.
    RTz tzHandle;
    User::LeaveIfError( tzHandle.Connect() );
    CleanupClosePushL( tzHandle );
    
    // Get the current timezone ID.
    CTzId* timeZoneId;
    timeZoneId = tzHandle.GetTimeZoneIdL();
    CleanupStack::PushL( timeZoneId);

    CTzLocalizedTimeZone* localizedTimeZone( NULL );
    CTzLocalizer* localizer( NULL );
        
    TRAPD( errVal, localizer = CTzLocalizer::NewL() );
    if( localizer && ( !errVal ) )
        {
        CleanupStack::PushL( localizer );
        // Get the currently set localized timezone.
        TRAPD( errVal, localizedTimeZone = localizer->GetLocalizedTimeZoneL( timeZoneId->TimeZoneNumericID() ) );
        CleanupStack::PushL( localizedTimeZone );
        
        if( localizedTimeZone && ( !errVal ) )
            {
            // This returns the previously stored value of homecity.
            CTzLocalizedCity* localizedCity = localizer->GetFrequentlyUsedZoneCityL(CTzLocalizedTimeZone::ECurrentZone);
            CleanupStack::PushL(localizedCity);
            
            // Update the local copy of homecity.
            iHomeCity.Copy(localizedCity->Name());
            
            // Cleanup.
            CleanupStack::PopAndDestroy(localizedCity); 
            }
        
        // Cleanup.
        CleanupStack::PopAndDestroy( localizedTimeZone );   
        CleanupStack::PopAndDestroy(localizer);
        }
    
    // Cleanup.
    CleanupStack::PopAndDestroy( timeZoneId );
    CleanupStack::PopAndDestroy( &tzHandle );
    }

// CClockDocument::CClockDocument
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CClockDocument::CClockDocument( CEikApplication& aApp ) : CAknDocument( aApp )
    {
    // No implementation yet.
    }

// ---------------------------------------------------------
// CClockDocument::ConstructL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockDocument::ConstructL()
    {
    // Construct the localizer.
    iTzLocalizer = CTzLocalizer::NewL();
    // Construct the alarm model.
    iAlarmModel = CClkUiAlarmModel::NewL( NULL, KAlarmListenerPriority );
    // Construct the world clock cities list.
    iWorldClockList = new( ELeave ) CArrayPakFlat< TCityInfo >( KWorldClockListGranularity );
    
    // Try to open the document file and read the data.
    TRAPD( readError, ReadDataL() );
    
    if( KErrNone != readError )
        {
        TTime homeTime;
        homeTime.HomeTime();
        TDateTime homeDateTime = homeTime.DateTime();
        // Set the hour minute and second.
        homeDateTime.SetHour( 9 );
        homeDateTime.SetMinute( 0 );
        homeDateTime.SetSecond( 0 );
        homeTime = homeDateTime;
        
        // Update the previous alarm time.
        iPrevAlarmTime = homeTime.Int64();
        
        // Reset the worldclocklist.
        iWorldClockList->Reset();
        }
    
    // Store the date read above.
    TRAP_IGNORE( StoreDataL() );
    // Update the homecity data.
    UpdateHomeCityL();
    }

// ---------------------------------------------------------
// CClockDocument::ReadCityL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockDocument::ReadCityL( RFileReadStream& aStream, TCityInfo& aCityInfo, RTz& aTzHandle )
	{
	// We store the offset and the city group id. So we just read them.
	TInt cityGroupId( aStream.ReadInt16L() );
	TInt cityOffset( aStream.ReadInt16L() );
	TInt imagePathLength ( aStream.ReadInt16L() );
	
	// These will hold the read zones and the respective UTC offsets.
	RArray<TInt> timeZones;
	RArray<TInt> utcOffsets;
		
	CTzLocalizedCityGroup* cityGroup( NULL );
	CTzLocalizedCityArray* cityArray( NULL );
	// Construct the cityArray and the cityGroup.
	cityArray = iTzLocalizer->GetCitiesInGroupL( cityGroupId, CTzLocalizer::ETzUnsorted );
	CleanupStack::PushL( cityArray );
	cityGroup = iTzLocalizer->GetCityGroupL( cityGroupId );
	CleanupStack::PushL( cityGroup );

	if( ( FALSE <= cityOffset ) && ( cityOffset < cityArray->Count() ) )
		{
		// First get the localized city and get the offset for the same.
		CTzLocalizedCity& localizedCity = cityArray->At( cityOffset );
		timeZones.Append( localizedCity.TimeZoneId() );
		aTzHandle.GetOffsetsForTimeZoneIdsL( timeZones, utcOffsets );    

		// Now with the data obtained, update the city information to be returned.
		aCityInfo.iCity.Copy( localizedCity.Name() );
		aCityInfo.iCountry.Copy(cityGroup->Name());
		aCityInfo.iCityGroupId = localizedCity.GroupId();
		aCityInfo.iUtcOffset = utcOffsets[ FALSE ];
		aCityInfo.iCityOffsetInGroup = cityOffset;
		aCityInfo.iTimeZoneId = localizedCity.TimeZoneId();
		}
	if( KZeroValue != imagePathLength )
		{
		aStream.ReadL( aCityInfo.iImagePath, imagePathLength );	
		}
		
	// Cleanup.
	CleanupStack::PopAndDestroy( cityGroup ); 
	CleanupStack::PopAndDestroy( cityArray ); 
	timeZones.Close();
	utcOffsets.Close();
	}

// ---------------------------------------------------------
// CClockDocument::CreateAppUiL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CEikAppUi* CClockDocument::CreateAppUiL()
    {
    return new( ELeave ) CClockAppUi;
    }

// End of file