tzservices/tzserver/Server/Source/tzsystemdata.cpp
author William Roberts <williamr@symbian.org>
Fri, 23 Apr 2010 14:37:17 +0100
branchRCL_3
changeset 22 c82a39b81a38
parent 0 2e3d3ce01487
child 81 676b6116ca93
permissions -rw-r--r--
Rework addition of Symbian splash screen to reduce the source impact (uses SVG from Bug 2414) Notes: by using the OPTION SOURCEDIR parameter in the mifconv extension instructions, I can arrange to use the same source file name in sfimage, without having to export over the original Nokia file. This means that the name inside splashscreen.mbg is the same, which removes the need for the conditional compilation in SplashScreen.cpp, and gets rid of sf_splashscreen.mmp.

// Copyright (c) 2008-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:
//

#include "tzsystemdata.h"
#include <bautils.h>
#include <tzlocalizedcityrecord.h>
#include <tzlocalizedtimezonerecord.h>

// Resource File locations
_LIT(KTzLocalizationTimeZoneResourceFileName,"\\Resource\\TimeZoneLocalization\\timezones.rSC");
_LIT(KTzLocalizationGroupResourceFileName,"\\Resource\\TimeZoneLocalization\\timezonegroups.rSC");
_LIT(KFlashPath,"c:\\Resource\\TimeZoneLocalization\\");
_LIT(KFlashDrive, "c:");
_LIT(KRom, "z:");

/**
Allocates and constructs a new CTzLocalizationResourceReader object
@return the newly constructed CTzLocalizationResourceReader
@internalTechnology
*/
CTzSystemDataDb* CTzSystemDataDb::NewLC()
	{
	CTzSystemDataDb* self = new(ELeave) CTzSystemDataDb();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

/**
Destructor
@internalTechnology
*/
CTzSystemDataDb::~CTzSystemDataDb()
	{
	iTimeZoneResourceFile.Close();
	if(iGroupResourceFileExists)
		{
		iGroupResourceFile.Close();
		}
	delete iResourceBuffer;
	iFs.Close();
	}

/**
Second phase contructor
@internalTechnology
*/
void CTzSystemDataDb::ConstructL()
	{
	User::LeaveIfError(iFs.Connect());
	
	// If resource files are found on flash drive,
  	// these will be used exclusively otherwise the
  	// default ones on ROM will be used.   
	CDir* dirList;
	// Get a list of files on flash drive
	TInt ret = iFs.GetDir(KFlashPath, KEntryAttMaskSupported, ESortNone, dirList);
	CleanupStack::PushL(dirList);
	TFileName* timeZoneResourceFileName = new(ELeave) TFileName;
	CleanupStack::PushL(timeZoneResourceFileName);
	TFileName* groupResourceFileName = new(ELeave) TFileName;
	CleanupStack::PushL(groupResourceFileName);

	TInt count = 0;
	if(dirList != NULL)
		{
		count = dirList->Count();		
		}
	// Use the files on ROM
	if(ret == KErrPathNotFound || count == 0)
		{
		timeZoneResourceFileName->Format(KRom);
		timeZoneResourceFileName->Append(KTzLocalizationTimeZoneResourceFileName);

		groupResourceFileName->Format(KRom);
		groupResourceFileName->Append(KTzLocalizationGroupResourceFileName);		
		}
	// Use the files on system drive
	else if(ret == KErrNone)
		{
		if(count > 0)
			{
			timeZoneResourceFileName->Format(KFlashDrive);
			timeZoneResourceFileName->Append(KTzLocalizationTimeZoneResourceFileName);
			
			groupResourceFileName->Format(KFlashDrive);
			groupResourceFileName->Append(KTzLocalizationGroupResourceFileName);
			}
		}
	else
		{
		User::Leave(ret);
		}
	// Form the time zone resource filename using BaflUtils::NearestLanguageFile
	BaflUtils::NearestLanguageFile(iFs,*timeZoneResourceFileName);

	// Form the time zone group resource filename using BaflUtils::NearestLanguageFile
	BaflUtils::NearestLanguageFile(iFs,*groupResourceFileName);
	
	// Open resource files - this can be done now, as it is opened in EFileShareReadersOnly mode		
	iTimeZoneResourceFile.OpenL(iFs,*timeZoneResourceFileName);
	iTimeZoneResourceFile.ConfirmSignatureL();
		
	TRAPD(groupResErr,iGroupResourceFile.OpenL(iFs,*groupResourceFileName));
	
	// Set iGroupResourceFileExists to so that it can be checked before 
	// iGroupResourceFile is used
	iGroupResourceFileExists = (groupResErr == KErrNone);
	if(iGroupResourceFileExists)
		{
		iGroupResourceFile.ConfirmSignatureL();
		iGroupResourceFileExists = ETrue;
		}
	CleanupStack::PopAndDestroy(3, dirList); // groupResourceFileName, timeZoneResourceFileName, dirList
	}

/**
Searches the time zone resource file for the given time zone ID. This function will
leave if the specified ID is not found.
@param aTimeZoneId time zone to search for.
@return The resource ID or KErrNotFound.
@internalTechnology
*/
TInt CTzSystemDataDb::FindTimeZoneResourceIdL(TInt aTimeZoneId)
	{
	TInt initialOffset = FirstTimeZoneResourceIdL();

	TInt idToCheck;

	// Search through all resources
	TInt i = 0;
	while(iTimeZoneResourceFile.OwnsResourceIdL(initialOffset + i))
		{
		// Read current resource contents
		BufferResourceL(iTimeZoneResourceFile,initialOffset + i);

		// get the first int16 (WORD in resource STRUCT)
		idToCheck = iResourceReader.ReadInt16();

		// get rid of the buffer, it's no longer needed
		ResetResourceBuffer();

		// perform check
		if(idToCheck == aTimeZoneId)
			{
			// return the current resource ID
			return initialOffset + i;
			}
		++i;
		}

	// If it's got to here the aId hasn't been found, so leave
	User::Leave(KErrNotFound);

	return KErrNotFound;	// To satisfy compiler
	}

/**
Returns the resource Id of the specified resource. This
leaves if this resource is not found in the resource file.
@param aResourceFile The resource file that the offset belongs to.
@param aOffset The offset to return.
@return The resource Id of the first resource containing localised data.
@internalTechnology
*/
TInt CTzSystemDataDb::LocalizedResourceIdL(const RResourceFile& aResourceFile, const TTzResourceOffset aOffset)
	{
	TInt resourceIdToReturn = aResourceFile.Offset();

	// Skip on the relevant number of resources, using the Offset enum
	resourceIdToReturn += aOffset;

	if(!aResourceFile.OwnsResourceIdL(resourceIdToReturn))
		{
		User::Leave(KErrNotFound);
		}

	return resourceIdToReturn;
	}

/**
Returns the resource Id of the first time zone resource. This
leaves if this resource is not found in the resource file.
@return The resource Id of the first time zone resource.
@internalTechnology
*/
TInt CTzSystemDataDb::FirstTimeZoneResourceIdL()
	{
	return LocalizedResourceIdL(iTimeZoneResourceFile,ETzFirstTimeZoneResource);
	}

/**
Returns the resource Id of the resource containing the default cached zone
information. This leaves if this resource is not found in the resource file.
@return The resource Id of the resource containing the default cached zone
information.
@internalTechnology
*/
TInt CTzSystemDataDb::CachedTimeZoneResourceIdL()
	{
	return LocalizedResourceIdL(iTimeZoneResourceFile,ETzFirstLocalizedResource);
	}

/**
Fills iResourceBuffer with the resource specified by aResourceId and sets up
iResourceReader to read from this resource. This should always be followed by a
call to ResetResourceBuffer.  This function will leave if the requested resource
is not found in the specified resource file.
@param aResourceFile The resourcefile to read from.
@param aResourceId The resource to read from.
@internalTechnology
*/
void CTzSystemDataDb::BufferResourceL(const RResourceFile& aResourceFile, TInt aResourceId)
	{
	if(!aResourceFile.OwnsResourceIdL(aResourceId))
		{
		User::Leave(KErrNotFound);
		}

	// Assign buffer for holding resource
	iResourceBuffer = aResourceFile.AllocReadL(aResourceId);

	// TResourceReader for getting data out of the buffer
	iResourceReader.SetBuffer(iResourceBuffer);
	}

/**
Resets the iResourceBuffer that contains the binary data of a resource.
@internalTechnology
*/
void CTzSystemDataDb::ResetResourceBuffer()
	{
	delete iResourceBuffer;
	iResourceBuffer = NULL;
	}

CTzLocalizedTimeZoneRecord* CTzSystemDataDb::ReadTimeZoneL(TInt aTimeZoneId)
	{
	TInt resourceId = FindTimeZoneResourceIdL(aTimeZoneId);
	return DoReadTimeZoneL(resourceId);
	}

/**
Reads in and returns a localized time zone found at the specified resource id.
@param aResourceId The resource ID of the time zone in the time zone resource
file
@return The localized time zone found at the specified resource ID.
@internalTechnology
*/
CTzLocalizedTimeZoneRecord* CTzSystemDataDb::DoReadTimeZoneL(TInt aResourceId)
	{
	BufferResourceL(iTimeZoneResourceFile,aResourceId);
	CTzLocalizedTimeZoneRecord* timeZone = CreateTimeZoneRecordFromResourceL(aResourceId);
	ResetResourceBuffer();
	return timeZone;
	}

/**
This does the actual reading of a localized time zone from the resource file.
The iResourceReader MUST already have been set up with a call to
BufferResourceL(iTimeZoneResourceFile,...), BEFORE this function is called.

@return A CTzLocalizedTimeZone containing the localized time zone information
that is currently found in iResourceReader.

@internalTechnology
*/
CTzLocalizedTimeZoneRecord* CTzSystemDataDb::CreateTimeZoneRecordFromResourceL(TInt aResourceId)
	{
	// Read localized time zone data form the resource file in the correct order
	TInt16 timeZoneId = (TInt16)iResourceReader.ReadInt16();
	TPtrC standardName(iResourceReader.ReadTPtrC());
	TPtrC daylightName(iResourceReader.ReadTPtrC());
	TPtrC shortStandardName(iResourceReader.ReadTPtrC());
	TPtrC shortDaylightName(iResourceReader.ReadTPtrC());

	CTzLocalizedTimeZoneRecord* timeZone = CTzLocalizedTimeZoneRecord::NewL(timeZoneId, standardName,
		daylightName, shortStandardName, shortDaylightName, aResourceId);

	return timeZone;
	}

/**
From MTzLocalizationReader Read the cities that are in the specified time zone
into the specified city array.
@param aCities An array of cities that will contain the cities from the
specified time zone.
@param aTimeZoneId The ID of the time zone containing the cities to return,.
@leave KErrNotFound Leaves if the specified time zone is not found or it
contains no cities.
@internalTechnology
*/
void CTzSystemDataDb::ReadCitiesL(RPointerArray<CTzLocalizedCityRecord>& aCities, TInt aTimeZoneId)
	{
	TInt resourceId = FindTimeZoneResourceIdL(aTimeZoneId);
	DoReadCitiesL(aCities, resourceId);
	}

/**
Reads in and adds the array of cities contained in the specified resource ID to
the supplied city array
@param The array of cities to which the the cities found in the time zone at
the specified resource ID will be appended to.
@param aResourceId The resource ID of the time zone that contains the cities to
be read.
@internalTechnology
*/
void CTzSystemDataDb::DoReadCitiesL(RPointerArray<CTzLocalizedCityRecord>& aCities, TInt aResourceId)
	{
	BufferResourceL(iTimeZoneResourceFile,aResourceId);
	AddCityArrayFromResourceL(aCities,aResourceId);
	ResetResourceBuffer();
	}

/**
This does the actual reading of the localized cities from the resource file.
The iResourceReader MUST already have been set up with a call to
BufferResourceL(iTimeZoneResourceFile,...) BEFORE this function is called.
@param aCities The array of cities to add the resource cities to.
@param aResourceId The resource ID of the time zone containing the cities to
read.
@return An array of CTzLocalizedCity objects containing the cities that are
currently found in iResourceReader.
@internalTechnology
*/
void CTzSystemDataDb::AddCityArrayFromResourceL(RPointerArray<CTzLocalizedCityRecord>& aCities, TInt aResourceId)
	{
	// Eat up the localised time zone info from the resource
	CTzLocalizedTimeZoneRecord* timeZone = CreateTimeZoneRecordFromResourceL(aResourceId);
	TUint tzid = timeZone->Id();
	delete timeZone;
	timeZone = NULL;

	// Get the number of cities (which automatically precedes the array as a WORD in the STRUCT)
	TInt numCities = iResourceReader.ReadInt16();

	// Leave if no cities are found
	if(numCities < 1)
		{
		User::Leave(KErrNotFound);
		}

	aCities.ReserveL(numCities + aCities.Count());
	// Loop through all the cities
	for(TInt i = 0; i < numCities; ++i)
		{
		TUint8 groupId = iResourceReader.ReadUint8();
		TPtrC cityName;
		cityName.Set(iResourceReader.ReadTPtrC());
		CTzLocalizedCityRecord* city = CTzLocalizedCityRecord::NewLC(cityName,groupId,i,tzid,aResourceId);
        aCities.Append(city);
		CleanupStack::Pop(city);
		}
	}

CTzLocalizedCityRecord* CTzSystemDataDb::ReadDefaultCityL(TInt aTimeZoneId)
	{
	// Read the cities from the specified resource
	RPointerArray<CTzLocalizedCityRecord> cities;
	CleanupStack::PushL(TCleanupItem(CTzLocalizedCityRecord::CleanupArray, &cities));
	ReadCitiesL(cities,aTimeZoneId);

	// Move first element (which is the default city) out of cities
	// to stop it being deleted when cities is
	CTzLocalizedCityRecord* defaultCity = cities[0];
	cities.Remove(0);

	CleanupStack::PopAndDestroy();	// cities
	
	return defaultCity;
	}

TInt CTzSystemDataDb::ReadFrequentlyUsedZoneIdL(TInt aFrequentlyUsedZone)
	{
	// You cannot pass ECachedTimeZones in as the argument, because it is only
	// used to keep count of how many cached zones there are.
	__ASSERT_ALWAYS(aFrequentlyUsedZone != CTzLocalizedTimeZone::ECachedTimeZones, User::Leave(KErrArgument));

	TInt offset = CachedTimeZoneResourceIdL();

	BufferResourceL(iTimeZoneResourceFile,offset);
	
	TInt tzid = 0;
	TInt defaultHomeZoneId = iResourceReader.ReadInt16();
	TInt defaultInterestZoneId = iResourceReader.ReadInt16();
	TInt defaultRecentZone1Id = iResourceReader.ReadInt16();
	TInt defaultRecentZone2Id = iResourceReader.ReadInt16();
	switch(aFrequentlyUsedZone)
			{
			case CTzLocalizedTimeZone::EHomeZone:
				tzid = defaultHomeZoneId;
				break;
			case CTzLocalizedTimeZone::EInterestZone:
				tzid = defaultInterestZoneId;
				break;
			case CTzLocalizedTimeZone::ERecentZone1:
				tzid = defaultRecentZone1Id;
				break;
			case CTzLocalizedTimeZone::ERecentZone2:
				tzid = defaultRecentZone2Id;
				break;
			case CTzLocalizedTimeZone::ECurrentZone:	// FALL THROUGH to default - current zone not supported
			default:
				User::Leave(KErrArgument);
			}
	ResetResourceBuffer();
	return tzid;
	}

CTzLocalizedTimeZoneRecord* CTzSystemDataDb::ReadFrequentlyUsedZoneL(TInt aFrequentlyUsedZone)
	{
	TInt tzid = ReadFrequentlyUsedZoneIdL(aFrequentlyUsedZone);
	return ReadTimeZoneL(tzid);
	}