ipsservices/nmipssettings/src/nmipssettingsdeletemailboxop.cpp
author hgs
Thu, 14 Oct 2010 17:33:43 +0300
changeset 76 38bf5461e270
permissions -rw-r--r--
201041

/*
* Copyright (c) 2010 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:
*
*/
#include <msvapi.h>
#include <msvids.h>

#include <QTimer>
#include <QServiceManager>
#include <QServiceFilter>
#include <QServiceInterfaceDescriptor>

#include <HbMessageBox>
#include <HbProgressDialog>
#include <HbAction>

#include "nmipssettingsdeletemailboxop.h"
#include "nmipssettingsmanagerbase.h"

/// CONSTANTS

/// How many times the delete is attempted before giving up.
const int KDeleteRetryCount = 3;
/// How long will the operation wait (ms) for the disconnect event to arrive before timing out
const int KDisconnectTimeout = 2500;
/// How long will the operation wait (ms) before attempting the delete again if error happened.
const int KRetryDelay = 250;


/*!
    \class CMailboxDisconnectWait
    \brief Symbian helper class for mailbox delete operation. Used for listening disconnect events
           from messaging server.

*/
class CMailboxDisconnectWait : public CBase, public MMsvSessionObserver
{
public:
    static CMailboxDisconnectWait* NewL(
        NmIpsSettingsDeleteMailboxOp& aDeleteOp, const TMsvId& aMailboxId );
    ~CMailboxDisconnectWait();

    TBool IsConnected();
    
public: // from MMsvSessionObserver
    void HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3);

private:
    CMailboxDisconnectWait( NmIpsSettingsDeleteMailboxOp& aDeleteOp, const TMsvId& aMailboxId );

private: // data
    /// Own. Messaging server session
    CMsvSession* iMsvSession;
    /// Mailbox ID that is observed
    TMsvId iMailboxId;
    /// Delete operation
    NmIpsSettingsDeleteMailboxOp& iDeleteOp;
};

/*!
    Constructor of CMailboxDisconnectWait.
*/
CMailboxDisconnectWait* CMailboxDisconnectWait::NewL( 
    NmIpsSettingsDeleteMailboxOp& aDeleteOp,
    const TMsvId& aMailboxId )
{
    CMailboxDisconnectWait* self = new(ELeave) CMailboxDisconnectWait( aDeleteOp, aMailboxId );
    CleanupStack::PushL( self );
    self->iMsvSession = CMsvSession::OpenSyncL( *self );
    CleanupStack::Pop( self );
    return self;
}

/*!
    Constructor of CMailboxDisconnectWait.
*/
CMailboxDisconnectWait::CMailboxDisconnectWait( 
    NmIpsSettingsDeleteMailboxOp& aDeleteOp, const TMsvId& aMailboxId ) : 
    iMailboxId( aMailboxId ),
    iDeleteOp( aDeleteOp )
{
}

/*!
    Destructor of CMailboxDisconnectWait.
*/
CMailboxDisconnectWait::~CMailboxDisconnectWait()
{
    delete iMsvSession;
}

/*!
    Check if observed mailbox is connected or not
*/
TBool CMailboxDisconnectWait::IsConnected()
{
    TBool connected = EFalse;
    TMsvEntry entry;
    TMsvId id;
    if( iMsvSession->GetEntry( iMailboxId, id, entry ) == KErrNone )
        {
        connected = entry.Connected();
        }
    return connected;
}

/*!
    Event handler of Messaging server events
*/
void CMailboxDisconnectWait::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* /*aArg3*/)
{
    // Entry changed event is received when online/offline state has changed
    if( EMsvEntriesChanged == aEvent )
        {
        // mailboxes are only on root level, so check the parent
        TMsvId parent = *static_cast<TMsvId*>(aArg2);
        if( parent == KMsvRootIndexEntryId )
            {
            // find the mailbox we're observing
            CMsvEntrySelection* selection = static_cast<CMsvEntrySelection*>(aArg1);
            TInt count = selection->Count();
            for( TInt i = 0; i < count; ++i )
                {
                if( (*selection)[i] == iMailboxId )
                    {
                    // if mailbox is not connected -> report to observer
                    TMsvEntry entry;
                    TMsvId id;
                    TInt err = iMsvSession->GetEntry( iMailboxId, id, entry );
                    if( !err && !entry.Connected() )
                        {
                        TInt err; // error code ignored
                        QT_TRYCATCH_ERROR( err, iDeleteOp.mailboxDisconnected() );
                        Q_UNUSED(err); // remove compile warning
                        }
                    }
                }
            }
        }
}


/*!
    \class NmIpsSettingsDeleteMailboxOp
    \brief Operation that handles the deletion of mailbox

*/

// ======== MEMBER FUNCTIONS ========

/*!
    Constructor of NmIpsSettingsDeleteMailboxOp.
*/
NmIpsSettingsDeleteMailboxOp::NmIpsSettingsDeleteMailboxOp(NmIpsSettingsManagerBase &settingsManager) :
    mDisconnectWait(NULL),
    mSettingsManager(settingsManager),
    mDeleteConfirmationDlg(NULL),
    mDeleteProgressDlg(NULL),
    mRetryCount(KDeleteRetryCount),
    mError(0)
{
    connect( this, SIGNAL(stateChanged()), this, SLOT(processState()), Qt::QueuedConnection );
}

/*!
    Destructor of NmIpsSettingsDeleteMailboxOp.
*/
NmIpsSettingsDeleteMailboxOp::~NmIpsSettingsDeleteMailboxOp()
{
    delete mDeleteConfirmationDlg;
    delete mDeleteProgressDlg;
    delete mDisconnectWait;
}

/*!
    Starts the operation
*/
void NmIpsSettingsDeleteMailboxOp::startOperation()
{
    // reset state
    mRetryCount = KDeleteRetryCount;
    mResult = DeleteMbResultSuccess;
    mError = 0;
    
    delete mDisconnectWait;
    mDisconnectWait = NULL;
    TRAPD( err, mDisconnectWait = CMailboxDisconnectWait::NewL( 
        *this, mSettingsManager.mailboxId().id32() ) );

    if(!err) {
        changeState(StateConfirmation);
    } else {
        // failed
        complete(DeleteMbResultFailure, err);
    }
}

/*!
    Observer method to get notifications when the handled mailbox has disconnected
*/
void NmIpsSettingsDeleteMailboxOp::mailboxDisconnected()
{
    if( mState == StateDisconnect )
        {
        changeState(StateDelete);
        }
}

/*!
    Notification method that is called when user has responded to confirmation query
*/
void NmIpsSettingsDeleteMailboxOp::handleConfimationDlg(HbAction *action)
{
    if (action == mDeleteConfirmationDlg->actions().at(0)) {
        changeState(StateDisconnect);
    } else {
        complete(DeleteMbResultCanceled, 0);
    }
}

/*!
    Notification method that is called when timeout has occured while waiting for disconnect event
*/
void NmIpsSettingsDeleteMailboxOp::handleDisconnectTimeout()
{
    if( mState == StateDisconnect )
        {
        changeState(StateDelete);
        }
}

/*!
    Operation's state machine. Handles states.
*/
void NmIpsSettingsDeleteMailboxOp::processState()
{
    switch( mState ) {
    case StateConfirmation: {
        // Ask user whether to delete or not
        if(!mDeleteConfirmationDlg) {
            mDeleteConfirmationDlg =
                new HbMessageBox(HbMessageBox::MessageTypeQuestion);
            mDeleteConfirmationDlg->setText(
                hbTrId("txt_mail_dialog_do_you_want_to_delete_the_mailbox"));
            mDeleteConfirmationDlg->setTimeout(HbMessageBox::NoTimeout);
            mDeleteConfirmationDlg->setStandardButtons(HbMessageBox::Yes | HbMessageBox::No);
        }
        mDeleteConfirmationDlg->open(this, SLOT(handleConfimationDlg(HbAction *)));
        break;
    }
    
    case StateDisconnect: {
        // Disconnect mailbox
        emit goOffline(mSettingsManager.mailboxId());

        // Display the progress note during rest of the operation
        if( !mDeleteProgressDlg ) {
            mDeleteProgressDlg = new HbProgressDialog(HbProgressDialog::WaitDialog);
            mDeleteProgressDlg->removeAction( mDeleteProgressDlg->actions().at(0));
            mDeleteProgressDlg->setText(hbTrId("txt_common_info_deleting"));
        }
        mDeleteProgressDlg->delayedShow();

        if( mDisconnectWait->IsConnected() ) {
            // connected -> wait for disconnect or timeout
            QTimer::singleShot(KDisconnectTimeout, this, SLOT(handleDisconnectTimeout()));
        } else {
            // not connected -> delete mailbox immediately
            changeState( StateDelete );
        }
        break;
    }
    
    case StateDelete: {
        // delete mailbox
        int error = mSettingsManager.deleteMailbox();
        if( !error ) {
            changeState(StateUnregisterMailbox);

        } else if( mRetryCount-- ) {
            // attempt again after small delay
            QTimer::singleShot(KRetryDelay, this, SLOT(processState()));
        
        } else {
            // enough failures. give up
            complete(DeleteMbResultFailure, error);
        }
        break;
    }
    
    case StateUnregisterMailbox: {
        // Unregister mailbox from application library
        QtMobility::QServiceManager manager;
        QtMobility::QServiceFilter filter("com.nokia.symbian.IEmailRegisterAccount");
        QList<QtMobility::QServiceInterfaceDescriptor> interfaces = manager.findInterfaces(filter);
        QObject *registerInterface = NULL;
        if (!interfaces.isEmpty()) {
            registerInterface = manager.loadInterface(interfaces.first());
        }

        if (registerInterface) {
            quint64 mailboxId(mSettingsManager.mailboxId().id());
            // Try to remove the mailbox from the App Library.
            (void)QMetaObject::invokeMethod(registerInterface,
                "unregisterMailbox", Q_ARG(quint64, mailboxId));
            }
        
        // All done -> complete
        complete(DeleteMbResultSuccess, 0);
        break;
    }
    
    case StateDone: // fall through
    default: {
        // Hide the progress note
        if( mDeleteProgressDlg ) {
            mDeleteProgressDlg->close();
        }
        emit operationComplete(mResult, mError);
        break;
    }
    }
}

/*!
    Changes the operation state
*/
void NmIpsSettingsDeleteMailboxOp::changeState(DeleteOpStates nextState)
{
    mState = nextState;
    emit stateChanged();
}

/*!
    Completes the operation by setting the result values and changing the state to [done]
*/
void NmIpsSettingsDeleteMailboxOp::complete(int result, int error)
{
    mError = error;
    mResult = result;
    mState = StateDone;
    emit stateChanged();
}