calendarui/globaldata/src/calenglobaldata.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 14:57:40 +0300
changeset 18 c198609911f9
parent 0 f979ecb2b13e
child 89 b57382753122
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 2002-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:  Global Data for Calendar application
*
*/


//debug
#include "calendarui_debug.h"

// INCLUDE FILES
#include "calenglobaldata.h"        // CalenGlobalData
#include "calencontext.h"           // Calendar context
#include "calencontextimpl.h"       // Calendar context implementation
#include "hb_calencommands.hrh"
#include <CalSession.h>             // Calendar database session
#include <calinstanceview.h>        // Calendar Instance view
#include <calentryview.h>           // Calendar Entry view

// Default Calendar database path
_LIT( KCalendarDatabaseFilePath, "c:Calendar" );


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

// -----------------------------------------------------------------------------
// CCalenGlobalData::CCalenGlobalData
// C++ default constructor can NOT contain any code, that might leave.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//

CCalenGlobalData::CCalenGlobalData( MCalProgressCallBack& aCalCallBack )
    : iCalCallBack( aCalCallBack )
    {
    TRACE_ENTRY_POINT;

    iGlobalDataOwnsCalSession = EFalse;

    TRACE_EXIT_POINT;
    }

// ----------------------------------------------------------------------------
// CCalenGlobalData::NewL
// Two phased construction. This will leave if an instance of global data
// already exists.  All access to an instance of the global data should be
// through the InstanceL function, except for the initial construction
// which should be handled by the controller.
// (other items were commented in a header).
// ----------------------------------------------------------------------------
//
EXPORT_C CCalenGlobalData* CCalenGlobalData::NewL( MCalProgressCallBack& aCalCallBack,
                                                   MCalenContextChangeObserver* aNotifier )
    {
    TRACE_ENTRY_POINT;
    CCalenGlobalData* self = NULL;
    TAny* tlsPtr = Dll::Tls();

    // Check Thread local storage
    if (!tlsPtr)
        {
        // TLS is NULL, so no CCalenGlobalData has been created yet.
        self = new( ELeave ) CCalenGlobalData( aCalCallBack );
        CleanupStack::PushL( self );
        // Store a self pointer in TLS
        User::LeaveIfError( Dll::SetTls( static_cast<TAny*>( self ) ) );
        // Increment ref count right away. If we don't do it here, and someone
        // calls CCalenGlobalData::InstanceL in ConstructL and then ConstructL
        // leaves, we will double delete the global data.
        ++self->iRefCount;
        self->ConstructL( aNotifier );
        CleanupStack::Pop( self );
        }
    else
        {
        // An instance of the global data exists already.
        // This function should only have been called once, by CCalenAppUi
        User::Leave( KErrAlreadyExists );
        }

    TRACE_EXIT_POINT;
    return self;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::InstanceL
// Two-phased constructor.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C CCalenGlobalData* CCalenGlobalData::InstanceL()
    {    	
    TRACE_ENTRY_POINT;

    CCalenGlobalData* self = NULL;
    TAny* tlsPtr = Dll::Tls();

    // Check Thread local storage
    if (!tlsPtr)
        {
        // The global data has not yet been constructed.
        // FIXME - Revise comment
        //TLS is NULL, so no CCalenGlobalData has been created yet.      
        User::Leave( KErrNotReady );
        }
    else
        {
        self = static_cast<CCalenGlobalData*>( tlsPtr );
        }

    ++self->iRefCount;

    TRACE_EXIT_POINT;
    return self;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::InstanceL
// Two-phased constructor.  Creates the CCalenGlobalData with an existing
// CCalSession.  CCalenGlobalData does NOT take ownership of the passed session
// The caller is responsible for ensuring that the session exists until all
// open references to the CCalenGlobalData are released.
// Calls User::Invariant() if CCalenGlobalData already has a valid session.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C CCalenGlobalData* CCalenGlobalData::InstanceL(CCalSession& aSession)
    {
    TRACE_ENTRY_POINT;

    CCalenGlobalData* self = CCalenGlobalData::InstanceL();
    CleanupStack::PushL(self);
    self->SetSessionL(&aSession);
    CleanupStack::Pop(self);

    TRACE_EXIT_POINT;
    return self;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::InstanceL
// Non-leaving version of constructor. Returns an instance of
// CCalenGlobalData if one exists or NULL otherwise
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C CCalenGlobalData* CCalenGlobalData::Instance()
    {
    TRACE_ENTRY_POINT;
    TAny* tlsPtr = Dll::Tls();
    CCalenGlobalData* self = static_cast<CCalenGlobalData*>( tlsPtr );

    if ( self )
        {
        ++self->iRefCount;
        }

    TRACE_EXIT_POINT;
    return self;
    }

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

    iContext = new (ELeave ) CalenContextImpl( aNotifier );

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::SetSessionL
// Sets the CCalenGlobalData to use an externally created CCalSession.
// Leaves with KErrAlreadyExists if a session has already been created by the
// CCalenGlobalData
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CCalenGlobalData::SetSessionL(CCalSession* aSession)
    {
    TRACE_ENTRY_POINT;

    if (iCalSession)
        {
        __ASSERT_ALWAYS(iCalSession == aSession, User::Leave(KErrAlreadyExists));
        }
    else
        {
        iGlobalDataOwnsCalSession = EFalse;
        iCalSession = aSession;
        }

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::Release
// Release handle to CCalenGlobalData.  If no other objects are referencing
// this class it will be deleted
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C void CCalenGlobalData::Release()
    {
    TRACE_ENTRY_POINT;

    --iRefCount;
    if (iRefCount == 0)
        {
        delete this;
        }

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// Destructor
// This is private and should only be called from the Release() function above
// (other items were commented in a header).
// -----------------------------------------------------------------------------
CCalenGlobalData::~CCalenGlobalData()
    {
    TRACE_ENTRY_POINT;
    
    delete iInterimUtils;    
    delete iEntryView;
    delete iInstanceView;
    delete iEntryViewCreation;
    delete iInstanceViewCreation;
    delete iContext;

    if (iGlobalDataOwnsCalSession)
        {
        delete iCalSession;
        }
    
    --iRefCount;
    
    // The controller owns its own instance of the services, therefore the
    // reference count will be one, immediatley before deletion.
    if (iRefCount == 1)
        {
        delete this;
        }

    Dll::SetTls(NULL);

    TRACE_EXIT_POINT;
    }


// -----------------------------------------------------------------------------
// CCalenGlobalData::CalSessionL
// Create a Calendar session if necessary and return a reference
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C CCalSession& CCalenGlobalData::CalSessionL()
    {
    TRACE_ENTRY_POINT;

    if (!iCalSession)
        {
        iGlobalDataOwnsCalSession = ETrue;
        iCalSession = CCalSession::NewL();

        TRAPD( err, iCalSession->OpenL(KCalendarDatabaseFilePath));
        if ( err == KErrNotFound )
            {
            iCalSession->CreateCalFileL(KCalendarDatabaseFilePath);
            iCalSession->OpenL(KCalendarDatabaseFilePath); // not trapped anymore
            }
        else
            {
            User::LeaveIfError( err );
            }

        }

    TRACE_EXIT_POINT;
    return *iCalSession;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::InstanceViewL
// Create an instance view if necessary and returns a reference.  Creating an
// instance view is an asynchronous operation, but this call returns
// synchronously.  When the view is created, Completed() is called, which stops
// iAs allowing this function to complete.
// Leaves with KErrInUse if this class is in the process of creating the
// instance view
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C CCalInstanceView* CCalenGlobalData::InstanceViewL()
    {
    TRACE_ENTRY_POINT;

    if (!iInstanceView && !iInstanceViewCreation)
        {
        if ( iEntryViewCreation )
            {
            /* We need queueing to avoid two immediate instance and entry view creation requests to symbian.
             * Though symbian handle two immediate requests ,this we require because we have only one observer
             * for callback and we would not be able to differentiate whether instance view got created or entry view got created.
             * If we dont queue the second request, we may end up giving incomplete object to the caller function.
             */
            iQueued = &CreateInstanceViewL;
            }
        else
            {
            CreateInstanceViewL();
            }
        }

    TRACE_EXIT_POINT;
    return iInstanceView;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::EntryViewL
// Create an entry view if necessary and returns a reference.  Creating an
// entry view is an asynchronous operation, but this call returns
// synchronously.  When the view is created, Completed() is called, which stops
// iAs allowing this function to complete.
// Leaves with KErrInUse if this class is in the process of creating the
// entry view
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C CCalEntryView* CCalenGlobalData::EntryViewL()
    {
    TRACE_ENTRY_POINT;

    if (!iEntryView && !iEntryViewCreation)
        {
        if ( iInstanceViewCreation )
            {
            /* We need queueing to avoid two immediate instance and entry view creation requests to symbian.
             * Though symbian handle two immediate requests ,this we require because we have only one observer
             * for callback and we would not be able to differentiate whether instance view got created or entry view got created.
             * If we dont queue the second request, we may end up giving incomplete object to the caller function.
             */
            iQueued = &CreateEntryViewL;
            }
        else
            {
            CreateEntryViewL();
            }
        }
    TRACE_EXIT_POINT;
    return iEntryView;
    }

void CCalenGlobalData::CreateEntryViewL()
    {
    TRACE_ENTRY_POINT;
    iEntryViewCreation = CCalEntryView::NewL( CalSessionL(), iCalCallBack );
    TRACE_EXIT_POINT;
    }

void CCalenGlobalData::CreateInstanceViewL()
    {
    TRACE_ENTRY_POINT;
    iInstanceViewCreation = CCalInstanceView::NewL( CalSessionL(), iCalCallBack );
    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CEntryViewObserver::ViewCreationCompleted
// FIXME -- Update description
// Get call after entryview / instance view being created
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CCalenGlobalData::ViewCreationCompleted( TBool aSuccess )
    {
    TRACE_ENTRY_POINT;

    if ( !aSuccess )
        {
        // Something has gone wrong
        delete iEntryViewCreation;
        delete iInstanceViewCreation;
        }
    else
        {
        if ( iEntryViewCreation )
            {
            iEntryView = iEntryViewCreation;
            }
        else if ( iInstanceViewCreation )
            {
            iInstanceView = iInstanceViewCreation;
            }
        }

    iEntryViewCreation = NULL;
    iInstanceViewCreation = NULL;

    if ( iQueued )
        {
        (this->*iQueued)();
        iQueued = NULL;
        }

    TRACE_EXIT_POINT;
    }

// -----------------------------------------------------------------------------
// CCalenGlobalData::RegisterEntryViewObserver
// Add observer into view observers entry observer list.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C TBool CCalenGlobalData::EntryViewExists()
    {
    TRACE_ENTRY_POINT;
    TRACE_EXIT_POINT;
    return ( iEntryView != NULL );
    }


// -----------------------------------------------------------------------------
// CCalenGlobalData::Context
// Return a reference to the CCalenContext object
// (other items were commented in a header).
// -----------------------------------------------------------------------------
EXPORT_C MCalenContext& CCalenGlobalData::Context()
    {
    TRACE_ENTRY_POINT;
    TRACE_EXIT_POINT;
    return *iContext;
    }

void CCalenGlobalData::HandleNotification(const TCalenNotification aNotification )
    {
    TRACE_ENTRY_POINT;

    if ( aNotification == ECalenNotifyEntryInstanceViewCreated )
        {
        ViewCreationCompleted( ETrue );
        }
    else if (aNotification == ECalenNotifyEntryInstanceViewCreationFailed )
        {
        ViewCreationCompleted( EFalse );
        }

    TRACE_EXIT_POINT;
    }

// Enf of file