meetingui/meetingrequestviewers/src/CMRCmdHandler.cpp
changeset 0 f979ecb2b13e
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Implementation for meeeting request command handler
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include "CMRCmdHandler.h"
       
    23 #include "MRHelpers.h"
       
    24 #include "MMRModelInterface.h"
       
    25 #include "MREntryConsultant.h"
       
    26 #include <e32std.h>
       
    27 #include <calentry.h> 		//CCalEntry (Calendar entry API V2)
       
    28 #include <caluser.h> 		//caluser and attendee
       
    29 #include "CMRUtilsInternal.h"
       
    30 #include <MsgMailUIDs.h> 	//uid for mail application
       
    31 #include "MRViewersPanic.h" //panic codes for meeting request viewers
       
    32 #include <mrcommands.hrh> 	//common constants
       
    33 #include <avkon.hrh>
       
    34 #include <aknlistquerydialog.h>
       
    35 #include <meetingrequestviewersuires.rsg>
       
    36 #include <stringloader.h>           // StringLoader
       
    37 #include <aknnotewrappers.h>
       
    38 #include <cmrmailboxutils.h>
       
    39 #include <AknGlobalNote.h>
       
    40 #include "ICalUILog.h"
       
    41 
       
    42 // CONSTANTS
       
    43 /// Unnamed namespace for local definitions
       
    44 namespace {
       
    45 
       
    46 _LIT( KPanicMsg, "CMRCmdHandler" );
       
    47 
       
    48 void Panic( TPanicCode aReason )
       
    49     {
       
    50     User::Panic( KPanicMsg, aReason );
       
    51     }
       
    52 
       
    53 }  // namespace
       
    54 
       
    55 // ============================ MEMBER FUNCTIONS ===============================
       
    56 
       
    57 // -----------------------------------------------------------------------------
       
    58 // CMRCmdHandler::NewL
       
    59 // Two-phased constructor.
       
    60 // -----------------------------------------------------------------------------
       
    61 //
       
    62 CMRCmdHandler* CMRCmdHandler::NewL(
       
    63     MMRModelInterface& aModel,
       
    64     const MAgnEntryUi::TAgnEntryUiInParams& aInParams,
       
    65     CMRMailboxUtils& aMRMailboxUtils,
       
    66     CMRUtilsInternal& aMRUtils )
       
    67     {
       
    68 
       
    69     LOG("CMRCmdHandler::NewL()");
       
    70 
       
    71     CMRCmdHandler* self = new( ELeave ) CMRCmdHandler( aModel,
       
    72                                                        aInParams,
       
    73                                                        aMRMailboxUtils,
       
    74                                                        aMRUtils );
       
    75 
       
    76     CleanupStack::PushL( self );
       
    77     self->ConstructL();
       
    78     CleanupStack::Pop();
       
    79 
       
    80 
       
    81 
       
    82     return self;
       
    83     }
       
    84 
       
    85 // -----------------------------------------------------------------------------
       
    86 // CMRCmdHandler::CMRCmdHandler
       
    87 // C++ default constructor can NOT contain any code, that
       
    88 // might leave.
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 CMRCmdHandler::CMRCmdHandler(
       
    92     MMRModelInterface& aModel,
       
    93     const MAgnEntryUi::TAgnEntryUiInParams& aInParams,
       
    94     CMRMailboxUtils& aMRMailboxUtils,
       
    95     CMRUtilsInternal& aMRUtils )
       
    96     : iModel( aModel ),
       
    97       iInParams( aInParams ),
       
    98       iMRUtils( aMRUtils ),
       
    99       iMRMailboxUtils( aMRMailboxUtils )
       
   100     {
       
   101     }
       
   102 
       
   103 // -----------------------------------------------------------------------------
       
   104 // CMRCmdHandler::ConstructL
       
   105 // Symbian 2nd phase constructor can leave.
       
   106 // -----------------------------------------------------------------------------
       
   107 //
       
   108 void CMRCmdHandler::ConstructL()
       
   109     {
       
   110     // Memorize original attendee list:
       
   111     RPointerArray<CCalAttendee>& attendees =
       
   112         iModel.CombinedEntry()->AttendeesL();
       
   113     TInt count( 0 );
       
   114     for ( TInt i( 0 ); i < count; ++i )
       
   115         {
       
   116         CCalAttendee* att = MRHelpers::CopyAttendeeLC( *( attendees[i] ) );
       
   117         iOriginalAttendees.AppendL( att ); // ownership transferred
       
   118         CleanupStack::Pop( att );
       
   119         }
       
   120     }
       
   121 
       
   122 // Destructor
       
   123 CMRCmdHandler::~CMRCmdHandler()
       
   124     {
       
   125     iOriginalAttendees.ResetAndDestroy();
       
   126     }
       
   127 
       
   128 // ----------------------------------------------------------------------------
       
   129 // CMRCmdHandler::SaveL
       
   130 // ----------------------------------------------------------------------------
       
   131 //
       
   132 TInt CMRCmdHandler::SaveL()
       
   133     {
       
   134     CCalEntry& combinedEntry = *( iModel.CombinedEntry() );
       
   135     // we are an organizer and must set protocol fields,
       
   136     // set entry as non-sent -> 2nd parameter == EFalse
       
   137     SetProtocolFieldsL( combinedEntry, EFalse );
       
   138     // save combined entry
       
   139     return iMRUtils.StoreL( combinedEntry, EFalse );
       
   140     }
       
   141 
       
   142 // ----------------------------------------------------------------------------
       
   143 // CMRCmdHandler::SaveFromFileL
       
   144 // ----------------------------------------------------------------------------
       
   145 //
       
   146 TInt CMRCmdHandler::SaveFromFileL( const RPointerArray<CCalEntry>& aEntries )
       
   147     {
       
   148     TInt retVal( KErrNone );
       
   149     CCalEntry& firstEntry = *( aEntries[0] );    
       
   150     TInt count( aEntries.Count() );
       
   151             
       
   152     // all entries have the same method
       
   153     if ( iModel.MethodL() == CCalEntry::EMethodReply )
       
   154         {
       
   155         // update first entry and take the result code
       
   156         retVal = iMRUtils.UpdateEntryL( firstEntry );        
       
   157         // update also other entries in file, but don't care about the result
       
   158         for ( TInt i( 1 ); i < count; ++i )
       
   159             {
       
   160             iMRUtils.UpdateEntryL( *( aEntries[i] ) );
       
   161             }        
       
   162         }
       
   163     else
       
   164         {
       
   165         // save first entry and take the result code
       
   166         retVal = iMRUtils.StoreL( firstEntry, EFalse );
       
   167         
       
   168         // save also other entries in file, but don't care about the result
       
   169         for ( TInt i( 1 ); i < count; ++i )
       
   170             {
       
   171             iMRUtils.StoreL( *( aEntries[i] ), EFalse );
       
   172             }
       
   173         }
       
   174     return retVal;        
       
   175     }
       
   176     
       
   177 // ----------------------------------------------------------------------------
       
   178 // CMRCmdHandler::SendL
       
   179 // Send a request edited by the organizer (in Calendar application)
       
   180 // ----------------------------------------------------------------------------
       
   181 //
       
   182 TInt CMRCmdHandler::SendL( TInt aSendCmd )
       
   183     {
       
   184     TMsvId boxToUse = MREntryConsultant::SendingMailBoxL( iInParams,
       
   185                                                           iMRMailboxUtils );
       
   186     CCalEntry& combinedEntry = *( iModel.CombinedEntry() );
       
   187 
       
   188     TInt retVal( KErrNone );
       
   189 
       
   190     if ( combinedEntry.SummaryL().Length() == 0 )
       
   191         { // Confirm that sending is ok although subject is empty
       
   192         CAknQueryDialog* dlg = CAknQueryDialog::NewL();
       
   193         if ( !dlg->ExecuteLD( R_SEND_CONFIRM_NO_SUBJECT ) )
       
   194             {
       
   195             retVal = KErrCancel;
       
   196             }
       
   197         }
       
   198 
       
   199     if ( retVal == KErrNone )
       
   200         {
       
   201         // When saving before sending we must update protocol fields and
       
   202         // set 2nd parameter == ETrue
       
   203         SetProtocolFieldsL( combinedEntry, ETrue );
       
   204         MMRUtilsTombsExt::TMRUtilsDbResult dbResult =
       
   205             iMRUtils.StoreL( combinedEntry, EFalse );
       
   206         // Saving may return positive values to report success
       
   207         if ( dbResult >= MMRUtilsTombsExt::EUndefined )
       
   208             {
       
   209             HBufC* note =
       
   210                 StringLoader::LoadLC( R_TEXT_CALENDAR_MEETING_REQUEST_SAVED );
       
   211             CAknConfirmationNote* dlg =
       
   212                 new( ELeave ) CAknConfirmationNote( ETrue );
       
   213             dlg->ExecuteLD( *note );
       
   214             CleanupStack::PopAndDestroy(); // note
       
   215             }
       
   216         else if ( dbResult != MMRUtilsTombsExt::EErrorIdenticalExists )
       
   217             { // identical exists is not an error in sending scenario
       
   218             retVal = KErrGeneral;
       
   219             }
       
   220         }
       
   221 
       
   222     if ( retVal == KErrNone )
       
   223         {
       
   224         iMRUtils.SendWithUiL( combinedEntry, boxToUse );
       
   225 
       
   226         if ( aSendCmd == EMRCommandSendUpdate )
       
   227             {
       
   228             // cancellation must be sent to removed attendees
       
   229             CCalEntry* cancel =
       
   230                 CreateCancelForRemovedAttendeesL( combinedEntry );
       
   231             if ( cancel )
       
   232                 {
       
   233                 CleanupStack::PushL( cancel );
       
   234                 iMRUtils.SendWithUiL( *cancel, boxToUse );
       
   235                 CleanupStack::PopAndDestroy( cancel );
       
   236                 
       
   237                 // since we have now notified removed attendees we should
       
   238                 // reset the array (although shouldn't make any difference
       
   239                 // in practise)
       
   240                 iOriginalAttendees.ResetAndDestroy();
       
   241                 }
       
   242             }
       
   243         }
       
   244 
       
   245     return retVal;
       
   246     }
       
   247 
       
   248 // ----------------------------------------------------------------------------
       
   249 // CMRCmdHandler::SendL
       
   250 // User may edit attendee list multiple times in one ICalUI session,
       
   251 // and may also save entry multiple times before sending it, therefore we
       
   252 // should collect attendees of an existing entry in the startup phase, and
       
   253 // then compare it to the edited list just before sending.
       
   254 // ----------------------------------------------------------------------------
       
   255 //
       
   256 CCalEntry* CMRCmdHandler::CreateCancelForRemovedAttendeesL(
       
   257     const CCalEntry& aEntry ) const
       
   258     {
       
   259     CCalEntry* cancel = NULL;
       
   260     
       
   261     RPointerArray<CCalAttendee> removedAttendees; // temporary helper array
       
   262     CleanupClosePushL( removedAttendees ); // doesn't own its items
       
   263     TInt originalCount( iOriginalAttendees.Count() );
       
   264     for ( TInt i( 0 ); i < originalCount; ++i )
       
   265         {
       
   266         CCalAttendee* att = MREntryConsultant::EqualAttendeeL(
       
   267             *( iOriginalAttendees[i] ), aEntry );
       
   268         if ( !att )
       
   269             {
       
   270             removedAttendees.AppendL( iOriginalAttendees[i] );
       
   271             }
       
   272         }
       
   273         
       
   274     TInt removedCount( removedAttendees.Count() );
       
   275     if ( removedCount > 0 )
       
   276         {
       
   277         // Create a skeleton for the cancellation, use the same sequence number
       
   278         // as aEntry (the update that was just sent) has
       
   279         cancel = MRHelpers::CopyEntryLC( aEntry, 
       
   280                                          CCalEntry::EMethodCancel, 
       
   281                                          MRHelpers::ECopyOrganizer );
       
   282         for ( TInt j( 0 ); j < removedCount; ++j )
       
   283             {        
       
   284 	        CCalAttendee* attCopy =
       
   285 	            MRHelpers::CopyAttendeeLC( *( removedAttendees[j] ) );
       
   286 	        cancel->AddAttendeeL( attCopy );
       
   287 	        CleanupStack::Pop(); // attCopy, ownership was transferred
       
   288             }
       
   289             
       
   290         CleanupStack::Pop( cancel );
       
   291         }
       
   292 
       
   293     CleanupStack::PopAndDestroy(); // removedAttendees, just close the array
       
   294     
       
   295     return cancel; // may be NULL    
       
   296     }
       
   297 
       
   298 // ----------------------------------------------------------------------------
       
   299 // CMRCmdHandler::CancelMRL
       
   300 // This method is only used from Calendar application, and in that case we
       
   301 // always handle just one entry at a time (entire series or one instance).
       
   302 // ----------------------------------------------------------------------------
       
   303 //
       
   304 TInt CMRCmdHandler::CancelMRL()
       
   305     {
       
   306     TMsvId boxToUse = MREntryConsultant::SendingMailBoxL( iInParams,
       
   307                                                           iMRMailboxUtils );
       
   308     TInt retVal( KErrNone );
       
   309     CCalEntry* combinedEntry = iModel.CombinedEntry();
       
   310     RPointerArray<CCalEntry> entryArray( 1 );
       
   311     entryArray.AppendL( combinedEntry );
       
   312     CleanupClosePushL( entryArray );
       
   313 
       
   314     retVal = iMRUtils.CancelWithUiL( entryArray, boxToUse );
       
   315     CleanupStack::PopAndDestroy(); // entryArray, only close arary
       
   316     return retVal;
       
   317     }
       
   318 
       
   319 // ----------------------------------------------------------------------------
       
   320 // CMRCmdHandler::DeleteMRL
       
   321 // This method is only used from Calendar application, and in that case we
       
   322 // always handle just one entry at a time (entire series or one instance).
       
   323 // ----------------------------------------------------------------------------
       
   324 //
       
   325 TInt CMRCmdHandler::DeleteMRL()
       
   326     {
       
   327     TMsvId boxToUse = MREntryConsultant::SendingMailBoxL( iInParams,
       
   328                                                           iMRMailboxUtils );
       
   329     TInt retVal( KErrNone );
       
   330     CCalEntry& combinedEntry = *( iModel.CombinedEntry() );
       
   331     retVal = iMRUtils.DeleteWithUiL( combinedEntry, boxToUse );
       
   332     return retVal;
       
   333     }
       
   334 
       
   335 // ----------------------------------------------------------------------------
       
   336 // CMRCmdHandler::CreateReplyL
       
   337 // ----------------------------------------------------------------------------
       
   338 //
       
   339 void CMRCmdHandler::CreateReplyL( TInt aReplyType )
       
   340 	{
       
   341 	__ASSERT_DEBUG( iInParams.iMessageId != KMsvNullIndexEntryId,
       
   342 	                Panic( ETMsvIDNull ) );
       
   343 
       
   344     CCalEntry& combinedEntry = *( iModel.CombinedEntry() );
       
   345 
       
   346 	CMRUtilsInternal::TMailRecipients aRecipients( CMRUtilsInternal::EAll );
       
   347 
       
   348 	switch( aReplyType )
       
   349 		{
       
   350 		case EMRCommandReplyToSender:
       
   351 			{
       
   352 			aRecipients = CMRUtilsInternal::ESender;
       
   353 			break;
       
   354 			}
       
   355 		case EMRCommandReplyToOrganiser:
       
   356 			{
       
   357 			aRecipients = CMRUtilsInternal::EOrganizer;
       
   358 			break;
       
   359 			}
       
   360 		case EMRCommandReplyToAll:
       
   361 			{
       
   362 			aRecipients = CMRUtilsInternal::EAll;
       
   363 			break;
       
   364 			}
       
   365 		}
       
   366 
       
   367     HBufC* senderAddr = MRHelpers::SenderAddressLC(
       
   368             *( iInParams.iMsgSession ),
       
   369             iInParams.iMessageId,
       
   370             EFalse );
       
   371     TMsvId boxToUse = MREntryConsultant::SendingMailBoxL( iInParams,
       
   372                                                           iMRMailboxUtils );
       
   373 	iMRUtils.ReplyToL( aRecipients, combinedEntry, *senderAddr, boxToUse );
       
   374 	CleanupStack::PopAndDestroy( senderAddr );
       
   375 	}
       
   376 
       
   377 // ----------------------------------------------------------------------------
       
   378 // CMRCmdHandler::RemoveFromCalendarL
       
   379 //
       
   380 // ----------------------------------------------------------------------------
       
   381 //
       
   382 void CMRCmdHandler::RemoveFromCalendarL(
       
   383     const RPointerArray<CCalEntry>& aEntries )
       
   384 	{
       
   385     CCalEntry& firstEntry = *( aEntries[0] );
       
   386 	if ( MREntryConsultant::IsModifyingEntryL( firstEntry ) )
       
   387 	    { // if entry at index 0 is modifying entry, then all entries are,
       
   388 	      // that means that we remove each of them but originating remains,
       
   389 	      // this branch is probably rarely, if ever, used in real life
       
   390 	    TInt count( aEntries.Count() );
       
   391 	    for ( TInt i( 0 ); i < count; ++i )
       
   392 	        {
       
   393 	        iMRUtils.DeleteL( *( aEntries[i] ) );
       
   394 	        }
       
   395 	    }
       
   396     else
       
   397         { // entry at index 0 is originating, all entries for this meeting
       
   398           // will get deleted, this is the usual case
       
   399         iMRUtils.DeleteL( firstEntry );
       
   400         }
       
   401 
       
   402 	HBufC* removeNote = StringLoader::LoadL( R_QTN_CALE_NOTE_MEETING_REMOVED );
       
   403 	CleanupStack::PushL( removeNote );
       
   404 	CAknGlobalNote* globalNote = CAknGlobalNote::NewLC();
       
   405 	globalNote->ShowNoteL( EAknGlobalInformationNote, *removeNote );
       
   406 	CleanupStack::PopAndDestroy( globalNote );
       
   407 	CleanupStack::PopAndDestroy( removeNote );
       
   408 	}
       
   409 
       
   410 // ----------------------------------------------------------------------------
       
   411 // CMRCmdHandler::CreateResponseL
       
   412 // This method may be called also from mail or BVA, and in that case we may
       
   413 // have to deal with an array of entries.
       
   414 // ----------------------------------------------------------------------------
       
   415 //
       
   416 TInt CMRCmdHandler::CreateResponseL(
       
   417     const RPointerArray<CCalEntry>& aEntries,
       
   418     TInt aResponseCmd )
       
   419 	{
       
   420 	CCalAttendee::TCalStatus status( CCalAttendee::ENeedsAction );
       
   421 	switch ( aResponseCmd )
       
   422 		{
       
   423 		case EMRCommandRespondAccept:
       
   424 			{
       
   425 			status = CCalAttendee::EAccepted;
       
   426 			break;
       
   427 			}
       
   428 		case EMRCommandRespondTentative:
       
   429 			{
       
   430 			status = CCalAttendee::ETentative;
       
   431 			break;
       
   432 			}
       
   433 		case EMRCommandRespondDecline:
       
   434 			{
       
   435 			status = CCalAttendee::EDeclined;
       
   436 			break;
       
   437 			}
       
   438 		default:
       
   439 			{
       
   440 			User::Leave( KErrNotSupported );
       
   441 			break;
       
   442 			}
       
   443 		}
       
   444     // TODO: Currently we are sending MR response via the mailbox which is stored
       
   445     // in cenrep settings, but it has been discussed that actually we should send
       
   446     // via the mailbox that is associated with ThisAttendeeL() email address.
       
   447     TMsvId boxToUse = MREntryConsultant::SendingMailBoxL( iInParams,
       
   448                                                           iMRMailboxUtils );
       
   449     return iMRUtils.RespondWithUiL( aEntries, status, boxToUse );
       
   450 	}
       
   451 
       
   452 void CMRCmdHandler::DisableAlarmL(
       
   453     const RPointerArray<CCalEntry>& aEntries )
       
   454 	{
       
   455     TInt count( aEntries.Count() );
       
   456     for ( TInt i( 0 ); i < count; ++i )
       
   457         {
       
   458         CCalEntry& entry = *( aEntries[i] );
       
   459 	    CCalEntry* dBEntry = iMRUtils.FetchEntryL( entry.UidL(),
       
   460 	                                               entry.RecurrenceIdL() );
       
   461     	if ( dBEntry )
       
   462     		{
       
   463     	    CleanupStack::PushL( dBEntry );
       
   464     		dBEntry->SetAlarmL( NULL );
       
   465     		iMRUtils.UpdateEntryL( *dBEntry );
       
   466             CleanupStack::PopAndDestroy( dBEntry );
       
   467     		}
       
   468         }
       
   469 	}
       
   470 
       
   471 // this method may be moved to some other class if other classes than
       
   472 // just CmdHandler need to use it.
       
   473 void CMRCmdHandler::SetProtocolFieldsL(
       
   474     CCalEntry& aEntry,
       
   475     TBool aWillBeSentNow ) const
       
   476     {
       
   477     __ASSERT_DEBUG( iMRMailboxUtils.IsOrganizerL( aEntry ),
       
   478                     Panic( ENonOrganizerSettingProtocolFields ) );    
       
   479     
       
   480     // TODO: set seq number, do we need to compare entry to db entry and
       
   481     // what fields have changed and what type of entry it is?
       
   482 
       
   483     // Store information whether this request / this particular entry
       
   484     // will be sent now or just saved.
       
   485 
       
   486     if ( aWillBeSentNow )
       
   487         { // TODO: this will be done differently when Symbian supports other fields
       
   488           // to indicate sending status
       
   489         TTime currentTime;
       
   490         currentTime.UniversalTime();
       
   491         TCalTime dtstamp;
       
   492         dtstamp.SetTimeUtcL( currentTime );
       
   493         aEntry.SetDTStampL( dtstamp );
       
   494         if ( aEntry.StatusL() == CCalEntry::ENullStatus )
       
   495             { // If entry has had ENullStatus, we use now EConfirmed
       
   496               // as a stamp to mark that entry has been sent at least once.
       
   497             aEntry.SetStatusL( CCalEntry::EConfirmed );
       
   498             }
       
   499         }
       
   500     else
       
   501         {
       
   502         TCalTime dtstamp; // initialized to null time
       
   503         aEntry.SetDTStampL( dtstamp );
       
   504         }    
       
   505     }
       
   506 
       
   507 //  End of File
       
   508