clock2/clockui/uilayer/clockmainview/src/clockmainview.cpp
branchRCL_3
changeset 16 55d60436f00b
parent 5 42814f902fe6
child 18 d68a4b5d5885
--- a/clock2/clockui/uilayer/clockmainview/src/clockmainview.cpp	Tue Apr 27 16:36:22 2010 +0300
+++ b/clock2/clockui/uilayer/clockmainview/src/clockmainview.cpp	Tue May 11 16:12:24 2010 +0300
@@ -41,6 +41,18 @@
 #include "clock_debug.h"
 
 // Constants
+const TInt KMaxCharsInNote( 32 );
+const TInt KZerothRule( 0 );
+const TInt KDaysInWeek( 7 );
+const TInt KOneMinuteInMicrosecond( 1000000 * 60 );
+const TInt KOneHourInMinute( 60 );
+const TInt KOneMinute( 1 );
+const TInt KOneHour( 1 );
+const TInt KNoDifference( 0 );
+
+_LIT( KDateTimeFormatter, "%-B%:0%J%:1%T%:3%+B" );  // For the date and time displayed in the rollover note.
+
+
 
 // Literals
 
@@ -183,6 +195,11 @@
         // Update the latest alarm details.
         iAlarmModel->ClockAlarmInfo( iAlarmId, iAlarmInfo );
         
+        if(CheckForDstChangesL())
+            {
+            DisplayRemainingTimeL();
+            }
+
         // First update the model with the latest alarm id.
         iAlarmModel->SaveLatestAlarmId( iAlarmId );
         
@@ -399,6 +416,11 @@
         // Update the latest alarm details.
         iAlarmModel->ClockAlarmInfo( iAlarmId, iAlarmInfo );
         
+		if(CheckForDstChangesL())
+            {
+            DisplayRemainingTimeL();
+            }
+
         // First update the model with the latest alarm id.
         iAlarmModel->SaveLatestAlarmId( iAlarmId );
         
@@ -879,4 +901,334 @@
     return static_cast< CClockAppUi* > ( AppUi() );
     }
 
+// ---------------------------------------------------------
+// CClockAlarmEditorImpl::DisplayRemainingTimeL
+// rest of the details are commented in the header
+// ---------------------------------------------------------
+//
+void CClockMainView::DisplayRemainingTimeL()
+    {
+    __PRINTS( "CClockAlarmEditorImpl::DisplayRemainingTimeL - Entry" );
+    
+    HBufC* stringHolder( NULL );
+
+    TTime currentTime;
+    currentTime.HomeTime();     
+
+    TTime alarmTime = iAlarmInfo.iOrigExpiryTime;
+    TBool oneDayDifference( EFalse );    
+
+    // Check for the day of the alarm.
+    if( currentTime < alarmTime )
+        {
+        currentTime += TTimeIntervalDays( 1 );
+        // Check if the alarm is for the current day.
+        oneDayDifference = ( currentTime < alarmTime )? ETrue : EFalse;
+        }
+
+    TInt alarmDay( alarmTime.DayNoInWeek() );
+    const TInt KTimeStringLength( 10 );
+    TBuf< KTimeStringLength > timeString;
+
+    HBufC* timeFormat = StringLoader::LoadLC( R_QTN_TIME_USUAL_WITH_ZERO, iCoeEnv );
+    CleanupStack::Pop( timeFormat );
+
+    alarmTime.FormatL( timeString, *timeFormat );
+
+    CDesCArrayFlat* stringArray = new( ELeave ) CDesCArrayFlat( 2 );
+    CDesCArrayFlat* workDaysList = iCoeEnv->ReadDesCArrayResourceL( R_CLOCK_WEEK_DAYS_ARRAY );
+
+    // The day on which alarm is set.
+    stringArray->AppendL( ( *workDaysList )[ alarmDay ] );
+    // The time string.
+    stringArray->AppendL( timeString );
+
+    // Choose the appropriate Repeat type.
+    switch( iAlarmInfo.iRepeat )
+        {
+        case EAlarmRepeatDefintionRepeatNext24Hours:
+        case EAlarmRepeatDefintionRepeatOnce:
+            {
+            if( oneDayDifference )
+                {
+                stringHolder = StringLoader::LoadLC( R_QTN_CLOCK_ALARM_NOTE_ONCE_NEXT, *stringArray, iEikonEnv );
+                }
+            }
+            break;
+        
+        case EAlarmRepeatDefintionRepeatDaily:
+            {
+            stringHolder = StringLoader::LoadLC( R_QTN_CLOCK_ALARM_NOTE_DAY_CLK, timeString, iEikonEnv );
+            }
+            break;
+            
+        case EAlarmRepeatDefintionRepeatWeekly:
+            {
+            stringHolder = StringLoader::LoadLC( R_QTN_CLOCK_ALARM_NOTE_WEEK_CLK, *stringArray, iEikonEnv );
+            }
+            break;
+            
+        case EAlarmRepeatDefintionRepeatWorkday:
+            {
+            stringHolder = StringLoader::LoadLC( R_QTN_CLOCK_ALARM_NOTE_WDAY_CLK, timeString, iEikonEnv );
+            }
+            break;
+            
+        default:
+            {
+            // No implementation yet.
+            }
+            break;
+        }
+    
+    // Cleanup.
+    delete timeFormat;
+    delete stringArray;
+    delete workDaysList;        
+
+    // Need to show the confirmation note.
+    if( ( EAlarmStatusEnabled == iAlarmInfo.iStatus ) && stringHolder )
+        {
+        // TODO: to be verified todo this or not.
+        CAknConfirmationNote* confirmationNote = new( ELeave ) CAknConfirmationNote( ETrue );
+
+        TPtr stringHolderPtr = stringHolder->Des();
+        AknTextUtils::DisplayTextLanguageSpecificNumberConversion( stringHolderPtr );    
+
+        confirmationNote->ExecuteLD( *stringHolder );
+
+        // Cleanup
+        CleanupStack::PopAndDestroy( stringHolder );
+        } 
+
+    // Dislpay the second note.
+    if( !oneDayDifference )
+        {
+        TTime homeTime;
+        homeTime.HomeTime();
+
+        TDateTime currentDate( homeTime.DateTime() );
+        TDateTime alarmDate( iAlarmInfo.iAlarmTime.DateTime() );
+
+        alarmDate.SetYear( currentDate.Year() );
+        alarmDate.SetMonth( currentDate.Month() );
+        alarmDate.SetDay( currentDate.Day() );
+
+        TTime newAlarmTime( alarmDate );
+
+        if( newAlarmTime < homeTime )
+            {
+            newAlarmTime += TTimeIntervalDays( 1 );
+            }
+
+        // Construct the remaining time.            
+        TTimeIntervalMicroSeconds remainingTime( newAlarmTime.MicroSecondsFrom( homeTime ) );
+        TInt64 tempInt = ( remainingTime.Int64() ) / KOneMinuteInMicrosecond;
+        TInt remainingMinutes = I64INT( tempInt );
+
+        CArrayFix< TInt >* timeArray = new( ELeave ) CArrayFixFlat< TInt >( 2 );
+        CleanupStack::PushL( timeArray );
+
+        TInt remainingHours( remainingMinutes / KOneHourInMinute );
+
+        remainingMinutes -= remainingHours * KOneHourInMinute;
+
+        timeArray->AppendL( remainingHours );
+        timeArray->AppendL( remainingMinutes );
+
+        // Alarm is with in 1 day. Choose the appropriate strings to be displayed.
+        switch( remainingHours )
+            {
+            case KOneMinute:
+                {
+                if( KOneMinute == remainingMinutes )
+                    {
+                    stringHolder = StringLoader::LoadLC( R_CLOCK_ALARM_CONF_SINGULAR, *timeArray, iEikonEnv );
+                    }
+                else
+                    {
+                    stringHolder = StringLoader::LoadLC( R_CLOCK_ALARM_CONF_HOUR_SEV_MIN, *timeArray, iEikonEnv );
+                    }
+                }
+                break;
+                
+            default:
+                {
+                if( KOneMinute == remainingMinutes )
+                    {
+                    stringHolder = StringLoader::LoadLC( R_CLOCK_ALARM_CONF_SEV_HOURS_MIN, *timeArray, iEikonEnv );
+                    }
+                else
+                    {
+                    stringHolder = StringLoader::LoadLC( R_CLOCK_ALARM_CONF_PLURAL, *timeArray, iEikonEnv );
+                    }
+                }
+                break;
+            }
+        
+        // TODO: to be verified todo this or not.
+        if( ( EAlarmStatusEnabled == iAlarmInfo.iStatus )  && stringHolder )
+            {
+            CAknConfirmationNote* confirmationNote = new( ELeave ) CAknConfirmationNote( ETrue );
+
+            TPtr stringHolderPtr = stringHolder->Des();
+            AknTextUtils::DisplayTextLanguageSpecificNumberConversion( stringHolderPtr );    
+
+            confirmationNote->ExecuteLD( *stringHolder ); 
+            }
+
+        // Cleanup.        
+        CleanupStack::PopAndDestroy( stringHolder );
+        CleanupStack::PopAndDestroy( timeArray );
+        }
+    
+    __PRINTS( "CClockAlarmEditorImpl::DisplayRemainingTimeL - Exit" );
+    }
+
+// ---------------------------------------------------------
+// CClockAlarmEditorImpl::CheckForDstChangesL
+// rest of the details are commented in the header
+// ---------------------------------------------------------
+//
+TBool CClockMainView::CheckForDstChangesL()
+    {
+    __PRINTS( "CClockAlarmEditorImpl::CheckForDstChangesL - Entry" );
+    
+    // User to be notified whether DST rollover happens in a day or 
+    // has happen within a day if he tries to change the time.
+    TBool returnValue( ETrue );
+    
+    // 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 TInt ruleCount( vActualisedRules->Count() );
+    TInt 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( TInt 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() )
+            {               
+            iAlarmInfo.iAlarmTime.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 > iAlarmInfo.iAlarmTime ) && 
+                ( actualisedRule.iTimeOfChange < iAlarmInfo.iAlarmTime ) && 
+                ( 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 );         
+
+        displayTime = iAlarmInfo.iAlarmTime;
+
+        TBuf< KMaxCharsInNote > dateTimeString;
+
+        // dateString will have "11:59 pm" - as above, but no seconds
+        displayTime.FormatL( dateTimeString, KDateTimeFormatter );
+
+        // If This note is displayed,
+        CAknInformationNote* informationNote = new( ELeave ) CAknInformationNote( ETrue );
+
+        HBufC* noteText = StringLoader::LoadLC(
+                R_QTN_CLOCK_NOTE_ALARM_DST_ROLLOVER, 
+                dateTimeString, 
+                iCoeEnv);               
+        TInt error = informationNote->ExecuteLD( noteText->Des() );
+
+        // Don't display the second note. Not necessary to show both notes.
+        returnValue = ETrue;
+        CleanupStack::PopAndDestroy( noteText );                                
+        } 
+
+    tzHandle.Close();
+    CleanupStack::PopAndDestroy( vActualisedRules);
+    CleanupStack::PopAndDestroy( currentRules );
+    CleanupStack::PopAndDestroy( currentTZId );
+    CleanupStack::PopAndDestroy( &tzHandle );
+    
+    __PRINTS( "CClockAlarmEditorImpl::CheckForDstChangesL - Exit" );
+
+    return returnValue;
+    }
+
 // End of file