/*
* Copyright (c) 2009 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: ESMR titled field implementation
*
*/
#include "cesmrattendeefield.h"
//<cmail>
#include "esmrcommands.h"
#include "cfsmailclient.h"
//</cmail>
#include "cesmrncspopuplistbox.h"
#include "cesmrncsemailaddressobject.h"
#include "mesmrlistobserver.h"
#include "cesmrcontacthandler.h"
#include "mesmrmeetingrequestentry.h"
#include "esmrfieldbuilderdef.h"
#include "cmrlabel.h"
#include "nmrlayoutmanager.h"
#include "nmrbitmapmanager.h"
#include "cmrimage.h"
#include "cmrbutton.h"
#include <AknsBasicBackgroundControlContext.h>
#include <calentry.h>
#include <StringLoader.h>
#include <esmrgui.rsg>
#include <aknbutton.h>
#include <gulicon.h>
#include <ct/rcpointerarray.h>
// DEBUG
#include "emailtrace.h"
// unnamed namespace for local definitions
namespace { // codescanner::namespace
//CONSTANTS
const TInt KMaxAmountOfItems( 4 );
const TInt KMaxRemoteSearchResponseLength = 255;
// Panic code literal
_LIT( KESMRAttendeeField, "ESMRAttendeeField" );
/** Panic code enumeration */
enum TESMRAttendeeFieldPanic
{
EESMRAttendeeFieldNotMeetingRequestEntry // Passed entry is not MR
};
void Panic( TESMRAttendeeFieldPanic aPanic )
{
User::Panic( KESMRAttendeeField, aPanic );
}
}//namespace
// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// CESMRAttendeeField::CESMRAttendeeField
// ---------------------------------------------------------------------------
//
CESMRAttendeeField::CESMRAttendeeField( CCalAttendee::TCalRole aRole )
:iRole( aRole )
{
FUNC_LOG;
SetFocusType( EESMRHighlightFocus );
SetFieldId ( (iRole == CCalAttendee::EReqParticipant) ?
EESMRFieldAttendee : EESMRFieldOptAttendee );
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::~CESMRAttendeeField
// ---------------------------------------------------------------------------
//
CESMRAttendeeField::~CESMRAttendeeField( )
{
FUNC_LOG;
delete iAacListBox;
delete iContactHandler;
delete iDefaultText;
delete iBgCtrlContext;
delete iFieldButton;
delete iTitle;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::NewL
// ---------------------------------------------------------------------------
//
CESMRAttendeeField* CESMRAttendeeField::NewL( CCalAttendee::TCalRole aRole )
{
FUNC_LOG;
CESMRAttendeeField* self = new (ELeave) CESMRAttendeeField( aRole );
CleanupStack::PushL ( self );
self->ConstructL ( );
CleanupStack::Pop ( self );
return self;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::ConstructL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::ConstructL( )
{
FUNC_LOG;
SetComponentsToInheritVisibility( ETrue );
iContactHandler = CESMRContactHandler::NewL();
iDefaultText = StringLoader::LoadL ( R_QTN_MEET_REQ_CONTACT_FIELD );
iFieldButton = CMRButton::NewL( NMRBitmapManager::EMRBitmapSearchContacts );
iFieldButton->SetParent( this );
iFieldButton->SetObserver( this );
iTitle = CMRLabel::NewL();
iTitle->SetParent( this );
HBufC* buf = NULL;
if( FieldId() == EESMRFieldAttendee )
{
buf = StringLoader::LoadLC( R_QTN_MEET_REQ_LABEL_REQUIRED );
}
if( FieldId() == EESMRFieldOptAttendee )
{
buf = StringLoader::LoadLC( R_QTN_MEET_REQ_LABEL_OPT );
}
iTitle->SetTextL( *buf ); // ownership transferred
CleanupStack::Pop( buf );
iEditor =
new ( ELeave ) CESMRNcsAifEditor( *iContactHandler, iDefaultText );
CESMRField::ConstructL( iEditor );
iEditor->ConstructL (
this,
KMaxAddressFieldLines,
0,
CEikEdwin::EAvkonEditor | CEikEdwin::EResizable |
CEikEdwin::ENoAutoSelection |CEikEdwin::EInclusiveSizeFixed |
CEikEdwin::ENoHorizScrolling
);
iEditor->SetEdwinSizeObserver( this );
iEditor->SetParent( this );
iEditor->SetPopupList( this );
iEditor->SetAlignment ( EAknEditorAlignBidi | EAknEditorAlignCenter );
iEditor->SetAknEditorInputMode ( EAknEditorTextInputMode );
iEditor->SetAknEditorFlags (
EAknEditorFlagNoT9| EAknEditorFlagUseSCTNumericCharmap );
iEditor->SetAknEditorCurrentCase ( EAknEditorLowerCase );
// Draw bg instead of using skin bg
TRect tempRect( 0, 0, 0, 0 );
NMRBitmapManager::TMRBitmapStruct bitmapStruct;
bitmapStruct = NMRBitmapManager::GetBitmapStruct( NMRBitmapManager::EMRBitmapInputCenter );
iBgCtrlContext = CAknsBasicBackgroundControlContext::NewL(
bitmapStruct.iItemId,
tempRect,
EFalse );
iEditor->SetSkinBackgroundControlContextL( iBgCtrlContext );
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::MinimumSize
// ---------------------------------------------------------------------------
//
TSize CESMRAttendeeField::MinimumSize()
{
TRect parentRect( Parent()->Rect() );
TRect richTextRect =
NMRLayoutManager::GetFieldLayoutRect( parentRect, 1 ).Rect();
TRect textRect( NMRLayoutManager::GetLayoutText(
richTextRect,
NMRLayoutManager::EMRTextLayoutTextEditor ).TextRect() );
// Adjust field size so that there's room for expandable editor.
richTextRect.Resize( 0, iSize.iHeight - textRect.Height() );
// Add title area to the required size
TSize titleSize( CESMRField::MinimumSize() );
TSize completeFieldSize( titleSize );
completeFieldSize.iHeight += richTextRect.Height();
return completeFieldSize;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::InitializeL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::InitializeL()
{
FUNC_LOG;
// No Implementation
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::InternalizeL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::InternalizeL( MESMRCalEntry& aEntry )
{
FUNC_LOG;
iEditor->CreateScrollBarFrameL()->SetScrollBarVisibilityL (
CEikScrollBarFrame::EOff,
CEikScrollBarFrame::EOff );
TInt fieldAttendeeCount( 0 );
CCalEntry& entry = aEntry.Entry ( );
RPointerArray< CCalAttendee > attendees = entry.AttendeesL ( );
RCPointerArray< CESMRNcsEmailAddressObject > addressList;
CleanupClosePushL( addressList );
for (TInt i(0); i < attendees.Count(); i++ )
{
if ( attendees[i]->RoleL() == iRole )
{
fieldAttendeeCount++;
const TDesC& addr = attendees[i]->Address ( );
const TDesC& commonName = attendees[i]->CommonName ( );
CESMRNcsEmailAddressObject* obj =
CESMRNcsEmailAddressObject::NewL ( commonName, addr );
CleanupStack::PushL (obj );
addressList.AppendL( obj );
CleanupStack::Pop( obj );
}
}
if ( fieldAttendeeCount > 0 )
{
if ( !iObserver->IsControlVisible(iFieldId ) )
{
iObserver->ShowControl( iFieldId );
}
iEditor->SetAddressesL( addressList );
}
else
{
AppendDefaultTextL();
//during initialisation, SelectAllL() in setoutlinefocus gets overridden so this is needed
iEditor->SelectAllL();
}
//don't show optional attendees field on initialisation if there are none
if ( ( EESMRFieldModeEdit == FieldMode() ) && ( iRole == CCalAttendee::EOptParticipant ) )
{
if ( fieldAttendeeCount == 0 )
{
this->MakeVisible(EFalse);
}
}
CleanupStack::PopAndDestroy( &addressList );
// this is needed to be re-called here, otherwise the CEikEdwin
// does not get correctly instantiated with default text
iEditor->FocusChanged(EDrawNow);
UpdateSendOptionL();
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::ExternalizeL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::ExternalizeL( MESMRCalEntry& aEntry )
{
FUNC_LOG;
MESMRMeetingRequestEntry* mrEntry = NULL;
if ( MESMRCalEntry::EESMRCalEntryMeetingRequest == aEntry.Type() )
{
mrEntry = static_cast<MESMRMeetingRequestEntry*>(&aEntry);
}
// This should always be called for MR entries
__ASSERT_ALWAYS( mrEntry, Panic( EESMRAttendeeFieldNotMeetingRequestEntry ));
if( iEditor->HasDefaultText() )
{
ClearDefaultTextL();
}
UpdateAttendeesL( *mrEntry );
HBufC* text = iEditor->GetTextInHBufL();
//If there is no attendees, put back the default text
if( !text )
{
AppendDefaultTextL();
//during initialisation, SelectAllL() in setoutlinefocus gets overridden so this is needed
iEditor->SelectAllL();
}
delete text;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::CountComponentControls
// ---------------------------------------------------------------------------
//
TInt CESMRAttendeeField::CountComponentControls( ) const
{
FUNC_LOG;
TInt count( 0 );
if( iFieldButton )
{
++count;
}
if ( iTitle )
{
++count;
}
if( iEditor )
{
++count;
}
return count;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::ComponentControl
// ---------------------------------------------------------------------------
//
CCoeControl* CESMRAttendeeField::ComponentControl( TInt aInd ) const
{
FUNC_LOG;
switch ( aInd )
{
case 0:
return iFieldButton;
case 1:
return iTitle;
case 2:
return iEditor;
default:
return NULL;
}
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::SizeChanged
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::SizeChanged( )
{
FUNC_LOG;
TRect rect( Rect() );
TAknLayoutRect firstRowLayoutRect(
NMRLayoutManager::GetFieldRowLayoutRect( rect, 1 ) );
TRect firstRowRect( firstRowLayoutRect.Rect() );
TRect secondRowRect( firstRowRect );
secondRowRect.Move( 0, firstRowRect.Height() );
// Layout field button
if( iFieldButton )
{
TAknWindowComponentLayout buttonLayout(
NMRLayoutManager::GetWindowComponentLayout(
NMRLayoutManager::EMRLayoutTextEditorIcon ) );
AknLayoutUtils::LayoutControl(
iFieldButton, firstRowRect, buttonLayout );
}
// Layout field title
if ( iTitle )
{
TAknTextComponentLayout editorLayout =
NMRLayoutManager::GetTextComponentLayout(
NMRLayoutManager::EMRTextLayoutTextEditor );
AknLayoutUtils::LayoutLabel( iTitle, rect, editorLayout );
}
// Layout field editor
if( iEditor )
{
TAknLayoutText editorLayoutText = NMRLayoutManager::GetLayoutText(
secondRowRect,
NMRLayoutManager::EMRTextLayoutTextEditor );
TRect editorRect = editorLayoutText.TextRect();
// Resize height according to actual height required by edwin.
editorRect.Resize( 0, iSize.iHeight - editorRect.Height() );
iEditor->SetRect( editorRect );
// Try setting font. Failures are ignored.
TRAP_IGNORE( iEditor->SetFontL( editorLayoutText.Font() ) );
}
// Layout field focus
if( iEditor )
{
// Layouting focus for rich text editor area
TRect bgRect( iEditor->Rect() );
// Move focus rect so that it's relative to field's position.
bgRect.Move( -Position() );
SetFocusRect( bgRect );
}
if ( iAacListBox && iAacListBox->IsVisible ( ) )
{
TRAPD( error, iAacListBox->SetPopupMaxRectL( ResolvePopupRectL()) )
if ( error )
{
iCoeEnv->HandleError( error );
}
}
}
// -----------------------------------------------------------------------------
// CESMRAttendeeField::ResolvePopupRectL
// -----------------------------------------------------------------------------
//
TRect CESMRAttendeeField::ResolvePopupRectL( )
{
FUNC_LOG;
if ( !iAacListBox )
{
return TRect( 0, 0, 0, 0 );
}
TRect popupRect( 0, 0, 0, 0 );
// Let's determine Popup's maximum height
TInt requiredPopupHeight = iAacListBox->CalcHeightBasedOnNumOfItems(
iAacListBox->Model()->NumberOfItems() );
TInt numberOfItemsInPopUp = iAacListBox->Model()->NumberOfItems();
if( numberOfItemsInPopUp > KMaxAmountOfItems )
{
// reducing popup item count shown at once to maximum value
requiredPopupHeight = iAacListBox->CalcHeightBasedOnNumOfItems(
KMaxAmountOfItems );
}
// Popup x-coords are always the same
TInt topLeftX = iEditor->Rect().iTl.iX;
TInt bottomRightX = iEditor->Rect().iBr.iX;
// Popup y-coords need to be calculated
TInt topLeftY( 0 );
TInt bottomRightY( 0 );
// Next we have to resolve if popup needs to be drawn below or
// above the cursor (space requirement)
TRect editorLineRect;
iEditor->GetLineRectL( editorLineRect );
TInt editorLineTopLeftY = editorLineRect.iTl.iY;
TInt diff = iEditor->Rect().iTl.iY;
TInt editorLineTopLeftYRelativeToParent = editorLineTopLeftY + diff;
TInt listPaneHeight = Parent()->Rect().Height();
// Popup will be drawn above the cursor
if( editorLineTopLeftYRelativeToParent > TReal( listPaneHeight / 2 ) )
{
topLeftY = editorLineTopLeftYRelativeToParent - requiredPopupHeight;
bottomRightY = editorLineTopLeftYRelativeToParent;
}
// Popup will be drawn below the cursor
else
{
topLeftY = editorLineTopLeftYRelativeToParent + iEditor->GetLineHeightL();
bottomRightY = topLeftY + requiredPopupHeight;
}
popupRect.SetRect( topLeftX, topLeftY, bottomRightX, bottomRightY );
return popupRect;
}
// -----------------------------------------------------------------------------
// CNcsAddressInputField:::AppendDefaultTextL()
// -----------------------------------------------------------------------------
//
void CESMRAttendeeField::AppendDefaultTextL()
{
FUNC_LOG;
iEditor->SetTextL( iDefaultText );
iEditor->HandleTextChangedL();
}
// -----------------------------------------------------------------------------
// CNcsAddressInputField::ClearDefaultTextL()
// -----------------------------------------------------------------------------
//
void CESMRAttendeeField::ClearDefaultTextL()
{
FUNC_LOG;
iEditor->SetTextL( &KNullDesC );
iEditor->HandleTextChangedL();
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::OfferKeyEventL
// ---------------------------------------------------------------------------
//
TKeyResponse CESMRAttendeeField::OfferKeyEventL(
const TKeyEvent& aKeyEvent,
TEventCode aType )
{
FUNC_LOG;
TKeyResponse ret( EKeyWasNotConsumed);
if ( aKeyEvent.iCode == EKeyEnter ||
aKeyEvent.iScanCode == EStdKeyEnter ||
aKeyEvent.iCode == EKeyYes ||
aKeyEvent.iScanCode == EStdKeyYes )
{//prevent these keys from being used in any attendee field editor
return EKeyWasConsumed;
}
if ( aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyDownArrow )
{
if( iAacListBox && iAacListBox->IsVisible() && !iAacListBox->IsPopupEmpty() )
{
return iAacListBox->OfferKeyEventL( aKeyEvent, aType );
}
else
{
ret = iEditor->OfferKeyEventL (aKeyEvent, aType );
}
}
else
{
if ( iAacListBox && iAacListBox->IsVisible ( ) )
{
if( aKeyEvent.iCode == EKeyDevice3 || aKeyEvent.iCode == EKeyDevice4 ||
aKeyEvent.iCode == EKeyOK )
{
DoPopupSelectL();
ret = EKeyWasConsumed;
}
}
}
if ( ret == EKeyWasNotConsumed )
{
ret = iEditor->OfferKeyEventL (aKeyEvent, aType );
UpdateSendOptionL();
}
// Scroll editor visible, if for example cursor is out of the
// viewable area when user enters more text.
if ( iObserver && aType == EEventKey )
{
CTextLayout* textLayout = iEditor->TextLayout();
TInt lineHeight = iEditor->GetLineHeightL();
TPoint cursorPos( 0,0 );
textLayout->DocPosToXyPosL( iEditor->CursorPos(), cursorPos );
TInt editorTlY = iEditor->Position().iY;
TInt listHeight = iObserver->ViewableAreaRect().Height();
TInt cursorTopY = cursorPos.iY - lineHeight + editorTlY;
TInt cursorBottomY = cursorPos.iY + lineHeight + editorTlY;
// If cursor is below visible area
if ( cursorBottomY > listHeight )
{
iObserver->RePositionFields( -( cursorBottomY - listHeight ) );
}
// If cursor is over the top of visible area
else if ( cursorTopY < 0 )
{
iObserver->RePositionFields( -cursorTopY );
}
}
return ret;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::SetContainerWindowL()
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::SetContainerWindowL( const CCoeControl& aControl )
{
FUNC_LOG;
CCoeControl::SetContainerWindowL( aControl );
iFieldButton->SetContainerWindowL( aControl );
iFieldButton->SetParent( this );
iTitle->SetContainerWindowL( aControl );
iTitle->SetParent( this );
iEditor->SetContainerWindowL( aControl );
iEditor->SetParent( this );
iAacListBox = CESMRNcsPopupListBox::NewL ( this, *iContactHandler );
iAacListBox->MakeVisible ( EFalse );
iAacListBox->SetListBoxObserver( this );
iAacListBox->SetObserver( this );
iAacListBox->ActivateL();
iButtonGroupContainer = CEikButtonGroupContainer::Current();
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::HandleEdwinSizeEventL
// ---------------------------------------------------------------------------
//
TBool CESMRAttendeeField::HandleEdwinSizeEventL( CEikEdwin* aEdwin,
TEdwinSizeEvent /*aType*/, TSize aSize )
{
FUNC_LOG;
TBool reDraw( EFalse );
if( iSize != aSize )
{
// Let's save the required size for the iEditor
iSize = aSize;
if ( iObserver && aEdwin == iEditor )
{
iObserver->ControlSizeChanged ( this );
reDraw = ETrue;
}
}
return reDraw;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::UpdatePopupContactListL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::UpdatePopupContactListL(
const TDesC& aMatchString,
TBool /*iListAll*/)
{
FUNC_LOG;
if ( aMatchString.CompareC( KNullDesC ) == 0 ||
aMatchString.CompareC( *iDefaultText ) == 0 )
{
ClosePopupContactListL();
}
else if ( iAacListBox )
{
// Popup will be shown when async HandleControlEventL is received
iAacListBoxEnabled = ETrue;
if ( iAacListBox->IsVisible() )
{
iAacListBox->SetSearchTextL( aMatchString );
}
else
{
iAacListBox->InitAndSearchL( aMatchString );
}
}
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::ShowPopupCbaL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::ShowPopupCbaL( TBool aShow )
{
if( aShow )
{
iButtonGroupContainer->SetCommandSetL(
R_CONTACT_POPUP_SOFTKEYS_SELECT_CANCEL);
}
else
{
iButtonGroupContainer->SetCommandSetL(
R_CONTACT_EDITOR_SOFTKEYS_OPTIONS_DONE__ADD);
}
iButtonGroupContainer->DrawDeferred();
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::ExecuteGenericCommandL
// ---------------------------------------------------------------------------
//
TBool CESMRAttendeeField::ExecuteGenericCommandL( TInt aCommand )
{
FUNC_LOG;
TBool isUsed( EFalse );
switch ( aCommand )
{
case EESMRCmdAttendeeInsertContact:
{
HandleTactileFeedbackL();
iContactHandler->GetAddressesFromPhonebookL( this );
isUsed = ETrue;
break;
}
case EESMRCmdAttendeeSoftkeySelect:
{
DoPopupSelectL();
isUsed = ETrue;
break;
}
case EESMRCmdAttendeeSoftkeyCancel:
{
ClosePopupContactListL();
isUsed = ETrue;
break;
}
case EESMRCmdLongtapDetected:
{
if(iEditor->IsFocused())
NotifyEventL(EESMRCmdLongtapDetected);
isUsed = ETrue;
HandleTactileFeedbackL();
break;
}
default:
break;
}
return isUsed;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::SetOutlineFocusL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::SetOutlineFocusL( TBool aFocus )
{
FUNC_LOG;
CESMRField::SetOutlineFocusL( aFocus );
if (aFocus) //Focus is gained on the field
{
if ( iEditor->HasDefaultText() )
{
iEditor->SelectAllL();
}
ChangeMiddleSoftKeyL( R_MR_ADD_SOFTKEY );
}
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::OperationComplete()
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::OperationCompleteL(
TContactHandlerCmd /*aCmd*/,
const RPointerArray<CESMRClsItem>* aContacts )
{
FUNC_LOG;
if ( aContacts )
{
if( aContacts->Count() > 0 )
{
RCPointerArray<CESMRNcsEmailAddressObject> ncsObjects; // codescanner::resourcenotoncleanupstack
CleanupClosePushL( ncsObjects );
for ( int i = 0; i < aContacts->Count(); i++ )
{
CESMRNcsEmailAddressObject* object =
CESMRNcsEmailAddressObject::NewL(
( *aContacts )[i]->DisplayName(),
( *aContacts )[i]->EmailAddress() );
object->SetDisplayFull( ( *aContacts)[i]->MultipleEmails() );
ncsObjects.Append( object );
}
iEditor->AppendAddressesL( ncsObjects );
CleanupStack::PopAndDestroy( &ncsObjects );
UpdateSendOptionL();
}
}
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::OperationError
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::OperationErrorL( TContactHandlerCmd /*aCmd*/,
TInt /*aError*/ )
{
FUNC_LOG;
//Nothing to do
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::HandleControlEventL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::HandleControlEventL(
CCoeControl *aControl,
TCoeEvent aEventType )
{
FUNC_LOG;
if ( aControl == iAacListBox &&
aEventType == MCoeControlObserver::EEventStateChanged &&
iAacListBoxEnabled )
{
if ( iAacListBox && iAacListBox->IsVisible() && iAacListBox->IsPopupEmpty() )
{
ClosePopupContactListL();
}
else if ( iAacListBox && !iAacListBox->IsPopupEmpty() )
{
iAacListBox->SetPopupMaxRectL( ResolvePopupRectL() );
iAacListBox->MakeVisible ( ETrue );
ShowPopupCbaL( ETrue );
}
else
{
UpdateSendOptionL();
}
}
}
// -----------------------------------------------------------------------------
// CESMRAttendeeField::DoPopupSelect
// -----------------------------------------------------------------------------
//
void CESMRAttendeeField::DoPopupSelectL()
{
FUNC_LOG;
if( iAacListBox && iAacListBox->IsRemoteLookupItemSelected() )
{
// Launch remote lookup
HBufC* lookupText = iEditor->GetLookupTextLC();
CPbkxRemoteContactLookupServiceUiContext::TResult::TExitReason exitReason;
CESMRNcsEmailAddressObject* address = ExecuteRemoteSearchL(
exitReason,
*lookupText );
if ( address )
{
CleanupStack::PushL( address );
iEditor->AddAddressL( *address );
CleanupStack::PopAndDestroy( address );
}
CleanupStack::PopAndDestroy( lookupText );
}
else if( iAacListBox && !iAacListBox->IsPopupEmpty() )
{
CESMRNcsEmailAddressObject* emailAddress =
iAacListBox->ReturnCurrentEmailAddressLC();
if( emailAddress )
{
if ( emailAddress->EmailAddress().Compare( KNullDesC ))
{
iEditor->AddAddressL( *emailAddress );
}
else
{
// selected contact doesn't have email address, launch remote contact lookup
// rcl must be usable, since otherwise there couldn't be any items
// without email addresses
CPbkxRemoteContactLookupServiceUiContext::TResult::TExitReason exitReason;
CESMRNcsEmailAddressObject* remAddress = ExecuteRemoteSearchL(
exitReason,
emailAddress->DisplayName() );
if ( remAddress )
{
CleanupStack::PushL( remAddress );
iEditor->AddAddressL( *remAddress );
CleanupStack::PopAndDestroy( remAddress );
}
}
CleanupStack::PopAndDestroy( emailAddress );
}
}
ClosePopupContactListL();
}
// -----------------------------------------------------------------------------
// CESMRAttendeeField::ClosePopupContactListL()
// -----------------------------------------------------------------------------
//
void CESMRAttendeeField::ClosePopupContactListL()
{
FUNC_LOG;
// Disable popup if we get async HandleControlEventL later
iAacListBoxEnabled = EFalse;
if ( iAacListBox && iAacListBox->IsVisible() )
{
iAacListBox->MakeVisible( EFalse );
AknsUtils::SetAvkonSkinEnabledL( ETrue );
}
ShowPopupCbaL( EFalse );
UpdateSendOptionL();
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::ExecuteRemoteSearchL
// ---------------------------------------------------------------------------
//
CESMRNcsEmailAddressObject* CESMRAttendeeField::ExecuteRemoteSearchL(
CPbkxRemoteContactLookupServiceUiContext::TResult::TExitReason& /*aExitReason*/,
const TDesC& aSearchText )
{
FUNC_LOG;
RBuf displayname; // codescanner::resourcenotoncleanupstack
displayname.CreateL( KMaxRemoteSearchResponseLength );
displayname.CleanupClosePushL();
RBuf emailAddress; // codescanner::resourcenotoncleanupstack
emailAddress.CreateL( KMaxRemoteSearchResponseLength );
emailAddress.CleanupClosePushL();
// Pop-up needs to be closed before executing remote lookup with
// query dialog, because combination of this pop-up and any query dialog
// causes background drawing problems with CEikMfne editors.
// Reason unknown.
ClosePopupContactListL();
TBool contactSelected = iContactHandler->LaunchRemoteLookupL( aSearchText,
displayname,
emailAddress );
CESMRNcsEmailAddressObject* address = NULL;
if ( contactSelected )
{
if ( !displayname.Length() )
{
address = CESMRNcsEmailAddressObject::NewL( emailAddress, emailAddress );
}
else
{
address = CESMRNcsEmailAddressObject::NewL( displayname, emailAddress );
}
}
CleanupStack::PopAndDestroy( &emailAddress );
CleanupStack::PopAndDestroy( &displayname );
return address;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::UpdateSendOptionL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::UpdateSendOptionL()
{
FUNC_LOG;
// Check if editor has text and it is different from default text.
HBufC *text = iEditor->GetTextInHBufL();
TBool enable = text && text->Length() > 0 && text->Compare( *iDefaultText ) != 0;
if( enable )
{
TPtr ptr = text->Des();
ptr.Trim();
}
enable = text && text->Length() > 0 && text->Compare( *iDefaultText ) != 0;
delete text;
// Send proper command to CESMREditorDialog::ProcessCommandL
TInt command = 0;
if ( iRole == CCalAttendee::EReqParticipant )
{
if ( enable )
{
command = EESMRCmdAttendeeRequiredEnabled;
}
else
{
command = EESMRCmdAttendeeRequiredDisabled;
}
}
else if ( iRole == CCalAttendee::EOptParticipant )
{
if ( enable )
{
command = EESMRCmdAttendeeOptionalEnabled;
}
else
{
command = EESMRCmdAttendeeOptionalDisabled;
}
}
NotifyEventL( command );
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::HandleListBoxEventL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::HandleListBoxEventL( CEikListBox* aListBox,
TListBoxEvent aEventType )
{
if( aEventType == EEventEnterKeyPressed || aEventType == EEventItemClicked
|| aEventType == EEventItemDoubleClicked || aEventType == EEventItemSingleClicked )
{
TInt newIndex = aListBox->CurrentItemIndex();
// if item is already highlighted and then clicked,
// it is considered that it has been selected
if( newIndex == iPreviousIndex )
{
HandleTactileFeedbackL();
DoPopupSelectL();
// Item selected, index reseted
iPreviousIndex = 0;
}
else
{
iPreviousIndex = newIndex;
}
}
}
// -----------------------------------------------------------------------------
// CESMRAttendeeField::GetCursorLineVerticalPos
// -----------------------------------------------------------------------------
//
void CESMRAttendeeField::GetCursorLineVerticalPos(
TInt& aUpper, TInt& aLower)
{
FUNC_LOG;
TRect rect;
TRAPD( err, iEditor->GetLineRectL( rect ) );
if ( err == KErrNone )
{
rect.Move( 0, iFieldButton->Rect().Size().iHeight );
aUpper = rect.iTl.iY;
aLower = rect.iBr.iY;
}
else
{
// This isn't expected to happen in any situation.
// but if it does at least there will be no zero size
CESMRField::GetCursorLineVerticalPos( aUpper, aLower );
}
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::HandleSingletapEventL
// ---------------------------------------------------------------------------
//
TBool CESMRAttendeeField::HandleSingletapEventL( const TPoint& aPosition )
{
FUNC_LOG;
TBool ret( EFalse );
if( iTitle->Rect().Contains( aPosition ) ||
iFieldButton->Rect().Contains( aPosition ) )
{
HandleTactileFeedbackL();
iContactHandler->GetAddressesFromPhonebookL( this );
ret = ETrue;
}
return ret;
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::HandleLongtapEventL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::HandleLongtapEventL( const TPoint& aPosition )
{
FUNC_LOG;
if( iTitle->Rect().Contains( aPosition ) ||
iFieldButton->Rect().Contains( aPosition ) )
{
NotifyEventL( EAknSoftkeyContextOptions );
}
}
// ---------------------------------------------------------------------------
// CESMRAttendeeField::UpdateAttendeesL
// ---------------------------------------------------------------------------
//
void CESMRAttendeeField::UpdateAttendeesL( MESMRMeetingRequestEntry& aMREntry )
{
FUNC_LOG;
/*
* Compare editor attendees to existing attendees and add / remove
* when necessary.
*/
iEditor->CheckAddressWhenFocusLostL();
CCalEntry& entry( aMREntry.Entry() );
// Get editor's attendees
RPointerArray<CESMRNcsEmailAddressObject> editorAttendees =
iEditor->GetAddressesL();
TInt editorAttendeesCount( editorAttendees.Count() );
// Get existing attendees
RPointerArray<CCalAttendee>& existingAttendees = entry.AttendeesL();
TInt existingAttendeesCount( existingAttendees.Count() );
// Remove removed attendees from entry
for( TInt i( existingAttendeesCount - 1 ); i >= 0 ; --i )
{
// existing address and role
const TDesC& address = existingAttendees[i]->Address();
CCalAttendee::TCalRole role = existingAttendees[i]->RoleL();
// Let's try to find them amongst editor attendees
TBool matchFound( EFalse );
for( TInt j( 0 ); j < editorAttendeesCount ; ++j )
{
// if address match is found ...
if( editorAttendees[j]->EmailAddress().Compare( address ) == 0 )
{
// ... And roles match also
if( role == iRole )
{
// This attendee is left to the entry
matchFound = ETrue;
break;
}
}
}
if( !matchFound )
{
// Existing attendee not found from editor -> Let's delete that
// from entry if roles match
if ( existingAttendees[i]->RoleL( )== iRole )
{
entry.DeleteAttendeeL( i );
}
}
}
// Update existing attendees count, because some attendees might
// have been removed
existingAttendees.Reset();
existingAttendees = entry.AttendeesL();
existingAttendeesCount = existingAttendees.Count();
// Add new attendees to entry
for( TInt i( 0 ); i < editorAttendeesCount ; ++i )
{
CESMRNcsEmailAddressObject* obj = editorAttendees[i];
CCalAttendee* attendee = CCalAttendee::NewL( obj->EmailAddress() );
attendee->SetRoleL( iRole );
attendee->SetCommonNameL( obj->DisplayName() );
if ( EESMRRoleOrganizer == aMREntry.RoleL() ||
aMREntry.IsForwardedL() )
{
attendee->SetResponseRequested( ETrue );
}
TBool isNewAttendee( ETrue );
for( TInt i( 0 ); i < existingAttendeesCount; ++i )
{
if( existingAttendees[i]->Address().Compare( attendee->Address() ) == 0 )
{
if( existingAttendees[i]->RoleL() == iRole )
{
// Match found, this is not a new attendee
isNewAttendee = EFalse;
break;
}
}
}
// If this is new attendee, let's add it to entry
if( isNewAttendee )
{
entry.AddAttendeeL( attendee );
}
}
}
//EOF