|
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 |