calendarui/controller/src/calendbchangenotifier.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 10:12:19 +0200
changeset 0 f979ecb2b13e
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2006 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:   Notifies observers of external changes to the calendar database
*
*/



//debug
#include "calendarui_debug.h"

// INCLUDE FILES
#include "calendbchangenotifier.h"    // CCalenDbChangeNotifier
#include "calenglobaldata.h"            // Calendar global data
#include <calsession.h>                 // CalSession

// -----------------------------------------------------------------------------
// KTimerResolution limits the number of notifications sent to registered
// MCalenDBChangeObserver instances.  Notifications may come from 
// MCalChangeCallBack2 at a very high rate which could impact performance, 
// for example by causing constant view refreshes.
// CCalenDbChangeNotifier notifies observers when KTimerResolution has elapsed
// since the last notification was received from MCalChangeCallBack2
// -----------------------------------------------------------------------------
const TInt KTimerResolution = 1000000;  // 1 Second

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::CCalenDbChangeNotifier
// C++ default constructor can NOT contain any code, that might leave.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
CCalenDbChangeNotifier::CCalenDbChangeNotifier( CCalenGlobalData& aGlobalData ) 
    : CActive( EPriorityNormal ),
      iGlobalData( aGlobalData )
    {
    TRACE_ENTRY_POINT;

    iRestartTimer = EFalse;

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::NewL
// Two-phased constructor.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
CCalenDbChangeNotifier* CCalenDbChangeNotifier::NewL( CCalenGlobalData& aGlobalData )
    {
    TRACE_ENTRY_POINT;

    CCalenDbChangeNotifier* self = new( ELeave ) CCalenDbChangeNotifier( aGlobalData );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );

    TRACE_EXIT_POINT;
    return self;
    }

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::ConstructL
// Symbian 2nd phase constructor can leave.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CCalenDbChangeNotifier::ConstructL()
    {
    TRACE_ENTRY_POINT;

    // We want to receive notifications for the full agenda date range
    TCalTime start, end;
    start.SetTimeUtcL( TCalTime::MinTime() );
    end.SetTimeUtcL( TCalTime::MaxTime() );
    CalCommon::TCalTimeRange range( start, end ); 

    // Create a notification filter
    iCalChangeFilter = CCalChangeNotificationFilter::NewL(
                                                        MCalChangeCallBack2::EChangeEntryAll, 
                                                        ETrue, 
                                                        range );

    // Enable database change notifications on current global data session
    iGlobalData.CalSessionL().StartChangeNotification( *this, *iCalChangeFilter );

    // Create a timer to limit the number of notifications broadcast
    iNotificationTimer.CreateLocal();

    // Active object, add to active scheduler
    CActiveScheduler::Add( this );

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::~CCalenDbChangeNotifier
// Destructor
// (other items were commented in a header).
// -----------------------------------------------------------------------------
CCalenDbChangeNotifier::~CCalenDbChangeNotifier()
    {
    TRACE_ENTRY_POINT;

    Cancel();
    // Reset the observer array.  Array contents are NOT owned by this class
    iDBObservers.Reset();

    iNotificationTimer.Close();

    // Disable database change notifications on current global data session   
    PIM_TRAPD_HANDLE( iGlobalData.CalSessionL().StopChangeNotification() );

    // Destroy the notification filter
    delete iCalChangeFilter;
    
    TRACE_EXIT_POINT;    
    }

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::LastDBModificationTime
// Returns the time of the last database change notification.  This may not be
// the time of the last notification sent to MCalenDBChangeObservers.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
TTime CCalenDbChangeNotifier::LastDBModificationTime() const
    {
    TRACE_ENTRY_POINT;

    TRACE_EXIT_POINT;
    return iLastDbChangeNotification;
    }

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::CalChangeNotification
// Called when a change to the agenda database occurs from a different session
// to the one we are currently using.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CCalenDbChangeNotifier::CalChangeNotification( RArray<TCalChangeEntry>& /*aChangeItems*/ )
    {
    TRACE_ENTRY_POINT;

    // Always update the last notification time, even if we don't notify 
    // our observers
    iLastDbChangeNotification.UniversalTime();
    if( !IsActive() )
        {
        iNotificationTimer.After( iStatus, KTimerResolution );
        SetActive();
        }
    else
        {
        iRestartTimer = ETrue;
        iNotificationTimer.Cancel();
        }

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::RegisterObserverL
// Adds the passed observer to the observer array.  All observers in the array 
// will be notified of changes to the agenda database.
// (other items were commented in a header).
// -----------------------------------------------------------------------------    
 void CCalenDbChangeNotifier::RegisterObserverL( MCalenDBChangeObserver& aDBObserver )
    {
    TRACE_ENTRY_POINT;

    iDBObservers.Append( &aDBObserver );

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CCalenDbChangeNotifier::DeRegisterObserverL
// Removes the passed observer to the observer array.  All observers in the array 
// will be notified of changes to the agenda database.
// -----------------------------------------------------------------------------       
void CCalenDbChangeNotifier::DeRegisterObserverL( MCalenDBChangeObserver& aDBObserver )
    {
    TRACE_ENTRY_POINT;

    for( TInt x = 0; x < iDBObservers.Count(); ++x )
        {
        if( iDBObservers[x] == &aDBObserver )
            {
            iDBObservers.Remove( x );
            return;
            }
        }
    User::Leave( KErrNotFound );

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------       
// CCalenDbChangeNotifier::RunL
// From CActive::RunL
// Called when notification timer expires
// (other items were commented in a header).
// -----------------------------------------------------------------------------       
void CCalenDbChangeNotifier::RunL()
    {
    TRACE_ENTRY_POINT;

    switch( iStatus.Int() )
        {
        case KErrCancel:
            {
            // The normal reason for the timer being cancelled is another
            // database change.  Restart the timer.
            if( iRestartTimer )
                {
                iRestartTimer = EFalse;
                iNotificationTimer.After( iStatus, KTimerResolution );
                SetActive();
                }        
            }
        break;

        case KErrNone:
            {
            //Timer completion, notify observers
            for( TInt x = 0; x < iDBObservers.Count(); ++x )
                {
                iDBObservers[x]->HandleDBChangeL();
                }
            }
        break;

        default:
            {
            User::Leave( KErrArgument );
            }
        break;
        }

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------       
// CCalenDbChangeNotifier::RunError
// From CActive::RunError
// (other items were commented in a header).
// -----------------------------------------------------------------------------
TInt CCalenDbChangeNotifier::RunError( TInt aError )
    {
    TRACE_ENTRY_POINT;

    //RunL leaving means that the view could not be refreshed.
    //Theres not much we can do except be ready for the next database event.
    iRestartTimer = EFalse;

    TRACE_EXIT_POINT;
    return aError;
    }

// -----------------------------------------------------------------------------       
// CCalenDbChangeNotifier::DoCancel
// From CActive::DoCancel
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CCalenDbChangeNotifier::DoCancel()
    {
    TRACE_ENTRY_POINT;

    // Stop the notification timer
    iRestartTimer = EFalse;
    iNotificationTimer.Cancel();

    TRACE_EXIT_POINT;
    }

// End of File