diff -r 48780e181b38 -r 578be2adaf3e Symbian3/PDK/Source/GUID-E180D222-CC4F-5007-93FC-C339BBE708BC.dita --- a/Symbian3/PDK/Source/GUID-E180D222-CC4F-5007-93FC-C339BBE708BC.dita Tue Jul 20 12:00:49 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-E180D222-CC4F-5007-93FC-C339BBE708BC.dita Fri Aug 13 16:47:46 2010 +0100 @@ -1,384 +1,384 @@ - - - - - -Client -MTM -

Client MTMs provide a client-side API to functionality provided by the -Server MTM, mainly for message manipulation and transport. It acts as the -interface between the internal representation of a message’s data and the -User Interface (UI) MTM. This architecture provides certain advantages; for -example, a UI MTM can offer a user interface to enter message addresses without -knowing the address storage format. Message client applications that do not -require a user interface can use these client-side functions directly for -automated message handling.

-

The Message Server entry with which Client MTMs currently work is referred -to as the context. UI MTMs always operate on the contexts set through Client -MTMs.

-

Client MTMs offer some or all of the following capabilities:

- -
Client MTM -base class

The base class for Client MTMs is CBaseMtm which -provides a high-level interface for accessing and manipulating a Message Server -entry

The following are some significant functions in CBaseMtm. -Some functions are implemented by the base class, and others must be implemented -in a derived class:

    -
  • Context functions

    The CBaseMtm::SetCurrentEntryL (CMsvEntry *) and CBaseMtm::SwitchCurrentEntryL (TMsvId) functions -change the Message Server entry (the context) on which later actions are performed. -After creating a new Client MTM object, a message client application must -set an initial context before using other functions.

  • -
  • Store and restore -entry data functions

    The changes that a message client application -makes to a message context through Client MTM functions, such as altering -the body text obtained through CBaseMtm::Body(), are, for -efficiency, cached in memory by a Client MTM. The message store (SaveMessageL())and -restore (LoadMessageL()), functions are concerned with -transferring data between that cache and committed storage.

    Note: Unlike -message contexts, message client applications are not expected to manipulate -directly contexts for message services. Instead, the corresponding User Interface -MTM provides a dialog to allow the user to alter service settings, and calls -Client MTM functions to handle their retrieval and storage.

  • -
  • Store and restore -body text functions

    The base class maintains a private CRichText object -cache to store the body text for the current context. This can be accessed -for reading and writing by message client applications through CBaseMtm::Body(). -The CBaseMtm::StoreBodyL() (CMsvStore &) and CBaseMtm::RestoreBodyL() (CMsvStore -&) functions encapsulate the retrieval and storage of this CRichText object -to a CMsvStore.

  • -
  • Address list functions

    The -format and storage of message addresses is MTM-specific. The CBaseMtm::AddresseeList() const, CBaseMtm::AddAddresseeL (const TDesC &), and CBaseMtm::RemoveAddressee (TInt) allow -clients to access address information in a generic way without having MTM-specific -knowledge.

  • -
  • MTM-specific client -functions

    MTM components can offer protocol-specific functionality -not provided by base class interface functions. MTM components define IDs -that correspond to each protocol-specific operation offered, and implement -the CBaseMtm::InvokeSyncFunctionL() and CBaseMtm::InvokeAsyncFunctionL() functions -to allow clients to access these operations by passing in the appropriate -ID. These functions are provided to allow the MTM component to offer both -synchronous and asynchronous functionality. Message client applications can -dynamically add user-interface features for these operations using CBaseMtmUiData::MtmSpecificFunctions().

  • -
  • Query function

    The -Client MTM QueryCapability() function is used to inquire -whether an MTM supports a given feature. The first argument is a UID defined -to correspond to a particular capability. The function returns a system error -code and the response (whether the MTM supports the queried capability) is -passed back through the second (by-reference)aResponse parameter. -This value can be an integer or a bit set, depending on the capability.

    The -UIDs for the different types of query are as follows:

    - - - -UID -Capability - - - - -

    KUidMsvMtmQueryMaxBodySize

    -

    Maximum message body size

    -
    - -

    KUidMtmQueryMaxTotalMsgSize

    -

    Maximum total size of message.

    -
    - -

    KUidMtmQuerySupportedBody

    -

    Character widths supported by message type. The returned value is -the sum of the appropriate values. The return type is either of KMtm7BitBody, -KMtm8BitBody, KMtm16BitBody, and KMtmBinaryBody)

    -
    - -

    KUidMtmQuerySupportAttachments

    -

    To check if the attachments are supported

    -
    - -

    KUidMtmQuerySupportSubject

    -

    Does the MTM message type have a subject field

    -
    - -

    KUidMtmQuerySupportsFolder

    -

    Does the MTM support folders

    -
    - -

    KUidMtmQueryOffLineAllowed

    -

    Off-line operation allowed

    -
    - -

    KUidMtmQueryCanSendMsg

    -

    Can send the message

    -
    - -

    KUidMtmQueryCanReceiveMsg

    -

    Can receive the message

    -
    - -

    KUidMtmQueryMaxRecipientCount

    -

    Maximum number of recipients (-1 indicates unlimited numbers).

    -
    - -

    KUidMtmQuerySendAsRequiresRenderedImage

    -

    When using the MTM in Send As, does a rendered image have to be -prepared.

    -
    - -

    KUidMtmQuerySendAsRenderingUid

    -

    Printer driver UID for rendering the fax image.

    -
    - -

    KUidMsvMtmQueryEditorUid

    -

    UID of default message editor.

    -
    - -

    KUidMsvQuerySupportsBioMsg

    -

    Does the MTM support BIO messages

    -
    - -

    KUidMsvQuerySupportsScheduling

    -

    Does the MTM support scheduled sending.

    -
    - -

    KUidMtmQuerySupportsRecipientType

    -

    Does the MTM support the use of recipient type.

    -
    - -

    KUidMtmQuerySendAsMessageSendSupport

    -

    Support for Sending messages using SendAs.

    If this is supported, -then the MTM supports sending messages created through the SendAs API.

    -
    - - -

    The following example is a snapshot of the Text MTM example. For -more implementation details, see Messaging -Text MTM example code.

    TInt CTextMtmClient::QueryCapability(TUid aCapability, TInt& aResponse) - { - TInt error = KErrNone; - switch (aCapability.iUid) - { - case KUidMtmQueryMaxBodySizeValue: - case KUidMtmQueryMaxTotalMsgSizeValue: - aResponse = KMaxTextMessageSize; - break; - case KUidMtmQuerySupportedBodyValue: - aResponse = KMtm8BitBody + KMtm7BitBody; - break; - case KUidMtmQueryOffLineAllowedValue: - case KUidMtmQueryCanReceiveMsgValue: - aResponse = ETrue; - break; - case KUidMtmQuerySupportAttachmentsValue: - default: - return KErrNotSupported; - } - return error; - } -
  • -

The CBaseMtm class provides the virtual functions -for overriding in derived classes.

-
Client-side -operations

Many Messaging tasks can take a long time to complete. -For example, sending all items from the Outbox or downloading a large number -of items from a POP3 server. In these situations, the use of active objects -to wait for the completion of the task is inadequate, since applications also -require to obtain progress information while the task is running (for example, -to update a progress dialog). To solve this problem, most asynchronous functions -in Messaging create a CMsvOperation object and return a -pointer to it, as well as taking a TRequestStatus& parameter. -The CMsvOperation class is derived from CActive and -is used to obtain progress information about a long-running task.

The -base class for all client-side Messaging operations is CMsvOperation. -The asynchronous methods in the CBaseMtm interface all -return a pointer to a CMsvOperation object. When you implement -an MTM, you will have to provide your own custom operations, derived from CMsvOperation, -and return those polymorphically from your implementations of the asynchronous -APIs.

Example

The forward operation of the Text MTM -is explained in the following example.

The forward operation is an -active object state machine that runs a series of asynchronous tasks one after -another and waits for each to complete before moving on to the next. After -the operation has been completed, an active object is notified through its TRequestStatus passed -into the operation at construction.

The forward operation is constructed -using standard two-phase construction. The NewL() function -takes two arguments of a TMsvId (source message and destination -folder) type, a CMsvSession reference, and the observer’s TRequestStatus, -which is notified on completion. The active object is constructed and added -to the scheduler, and then ConstructL() is called:

void CTxtMtmForwardOperation::ConstructL() - { - iObserverRequestStatus = KRequestPending; - SetActive(); - TRequestStatus* stat = &iStatus; - User::RequestComplete(stat, KErrNone); - } -

This has the effect of marking this stage of the operation -as complete and means that RunL() is called at the next -opportunity. This simplifies the state machine because it means that all states -and tasks are started in RunL() and not in ConstructL().

The RunL() function -starts each task and receives a notification when it completes. The current -task being executed is stored in iProgress and iState, -as are the errors and the ID of the new forwarded message, once complete. -The default state for iState on construction is EInit.

void CTxtMtmForwardOperation::RunL() - { - User::LeaveIfError(iStatus.Int()); - switch(iProgress.iState) - { - case TTxtMtmForwardOpProgress::EInit: - iProgress.iState = - TTxtMtmForwardOpProgress::ECreateMessage; - CreateMessageL(); - break; - - case TTxtMtmForwardOpProgress::ECreateMessage: - iProgress.iState = - TTxtMtmForwardOpProgress::EFormatBodyText; - FormatBodyTextL(); - break; - - case TTxtMtmForwardOpProgress::EFormatBodyText: - iProgress.iState = - TTxtMtmForwardOpProgress::EFinished; - - default: - break; - } - if(!IsActive()) - { - TRequestStatus* stat = &iObserverRequestStatus; - User::RequestComplete(stat, KErrNone); - } - } -

If the state is EInit, the RunL() changes -state to ECreateMessage and then calls CreateMessageL() to -start the process of creating a message asynchronously.

void CTxtMtmForwardOperation::CreateMessageL() - { -

The function constructs a CMsvEntry for -the source entry and then retrieves its index entry.

delete iMsvEntry; - iMsvEntry = NULL; - iMsvEntry = iMsvSession.GetEntryL(iSourceMessage); - - // Get the entry to be forwarded - TMsvEntry forwardEntry = iMsvEntry->Entry(); -

The context of iMsvEntry is changed to -the destination folder and an entry is created.

// Set the context to the destination folder - iMsvEntry->SetEntryL(iDestinationFolder); -

The index entry’s date is updated to reflect the current date.

// Create the forwarded index entry - forwardEntry.iDate.HomeTime(); - iMsvEntry->CreateL(forwardEntry); -

The iFinalMsgId member of the progress -is updated to reflect the newly created entry.

iProgress.iFinalMsgId = forwardEntry.Id(); - - // schedules the active object to complete so that this - // class's RunL method - // will be called by the active scheduler - SetActive(); -

The operation’s TRequestStatus is then flagged -to cause RunL().

TRequestStatus* stat = &iStatus; - User::RequestComplete(stat, KErrNone); - } -

When this happens, iProgress.iState is set -to ECreateMessage, so the following code is executed:

case TTxtMtmForwardOpProgress::ECreateMessage: - iProgress.iState = TTxtMtmForwardOpProgress::EFormatBodyText; - FormatBodyTextL(); - break;

The state is set to EFormatBodyText and -the FormatBodyTextL() function is called.

-void CTxtMtmForwardOperation::FormatBodyTextL() - { -

The function constructs a CParaFormatLayer, -a CCharFormatLayer, and a CRichText object. -These objects are required to store the body text of the forwarded message.

CParaFormatLayer* paraLayer = CParaFormatLayer::NewL(); - CleanupStack::PushL(paraLayer); - CCharFormatLayer* charLayer = CCharFormatLayer::NewL(); - CleanupStack::PushL(charLayer); - CRichText* body = CRichText::NewL(paraLayer, charLayer); - CleanupStack::PushL(body); -

Then the context of iMsvEntry is changed -to point at the source message and a read-only CMsvStore is -opened for that entry.

// Get the message store from the source entry - iMsvEntry->SetEntryL(iSourceMessage); - CMsvStore* readStore = iMsvEntry->ReadStoreL(); - CleanupStack::PushL(readStore);

The context of the iMsvEntry object -is changed to point at the newly created entry and a CMsvStore is -opened for that entry.

// Get the message store from the newly created destination - // entry - iMsvEntry->SetEntryL(iProgress.iFinalMsgId); - CMsvStore* writeStore = iMsvEntry->EditStoreL(); - CleanupStack::PushL(writeStore); - - // Get the body text from the source entry and write it - // to the destination entry, prepending the forward - // prefix - readStore->RestoreBodyTextL(*body); - body->InsertL(0, KTxtMtmFwdPrefix); - - // this method performs a commit for us - writeStore->StoreBodyTextL(*body); - - CleanupStack::PopAndDestroy(5, paraLayer); - - // schedules the active object to complete so that this - // class's RunL method - // will be called by the active scheduler - SetActive(); - TRequestStatus* stat = &iStatus; - User::RequestComplete(stat, KErrNone); - } -

The iProgress.iState is set to EFinished, -and because the object has not been activated the following conditional statement -evaluates true:

if(!IsActive()) - { - TRequestStatus* stat = &iObserverRequestStatus; - User::RequestComplete(stat, KErrNone); - } -

The observer active object’s TRequestStatus is -flagged to let it know that the operation is complete.

To return progress -from the operation, implement the ProgressL() and FinalProgress() functions. ProgressL() must -be used to return progress information on the operation during processing, -and FinalProgress() is guaranteed to return the status -of a completed operation. ProgressL() must be implemented -to leave with KErrNotReady if the operation is not in progress, -and FinalProgress() must panic if the operation is not -complete.

const TDesC8& CTxtMtmForwardOperation::ProgressL() - { - if (!IsActive()) - { - User::Leave(KErrNotReady); - } - iProgressBuf() = iProgress; - return iProgressBuf; - } - -const TDesC8& CTxtMtmForwardOperation::FinalProgress() - { - __ASSERT_ALWAYS(!IsActive(), User::Panic(KTxtCPanic, - ETxtcOperationIsActive)); - iProgressBuf() = iProgress; - return iProgressBuf; - }

The RunError() function must also be -implemented to get any leaves in RunL().

TInt CTxtMtmForwardOperation::RunError(TInt aError) - { - iProgress.iError = aError; - TRequestStatus* stat = &iObserverRequestStatus; - User::RequestComplete(stat, aError); - return KErrNone; - }
-
-MTM overview - -MTM Capabilities - -Writing a -Client MTM + + + + + +Client +MTM +

Client MTMs provide a client-side API to functionality provided by the +Server MTM, mainly for message manipulation and transport. It acts as the +interface between the internal representation of a message’s data and the +User Interface (UI) MTM. This architecture provides certain advantages; for +example, a UI MTM can offer a user interface to enter message addresses without +knowing the address storage format. Message client applications that do not +require a user interface can use these client-side functions directly for +automated message handling.

+

The Message Server entry with which Client MTMs currently work is referred +to as the context. UI MTMs always operate on the contexts set through Client +MTMs.

+

Client MTMs offer some or all of the following capabilities:

+
    +
  • Address list manipulation

  • +
  • Creation of forward +and response messages

  • +
  • Message subject access

  • +
  • Message validation

  • +
  • Internalising and externalising +MTM-specific data to the Message Store

  • +
+
Client MTM +base class

The base class for Client MTMs is CBaseMtm which +provides a high-level interface for accessing and manipulating a Message Server +entry

The following are some significant functions in CBaseMtm. +Some functions are implemented by the base class, and others must be implemented +in a derived class:

    +
  • Context functions

    The CBaseMtm::SetCurrentEntryL (CMsvEntry *) and CBaseMtm::SwitchCurrentEntryL (TMsvId) functions +change the Message Server entry (the context) on which later actions are performed. +After creating a new Client MTM object, a message client application must +set an initial context before using other functions.

  • +
  • Store and restore +entry data functions

    The changes that a message client application +makes to a message context through Client MTM functions, such as altering +the body text obtained through CBaseMtm::Body(), are, for +efficiency, cached in memory by a Client MTM. The message store (SaveMessageL())and +restore (LoadMessageL()), functions are concerned with +transferring data between that cache and committed storage.

    Note: Unlike +message contexts, message client applications are not expected to manipulate +directly contexts for message services. Instead, the corresponding User Interface +MTM provides a dialog to allow the user to alter service settings, and calls +Client MTM functions to handle their retrieval and storage.

  • +
  • Store and restore +body text functions

    The base class maintains a private CRichText object +cache to store the body text for the current context. This can be accessed +for reading and writing by message client applications through CBaseMtm::Body(). +The CBaseMtm::StoreBodyL() (CMsvStore &) and CBaseMtm::RestoreBodyL() (CMsvStore +&) functions encapsulate the retrieval and storage of this CRichText object +to a CMsvStore.

  • +
  • Address list functions

    The +format and storage of message addresses is MTM-specific. The CBaseMtm::AddresseeList() const, CBaseMtm::AddAddresseeL (const TDesC &), and CBaseMtm::RemoveAddressee (TInt) allow +clients to access address information in a generic way without having MTM-specific +knowledge.

  • +
  • MTM-specific client +functions

    MTM components can offer protocol-specific functionality +not provided by base class interface functions. MTM components define IDs +that correspond to each protocol-specific operation offered, and implement +the CBaseMtm::InvokeSyncFunctionL() and CBaseMtm::InvokeAsyncFunctionL() functions +to allow clients to access these operations by passing in the appropriate +ID. These functions are provided to allow the MTM component to offer both +synchronous and asynchronous functionality. Message client applications can +dynamically add user-interface features for these operations using CBaseMtmUiData::MtmSpecificFunctions().

  • +
  • Query function

    The +Client MTM QueryCapability() function is used to inquire +whether an MTM supports a given feature. The first argument is a UID defined +to correspond to a particular capability. The function returns a system error +code and the response (whether the MTM supports the queried capability) is +passed back through the second (by-reference)aResponse parameter. +This value can be an integer or a bit set, depending on the capability.

    The +UIDs for the different types of query are as follows:

    + + + +UID +Capability + + + + +

    KUidMsvMtmQueryMaxBodySize

    +

    Maximum message body size

    +
    + +

    KUidMtmQueryMaxTotalMsgSize

    +

    Maximum total size of message.

    +
    + +

    KUidMtmQuerySupportedBody

    +

    Character widths supported by message type. The returned value is +the sum of the appropriate values. The return type is either of KMtm7BitBody, +KMtm8BitBody, KMtm16BitBody, and KMtmBinaryBody)

    +
    + +

    KUidMtmQuerySupportAttachments

    +

    To check if the attachments are supported

    +
    + +

    KUidMtmQuerySupportSubject

    +

    Does the MTM message type have a subject field

    +
    + +

    KUidMtmQuerySupportsFolder

    +

    Does the MTM support folders

    +
    + +

    KUidMtmQueryOffLineAllowed

    +

    Off-line operation allowed

    +
    + +

    KUidMtmQueryCanSendMsg

    +

    Can send the message

    +
    + +

    KUidMtmQueryCanReceiveMsg

    +

    Can receive the message

    +
    + +

    KUidMtmQueryMaxRecipientCount

    +

    Maximum number of recipients (-1 indicates unlimited numbers).

    +
    + +

    KUidMtmQuerySendAsRequiresRenderedImage

    +

    When using the MTM in Send As, does a rendered image have to be +prepared.

    +
    + +

    KUidMtmQuerySendAsRenderingUid

    +

    Printer driver UID for rendering the fax image.

    +
    + +

    KUidMsvMtmQueryEditorUid

    +

    UID of default message editor.

    +
    + +

    KUidMsvQuerySupportsBioMsg

    +

    Does the MTM support BIO messages

    +
    + +

    KUidMsvQuerySupportsScheduling

    +

    Does the MTM support scheduled sending.

    +
    + +

    KUidMtmQuerySupportsRecipientType

    +

    Does the MTM support the use of recipient type.

    +
    + +

    KUidMtmQuerySendAsMessageSendSupport

    +

    Support for Sending messages using SendAs.

    If this is supported, +then the MTM supports sending messages created through the SendAs API.

    +
    + + +

    The following example is a snapshot of the Text MTM example. For +more implementation details, see Messaging +Text MTM example code.

    TInt CTextMtmClient::QueryCapability(TUid aCapability, TInt& aResponse) + { + TInt error = KErrNone; + switch (aCapability.iUid) + { + case KUidMtmQueryMaxBodySizeValue: + case KUidMtmQueryMaxTotalMsgSizeValue: + aResponse = KMaxTextMessageSize; + break; + case KUidMtmQuerySupportedBodyValue: + aResponse = KMtm8BitBody + KMtm7BitBody; + break; + case KUidMtmQueryOffLineAllowedValue: + case KUidMtmQueryCanReceiveMsgValue: + aResponse = ETrue; + break; + case KUidMtmQuerySupportAttachmentsValue: + default: + return KErrNotSupported; + } + return error; + } +
  • +

The CBaseMtm class provides the virtual functions +for overriding in derived classes.

+
Client-side +operations

Many Messaging tasks can take a long time to complete. +For example, sending all items from the Outbox or downloading a large number +of items from a POP3 server. In these situations, the use of active objects +to wait for the completion of the task is inadequate, since applications also +require to obtain progress information while the task is running (for example, +to update a progress dialog). To solve this problem, most asynchronous functions +in Messaging create a CMsvOperation object and return a +pointer to it, as well as taking a TRequestStatus& parameter. +The CMsvOperation class is derived from CActive and +is used to obtain progress information about a long-running task.

The +base class for all client-side Messaging operations is CMsvOperation. +The asynchronous methods in the CBaseMtm interface all +return a pointer to a CMsvOperation object. When you implement +an MTM, you will have to provide your own custom operations, derived from CMsvOperation, +and return those polymorphically from your implementations of the asynchronous +APIs.

Example

The forward operation of the Text MTM +is explained in the following example.

The forward operation is an +active object state machine that runs a series of asynchronous tasks one after +another and waits for each to complete before moving on to the next. After +the operation has been completed, an active object is notified through its TRequestStatus passed +into the operation at construction.

The forward operation is constructed +using standard two-phase construction. The NewL() function +takes two arguments of a TMsvId (source message and destination +folder) type, a CMsvSession reference, and the observer’s TRequestStatus, +which is notified on completion. The active object is constructed and added +to the scheduler, and then ConstructL() is called:

void CTxtMtmForwardOperation::ConstructL() + { + iObserverRequestStatus = KRequestPending; + SetActive(); + TRequestStatus* stat = &iStatus; + User::RequestComplete(stat, KErrNone); + } +

This has the effect of marking this stage of the operation +as complete and means that RunL() is called at the next +opportunity. This simplifies the state machine because it means that all states +and tasks are started in RunL() and not in ConstructL().

The RunL() function +starts each task and receives a notification when it completes. The current +task being executed is stored in iProgress and iState, +as are the errors and the ID of the new forwarded message, once complete. +The default state for iState on construction is EInit.

void CTxtMtmForwardOperation::RunL() + { + User::LeaveIfError(iStatus.Int()); + switch(iProgress.iState) + { + case TTxtMtmForwardOpProgress::EInit: + iProgress.iState = + TTxtMtmForwardOpProgress::ECreateMessage; + CreateMessageL(); + break; + + case TTxtMtmForwardOpProgress::ECreateMessage: + iProgress.iState = + TTxtMtmForwardOpProgress::EFormatBodyText; + FormatBodyTextL(); + break; + + case TTxtMtmForwardOpProgress::EFormatBodyText: + iProgress.iState = + TTxtMtmForwardOpProgress::EFinished; + + default: + break; + } + if(!IsActive()) + { + TRequestStatus* stat = &iObserverRequestStatus; + User::RequestComplete(stat, KErrNone); + } + } +

If the state is EInit, the RunL() changes +state to ECreateMessage and then calls CreateMessageL() to +start the process of creating a message asynchronously.

void CTxtMtmForwardOperation::CreateMessageL() + { +

The function constructs a CMsvEntry for +the source entry and then retrieves its index entry.

delete iMsvEntry; + iMsvEntry = NULL; + iMsvEntry = iMsvSession.GetEntryL(iSourceMessage); + + // Get the entry to be forwarded + TMsvEntry forwardEntry = iMsvEntry->Entry(); +

The context of iMsvEntry is changed to +the destination folder and an entry is created.

// Set the context to the destination folder + iMsvEntry->SetEntryL(iDestinationFolder); +

The index entry’s date is updated to reflect the current date.

// Create the forwarded index entry + forwardEntry.iDate.HomeTime(); + iMsvEntry->CreateL(forwardEntry); +

The iFinalMsgId member of the progress +is updated to reflect the newly created entry.

iProgress.iFinalMsgId = forwardEntry.Id(); + + // schedules the active object to complete so that this + // class's RunL method + // will be called by the active scheduler + SetActive(); +

The operation’s TRequestStatus is then flagged +to cause RunL().

TRequestStatus* stat = &iStatus; + User::RequestComplete(stat, KErrNone); + } +

When this happens, iProgress.iState is set +to ECreateMessage, so the following code is executed:

case TTxtMtmForwardOpProgress::ECreateMessage: + iProgress.iState = TTxtMtmForwardOpProgress::EFormatBodyText; + FormatBodyTextL(); + break;

The state is set to EFormatBodyText and +the FormatBodyTextL() function is called.

+void CTxtMtmForwardOperation::FormatBodyTextL() + { +

The function constructs a CParaFormatLayer, +a CCharFormatLayer, and a CRichText object. +These objects are required to store the body text of the forwarded message.

CParaFormatLayer* paraLayer = CParaFormatLayer::NewL(); + CleanupStack::PushL(paraLayer); + CCharFormatLayer* charLayer = CCharFormatLayer::NewL(); + CleanupStack::PushL(charLayer); + CRichText* body = CRichText::NewL(paraLayer, charLayer); + CleanupStack::PushL(body); +

Then the context of iMsvEntry is changed +to point at the source message and a read-only CMsvStore is +opened for that entry.

// Get the message store from the source entry + iMsvEntry->SetEntryL(iSourceMessage); + CMsvStore* readStore = iMsvEntry->ReadStoreL(); + CleanupStack::PushL(readStore);

The context of the iMsvEntry object +is changed to point at the newly created entry and a CMsvStore is +opened for that entry.

// Get the message store from the newly created destination + // entry + iMsvEntry->SetEntryL(iProgress.iFinalMsgId); + CMsvStore* writeStore = iMsvEntry->EditStoreL(); + CleanupStack::PushL(writeStore); + + // Get the body text from the source entry and write it + // to the destination entry, prepending the forward + // prefix + readStore->RestoreBodyTextL(*body); + body->InsertL(0, KTxtMtmFwdPrefix); + + // this method performs a commit for us + writeStore->StoreBodyTextL(*body); + + CleanupStack::PopAndDestroy(5, paraLayer); + + // schedules the active object to complete so that this + // class's RunL method + // will be called by the active scheduler + SetActive(); + TRequestStatus* stat = &iStatus; + User::RequestComplete(stat, KErrNone); + } +

The iProgress.iState is set to EFinished, +and because the object has not been activated the following conditional statement +evaluates true:

if(!IsActive()) + { + TRequestStatus* stat = &iObserverRequestStatus; + User::RequestComplete(stat, KErrNone); + } +

The observer active object’s TRequestStatus is +flagged to let it know that the operation is complete.

To return progress +from the operation, implement the ProgressL() and FinalProgress() functions. ProgressL() must +be used to return progress information on the operation during processing, +and FinalProgress() is guaranteed to return the status +of a completed operation. ProgressL() must be implemented +to leave with KErrNotReady if the operation is not in progress, +and FinalProgress() must panic if the operation is not +complete.

const TDesC8& CTxtMtmForwardOperation::ProgressL() + { + if (!IsActive()) + { + User::Leave(KErrNotReady); + } + iProgressBuf() = iProgress; + return iProgressBuf; + } + +const TDesC8& CTxtMtmForwardOperation::FinalProgress() + { + __ASSERT_ALWAYS(!IsActive(), User::Panic(KTxtCPanic, + ETxtcOperationIsActive)); + iProgressBuf() = iProgress; + return iProgressBuf; + }

The RunError() function must also be +implemented to get any leaves in RunL().

TInt CTxtMtmForwardOperation::RunError(TInt aError) + { + iProgress.iError = aError; + TRequestStatus* stat = &iObserverRequestStatus; + User::RequestComplete(stat, aError); + return KErrNone; + }
+
+MTM overview + +MTM Capabilities + +Writing a +Client MTM
\ No newline at end of file