calendarui/organizerplugin/aiagendaplugin2/src/aicalendarplugin2eventstrings.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) 2005-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:  
 *
*/

#include "aicalendarplugin2eventstrings.h"
#include "aicalendarplugin2eventitem.h"
#include "aicalendarplugin2constants.hrh"
#include "aicalendarplugin2eventitem.h"
#include "calendar.hrh" // for ECalendMax###
#include <Calendar.rsg> // for R_CALEN_QTN_CALE_NO_SUBJECT
#include <StringLoader.h> // for loading R_CALEN_QTN_CALE_NO_SUBJECT
#include <calinstance.h>
#include <AknBidiTextUtils.h>
#include <AknUtils.h>

// Local function

const TDesC& ReturnProperReference( const HBufC* aBuffer )
    {
    if( aBuffer )
        return *aBuffer;
    else
        return KNullDesC;
    }

// Class methods

CAiCalendarPlugin2EventStrings* CAiCalendarPlugin2EventStrings::NewL(
                                            const CCalInstance& aInstance,
                                            const TDesC& aTimeFormat,
                                            const TDesC& aDateFormat,
                                            TBool aAppendEndTimeToOngoingEvents,
                                            TBool aUseAlternate,
                                            CAiCalendarPlugin2EventItem& aOwner )
    {
    CAiCalendarPlugin2EventStrings* self = new( ELeave )CAiCalendarPlugin2EventStrings(
                                                        aAppendEndTimeToOngoingEvents,
                                                        aUseAlternate,
                                                        aOwner );
    CleanupStack::PushL( self );
    self->ConstructL( aInstance, aTimeFormat, aDateFormat );
    CleanupStack::Pop( self );
    return self;
    }

CAiCalendarPlugin2EventStrings::CAiCalendarPlugin2EventStrings(
                                            TBool aAppendEndTimeToOngoingEvents,
                                            TBool aUseAlternate,
                                            CAiCalendarPlugin2EventItem& aOwner )
  : iAppendEndTimeToOngoingEvents( aAppendEndTimeToOngoingEvents ),
    iUseAlternatePublish( aUseAlternate ),
    iOwner( aOwner )
    {
    }

CAiCalendarPlugin2EventStrings::~CAiCalendarPlugin2EventStrings()
    {
    delete iLocation;
    delete iSubject;
    delete iSubjectLocationConstruct;
    delete iTimeConstruct;
    delete iStartTime;
    delete iEndTime;
    delete iEndDate;
    delete iDate;
    }

void CAiCalendarPlugin2EventStrings::ConstructL(
                                            const CCalInstance& aCalInstance,
                                            const TDesC& aTimeFormat,
                                            const TDesC& aDateFormat )
    {
    ExtractDatesL( aCalInstance,
                   aDateFormat );
        
    // First reserve base lenght for space characted and extra control
    // characters.
    iBaseLength = KAICal2LenSpaceChar + KAknBidiExtraSpacePerLine;
    if( iDate )
        {
        // Add to baselenght the date if needed.
        iBaseLength += iDate->Length();
        }
        
    ExtractTimeL( aCalInstance,
                  aTimeFormat );
                  
    ExtractSubjectAndLocationL( aCalInstance );
    
    if( iUseAlternatePublish )
        {
        MakeAlternateStringsL();
        }
    }

void CAiCalendarPlugin2EventStrings::ExtractDatesL(
                                            const CCalInstance& aCalInstance,
                                            const TDesC& aFormat)
    {
    if( iOwner.DateNeeded() ||
        ( ( iOwner.Type() == EPluginItemOlderOnGoingEvent ||
            iOwner.Type() == EPluginItemOnGoingEvent ||
            iOwner.Type() == EPluginItemMeeting ||
            iOwner.Type() == EPluginItemUpcomingMeeting ) &&
          !iOwner.IsEndTimeToday() ) )
        {
        TTime start = aCalInstance.StartTimeL().TimeLocalL();
        const TTime end = aCalInstance.EndTimeL().TimeLocalL();

        if( iOwner.Type() == EPluginItemToDo )
            {
            start = end;
            }

        iDate = HBufC::NewL( KAICal2SizeDateShort );
        TPtr bufPtr = iDate->Des();

        start.FormatL( bufPtr, aFormat );

        iEndDate = HBufC::NewL( KAICal2SizeDateShort );
        TPtr bufPtr2 = iEndDate->Des();

        end.FormatL( bufPtr2, aFormat );
        }
    }

void CAiCalendarPlugin2EventStrings::ExtractTimeL( const CCalInstance& aCalInstance,
                                                   const TDesC& aFormat )
    {
    TTime adjustedStartTime( aCalInstance.StartTimeL().TimeLocalL() );
    const TTime unadjustedStartTime( aCalInstance.StartTimeL().TimeLocalL() );
    TTime end( aCalInstance.EndTimeL().TimeLocalL() );
    TTime today;
    today.HomeTime();

    if( iOwner.Type() == EPluginItemToDo )
        {
        adjustedStartTime = end;
        }

    // Locale instance for digit type check
    TLocale locale;
    TDigitType digitType = locale.DigitType();
    // Constants
    //_LIT(KPDF, "\x202C"); // Pop directional formatting
    //_LIT(KRLM, "\x200F"); // R to L marker
    //_LIT(KRLE, "\x202B"); // R to L embedding
    //_LIT(KLRM, "\x200E"); // L to R marker
    //_LIT(KLRE, "\x202A"); // L to R embedding

    // skip for "not today" items...
    if( ! ( !CAiCalendarPlugin2EventItem::OnSameDay( today, adjustedStartTime ) &&
        adjustedStartTime > today ) )
        {
        // handle events starting/ending on a different day
        if( !CAiCalendarPlugin2EventItem::OnSameDay( adjustedStartTime, today) &&
            adjustedStartTime < today ) // starts before
            {
            TDateTime todayStart;
            todayStart = today.DateTime();
            todayStart.SetHour( ECalenMinHour );
            todayStart.SetMinute( ECalenMinMinute );
            todayStart.SetSecond( ECalenMinSecond );
            todayStart.SetMicroSecond( 0 );

            adjustedStartTime = todayStart;  // start today at 00:00 
            }
        }

    iTimeConstruct = HBufC::NewL( KAICal2SizeTimeFormatUsual + iBaseLength );
    iStartTime = HBufC::NewL( KAICal2SizeTimeFormatUsual + iBaseLength );
    iEndTime = HBufC::NewL( KAICal2SizeTimeFormatUsual + iBaseLength );

    TPtr constructTimePtr = iTimeConstruct->Des();
    TPtr startTimePtr = iStartTime->Des();
    TPtr endTimePtr = iEndTime->Des();
    
    // If Arabic digits. Start RLO and RLE
    if (AknLayoutUtils::LayoutMirrored()) 
        {
        //constructTimePtr.Append(KRLM);
        }
    else
        {
        //constructTimePtr.Append(KLRM);
        //constructTimePtr.Append(KLRE);
        }

    // Now do the following:
    // if date+time needed:
    //      time construct has "date time - time"
    //      start time has "date starttime"
    //      end time has "date endtime"

    // if only date needed:
    //      time construct has "date"
    //      start time has "date"
    //      end time has "date"
    
    // if only time needed:
    //      time construct has "time - time"
    //      start time has "starttime"
    //      end time has "endtime"
    
    if( iOwner.DateNeeded() && iDate && iEndDate )
        {
        constructTimePtr.Append( iDate->Des() );
        startTimePtr.Append( iDate->Des() );
        endTimePtr.Append( iEndDate->Des() );
        }
    TBuf<KAICal2SizeTimeFormatUsual> timeBuf;
    if( iOwner.TimeNeeded() )
        {
        // No start time for event that started before today
        if( CAiCalendarPlugin2EventItem::OnSameDay( unadjustedStartTime, today) ||
            ( unadjustedStartTime > today ) )
            {
            unadjustedStartTime.FormatL( timeBuf, aFormat );  // start time
            }
        
        if( iOwner.DateNeeded() && iDate && iEndDate && timeBuf.Length() > 0 )
            {
            // start date appeded, append space
            constructTimePtr.Append( KAICal2SpaceChar );
            startTimePtr.Append( KAICal2SpaceChar );
            }

        if (AknLayoutUtils::LayoutMirrored()) 
            {
            //constructTimePtr.Append(KLRM);
            }
            
        constructTimePtr.Append( timeBuf );
        startTimePtr.Append( timeBuf );
        
        end.FormatL( timeBuf, aFormat );  // end time


        if( ( unadjustedStartTime != end ) )
            {
            constructTimePtr.Append( KAICal2HyphenChar );  // -
            }
        
        // Start new RLE
        if( AknLayoutUtils::LayoutMirrored() )
            {
            //constructTimePtr.Append(KRLM);
            //constructTimePtr.Append(KRLE);
            }
        else
            {
            //constructTimePtr.Append(KLRM);
            //constructTimePtr.Append(KLRE);
            }
        TBool endDateAppended = EFalse;
        if( ( ( iOwner.Type() == EPluginItemOlderOnGoingEvent ||
                iOwner.Type() == EPluginItemOnGoingEvent ||
                ( iOwner.Type() == EPluginItemMeeting && iOwner.IsToday() ) ||
                iOwner.Type() == EPluginItemUpcomingMeeting ) &&
            !iOwner.IsEndTimeToday() )/* && !iOwner.DateNeeded()*/ && iEndDate )
            {
            endDateAppended = ETrue;
            constructTimePtr.Append( iEndDate->Des() );  // add end date
               if( !iOwner.DateNeeded() )
                {
                endTimePtr.Append( iEndDate->Des() );
                }
            }

        TBool appendEndTime = EFalse;

        // The following code may be  abit confusing. But so is the spec about this matter.        
        if( iAppendEndTimeToOngoingEvents )
            {
            if( !iOwner.IsFutureEvent() )
                {
                if( ( iOwner.Type() == EPluginItemOlderOnGoingEvent && iOwner.IsEndTimeToday() ) ||
                    ( iOwner.Type() == EPluginItemOnGoingEvent && iOwner.IsEndTimeToday()  ) )
                    {
                    appendEndTime = ETrue;
                    }
                }
           }
       if( iOwner.IsEndTimeToday() )
            {
            if( !iOwner.IsFutureEvent() || iOwner.IsToday() )
                {
                appendEndTime = ETrue;
                }
            }

        if( ( iOwner.Type() == EPluginItemMeeting || 
              iOwner.Type() == EPluginItemUpcomingMeeting ) && iOwner.IsEndTimeToday() )
            {
            appendEndTime = ETrue;
            }

        if( unadjustedStartTime == end )
            {
            appendEndTime = EFalse;
            }

        if( appendEndTime )
            {
            if( endDateAppended )
                {
                // Append space char
                constructTimePtr.Append( KAICal2SpaceChar );
                }
            constructTimePtr.Append( timeBuf );  // add end time
            endTimePtr.Append( timeBuf );
            }
        }

    // End of LR or RL embeddings
    //constructTimePtr.Append(KPDF);
        
    if( iOwner.DateNeeded() || iOwner.TimeNeeded() )
        {
        AknTextUtils::LanguageSpecificNumberConversion( constructTimePtr );            
        AknTextUtils::LanguageSpecificNumberConversion( startTimePtr );            
        AknTextUtils::LanguageSpecificNumberConversion( endTimePtr );
        }
    }

void CAiCalendarPlugin2EventStrings::ExtractSubjectAndLocationL(
                                    const CCalInstance& aCalInstance )
    {
    // SUBJECT STRING
    iSubject = ExtractSubjectL( aCalInstance );

    // LOCATION STRING
    iLocation = ExtractLocationL( aCalInstance );
    TInt bufLength = iSubject->Length();

    if( User::Language() == ELangArabic )
        {
        bufLength += KAICal2ArabicSummaryLocationSeparator().Length();
        }
    else
        {
        bufLength += KAICal2WesternSummaryLocationSeparator().Length();
        }

    bufLength += iLocation->Length() + ( KAICal2MaxItemSize * KAknBidiExtraSpacePerLine );

    if( !iOwner.IsToday() &&
        ( ( iOwner.Type() == EPluginItemToDo ) ||
          ( iOwner.Type() == EPluginItemDayNote ) ||
          ( iOwner.Type() == EPluginItemAnniv ) ) )
        {
        // Add extra space for not today nontimed events
        bufLength += CombinedTimeString().Length() + KAICal2LenSpaceChar;
        }
    else if( ( iOwner.Type() == EPluginItemMeeting ||
          iOwner.Type() >= EPluginItemUpcomingMeeting ) &&
        !iUseAlternatePublish )
        {
        // Multiline cale
        bufLength += CombinedTimeString().Length() + KAICal2LenSpaceChar;
        }

    // COMBINE TEXT
    iSubjectLocationConstruct = HBufC::NewL( bufLength );
    TPtr textStrPtr = iSubjectLocationConstruct->Des();

    if( !iOwner.IsToday() &&
        ( ( iOwner.Type() == EPluginItemToDo ) ||
          ( iOwner.Type() == EPluginItemDayNote ) ||
          ( iOwner.Type() == EPluginItemAnniv ) ) )
        {
        textStrPtr.Append( CombinedTimeString() );
        textStrPtr.Append( KAICal2SpaceChar );
        delete iTimeConstruct;
        iTimeConstruct = NULL;
        }
    else if( ( iOwner.Type() == EPluginItemMeeting ||
          iOwner.Type() >= EPluginItemUpcomingMeeting ) &&
        !iUseAlternatePublish )
        {
        // Multiline cale
        textStrPtr.Append( CombinedTimeString() );
        textStrPtr.Append( KAICal2SpaceChar );
        }

    textStrPtr.Append( iSubject->Des() );

    if( iSubject->Length() && iLocation->Length() )
        {
        // If both subject/summary and location exist, add a separator between them
        if( User::Language() == ELangArabic )
            {
            textStrPtr.Append( KAICal2ArabicSummaryLocationSeparator );
            }
        else
            {
            textStrPtr.Append( KAICal2WesternSummaryLocationSeparator );
            }
        }

    // After the subject (and separator) append the location
    textStrPtr.Append( iLocation->Des() );
    }
    
HBufC* CAiCalendarPlugin2EventStrings::ExtractSubjectL( const CCalInstance& aCalInstance )
    {
    const CCalEntry& entry = aCalInstance.Entry();

    HBufC* subject = NULL;
    if( entry.SummaryL().Length() != 0 )
        {
        subject = entry.SummaryL().AllocL();
        }
    else
        {
        subject = StringLoader::LoadL( R_CALEN_QTN_CALE_NO_SUBJECT );
        }

    TPtr buf = subject->Des();
    AknTextUtils::ReplaceCharacters( buf, KAICal2ReplaceWhitespaceChars, TChar(' ') );

    // remove all leading and trailing spaces
    buf.TrimAll();

    return subject;
    }

HBufC* CAiCalendarPlugin2EventStrings::ExtractLocationL( const CCalInstance& aCalInstance )
    {
    const CCalEntry& entry = aCalInstance.Entry();

    HBufC* location = entry.LocationL().AllocL();
    TPtr buf = location->Des();
    AknTextUtils::ReplaceCharacters( buf, KAICal2ReplaceWhitespaceChars, TChar(' ') );

    // remove all leading and trailing spaces
    buf.TrimAll();

    return location;
    }
    
void CAiCalendarPlugin2EventStrings::MakeAlternateStringsL()
    {
    // Rearrange strings
    if( iOwner.Type() == EPluginItemUpcomingMeeting ||
        iOwner.Type() == EPluginItemOnGoingEvent ||
        ( iOwner.Type() == EPluginItemMeeting &&
          iOwner.IsToday() ) )
        {
        if( iLocation->Length() ) // location defined
            {
            // Multiline cale
            HBufC* newS = HBufC::NewL( iTimeConstruct->Length() + iSubjectLocationConstruct->Length() + KAICal2SpaceChar().Length() );
            newS->Des().Append( *iTimeConstruct );
            newS->Des().Append( KAICal2SpaceChar );
            newS->Des().Append( *iSubjectLocationConstruct );
            
            delete iSubjectLocationConstruct;
            iSubjectLocationConstruct = newS;
            }
        else // location NOT defined
            {
            // Append subject to time construct
            iTimeConstruct = iTimeConstruct->ReAllocL(
                        iTimeConstruct->Length() +
                        KAICal2SpaceChar().Length() +
                        iSubject->Length() );
            iTimeConstruct->Des().Append( KAICal2SpaceChar );
            iTimeConstruct->Des().Append( *iSubject );
            
            // Clean S&L construct
            delete iSubjectLocationConstruct;
            iSubjectLocationConstruct = NULL;
            }
        }
    else if( iOwner.Type() == EPluginItemOlderOnGoingEvent ||
             ( iOwner.Type() == EPluginItemMeeting &&
               !iOwner.IsToday() ) )
        {
        // Append S&L to time construct
        iTimeConstruct = iTimeConstruct->ReAllocL(
                    iTimeConstruct->Length() +
                    KAICal2SpaceChar().Length() +
                    iSubjectLocationConstruct->Length() );
        iTimeConstruct->Des().Append( KAICal2SpaceChar );
        iTimeConstruct->Des().Append( *iSubjectLocationConstruct );
        
        // Clean S&L construct
        delete iSubjectLocationConstruct;
        iSubjectLocationConstruct = NULL;
        }
    }

const TDesC& CAiCalendarPlugin2EventStrings::CombinedTimeString()
    {
    return ReturnProperReference( iTimeConstruct );
    }
        
const TDesC& CAiCalendarPlugin2EventStrings::StartTimeString()
    {
    return ReturnProperReference( iStartTime );
    }

const TDesC& CAiCalendarPlugin2EventStrings::EndTimeString()
    {
    return ReturnProperReference( iEndTime );
    }
    
const TDesC& CAiCalendarPlugin2EventStrings::CombinedSubjectLocationString()
    {
    return ReturnProperReference( iSubjectLocationConstruct );
    }
        
const TDesC& CAiCalendarPlugin2EventStrings::SubjectString()
    {
    return ReturnProperReference( iSubject );
    }

const TDesC& CAiCalendarPlugin2EventStrings::LocationString()
    {
    return ReturnProperReference( iLocation );
    }