diff -r 000000000000 -r 4e91876724a2 photosgallery/viewframework/commandhandlers/commandhandlerbase/src/glxmpxcommandcommandhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/photosgallery/viewframework/commandhandlers/commandhandlerbase/src/glxmpxcommandcommandhandler.cpp Thu Dec 17 08:45:44 2009 +0200 @@ -0,0 +1,666 @@ +/* +* Copyright (c) 2008-2009 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: Media List Command Handler +* +*/ + + + + +#include + +#include "glxmpxcommandcommandhandler.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for CGlxResourceUtilities + +/// @todo Move elsewhere +const TInt KGlxMaxNoteLength = 256; + +// ----------------------------------------------------------------------------- +// ConstructL +// ----------------------------------------------------------------------------- +// +EXPORT_C CGlxMpxCommandCommandHandler:: + CGlxMpxCommandCommandHandler(MGlxMediaListProvider* aMediaListProvider, TBool aHasToolbarItem) + : CGlxMediaListCommandHandler(aMediaListProvider, aHasToolbarItem) + { + iAppUi = static_cast< CAknAppUi* >( CCoeEnv::Static()->AppUi() ); + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CGlxMpxCommandCommandHandler::~CGlxMpxCommandCommandHandler() + { + // cancel command if running + if (iProgressComplete) + { +// MediaList().Cancel(); + } + + delete iProgressDialog; + + if ( iResourceOffset ) + { + CCoeEnv::Static()->DeleteResourceFile(iResourceOffset); + } + } + +// ----------------------------------------------------------------------------- +// DoExecuteL +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CGlxMpxCommandCommandHandler::DoExecuteL(TInt aCommandId, + MGlxMediaList& aList) + { + // reset progress complete flag + iProgressComplete = EFalse; + + // deriving class consumes command by default + TBool consume = ETrue; + TInt selectionCount = aList.SelectionCount(); + const TGlxMedia& focusedMedia = aList.Item(aList.FocusIndex()); + // show confirmation note + consume = ConfirmationNoteL(aCommandId, aList); + + // Check if the selected / focused file(s)s have been deleted from + // another application while the confirmation note is displayed + if (((selectionCount > 0) && (aList.SelectionCount() == 0)) || + ((selectionCount == 0) && + (focusedMedia.Id() != aList.Item(aList.FocusIndex()).Id()))) + { + // All the selected / focused item(s) have been deleted, + // do not allow the command to execute. + consume = EFalse; + } + + if ( consume ) + { + // get a command object from the deriving class. + // Allow deriving class modify the consume value, even without + // creating a commmand (in case it wants to filter out a command) + CMPXCommand* command = CreateCommandL(aCommandId, aList, consume); + + if (command) + { + CleanupStack::PushL(command); + + if ( CommandInfo(aCommandId).iStopAnimationForExecution ) + { + // Stop GIF animation + iAppUi->ProcessCommandL(EGlxCmdDisableAnimations); + iAnimationStopped = ETrue; + } + + // Add the pointer of this command handler as session id into the message + // This can be used to ensure that this object is the intended recipient + // of a message + command->SetTObjectValueL(KMPXCommandGeneralSessionId, + static_cast(this)); + + aList.AddMediaListObserverL(this); + + // @todo TRAP this? + aList.CommandL(*command); + + // raise progress note. Note will be closed when complete message received + ProgressNoteL(aCommandId); + + CleanupStack::PopAndDestroy(command); + } + } + + return consume; + } + +// ----------------------------------------------------------------------------- +// TryExitL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::TryExitL(TInt aErrorCode) + { + // any error will abort the command execution + if ( KErrNone != aErrorCode ) + { + // error received. Close progress note + DismissProgressNoteL(); + + // Remove medialist observer + RemoveMediaListObserver(); + + // handle error + HandleErrorL(aErrorCode); + } + else if (iProgressComplete) + { + // ask deriving class if it is ready to exit (i.e., to close progress note). + // (It may be waiting for another message, etc.) + if (OkToExit()) + { + // close progress note + DismissProgressNoteL(); + + // Remove medialist observer + RemoveMediaListObserver(); + + // show completion note + CompletionNoteL(); + } + } + } + + +// ----------------------------------------------------------------------------- +// Default implementation shows an error note +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleErrorL(TInt aErrorCode) + { + // show error note + GlxGeneralUiUtilities::ShowErrorNoteL(aErrorCode); + } + +// ----------------------------------------------------------------------------- +// Update progress +// ----------------------------------------------------------------------------- +// +TBool CGlxMpxCommandCommandHandler::UpdateProgressL(const CMPXMessage& aMessage, + TInt& aError) + { + TBool isComplete = EFalse; + + // should not receive any progress messages after progress is completed + __ASSERT_DEBUG(!iProgressComplete, Panic(EGlxPanicIllegalState)); + + /// @todo remove progress update error handling + TMPXAttribute currentCountAttr(KMPXMessageContentIdProgress, EMPXMessageProgressCurrentCount); + TMPXAttribute totalCountAttr(KMPXMessageContentIdProgress, EMPXMessageProgressTotalCount); + if ( ( KErrNone == aError ) && (aMessage.IsSupported(currentCountAttr)) + && (aMessage.IsSupported(totalCountAttr) ) ) + { + // get current and total count from the message + TInt currentValue = aMessage.ValueTObjectL(currentCountAttr); + TInt total= aMessage.ValueTObjectL(totalCountAttr); + + // update progress bar if not complete yet, otherwise remember completion + if ( currentValue < total ) + { + // Progress info construction may have failed, but command was issued before + if (iProgressInfo) + { + iProgressInfo->SetFinalValue(total); + iProgressInfo->SetAndDraw(currentValue); + } + } + else + { + isComplete = ETrue; + + if ( iAnimationStopped ) + { + // Restart animation + iAppUi->ProcessCommandL(EGlxCmdEnableAnimations); + iAnimationStopped = EFalse; + } + } + } + + return isComplete; + } + +// ----------------------------------------------------------------------------- +// Default implementation of advanced command handling does nothing +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::DoHandleCommandCompleteL(TAny* /*aSessionId*/, + CMPXCommand* /*aCommandResult*/, TInt /*aError*/, MGlxMediaList* /*aList*/) + { + } + + +// ----------------------------------------------------------------------------- +// Default implementation of advanced message handling does nothing +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CGlxMpxCommandCommandHandler::DoHandleMessageL(const CMPXMessage& /*aMessage*/, + MGlxMediaList& /*aList*/) + { + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// Default implementation DoHandleItemAddedL does not do anything +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::DoHandleItemAddedL(TInt /*aStartIndex*/, + TInt /*aEndIndex*/, MGlxMediaList* /*aList*/) + { + } + +// ----------------------------------------------------------------------------- +// Default implementation is always ready to exit +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CGlxMpxCommandCommandHandler::OkToExit() const + { + return ETrue; + } + +// ----------------------------------------------------------------------------- +// Show confirmation note +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CGlxMpxCommandCommandHandler::ConfirmationNoteL(TInt aCommandId, + MGlxMediaList& aMediaList) const + { + TInt selectionCount = aMediaList.SelectionCount(); + + // If media list is not empty, treat focused item as selected + // At this point can assume that the command was disabled + // if static items were not supported + if ( selectionCount == 0 && aMediaList.Count() > 0 ) + { + selectionCount = 1; + } + + // Show confirmation note + TBool confirmed = EFalse; + if ( selectionCount == 1 ) + { + confirmed = ConfirmationNoteSingleL(aCommandId, aMediaList); + } + else + { + confirmed = ConfirmationNoteMultipleL(aCommandId, aMediaList); + } + + return confirmed; + } + +// ----------------------------------------------------------------------------- +// So confirmation note if a single item is selected +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CGlxMpxCommandCommandHandler::ConfirmationNoteSingleL(TInt aCommandId, + MGlxMediaList& aMediaList) const + { + // if no confirmation note shown, assume command is confirmed + TBool confirmed = ETrue; + + // get confirmation note text for single selection + HBufC* noteText = ConfirmationTextL(aCommandId, EFalse); // EFalse for single selection + if ( noteText ) + { + CleanupStack::PushL(noteText); + + // Retrieve title string for selected item from the collection plugin + + // create fetch context + TGlxSelectionIterator iterator; + iterator.SetRange(1); + CGlxAttributeContext* attributeContext = new(ELeave) CGlxAttributeContext(&iterator); + CleanupStack::PushL(attributeContext); + attributeContext->AddAttributeL(KMPXMediaGeneralTitle); + + // add context to media list + aMediaList.AddContextL(attributeContext, KGlxFetchContextPriorityLow); + + // TGlxContextRemover will remove the context when it goes out of scope + // Used here to avoid a trap and still have safe cleanup + TGlxFetchContextRemover contextRemover(attributeContext, aMediaList); + // put to cleanupstack as cleanupstack is emptied before stack objects + // are deleted + CleanupClosePushL( contextRemover); + // retrieve title attribute + TInt err = GlxAttributeRetriever::RetrieveL(*attributeContext, aMediaList, EFalse); + // context off the list + CleanupStack::PopAndDestroy( &contextRemover ); + + if ( err == KErrNone ) + { + // use iterator to get the index of the right item + iterator.SetToFirst(&aMediaList); + const CGlxMedia* media = aMediaList.Item(iterator++).Properties(); + + // noteText has a place for a title string in it + const TDesC& itemName = media->ValueText(KMPXMediaGeneralTitle); + + TBuf text; + StringLoader::Format(text, *noteText, -1, itemName); + + // show popup + confirmed = GlxGeneralUiUtilities::ConfirmQueryL(R_GLX_QUERY_YES_NO, text); + } + // (else) If error, assume confirmed anyway + + CleanupStack::PopAndDestroy(attributeContext); + CleanupStack::PopAndDestroy(noteText); + } + return confirmed; + } + +// ----------------------------------------------------------------------------- +// Confirmation note if multiple items are selected +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CGlxMpxCommandCommandHandler::ConfirmationNoteMultipleL(TInt aCommandId, + MGlxMediaList& aMediaList) const + { + // if no confirmation note shown, assume command is confirmed + TBool confirmed = ETrue; + + // get confirmation note text for multiselection + HBufC* noteText = ConfirmationTextL(aCommandId, ETrue); // ETrue for Multiselection + if ( noteText ) + { + CleanupStack::PushL(noteText); + + // string has a place for number in it, and that number should be populated with selected + // item count + TInt count = aMediaList.SelectionCount(); + + TBuf text; + GlxGeneralUiUtilities::FormatString(text, *noteText, -1, count, ETrue); + + // show popup + confirmed = GlxGeneralUiUtilities::ConfirmQueryL(R_GLX_QUERY_YES_NO, text); + + CleanupStack::PopAndDestroy(noteText); + } + return confirmed; + } + +// ----------------------------------------------------------------------------- +// Default implementation returns null, and no confirmation note will be shown +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC* CGlxMpxCommandCommandHandler::ConfirmationTextL(TInt /*aCommandId*/, + TBool /*aMultiSelection*/) const + { + return NULL; + } + +// ----------------------------------------------------------------------------- +// Return default progress string +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC* CGlxMpxCommandCommandHandler::ProgressTextL(TInt /*aCommandId*/) const + { + // Lazy construction for resource file + if (iResourceOffset == 0) + { + // Load resource file + TParse parse; + parse.Set(KGlxUiUtilitiesResource, &KDC_APP_RESOURCE_DIR, NULL); + TFileName resourceFile; + resourceFile.Append(parse.FullName()); + CGlxResourceUtilities::GetResourceFilenameL(resourceFile); + + // Store resource offset as member variable, so don't have to trap the + // leaving calls here + iResourceOffset = CCoeEnv::Static()->AddResourceFileL(resourceFile); + } + + // get progress note string + return StringLoader::LoadL( R_GLX_PROGRESS_GENERAL ); + } + +// ----------------------------------------------------------------------------- +// Default implementation returns null, and no completion note will be shown +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC* CGlxMpxCommandCommandHandler::CompletionTextL() const + { + return NULL; + } + +// ----------------------------------------------------------------------------- +// ProgressNoteL +// ----------------------------------------------------------------------------- +// +void CGlxMpxCommandCommandHandler::ProgressNoteL(TInt aCommandId) + { + //MGlxMediaList& mediaList = MediaList(); + + // get progress note + HBufC* progressText = ProgressTextL(aCommandId); + __ASSERT_DEBUG(progressText, Panic(EGlxPanicNullDescriptor)); + CleanupStack::PushL(progressText); + // construct progress dialog + iProgressDialog = new(ELeave)CAknProgressDialog( + (REINTERPRET_CAST(CEikDialog**,&iProgressDialog))); + iProgressDialog->PrepareLC(R_GLX_PROGRESS_NOTE); + iProgressDialog->SetTextL(*progressText); + iProgressDialog->SetCallback(this); + + // pick up progress info so that progress notification can be later updated + iProgressInfo = iProgressDialog->GetProgressInfoL(); + + // launch the note + iProgressDialog->RunLD(); + CleanupStack::PopAndDestroy(progressText); + } + +// ----------------------------------------------------------------------------- +// DismissProgressNoteL +// ----------------------------------------------------------------------------- +// +void CGlxMpxCommandCommandHandler::DismissProgressNoteL() + { + // Close the progress note, if displayed + if (iProgressDialog) + { + iProgressDialog->ProcessFinishedL(); + iProgressDialog = NULL; + iProgressInfo = NULL; + } + } + +// ----------------------------------------------------------------------------- +// Remove MediaList Observer +// ----------------------------------------------------------------------------- +// +void CGlxMpxCommandCommandHandler::RemoveMediaListObserver() + { + MGlxMediaList& mediaList = MediaList(); + mediaList.RemoveMediaListObserver(this); + } + +// ----------------------------------------------------------------------------- +// Show a completion note +// ----------------------------------------------------------------------------- +// +void CGlxMpxCommandCommandHandler::CompletionNoteL() const + { + // Get completion note text + HBufC* noteText = CompletionTextL(); + if ( noteText ) + { + CleanupStack::PushL(noteText); + GlxGeneralUiUtilities::ShowConfirmationNoteL(*noteText, ETrue); + CleanupStack::PopAndDestroy(noteText); + } + } + +// ----------------------------------------------------------------------------- +// HandleItemAddedL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleItemAddedL(TInt /*aStartIndex*/, TInt /*aEndIndex*/, MGlxMediaList* /*aList*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// HandleMediaL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleMediaL(TInt /*aListIndex*/, MGlxMediaList* /*aList*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// HandleItemRemovedL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleItemRemovedL(TInt /*aStartIndex*/, TInt /*aEndIndex*/, MGlxMediaList* /*aList*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// HandleItemModifiedL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleItemModifiedL(const RArray& /*aItemIndexes*/, + MGlxMediaList* /*aList*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// HandleAttributesAvailableL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleAttributesAvailableL(TInt /*aItemIndex*/, + const RArray& /*aAttributes*/, MGlxMediaList* /*aList*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// HandleFocusChangedL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleFocusChangedL(NGlxListDefs::TFocusChangeType /*aType*/, + TInt /*aNewIndex*/, TInt /*aOldIndex*/, MGlxMediaList* /*aList*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// HandleItemSelectedL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleItemSelectedL(TInt /*aIndex*/, + TBool /*aSelected*/, MGlxMediaList* /*aList*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// HandleMessageL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleMessageL(const CMPXMessage& aMessage, + MGlxMediaList* aList) + { + if ((aMessage.IsSupported(KMPXMessageGeneralId) && + (aMessage.IsSupported(KMPXCommandGeneralSessionId)))) + { + TInt msgId = aMessage.ValueTObjectL(KMPXMessageGeneralId); + TAny* sessionId = aMessage.ValueTObjectL(KMPXCommandGeneralSessionId); + + TInt error = KErrNone; + // Check if this is a progress message and intended for this object + if ( KMPXMessageContentIdProgress == msgId && static_cast(this) == sessionId ) + { + // Update progress note + iProgressComplete = UpdateProgressL(aMessage, error); + } + else + { + // This is not a progress message - let deriving class handle + error = DoHandleMessageL(aMessage, *aList); + } + + // Check if ready to exit, i.e., to close progress note, and allow user + // to select another menu option + TryExitL(error); + } + } + +// ----------------------------------------------------------------------------- +// HandleMessageL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::HandleCommandCompleteL(TAny* aSessionId, + CMPXCommand* aCommandResult, TInt aError, MGlxMediaList* aList) + { + // Unmark all medialist items. Exit Multiple marking mode upon command completion + iAppUi->ProcessCommandL(EGlxCmdEndMultipleMarking); + + ///@todo Enforce a single command request at a time on the media list. + DoHandleCommandCompleteL(aSessionId, aCommandResult, aError, aList); + iProgressComplete = ETrue; + TryExitL(aError); + } + +// ----------------------------------------------------------------------------- +// DialogDismissedL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::DialogDismissedL(TInt /*aButtonId*/) + { + if (!iProgressComplete) + { + // Remove as media list observer + MGlxMediaList& mediaList = MediaList(); + mediaList.CancelCommand(); + mediaList.RemoveMediaListObserver(this); + } + } + +//----------------------------------------------------------------------------- +// DoActivateL +//----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::DoActivateL(TInt /*aViewId*/) + { + // Do nothing + } + +// ----------------------------------------------------------------------------- +// Deactivate - Deactivate this command handler +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGlxMpxCommandCommandHandler::Deactivate() + { + // Close the progress note, if displayed + if (iProgressDialog) + { + TRAP_IGNORE(DismissProgressNoteL()); + } + }