clock/clockmw/clocktimezone/src/timezoneclient.cpp
changeset 18 c198609911f9
child 26 a949c2543c15
child 45 b6db4fd4947b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clock/clockmw/clocktimezone/src/timezoneclient.cpp	Fri Apr 16 14:57:40 2010 +0300
@@ -0,0 +1,1248 @@
+/*
+* Copyright (c) 2009-2010 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:
+* Definition file for the TimeZoneClient class.
+*
+*/
+
+// System includes
+#include <QList>
+#include <QStandardItemModel>
+#include <QDebug>
+#include <QtAlgorithms>
+#include <tzlocalizationdatatypes.h>
+#include <tzlocalizer.h>
+#include <tz.h>
+#include <vtzrules.h>
+
+// User includes
+#include "timezoneclient.h"
+#include "clockcommon.h"
+#include "debug.h"
+#include "clockserverclt.h"
+
+const int KDaysInWeek(7);
+const int KZerothRule(0);
+const int KOneHour(1);
+const int KNoDifference(0);
+
+/*!
+	\class TimezoneClient
+
+	This class is the QObject based client interface for services offered by
+	tzserver and timezonelocalization.
+ */
+
+/*!
+	Default constructor.
+
+	\param parent The parent.
+ */
+TimezoneClient::TimezoneClient(QObject* parent)
+:QObject(parent),
+ mTimeUpdateOn(false),
+ mFetchCount(0)
+{
+	qDebug("clock: TimezoneClient::TimezoneClient() -->");
+
+	TCallBack callback(environmentCallback, this);
+
+	mNotifier = CEnvironmentChangeNotifier::NewL(
+			CActive::EPriorityStandard, callback);
+	mNotifier->Start();
+
+	RClkSrvInterface clkSrvInterface1;
+	User::LeaveIfError(clkSrvInterface1.Connect());
+	TBool aUpdate;
+	clkSrvInterface1.IsAutoTimeUpdateOn(aUpdate);
+	if(aUpdate){
+	mTimeUpdateOn = true;
+	}
+	else {
+	mTimeUpdateOn = false;
+	}
+	clkSrvInterface1.Close();
+
+	mTzLocalizer = CTzLocalizer::NewL();
+
+	qDebug("clock: TimezoneClient::TimezoneClient() <--");
+}
+
+/*!
+	Destructor.
+ */
+TimezoneClient::~TimezoneClient()
+{
+	if (mNotifier) {
+		mNotifier->Cancel();
+		delete mNotifier;
+		mNotifier = 0;
+	}
+	if (mWorldClockModel) {
+		mWorldClockModel->clear();
+	}
+	if (mTzLocalizer) {
+		delete mTzLocalizer;
+		mTzLocalizer = NULL;
+	}
+	if (mTimeZoneIds.count()) {
+		mTimeZoneIds.clear();
+	}
+}
+
+/*!
+	This functions returns a QList of location info which represent all the
+	cities preset in the device returned by the tz server.
+
+	\return QList<LocationInfo> A list of location info objects which contain a
+			valid cityName, countryName, tz id and city group id. None of the other
+			data is filled.
+ */
+QList<LocationInfo> TimezoneClient::getLocations()
+{
+	qDebug("clock: TimezoneClient::getLocations() -->");
+
+	// This list will contain the info of the cities fetched from tz server.
+	QList<LocationInfo> infoList;
+
+	// Construct the timezone localizer.
+	CTzLocalizer* localizer = CTzLocalizer::NewL();
+	CleanupStack::PushL(localizer);
+
+	// Get the cities, in alphabetical-ascending sorted order.
+	CTzLocalizedCityArray* cityArray =
+			localizer->GetCitiesL(CTzLocalizer::ETzAlphaNameAscending);
+	ASSERT(cityArray);
+	CleanupStack::PushL(cityArray);
+	int cityCount = cityArray->Count();
+
+	CTzLocalizedCityGroup* country = 0;
+	int prevGroupId = -1;
+	TPtrC countryName;
+
+	// Now get the country\city-group of each of the city.
+	// Print the timezone id and city group id as well.
+	for (int iter = 0; iter < cityCount; iter++) {
+		CTzLocalizedCity* localizedCity = &(cityArray->At(iter));
+		TPtrC cityName(localizedCity->Name());
+		int tzId(localizedCity->TimeZoneId());
+
+		if(-1==mTimeZoneIds.indexOf(tzId)) {
+			mTimeZoneIds.append(tzId);
+		}
+
+		int cityGroupId(localizedCity->GroupId());
+
+		if (cityGroupId != prevGroupId) {
+			prevGroupId = cityGroupId;
+
+			if (country) {
+				delete country;
+			}
+			country = localizer->GetCityGroupL(cityGroupId);
+			countryName.Set(country->Name());
+		}
+
+		// Now insert that data into the info list.
+		LocationInfo cityInfo;
+		cityInfo.cityGroupId = cityGroupId;
+		cityInfo.timezoneId = tzId;
+		cityInfo.cityName = QString::fromUtf16(
+				cityName.Ptr(), cityName.Length());
+		cityInfo.countryName = QString::fromUtf16(
+				countryName.Ptr(), countryName.Length());
+		infoList.append(cityInfo);
+	}
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(cityArray);
+	CleanupStack::PopAndDestroy(localizer);
+
+	qDebug("clock: TimezoneClient::getLocations() <--");
+
+	return infoList;
+}
+
+bool TimezoneClient::getUtcDstOffsetL(int& dstOffset, const CTzId& timezoneId)
+{
+	RTz tzHandle;
+	User::LeaveIfError(tzHandle.Connect());
+	CleanupClosePushL(tzHandle);
+
+	// Local time.
+	TTime homeTime;
+	homeTime.HomeTime();
+
+	TDateTime dateTime;
+	dateTime = homeTime.DateTime();
+
+	// Get the CTzRules for the current year and for the given time zone id.
+	CTzRules* timezoneRules = tzHandle.GetTimeZoneRulesL(
+			timezoneId, dateTime.Year(), dateTime.Year(), ETzWallTimeReference);
+	CleanupStack::PushL(timezoneRules);
+
+	// Get the Actualised rules for the same year.
+	// These are the DST rules from which we get the iNewOffset.
+	CVTzActualisedRules *actualizedRules =
+			CVTzActualisedRules::NewL(
+					homeTime.DateTime().Year(), homeTime.DateTime().Year());
+	CleanupStack::PushL(actualizedRules);
+	timezoneRules->GetActualisedRulesL(*actualizedRules);
+
+	// This way of fetching initial offset is being used rather than
+	// tzRules->InitialStdTimeOffset() because in some cases,
+	// the offset returned is incorrect. (For ex: Argentina and Canada/Iqaluit)
+	RArray<TInt> timeZones;
+	RArray<TInt> zoneOffsets;
+
+	// Append the current timezone ID and request for the standard offset
+	timeZones.Append(timezoneId.TimeZoneNumericID());
+	tzHandle.GetOffsetsForTimeZoneIdsL(timeZones, zoneOffsets);
+
+	// The initial offset or the standard offset (w/o DST)
+	int initialTimeZoneOffset = zoneOffsets[ 0 ];
+
+	// Close the resource handles
+	timeZones.Close();
+	zoneOffsets.Close();
+
+	// The number of actualised rules
+	int ruleCount = actualizedRules->Count();
+
+	for (int ruleIndex(0); ruleIndex < ruleCount; ruleIndex++) {
+		const TVTzActualisedRule& tVTzactRule = (*actualizedRules)[ruleIndex];
+
+		// If the standard offset and the new offset do not match then we have
+		// a dst offset. Technically if a timezone has DST then it can have a
+		// max of two offsets. One is the standard which doesn't show the DST
+		// usage, and the other is the DST offset which is
+		// standard offset + the amount of DST.
+		if (initialTimeZoneOffset != tVTzactRule.iNewOffset) {
+			dstOffset = tVTzactRule.iNewOffset;
+			CleanupStack::PopAndDestroy(actualizedRules);
+			CleanupStack::PopAndDestroy(timezoneRules);
+			CleanupStack::PopAndDestroy(&tzHandle);
+			return true;
+		} else {
+			dstOffset = initialTimeZoneOffset;
+		}
+	}
+	CleanupStack::PopAndDestroy(actualizedRules);
+	CleanupStack::PopAndDestroy(timezoneRules);
+	CleanupStack::PopAndDestroy(&tzHandle);
+	return false;
+}
+
+LocationInfo TimezoneClient::getCurrentZoneInfoL()
+{
+	qDebug() << "clock: TimezoneClient::getCurrentZoneInfoL -->";
+
+	// Current zone info.
+	LocationInfo currentLocation;
+	int timezoneId(0);
+	int utcOffset(0);
+
+	// Connect to the timezone server.
+	RTz tzHandle;
+	User::LeaveIfError(tzHandle.Connect());
+	CleanupClosePushL(tzHandle);
+
+	// Get the current timezone ID.
+	CTzId* tzId;
+	tzId = tzHandle.GetTimeZoneIdL();
+	CleanupStack::PushL(tzId);
+
+	// TODO: Get the standard offset for current timezone.
+	// This way of fetching initial offset is being used rather than
+	// tzRules->InitialStdTimeOffset()because in some cases, the offset returned
+	// is incorrect. (For ex: Argentina and Canada/Iqaluit)
+	RArray<TInt> timeZones;
+	RArray<TInt> zoneOffsets;
+
+	// Append the current timezone ID and request for the standard offset
+	timeZones.Append(tzId->TimeZoneNumericID());
+	tzHandle.GetOffsetsForTimeZoneIdsL(timeZones, zoneOffsets);
+
+	// The initial offset or the standard offset (w/o DST)
+	int initialTimeZoneOffset = zoneOffsets[0];
+
+	// Close the resource handles
+	timeZones.Close();
+	zoneOffsets.Close();
+
+	// Construct CTzLocalizer object to get the timezone from the ID.
+	CTzLocalizer* tzLocalizer = CTzLocalizer::NewL();
+
+	// Get all the localized timezones for the current timezone ID.
+	CTzLocalizedTimeZone* localizedTimeZone(NULL);
+
+	if (tzLocalizer) {
+		// Get the currently set localized timezone.
+		CleanupStack::PushL(tzLocalizer);
+		localizedTimeZone =
+			tzLocalizer->GetLocalizedTimeZoneL(tzId->TimeZoneNumericID());
+
+		if (localizedTimeZone) {
+			CleanupStack::PushL(localizedTimeZone);
+
+			// Get the frequently used localized city.
+			CTzLocalizedCity* localizedCity(0);
+			localizedCity = tzLocalizer->GetFrequentlyUsedZoneCityL(
+					CTzLocalizedTimeZone::ECurrentZone);
+			CleanupStack::PushL(localizedCity);
+
+			// Get all the city groups.
+			CTzLocalizedCityGroupArray* cityGroupArray =
+					tzLocalizer->GetAllCityGroupsL(
+							CTzLocalizer::ETzAlphaNameAscending);
+			CleanupStack::PushL(cityGroupArray);
+
+			// Get the index of the country corresponding to the city group ID.
+			int countryIndex(1);
+
+			for (int index = 0; index < cityGroupArray->Count(); index++) {
+				if (localizedCity->GroupId() ==
+						cityGroupArray->At(index).Id()) {
+					countryIndex = index;
+				}
+			}
+
+			// Get all the cities within the currently set country.
+			CTzLocalizedCityArray* cityList = tzLocalizer->GetCitiesInGroupL(
+					(cityGroupArray->At(countryIndex )).Id(),
+					CTzLocalizer::ETzAlphaNameAscending);
+			CleanupStack::PushL(cityList);
+
+			// Check if automatic time update is enabled.
+			bool timeUpdateOn( false );
+
+			// Connect to the clock server.
+			// TODO: connect to the clock server and get auto update status in
+			// var:  timeUpdateOn
+			// Check if the country contains only one city or if automatic
+			// time update is on.
+			if (1 == cityList->Count() || timeUpdateOn) {
+				// If yes, then display only the country name.
+				// TODO
+			} else {
+				// Display city name.
+				// TODO:
+			}
+
+			// Get the country name.
+			TPtrC countryName(cityGroupArray->At(countryIndex).Name());
+			currentLocation.countryName = QString::fromUtf16(
+					countryName.Ptr(), countryName.Length());
+
+			// Get the city name.
+			TPtrC cityName(localizedCity->Name());
+			currentLocation.cityName = QString::fromUtf16(
+					cityName.Ptr(), cityName.Length());
+
+			// Get the UTC offset.
+			timezoneId = localizedCity->TimeZoneId();
+
+			if (timezoneId) {
+				// Check if the DST is on for the current timezone.
+				if (isDSTOnL(timezoneId)) {
+					// Get the offset with DST enabled.
+					getUtcDstOffsetL(utcOffset, *tzId);
+
+					currentLocation.dstOn = true;
+					currentLocation.timezoneId = timezoneId;
+					currentLocation.zoneOffset = utcOffset;
+				} else {
+					// Use the standard offset.
+					currentLocation.dstOn = false;
+					currentLocation.timezoneId = timezoneId;
+					currentLocation.zoneOffset = initialTimeZoneOffset;
+				}
+			}
+
+			// Cleanup.
+			CleanupStack::PopAndDestroy( cityList );
+			CleanupStack::PopAndDestroy( cityGroupArray );
+			CleanupStack::PopAndDestroy( localizedCity );
+			CleanupStack::PopAndDestroy( localizedTimeZone );
+		}
+
+		// Cleanup.
+		CleanupStack::PopAndDestroy( tzLocalizer );
+	}
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy( tzId );
+	CleanupStack::PopAndDestroy( &tzHandle );
+
+	qDebug() << "clock: TimezoneClient::getCurrentZoneInfoL <--";
+
+	return currentLocation;
+}
+
+void TimezoneClient::setAsCurrentLocationL(LocationInfo &location)
+{
+	Debug::writeDebugMsg(
+			"In time zone client setAsCurrentLocationL " + location.cityName +
+			" " +
+			location.countryName +
+			" " +
+			QString::number(location.zoneOffset));
+
+	// Construct CTzLocalizer object.
+	CTzLocalizer* tzLocalizer = CTzLocalizer::NewL();
+	CleanupStack::PushL( tzLocalizer );
+	tzLocalizer->SetTimeZoneL( location.timezoneId );
+
+	TPtrC ptrCityName(
+			reinterpret_cast<const TText*>(location.cityName.constData()));
+	CTzLocalizedCity* localizedCity =
+			tzLocalizer->FindCityByNameL(ptrCityName, location.timezoneId);
+	CleanupStack::PushL( localizedCity );
+	tzLocalizer->SetFrequentlyUsedZoneL(
+			*localizedCity, CTzLocalizedTimeZone::ECurrentZone);
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy( localizedCity );
+	CleanupStack::PopAndDestroy( tzLocalizer );
+}
+
+bool TimezoneClient::isDSTOnL(int timezoneId)
+{
+	bool returnVal( false );
+	CTzId* tzId = CTzId::NewL( timezoneId );
+	CleanupStack::PushL( tzId );
+
+	RTz tzHandle;
+	User::LeaveIfError( tzHandle.Connect() );
+	CleanupClosePushL( tzHandle );
+
+	returnVal = tzHandle.IsDaylightSavingOnL( *tzId );
+
+	tzHandle.Close();
+	CleanupStack::PopAndDestroy( &tzHandle );
+	CleanupStack::PopAndDestroy( tzId );
+
+	return returnVal;
+}
+
+int TimezoneClient::getStandardOffset(int timezoneId)
+{
+	RTz tzHandle;
+	User::LeaveIfError(tzHandle.Connect());
+	CleanupClosePushL(tzHandle);
+
+	RArray<int> idArray;
+	RArray<int> offsetArray;
+	idArray.Append(timezoneId);
+
+	tzHandle.GetOffsetsForTimeZoneIdsL(idArray, offsetArray);
+	int stdOffset = offsetArray[0];
+
+	offsetArray.Close();
+	idArray.Close();
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(&tzHandle);
+
+	return stdOffset;
+}
+
+void TimezoneClient::getDstRulesL(
+		QDateTime &startTime, QDateTime &endTime, int timezoneId)
+{
+	RTz tzHandle;
+	User::LeaveIfError(tzHandle.Connect());
+	CleanupClosePushL(tzHandle);
+
+	// Local time.
+	TTime homeTime;
+	homeTime.HomeTime();
+
+	TDateTime dateTime;
+	dateTime = homeTime.DateTime();
+
+	CTzId *tzId = CTzId::NewL(timezoneId);
+	CleanupStack::PushL(tzId);
+	// Get the CTzRules for the current year and for the given time zone id.
+	CTzRules* timezoneRules = tzHandle.GetTimeZoneRulesL(
+			*tzId, dateTime.Year(), dateTime.Year(), ETzWallTimeReference);
+	CleanupStack::PushL(timezoneRules);
+
+	// Get the Actualised rules for the same year.
+	// These are the DST rules from which we get the iNewOffset.
+	CVTzActualisedRules *actualizedRules = CVTzActualisedRules::NewL(
+			homeTime.DateTime().Year(), homeTime.DateTime().Year() );
+	CleanupStack::PushL(actualizedRules);
+	timezoneRules->GetActualisedRulesL(*actualizedRules);
+
+	// This way of fetching initial offset is being used rather than
+	// tzRules->InitialStdTimeOffset() because in some cases,
+	// the offset returned is incorrect. (For ex: Argentina and Canada/Iqaluit)
+	RArray<TInt> timeZones;
+	RArray<TInt> zoneOffsets;
+
+	// Append the current timezone ID and request for the standard offset
+	timeZones.Append(timezoneId);
+	tzHandle.GetOffsetsForTimeZoneIdsL(timeZones, zoneOffsets);
+
+	// The initial offset or the standard offset (w/o DST)
+	int initialTimeZoneOffset = zoneOffsets[ 0 ];
+
+	// Close the resource handles
+	timeZones.Close();
+	zoneOffsets.Close();
+
+	// The number of actualised rules
+	int ruleCount = actualizedRules->Count();
+
+	for(int ruleIndex(1); ruleIndex < ruleCount; ruleIndex++) {
+		const TVTzActualisedRule& tVTzactRule = (*actualizedRules)[ruleIndex];
+
+		TTime ruleTime(tVTzactRule.iTimeOfChange);
+
+		if (initialTimeZoneOffset == tVTzactRule.iNewOffset) {
+			TTime tempRuleTime(ruleTime);
+			if (tVTzactRule.iTimeReference == ETzUtcTimeReference) {
+				tempRuleTime += TTimeIntervalMinutes(tVTzactRule.iNewOffset);
+			}
+
+			QTime tempTime;
+			QDate tempDate;
+			tempTime.setHMS(tempRuleTime.DateTime().Hour(),
+			                tempRuleTime.DateTime().Minute(),
+			                tempRuleTime.DateTime().Second());
+			tempDate.setYMD(tempRuleTime.DateTime().Year(),
+			                tempRuleTime.DateTime().Month()+1,
+			                tempRuleTime.DateTime().Day()+1);
+			endTime.setDate(tempDate);
+			endTime.setTime(tempTime);
+		} else {
+			TTime tempRuleTime(ruleTime);
+			if (tVTzactRule.iTimeReference == ETzUtcTimeReference) {
+				tempRuleTime += TTimeIntervalMinutes(tVTzactRule.iNewOffset);
+			}
+			QTime tempTime;
+			QDate tempDate;
+			tempTime.setHMS(tempRuleTime.DateTime().Hour(),
+			                tempRuleTime.DateTime().Minute(),
+			                tempRuleTime.DateTime().Second());
+			tempDate.setYMD(tempRuleTime.DateTime().Year(),
+			                tempRuleTime.DateTime().Month() + 1,
+			                tempRuleTime.DateTime().Day() + 1);
+			startTime.setDate(tempDate);
+			startTime.setTime(tempTime);
+		}
+	}
+	CleanupStack::PopAndDestroy(actualizedRules);
+	CleanupStack::PopAndDestroy(timezoneRules);
+	CleanupStack::PopAndDestroy(tzId);
+	CleanupStack::PopAndDestroy(&tzHandle);
+}
+
+QList<LocationInfo> TimezoneClient::getSavedLocations()
+{
+	QList<LocationInfo> locationList;
+
+	QString fileName(CITY_INFO_DB_PATH);
+	fileName.append(CITY_INFO_DB);
+
+	QFile cityInfoFile(fileName);
+	if (cityInfoFile.open(QIODevice::ReadOnly)) {
+		QDataStream writeStream(&cityInfoFile);
+		writeStream >> locationList;
+		cityInfoFile.close();
+	}
+	return locationList;
+}
+
+void TimezoneClient::saveLocations(const QList<LocationInfo> &locationList)
+{
+	QDir cityDbDir;
+	cityDbDir.mkpath(CITY_INFO_DB_PATH);
+
+	QString fileName(CITY_INFO_DB_PATH);
+	fileName.append(CITY_INFO_DB);
+
+	QFile cityInfoFile(fileName);
+	if (!cityInfoFile.open(QIODevice::WriteOnly)) {
+		// Error opening or creating file.
+		return;
+	}
+	QDataStream writeStream(&cityInfoFile);
+	writeStream << locationList;
+	cityInfoFile.close();
+
+	emit listUpdated();
+}
+
+void TimezoneClient::getCountries(QMap<QString, int>& countries)
+{
+	// Construct the timezone localizer.
+	CTzLocalizer* localizer = CTzLocalizer::NewL();
+	CleanupStack::PushL(localizer);
+
+	// Get all the city groups(countries).
+	QTime t;
+	t.start();
+	CTzLocalizedCityGroupArray* cityGroupArray =
+		localizer->GetAllCityGroupsL(CTzLocalizer::ETzAlphaNameAscending);
+	qDebug() << "Fetching city groups from tzloc: " << t.elapsed();
+	CleanupStack::PushL(cityGroupArray);
+
+	t.restart();
+	// Iterate through each of the city groups.
+	for (int i = 0; i < cityGroupArray->Count(); i++) {
+		CTzLocalizedCityGroup& cityGroup(cityGroupArray->At(i));
+		TPtrC countryName(cityGroup.Name());
+
+		// Get the QString of country name
+		QString qCountryName = QString::fromUtf16(
+				countryName.Ptr(),countryName.Length());
+	    countries[qCountryName] = cityGroup.Id();
+	}
+	qDebug() << "Converting " <<
+			cityGroupArray->Count() <<
+			"countries to qstring: " <<
+			t.elapsed();
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(cityGroupArray);
+	CleanupStack::PopAndDestroy(localizer);
+}
+
+void TimezoneClient::getCitiesForCountry(int id, QMap<QString, int>& cities)
+{
+	// Construct the timezone localizer.
+	CTzLocalizer* localizer = CTzLocalizer::NewL();
+	CleanupStack::PushL(localizer);
+
+	// Get the city group for the given id.
+	CTzLocalizedCityArray* cityArray = localizer->GetCitiesInGroupL(id,
+			CTzLocalizer::ETzAlphaNameAscending);
+	CleanupStack::PushL(cityArray);
+	CTzLocalizedCityArray* unsortedArray = localizer->GetCitiesInGroupL(id,
+			CTzLocalizer::ETzUnsorted);
+	CleanupStack::PushL(unsortedArray);
+
+	for (int i = 0; i < cityArray->Count(); i++) {
+		CTzLocalizedCity *city = &(cityArray->At(i));
+		TPtrC cityName = city->Name();
+
+		for (int j = 0; j < unsortedArray->Count(); j++) {
+			if (KErrNone ==
+					(unsortedArray->At(j)).Name().Compare(city->Name())) {
+				QString qCityname = QString::fromUtf16(
+						cityName.Ptr(),cityName.Length());
+				cities[qCityname] = j;
+
+				break;
+			}
+		}
+	}
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(unsortedArray);
+	CleanupStack::PopAndDestroy(cityArray);
+	CleanupStack::PopAndDestroy(localizer);
+}
+
+void TimezoneClient::getLocationInfo(
+		int groupId, int cityIndex, LocationInfo& cityInfo)
+{
+	TRAPD(
+			error,
+
+			// Construct the localizer.
+			CTzLocalizer* localizer = CTzLocalizer::NewLC();
+
+			// Get the localized city group.
+			CTzLocalizedCityGroup* cityGroup = localizer->GetCityGroupL(groupId);
+			CleanupStack::PushL(cityGroup);
+
+			// Get the localized city array for the given city group.
+			CTzLocalizedCityArray* cityArray = localizer->GetCitiesInGroupL(
+					groupId, CTzLocalizer::ETzUnsorted);
+			CleanupStack::PushL(cityArray);
+
+			// Get the required city.
+			CTzLocalizedCity* neededCity = &(cityArray->At(cityIndex));
+
+			// Fill the location information.
+			cityInfo.countryName = QString::fromUtf16(
+					cityGroup->Name().Ptr(), cityGroup->Name().Length());
+			cityInfo.cityName = QString::fromUtf16(
+					neededCity->Name().Ptr(), neededCity->Name().Length());
+			cityInfo.timezoneId = neededCity->TimeZoneId();
+			cityInfo.dstOn = dstOn(cityInfo.timezoneId);
+			cityInfo.zoneOffset = getDstZoneOffset(cityInfo.timezoneId);
+
+			// Cleanup.
+			CleanupStack::PopAndDestroy(cityArray);
+			CleanupStack::PopAndDestroy(cityGroup);
+			CleanupStack::PopAndDestroy(localizer);
+	)
+	Q_UNUSED(error)
+}
+
+QDataStream &operator<<(
+		QDataStream &writeStream, const LocationInfo& locationInfo)
+{
+	writeStream << locationInfo.cityName
+			<< locationInfo.countryName
+			<< locationInfo.listImageName
+			<< locationInfo.dstOn
+			<< locationInfo.timezoneId
+			<< locationInfo.zoneOffset;
+	return writeStream;
+}
+
+QDataStream &operator>>(
+		QDataStream &readStream, LocationInfo &locationInfo)
+{
+	readStream >> locationInfo.cityName
+	>> locationInfo.countryName
+	>> locationInfo.listImageName
+	>> locationInfo.dstOn
+	>> locationInfo.timezoneId
+	>> locationInfo.zoneOffset;
+	return readStream;
+}
+
+int TimezoneClient::environmentCallback(TAny* obj)
+{
+	TimezoneClient* self = static_cast<TimezoneClient *> (obj);
+
+	int changes = KInitialEvent;
+	if (self->mNotifier) {
+		changes = self->mNotifier->Change();
+	}
+
+	if (KInitialEvent <= changes) {
+		// We're not concerned about handling environment changes in that range.
+		return 0;
+	}
+
+	if (changes & (EChangesMidnightCrossover |
+			EChangesLocale |
+			EChangesSystemTime)) {
+		emit self->timechanged();
+	} else {
+		// Nothing to do.
+	}
+	return 0;
+}
+
+int TimezoneClient::getDstZoneOffset(int tzId)
+{
+	// Connect to the timezone server.
+	RTz client;
+	User::LeaveIfError(client.Connect());
+	CleanupClosePushL(client);
+
+	RArray<int> zoneIds;
+	RArray<int> zoneOffsets;
+	zoneIds.Append(tzId);
+
+	// Get the offsets.
+	client.GetOffsetsForTimeZoneIdsL(zoneIds, zoneOffsets);
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(&client);
+
+	return zoneOffsets[0];
+}
+
+bool TimezoneClient::dstOn(int tzId)
+{
+	// Connect to the timezone server.
+	RTz client;
+	User::LeaveIfError(client.Connect());
+	CleanupClosePushL(client);
+
+	CTzId *zoneId = CTzId::NewL(tzId);
+	CleanupStack::PushL(zoneId);
+
+	bool returnVal = client.IsDaylightSavingOnL(*zoneId);
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(zoneId);
+	CleanupStack::PopAndDestroy(&client);
+
+	return returnVal;
+}
+
+int TimezoneClient::getCityGroupIdByName(const QString& name)
+{
+	TPtrC namePtr;
+	namePtr.Set(name.utf16(), name.length());
+
+	// Construct the timezone localizer.
+	CTzLocalizer *localizer = CTzLocalizer::NewLC();
+
+	// Get the citygroup matching the name.
+	CTzLocalizedCityGroup *cityGroup = localizer->FindCityGroupByNameL(namePtr);
+	CleanupStack::PushL(cityGroup);
+
+	// Get the id.
+	int id = cityGroup->Id();
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(cityGroup);
+	CleanupStack::PopAndDestroy(localizer);
+
+	return id;
+}
+
+int TimezoneClient::getCityOffsetByNameAndId(const QString& name, int tzId)
+{
+	TPtrC namePtr;
+	namePtr.Set(name.utf16(), name.length());
+
+	// Construct the timezone localizer.
+	CTzLocalizer *localizer = CTzLocalizer::NewLC();
+
+	// Get the citygroup matching the name.
+	CTzLocalizedCityArray *cityArray = localizer->GetCitiesL(tzId);
+	CleanupStack::PushL(cityArray);
+
+	int id;
+	for (id = 0; id < cityArray->Count(); id++) {
+		if (KErrNone == cityArray->At(id).Name().Compare(namePtr)) {
+			break;
+		}
+	}
+	if (id == cityArray->Count()) {
+		id = -1;
+	}
+
+	// Cleanup.
+	CleanupStack::PopAndDestroy(cityArray);
+	CleanupStack::PopAndDestroy(localizer);
+
+	return id;
+
+}
+
+void TimezoneClient::setDateTime(QDateTime dateTime)
+{
+	TMonth month = intToMonth(dateTime.date().month());
+	TTime current(TDateTime(
+			dateTime.date().year(), month, dateTime.date().day() - 1,
+			dateTime.time().hour(), dateTime.time().minute(),
+			dateTime.time().second(), dateTime.time().msec() * 1000));
+	RTz tz;
+	User::LeaveIfError(tz.Connect());
+	CleanupClosePushL(tz);
+	TInt ret(tz.SetHomeTime(current));
+	CleanupStack::PopAndDestroy(&tz);
+}
+
+void TimezoneClient::setTimeUpdateOn(bool timeUpdate)
+{
+    RClkSrvInterface clkSrvInterface;
+    User::LeaveIfError(clkSrvInterface.Connect());
+    if (timeUpdate) {
+    clkSrvInterface.ActivateAllProtocols();
+    }
+    else {
+    clkSrvInterface.DeActivateAllProtocols();
+    }
+	mTimeUpdateOn = timeUpdate;
+	clkSrvInterface.Close();
+}
+
+bool TimezoneClient::timeUpdateOn()
+{
+	return mTimeUpdateOn;
+}
+
+QStandardItemModel *TimezoneClient::locationSelectorModel()
+{
+	if (!mWorldClockModel) {
+		createWorldClockModel();
+	}
+	return mWorldClockModel;
+}
+
+TMonth TimezoneClient::intToMonth(int month)
+{
+	switch (month) {
+		case 1:
+			return EJanuary;
+		case 2:
+			return EFebruary;
+		case 3:
+			return EMarch;
+		case 4:
+			return EApril;
+		case 5:
+			return EMay;
+		case 6:
+			return EJune;
+		case 7:
+			return EJuly;
+		case 8:
+			return EAugust;
+		case 9:
+			return ESeptember;
+		case 10:
+			return EOctober;
+		case 11:
+			return ENovember;
+		case 12:
+			return EDecember;
+		default:
+			// Nothing to do.
+			break;
+	}
+	return (TMonth) -1;
+}
+
+void TimezoneClient::createWorldClockModel()
+{
+	// Construct the model if its not yet done
+	if (!mWorldClockModel) {
+		// Create the model
+		mWorldClockModel = new QStandardItemModel(this);
+
+		getCountries(mAllCountries);
+		mCountryCount = mAllCountries.count();
+
+		// Construct the model in asynchronously
+		QTimer::singleShot(2000, this, SLOT(populateCities()));
+	}
+}
+
+void TimezoneClient::populateCities()
+{
+	// First iterate over all the counties
+	QMapIterator<QString, int> countryIter(mAllCountries);
+	while (countryIter.hasNext()) {
+		countryIter.next();
+		// Create an item for each country and append it to the model
+		QStandardItem *country = new QStandardItem(countryIter.key());
+		// Add the city group id
+		// TODO: Define and use proper role
+		country->setData(countryIter.value(), Qt::UserRole + 200);
+		mWorldClockModel->appendRow(country);
+
+		// Iterate through the city list of each country
+		QMap<QString, int> cityList;
+		getCitiesForCountry(countryIter.value(), cityList);
+		QMapIterator<QString, int> cityIter(cityList);
+		while (cityIter.hasNext()) {
+			cityIter.next();
+			// Create an item for the city and append it to that country
+			QStandardItem *city = new QStandardItem(cityIter.key());
+			// TODO: Define and use proper role
+			city->setData(cityIter.value(), Qt::UserRole + 200);
+			country->appendRow(city);
+		}
+	}
+}
+
+/*!
+	 Checks if DST changes will be applied in the next 24 hours.
+
+	 \param alarmInfo reference to alarm info
+	 \return true if there is DST change otherwise false
+ */
+bool TimezoneClient::checkForDstChange(AlarmInfo& alarmInfo)
+{
+	// User to be notified whether DST rollover happens in a day or
+	// has happen within a day if he tries to change the time.
+	bool returnValue( EFalse );
+
+	// Establish connection with RTz to get the timezone ID
+	RTz tzHandle;
+	User::LeaveIfError( tzHandle.Connect() );
+	CleanupClosePushL( tzHandle );
+
+	// The timezone ID (current)
+	CTzId* currentTZId = tzHandle.GetTimeZoneIdL();
+	CleanupStack::PushL( currentTZId );
+
+	// The current time in UTC
+	TTime currentTime;
+	currentTime.UniversalTime();
+
+	// hometime (local time)
+	TTime homeTime;
+	homeTime.HomeTime();
+
+	//(Year, Month, Day, Hour, Minute, Second, Micrsecond)
+	TDateTime dateTime(homeTime.DateTime().Year(), EJanuary, 1, FALSE, FALSE,
+			FALSE, FALSE);
+
+	TTime tempTime( dateTime );
+
+	// Get the current rules for the timezone
+	CTzRules* currentRules = tzHandle.GetTimeZoneRulesL(*currentTZId,
+							tempTime, currentTime, ETzUtcTimeReference);
+	CleanupStack::PushL( currentRules );
+
+	// CVTzActualisedRules encapsulates the rules for a specific year.
+	// Every year has a dummy rule and further DST rules if DST is applicable
+	// (if Ohlson provides them)
+	CVTzActualisedRules *vActualisedRules = CVTzActualisedRules::NewL(
+			homeTime.DateTime().Year(),
+			homeTime.DateTime().Year());
+	CleanupStack::PushL( vActualisedRules );
+
+	// The dummy rule is always the begining of the year.
+	// For example there is only 1 rule for
+	// India/NewDelhi but USA/Atlanta has 3 rules.
+	currentRules->GetActualisedRulesL( *vActualisedRules );
+
+	const int ruleCount( vActualisedRules->Count() );
+	int ruleMatchIndex( KNoDifference );
+
+	TTimeIntervalSeconds secondsDifference;
+	TTime ruleMatchTime;
+
+	// Fetch lowest time offset for the year residing at aTime.
+	// This is used to determine if DST is on.
+	for ( int ruleIndex( FALSE ); ruleIndex < ruleCount; ++ruleIndex ) {
+		const TVTzActualisedRule& actualisedRule =
+				( *vActualisedRules )[ ruleIndex ];
+
+		// Only check for the same year as requested (aTime)
+		if (actualisedRule.iTimeOfChange.DateTime().Year()
+				== homeTime.DateTime().Year()) {
+			TMonth month = intToMonth(alarmInfo.alarmDateTime.month());
+			TTime alarmTime(TDateTime(
+					alarmInfo.alarmDateTime.year(),
+					month,
+					alarmInfo.alarmDateTime.day() - 1,
+					alarmInfo.origAlarmTime.hour(),
+					alarmInfo.origAlarmTime.minute(),
+					alarmInfo.origAlarmTime.second(),
+					alarmInfo.origAlarmTime.msec()*1000));
+			int tempSecDiff = actualisedRule.iTimeOfChange.DateTime().Second() -
+					alarmInfo.origAlarmTime.second() ;
+
+			alarmTime.SecondsFrom(actualisedRule.iTimeOfChange,
+							secondsDifference);
+			// Considering the time reference is important as America
+			// (North & South) uses the Wall time (local time) reference
+			// where as whole of Europe refers to time in terms of UTC time.
+			// Correspondingly, the choise of local time or utc time
+			// has to be made.
+			TTime ruleTime;
+
+			if ( ETzUtcTimeReference == actualisedRule.iTimeReference ) {
+				ruleTime = currentTime;
+			}
+			else if ( ETzWallTimeReference == actualisedRule.iTimeReference ) {
+				ruleTime = homeTime;
+			}
+			else if( ETzStdTimeReference == actualisedRule.iTimeReference ) {
+				// TODO: Testing so far hasn't encountered a rule in this time reference.
+				// If in case an error is found, corresponding code can be added here.
+				// No support from symbian for this.
+			}
+
+			TDateTime sevenDays(FALSE, EJanuary, KDaysInWeek, FALSE, FALSE,
+							FALSE, FALSE);
+			TTime tempTime( sevenDays );
+			TTime newTime( ruleTime.Int64() + tempTime.Int64() );
+
+			TTimeIntervalDays temp;
+			temp = newTime.DaysFrom( ruleTime );
+
+			if ( ( secondsDifference.Int() >= KNoDifference ) &&
+					( newTime > alarmTime) &&
+					( actualisedRule.iTimeOfChange < alarmTime ) &&
+					( ruleTime < actualisedRule.iTimeOfChange ) ) {
+				// If there is a match, save the index and break.
+				// We've got the rule and there's no need to continue with other rules.
+				ruleMatchIndex = ruleIndex;
+				ruleMatchTime = actualisedRule.iTimeOfChange;
+				break;
+			}
+		}
+	}
+
+	if ( ruleMatchIndex > KZerothRule ) {
+		// There's a match, display the information note about DST change.
+		TTime displayTime;
+		TTimeIntervalHours oneHour( KOneHour );
+		returnValue = ETrue;
+	}
+
+	tzHandle.Close();
+	CleanupStack::PopAndDestroy( vActualisedRules);
+	CleanupStack::PopAndDestroy( currentRules );
+	CleanupStack::PopAndDestroy( currentTZId );
+	CleanupStack::PopAndDestroy( &tzHandle );
+
+	return returnValue;
+}
+
+/*!
+	Get all time zone ids
+
+	\return list of time zone ids
+ */
+QList<int> TimezoneClient::getAllTimeZoneIds()
+{
+	if (mTimeZoneIds.count()) {
+		return mTimeZoneIds;
+	} else {
+		// This list will contain the info of the cities fetched from tz server.
+		QList<LocationInfo> infoList;
+
+		// Get the cities, in alphabetical-ascending sorted order.
+		CTzLocalizedCityArray* cityArray =
+				mTzLocalizer->GetCitiesL(CTzLocalizer::ETzAlphaNameAscending);
+		ASSERT(cityArray);
+		CleanupStack::PushL(cityArray);
+		int cityCount = cityArray->Count();
+
+		// Now get the country\city-group of each of the city.
+		// Print the timezone id and city group id as well.
+		for (int iter = 0; iter < cityCount; iter++) {
+			CTzLocalizedCity* localizedCity = &(cityArray->At(iter));
+			int tzId(localizedCity->TimeZoneId());
+			if(-1==mTimeZoneIds.indexOf(tzId)) {
+				mTimeZoneIds.append(tzId);
+			}
+		}
+
+		CleanupStack::PopAndDestroy(cityArray);
+		return mTimeZoneIds;
+	}
+}
+
+/*!
+	Get all time zone ids
+
+	\return list of time zone ids
+ */
+QList<int> TimezoneClient::getAllTimeZoneOffsets()
+{
+	QList<int> timeZoneOffsetList;
+	QList<int> timeZoneIdList;
+	if (mTimeZoneIds.count()) {
+		timeZoneIdList = mTimeZoneIds;
+	} else {
+		timeZoneIdList = getAllTimeZoneIds();
+	}
+
+	RTz tzHandle;
+	User::LeaveIfError( tzHandle.Connect() );
+	CleanupClosePushL( tzHandle );
+
+	RArray<int> idArray;
+	RArray<int> offsetArray;
+	int offset;
+	int tzIdsCount = timeZoneIdList.count();
+	for (int index=0;index<tzIdsCount;index++) {
+		idArray.Append(timeZoneIdList.at(index));
+		// Get the offsets for the time zone ids
+		tzHandle.GetOffsetsForTimeZoneIdsL(idArray, offsetArray);
+		offset = offsetArray[0];
+
+		// Add the offset if not exists in the list
+		if(-1==(timeZoneOffsetList.indexOf(offset))) {
+			timeZoneOffsetList.append(offset);
+		}
+
+		offsetArray.Close();
+		idArray.Close();
+	}
+
+	tzHandle.Close();
+	CleanupStack::PopAndDestroy( &tzHandle );
+	// Sort the offset list
+	qSort(timeZoneOffsetList.begin(),timeZoneOffsetList.end());
+	return timeZoneOffsetList;
+}
+
+
+/*!
+	Get countries list for a UTC offset
+
+	\param list of countries infomation having the same UTC offsets
+ */
+QList<LocationInfo> TimezoneClient::getCountriesForUTCOffset(int utcOffset)
+{
+	// This list will contain the info of the countries.
+	QList<LocationInfo> countryList;
+	QList<int> cityGroupIdList;
+
+	// Get all cities for the UTC offset.
+	CTzLocalizedCityArray* cityList =
+			mTzLocalizer->GetCitiesWithUTCOffsetL(utcOffset);
+	CleanupStack::PushL(cityList);
+
+	int cityCount = cityList->Count();
+	CTzLocalizedCityGroup* country;
+	for(int index=0;index<cityCount;index++) {
+		CTzLocalizedCity* city = &(cityList->At(index));
+		int cityGroupId(city->GroupId());
+		int timeZoneId(city->TimeZoneId());
+
+		if(-1==cityGroupIdList.indexOf(cityGroupId)) {
+			cityGroupIdList.append(cityGroupId);
+
+			country = mTzLocalizer->GetCityGroupL(cityGroupId);
+
+			// Now insert that data into the country List.
+			LocationInfo cityInfo;
+			cityInfo.cityGroupId = cityGroupId;
+			cityInfo.countryName = QString::fromUtf16(
+					country->Name().Ptr(), country->Name().Length());
+			cityInfo.timezoneId = timeZoneId;
+
+			countryList.append(cityInfo);
+			delete country;
+		}
+	}
+	cityGroupIdList.clear();
+	CleanupStack::PopAndDestroy(cityList);
+	return countryList;
+}
+
+/*!
+	Add a new city to the city list using the
+	name, time zone id and city group id
+
+	\param timeZoneId time zone id of the new city
+	\cityName Name of the new city
+	\cityGroupId Group Id of the country
+ */
+LocationInfo TimezoneClient::addCity(
+		int timeZoneId,QString &cityName,int cityGroupId)
+{
+	TPtrC namePtr;
+	namePtr.Set(cityName.utf16(), cityName.length());
+
+	// Add a new city using the localizer
+	CTzLocalizedCity* newCity =
+			mTzLocalizer->AddCityL(timeZoneId, namePtr, cityGroupId);
+	CleanupStack::PushL(newCity);
+
+	LocationInfo info;
+	info.cityGroupId = newCity->GroupId();
+	info.timezoneId = newCity->TimeZoneId();
+	TPtrC newCityName(newCity->Name());
+	info.cityName = QString::fromUtf16(
+			newCityName.Ptr(), newCityName.Length());
+
+	CleanupStack::PopAndDestroy(newCity);
+
+	return info;
+}
+// End of file	--Don't remove this.