messagingappbase/ncnlist/src/NcnOutboxSendOperation.cpp
changeset 0 72b543305e3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/ncnlist/src/NcnOutboxSendOperation.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,431 @@
+/*
+* Copyright (c) 2004 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:   Implements class
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "NcnDebug.h"
+#include "NcnOutboxSendOperation.h"   // header
+#include "NcnModel.h"
+
+#include    <SenduiMtmUids.h>           // MTM Uids
+#include    <msvids.h>                  // Entry Ids
+#include    <muiumsvuiserviceutilitiesinternal.h> // Messaging utilites
+#include    <gsmerror.h>                // SMS sending failure error codes
+
+
+// CONSTANTS
+const TInt KNcnSendPriority=CActive::EPriorityStandard;
+const TInt KNcnSendSelectionGranularity=4;
+
+// ================= MEMBER FUNCTIONS =======================
+
+// Two-phased constructor.
+CNcnOutboxSendOperation* CNcnOutboxSendOperation::NewL(
+    CMsvSession& aMsvSession,
+    TRequestStatus& aObserverRequestStatus )
+    {
+    // Create the instance of sending operation
+    CNcnOutboxSendOperation* self =
+        new (ELeave) CNcnOutboxSendOperation(
+            aMsvSession, aObserverRequestStatus );
+
+    // Push self into cleanup stack during construction
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    // Return the object
+    return self;
+    }
+
+// C++ default constructor can NOT contain any code that
+// might leave.
+//
+CNcnOutboxSendOperation::CNcnOutboxSendOperation(
+    CMsvSession& aMsvSession,
+    TRequestStatus& aObserverRequestStatus )
+    :
+    CMsvOperation( aMsvSession, KNcnSendPriority, aObserverRequestStatus ),
+    iSelections( KNcnSendSelectionGranularity ),
+    iServices(),
+    iSupportedMsgs( CNcnOutboxSendOperation::ENcnSupportsSmsSending )
+    {
+    // Start scheduler
+    CActiveScheduler::Add(this);
+    }
+
+//destructor
+CNcnOutboxSendOperation::~CNcnOutboxSendOperation()
+    {
+    // Cancel sending
+    Cancel();
+
+    // Delete sending operation
+    delete iOperation;
+    iOperation = NULL;
+
+    // Delete entry
+    delete iEntry;
+    iEntry = NULL;
+
+    // Remove services from queue and destroy message selections
+    iServices.Reset();
+    iSelections.ResetAndDestroy();
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::ConstructL
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::ConstructL()
+    {
+    // Get rootindex entry
+    iEntry = iMsvSession.GetEntryL( KMsvRootIndexEntryId );
+    iEntry->SetSortTypeL(
+        TMsvSelectionOrdering( KMsvNoGrouping, EMsvSortByNone, ETrue ) );
+
+    // Set sending flags
+    iSupportedMsgs |= ENcnSendSms;
+
+    // Start sending
+    StartSendingL();
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::RunL
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::RunL()
+    {
+    NCN_RDEBUG(_L("CNcnOutboxSendOperation::RunL"));
+    User::LeaveIfError( iStatus.Int() );
+
+    // Check and start sending, if needed
+    TUid sendMtm;
+
+    // Check if messages needs to be sent
+    if( IsSendingNeeded( sendMtm ) )
+        {
+        StartSendingL();
+        }
+    // Nothing to send, complete operation
+    else
+        {
+        CompleteObserver( iStatus.Int() );
+        }
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::RunError
+// ----------------------------------------------------
+//
+TInt CNcnOutboxSendOperation::RunError( TInt aError )
+    {
+    NCN_RDEBUG_INT(_L("CNcnOutboxSendOperation::RunError - Error %d"), aError );
+    CompleteObserver( aError );
+    return aError;
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::DoCancel
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::DoCancel()
+    {
+    // Check if sending operation is running
+    if( iOperation )
+        {
+        // Cancel it
+        iOperation->Cancel();
+        }
+
+    // Complete operation with current status
+    CompleteObserver( iStatus.Int() );
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::ProgressL
+// ----------------------------------------------------
+//
+const TDesC8& CNcnOutboxSendOperation::ProgressL()
+    {
+    // Check if operation exists
+    if( iOperation )
+        {
+        // Return the operation
+        return iOperation->ProgressL();
+        }
+
+    // If no operation, return blank information
+    return KNcnBlankBuffer;
+    }
+
+// ---------------------------------------------------------
+// CNcnOutboxSendOperation::CompleteOperation
+// ---------------------------------------------------------
+//
+void CNcnOutboxSendOperation::CompleteObserver( TInt aStatus )
+    {
+    // Get the observer status
+    TRequestStatus* status = &iObserverRequestStatus;
+    User::RequestComplete( status, aStatus );
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::StartSendingL
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::StartSendingL()
+    {
+    // Remove any sending operation that currently may be running
+    delete iOperation;
+    iOperation = NULL;
+
+    // Check if selection can be created for selected
+
+    // Check if there was errors with creating selection
+    if  ( CheckAndCreateSelectionL() )
+        {
+        // Create new operation and trap any errors
+        SendWaitingSMSMessages();
+
+        // Clear selection after the operation is complete
+        RemoveSelection();
+        }
+    else
+        {
+    // Set state to pending
+        CompleteSelf( KErrNone );
+        }
+    }
+
+    // if error, then complete this pass with the error code
+void CNcnOutboxSendOperation::SendWaitingSMSMessages()
+    {
+    TRAPD( err, SendWaitingSMSMessagesL() );
+    if  ( err != KErrNone )
+        {
+        ASSERT( !IsActive() );
+        CompleteSelf( err );
+        }
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::SendWaitingSMSMessagesL
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::SendWaitingSMSMessagesL()
+    {
+    // Get first selection from queue
+    CMsvEntrySelection& selection = ( *iSelections[0] );
+
+    // Get count of messages in queue
+    TInt count = selection.Count();
+
+    // Go through all messages
+    while( count-- )
+        {
+        // Select message
+        iEntry->SetEntryL( selection[count] );
+        TMsvEntry entry( iEntry->Entry() );
+
+        // Check if the message is tried to send when in offline
+        if( ( entry.SendingState() == KMsvSendStateSuspended ||
+              entry.SendingState() == KMsvSendStateFailed ) &&
+            ( entry.iError == KErrGsmOfflineOpNotAllowed ||
+              entry.iError == KErrGsmOfflineSimOpNotAllowed ) )
+            {
+            // Set message to wait sending
+            NCN_RDEBUG(_L("SendWaitingSMSMessagesL: entry qualified" ) );
+            entry.SetSendingState( KMsvSendStateWaiting );
+            iEntry->ChangeL( entry );
+            }
+		else
+			{
+			NCN_RDEBUG_INT2(_L("SendWaitingSMSMessagesL: entry not qualified: state %d, error %d" ), entry.SendingState(), entry.iError );
+			selection.Delete( count );
+			}
+        }
+    selection.Compress();
+
+    // Set entry to outbox
+    iMtm = iEntry->Entry().iMtm;
+    iEntry->SetEntryL( KMsvGlobalOutBoxIndexEntryId );
+
+	NCN_RDEBUG_INT(_L("SendWaitingSMSMessagesL: %d entries to send" ), selection.Count() );
+    // Start sending
+	if ( selection.Count() )
+		{
+		iOperation = iEntry->CopyL( selection, iServices[0], iStatus );
+        SetActive();
+		}
+    else
+        {
+        // Nothing to send, but we must complete the observer via our RunL callback
+        CompleteSelf( KErrNone );
+        }
+    }
+
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::RemoveSelection
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::RemoveSelection()
+    {
+    // Clear the the current selection.
+    iServices.Delete(0);
+
+    // Delete selection object and index
+    delete iSelections[0];
+    iSelections.Delete(0);
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::CreateSelectionL
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::CreateSelectionL(
+    const TUid &aUidForSel,
+    const TMsvId& aServiceId,
+    CMsvEntrySelection*& aSelection )
+    {
+    // Set entry to outbox and get messages from outbox
+    iEntry->SetEntryL( KMsvGlobalOutBoxIndexEntryId );
+    aSelection = iEntry->ChildrenWithMtmL( *&aUidForSel );
+
+    // Check if there is anything to put into array
+    if( aSelection->Count() )
+        {
+        // Put selection to queue
+        CleanupStack::PushL( aSelection );
+        iSelections.AppendL( aSelection );
+        CleanupStack::Pop( aSelection );
+
+        // Put service to queue
+        iServices.AppendL( aServiceId );
+        }
+    else
+        {
+        // Remove selection
+        delete aSelection;
+        aSelection = NULL;
+        }
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::CheckAndCreateSelectionL
+// ----------------------------------------------------
+//
+TBool CNcnOutboxSendOperation::CheckAndCreateSelectionL()
+    {
+    // Get root index
+    iEntry->SetEntryL( KMsvRootIndexEntryId );
+
+    // MTM, for which the selection is collected
+    TUid sendMtm;
+
+    // Selection of messages for sending
+    CMsvEntrySelection* smsSelection = NULL;
+
+    // While MTM's available for sending
+    while( smsSelection == NULL && IsSendingNeeded( sendMtm ) )
+        {
+        // Find default SMS service
+        TMsvId serviceId =
+            MsvUiServiceUtilitiesInternal::DefaultServiceForMTML(
+                iMsvSession, *&sendMtm, ETrue );
+
+        // Check if the service ID is found
+        if( serviceId != KMsvNullIndexEntryId )
+            {
+            // Create selection of messages of specified MTM
+            CreateSelectionL( sendMtm, serviceId, smsSelection );
+            }
+		else
+			{
+			NCN_RDEBUG(_L("CNcnOutboxSendOperation::CheckAndCreateSelectionL: default SMS service not found"));
+			}
+
+        // Selection has been created, remove the flag
+        RemoveSendingFlag( *&sendMtm );
+        }
+
+    const TBool selectionAvailable = ( smsSelection != NULL );
+    return selectionAvailable;
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::RemoveSendingFlag
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::RemoveSendingFlag( const TUid& aMtm )
+    {
+    // Decide actions by mtm
+    switch( aMtm.iUid )
+        {
+        // SMS-messages
+        case KSenduiMtmSmsUidValue:
+            iSupportedMsgs &= ~ENcnSendSms;
+            break;
+        // Do nothing
+        default:
+            break;
+        }
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::IsSendingNeeded
+// ----------------------------------------------------
+//
+TBool CNcnOutboxSendOperation::IsSendingNeeded(
+    TUid& aMtm ) const
+    {
+    // Set starting condition
+    TBool needSending = EFalse;
+
+    // Check if sms-sending is supported and messages need to be sent
+    if( iSupportedMsgs & ENcnSupportsSmsSending &&
+        iSupportedMsgs & ENcnSendSms )
+        {
+        aMtm = KSenduiMtmSmsUid;
+        needSending = ETrue;
+        }
+    // Otherwise nothing needs to be done
+    else
+        {
+        aMtm.iUid = 0;
+        needSending = EFalse;
+        }
+
+    // Return the result
+    return needSending;
+    }
+
+// ----------------------------------------------------
+// CNcnOutboxSendOperation::CompleteSelf
+// ----------------------------------------------------
+//
+void CNcnOutboxSendOperation::CompleteSelf( TInt aValue )
+    {
+    TRequestStatus* status = &iStatus;
+    User::RequestComplete( status, aValue );
+    SetActive();
+    }
+    
+// End of file