--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/viewframework/commandhandlers/commoncommandhandlers/src/glxcommandhandlernewmedia.cpp Thu Dec 17 08:45:44 2009 +0200
@@ -0,0 +1,496 @@
+/*
+* 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: Delete command handler
+*
+*/
+
+
+
+
+/**
+ * @internal reviewed 06/06/2007 by Dave Schofield
+ */
+
+#include "glxcommandhandlernewmedia.h"
+
+#include <AknUtils.h>
+#include <badesca.h>
+#include <bautils.h>
+#include <glxattributecontext.h>
+#include <glxattributeretriever.h>
+#include <glxcollectiongeneraldefs.h>
+#include <glxcommandfactory.h>
+#include <glxcommandhandlers.hrh>
+#include <glxfetchcontextremover.h>
+#include <glxgeneraluiutilities.h>
+#include <glxpanic.h>
+#include <glxresourceutilities.h> // for CGlxResourceUtilities
+#include <glxsetappstate.h>
+#include <glxtextentrypopup.h>
+#include <glxuistd.h>
+#include <glxuiutilities.rsg>
+#include <mglxmedialist.h>
+#include <mpxcollectionpath.h>
+#include <mpxcommonframeworkdefs.h>
+#include <StringLoader.h>
+
+#include <data_caging_path_literals.hrh>
+#include <glxuiutilities.rsg>
+
+const TInt KMaxMediaPopupTitleLength = 0x28; // Accepts only 40 characters
+const TInt KMaxNewMediaItemTitleLength = 0x28; // Accepts only 40 characters
+const TInt KMaxNumberLength = 10;
+
+_LIT(KOpenBracket, "(");
+_LIT(KCloseBracket, ")");
+_LIT(KFileNameFormatString, "(%+02u)");
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CGlxCommandHandlerNewMedia* CGlxCommandHandlerNewMedia::NewL(MGlxMediaListProvider* aMediaListProvider)
+ {
+ CGlxCommandHandlerNewMedia* self = new (ELeave) CGlxCommandHandlerNewMedia(aMediaListProvider);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CGlxCommandHandlerNewMedia::CGlxCommandHandlerNewMedia(MGlxMediaListProvider* aMediaListProvider)
+ : CGlxMpxCommandCommandHandler(aMediaListProvider)
+ {
+ // Don't do anything.
+ }
+
+// -----------------------------------------------------------------------------
+// CGlxCommandHandlerNewMedia::DoHandleCommandCompleteL
+// -----------------------------------------------------------------------------
+//
+void CGlxCommandHandlerNewMedia::DoHandleCommandCompleteL(TAny* /*aSessionId*/, CMPXCommand* aCommandResult,
+ TInt aError, MGlxMediaList* /*aList*/)
+ {
+ if (aError == KErrNone && aCommandResult && aCommandResult->IsSupported(KMPXMediaGeneralId))
+ {
+ iNewMediaId = TGlxMediaId(aCommandResult->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
+ iOkToExit = EFalse; // wait for media id to be added to the list
+ // (unless we are using iSchedulerWait)
+ }
+
+ if (iSchedulerWait && aError != KErrAlreadyExists )
+ {
+ // if iSchedulerWait exists then we know the command is being executed from
+ // the ExecuteLD() method.
+ iNewMediaCreationError = aError;
+ iSchedulerWait->AsyncStop();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CGlxCommandHandlerNewMedia::OkToExit
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CGlxCommandHandlerNewMedia::OkToExit() const
+ {
+ return iOkToExit;
+ }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CGlxCommandHandlerNewMedia::ConstructL()
+ {
+ iFileNameAlreadyExists = EFalse ;
+ // Load resource file
+ TParse parse;
+ parse.Set(KGlxUiUtilitiesResource, &KDC_APP_RESOURCE_DIR, NULL);
+ TFileName resourceFile;
+ resourceFile.Append(parse.FullName());
+ CGlxResourceUtilities::GetResourceFilenameL(resourceFile);
+ iResourceOffset = CCoeEnv::Static()->AddResourceFileL(resourceFile);
+
+ iAsyncFocuser = new (ELeave) CGlxAsyncFocuser(this);
+ // Add supported command
+ TCommandInfo info(EGlxCmdAddMedia);
+ // Filter out static items
+ AddCommandL(info);
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CGlxCommandHandlerNewMedia::~CGlxCommandHandlerNewMedia()
+ {
+ if ( iResourceOffset )
+ {
+ CCoeEnv::Static()->DeleteResourceFile(iResourceOffset);
+ }
+
+ delete iSchedulerWait;
+ delete iAsyncFocuser;
+ delete iNewMediaItemTitle;
+ }
+
+// ---------------------------------------------------------------------------
+// CGlxCommandHandlerNewMedia::ExecuteLD()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CGlxCommandHandlerNewMedia::ExecuteLD(TGlxMediaId& aNewMediaId)
+ {
+ CleanupStack::PushL(this);
+ iSchedulerWait = new (ELeave) CActiveSchedulerWait();
+
+ CGlxMpxCommandCommandHandler::ExecuteL( EGlxCmdAddMedia );
+ if (iNewMediaCreationError == KErrNone)
+ {
+ // The user pressed OK on the dialog. We need to wait for DoHandleCommandComplete()
+ iSchedulerWait->Start();
+
+ if (iNewMediaCreationError == KErrNone)
+ {
+ aNewMediaId = iNewMediaId;
+ }
+ }
+
+ TInt error = iNewMediaCreationError;
+ CleanupStack::PopAndDestroy(this);
+ return error;
+ }
+
+// ---------------------------------------------------------------------------
+// Create an add to container command
+// ---------------------------------------------------------------------------
+//
+CMPXCommand* CGlxCommandHandlerNewMedia::CreateCommandL(TInt /*aCommandId*/,
+ MGlxMediaList& aMediaList, TBool& /*aConsume*/) const
+ {
+ iOkToExit = ETrue;
+
+ CMPXCollectionPath* path = aMediaList.PathLC( NGlxListDefs::EPathParent );
+ CMPXCommand* command = NULL;
+
+ TBuf <KMaxNewMediaItemTitleLength> defaultNewMediaItemTitle;
+
+ TitlesL(TGlxMediaId(path->Id(0)), defaultNewMediaItemTitle);
+
+ HBufC* mediaPopupTitle = StringLoader::LoadLC(R_GLX_PROMPT_NAME);
+ if(iFileNameAlreadyExists)
+ {
+ iFileNameAlreadyExists = EFalse ;
+ }
+ else
+ {
+ delete iNewMediaItemTitle;
+ iNewMediaItemTitle = NULL;
+ iNewMediaItemTitle = GenerateNewMediaItemTitleL(defaultNewMediaItemTitle, aMediaList);
+ }
+ TPtr newMediaItemTitleDes = iNewMediaItemTitle->Des();
+
+ CGlxTextEntryPopup* dialog = CGlxTextEntryPopup::NewL(*mediaPopupTitle, newMediaItemTitleDes);
+
+
+ if(dialog->ExecuteLD() == EEikBidOk)
+ {
+ command = TGlxCommandFactory::AddContainerCommandLC(*iNewMediaItemTitle, path->Id(0));
+ CleanupStack::Pop(command);
+ }
+ else
+ {
+ iNewMediaCreationError = KErrCancel;
+ }
+
+ CleanupStack::PopAndDestroy(mediaPopupTitle);
+ CleanupStack::PopAndDestroy(path);
+ return command;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CGlxCommandHandlerNewMedia::HandleErrorL
+// ---------------------------------------------------------------------------
+//
+void CGlxCommandHandlerNewMedia::HandleErrorL(TInt aError)
+ {
+ if (aError == KErrAlreadyExists && iNewMediaItemTitle)
+ {
+ HBufC* info = StringLoader::LoadLC(R_GLX_NAME_ALREADY_USED, *iNewMediaItemTitle);
+ GlxGeneralUiUtilities::ShowInfoNoteL(*info, ETrue);
+ CleanupStack::PopAndDestroy(info);
+ iFileNameAlreadyExists = ETrue ;
+ // As the new Item name already existing , re-execute the command to show entry pop-up
+ CGlxMpxCommandCommandHandler::ExecuteL( EGlxCmdAddMedia );
+ if (iSchedulerWait && iNewMediaCreationError == KErrCancel )
+ {
+ // if iSchedulerWait exists then we know the command is being executed from
+ // the ExecuteLD() method.
+ // Stop the schedulerwait loop if dialog is cancelled after starting the schedulerwait loop
+ iSchedulerWait->AsyncStop();
+ }
+ }
+ else
+ {
+ // Use default error handler
+ CGlxMpxCommandCommandHandler::HandleErrorL(aError);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// BypassFiltersForExecute
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CGlxCommandHandlerNewMedia::BypassFiltersForExecute() const
+ {
+ // if iSchedulerWait exists then we know the command is being executed from
+ // the ExecuteLD() method and filtering is not required.
+ return iSchedulerWait != NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// TitlesL fetches the 'media popup title' and 'default new media item title'
+// from the collection.
+// ---------------------------------------------------------------------------
+//
+
+void CGlxCommandHandlerNewMedia::TitlesL(const TGlxMediaId aCollectionId, TDes& aDefaultNewMediaItemTitle) const
+ {
+ CMPXCollectionPath* path = CMPXCollectionPath::NewL();
+ CleanupStack::PushL(path);
+ MGlxMediaList* rootList = MGlxMediaList::InstanceL(*path);
+ CleanupClosePushL(*rootList);
+
+ TGlxSpecificIdIterator iter(KGlxIdSpaceIdRoot, aCollectionId);
+ CGlxAttributeContext* attributeContext = new (ELeave) CGlxAttributeContext(&iter);
+ CleanupStack::PushL(attributeContext);
+ attributeContext->AddAttributeL(KGlxMediaCollectionPluginSpecificDefaultMediaTitle);
+ rootList->AddContextL(attributeContext, KGlxFetchContextPriorityBlocking);
+
+ TGlxFetchContextRemover contextRemover(attributeContext, *rootList);
+ // put to cleanupstack as cleanupstack is emptied before stack objects
+ // are deleted
+ CleanupClosePushL( contextRemover );
+ User::LeaveIfError(GlxAttributeRetriever::RetrieveL(*attributeContext, *rootList, ETrue));
+ // context off the list
+ CleanupStack::PopAndDestroy( &contextRemover );
+
+ TInt index = rootList->Index(KGlxIdSpaceIdRoot, aCollectionId);
+
+ __ASSERT_DEBUG(index != KErrNotFound, Panic(EGlxPanicRequiredItemNotFound));
+
+ TGlxMedia item = rootList->Item(index);
+
+ const CGlxMedia* media = item.Properties();
+ if (media)
+ {
+ aDefaultNewMediaItemTitle.Copy(media->ValueText(KGlxMediaCollectionPluginSpecificDefaultMediaTitle).Left(KMaxMediaPopupTitleLength));
+ }
+
+ CleanupStack::PopAndDestroy(attributeContext);
+ CleanupStack::PopAndDestroy(rootList);
+ CleanupStack::PopAndDestroy(path);
+ }
+
+// ---------------------------------------------------------------------------
+// TitlesL fetches the 'media popup title' and 'default new media item title'
+// from the collection.
+// ---------------------------------------------------------------------------
+//
+HBufC* CGlxCommandHandlerNewMedia::GenerateNewMediaItemTitleL
+ (const TDesC& aDefaultNewMediaItemTitle, MGlxMediaList& aList) const
+ {
+ TGlxSequentialIterator iter;
+ CGlxAttributeContext* attributeContext = new (ELeave) CGlxAttributeContext(&iter);
+ CleanupStack::PushL(attributeContext);
+ attributeContext->AddAttributeL(KMPXMediaGeneralTitle);
+ aList.AddContextL(attributeContext, KGlxFetchContextPriorityBlocking);
+ TGlxFetchContextRemover contextRemover(attributeContext, aList);
+ // put to cleanupstack as cleanupstack is emptied before stack objects
+ // are deleted
+ CleanupClosePushL( contextRemover );
+ User::LeaveIfError(GlxAttributeRetriever::RetrieveL(*attributeContext, aList, ETrue));
+ // context off the list
+ CleanupStack::PopAndDestroy( &contextRemover );
+ CleanupStack::PopAndDestroy(attributeContext);
+
+ RArray<TInt> numbers;
+ CleanupClosePushL(numbers);
+
+ TInt count = aList.Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ TGlxMedia item = aList.Item(i);
+ const CGlxMedia* media = item.Properties();
+ if (media)
+ {
+ const TDesC& title = media->ValueText(KMPXMediaGeneralTitle);
+
+ TInt length = aDefaultNewMediaItemTitle.Length();
+ if (title.Left(length).Compare(aDefaultNewMediaItemTitle) == 0)
+ {
+ if (length == title.Length())
+ {
+ numbers.InsertInOrder(0); // special case
+ }
+ else if(title.Length() > length + KOpenBracket().Length() + KCloseBracket().Length())
+ {
+ TInt pos = length;
+ length = KOpenBracket().Length();
+
+ if (title.Mid(pos, length).Compare(KOpenBracket) == 0 &&
+ title.Right(KCloseBracket().Length()).Compare(KCloseBracket) == 0)
+ {
+ pos += length;
+ length = title.Length() - pos - KCloseBracket().Length();
+ if (length > 0)
+ {
+ TLex lex = title.Mid(pos, length);
+ TInt val = 0;
+ if (lex.Val(val) == KErrNone)
+ {
+ numbers.InsertInOrder(val);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ TInt nextNumber = 0;
+ count = numbers.Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ if (numbers[i] == nextNumber)
+ {
+ nextNumber++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&numbers);
+
+ TInt defaultTitleLength = aDefaultNewMediaItemTitle.Length() + KFileNameFormatString().Length() + KCloseBracket().Length() + KMaxNumberLength;
+ // If the default title length is bigger than KMaxMediaPopupTitleLength, make sure we allocate enough space for it.
+ TInt titleLength = defaultTitleLength > KMaxMediaPopupTitleLength ? defaultTitleLength : KMaxMediaPopupTitleLength;
+ HBufC* newMediaItemTitle = HBufC::NewL(titleLength);
+ TPtr newMediaItemTitleDes = newMediaItemTitle->Des();
+ newMediaItemTitleDes.Append(aDefaultNewMediaItemTitle);
+
+ if (nextNumber > 0)
+ {
+ newMediaItemTitleDes.AppendFormat(KFileNameFormatString,nextNumber);
+ }
+ else
+ {
+ // 0 is a special case, return "New Media", not "New Media (0)"
+ }
+
+ return newMediaItemTitle;
+ }
+
+// -----------------------------------------------------------------------------
+// SetFocusL()
+// -----------------------------------------------------------------------------
+//
+void CGlxCommandHandlerNewMedia::SetFocusL(TInt aIndex)
+ {
+ iOkToExit = ETrue;
+ MediaList().SetFocusL(NGlxListDefs::EAbsolute, aIndex);
+ TryExitL(KErrNone);
+ }
+
+// -----------------------------------------------------------------------------
+// HandleItemAddedL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CGlxCommandHandlerNewMedia::HandleItemAddedL(TInt aStartIndex, TInt aEndIndex, MGlxMediaList* aList)
+ {
+ if(aList == &MediaList() && iNewMediaId != KGlxCollectionRootId)
+ {
+ for (TInt i = aStartIndex; i <= aEndIndex; i++)
+ {
+ if (aList->Item(i).Id() == iNewMediaId)
+ {
+ iAsyncFocuser->SetFocus(i); // calls CGlxCommandHandlerNewMedia::SetFocusL asynchronously
+ break;
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CGlxCommandHandlerNewMedia::CGlxAsyncFocuser::
+ CGlxAsyncFocuser(CGlxCommandHandlerNewMedia* aGlxCommandHandlerNewMedia)
+ : CActive(KMaxTInt), iGlxCommandHandlerNewMedia(aGlxCommandHandlerNewMedia)
+ // The active object has the maximum possible priority to prevent other active objects
+ // running before it. (Unless they too are scheduled to run and have the maximum
+ // possible priority
+ {
+ __ASSERT_DEBUG(aGlxCommandHandlerNewMedia, Panic(EGlxPanicNullPointer));
+ CActiveScheduler::Add(this);
+ }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CGlxCommandHandlerNewMedia::CGlxAsyncFocuser::
+ ~CGlxAsyncFocuser()
+ {
+ Cancel();
+ }
+
+// -----------------------------------------------------------------------------
+// RunL
+// -----------------------------------------------------------------------------
+//
+void CGlxCommandHandlerNewMedia::CGlxAsyncFocuser::RunL()
+ {
+ iGlxCommandHandlerNewMedia->SetFocusL(iFocusIndex);
+ }
+
+// -----------------------------------------------------------------------------
+// DoCancel
+// -----------------------------------------------------------------------------
+//
+void CGlxCommandHandlerNewMedia::CGlxAsyncFocuser::DoCancel()
+ {
+ // No need to do anything
+ // CActive::Cancel() will wait for the request to complete
+ }
+
+// -----------------------------------------------------------------------------
+// SetFocusL
+// -----------------------------------------------------------------------------
+//
+void CGlxCommandHandlerNewMedia::CGlxAsyncFocuser::SetFocus(TInt aIndex)
+ {
+ iFocusIndex = aIndex;
+ TRequestStatus* requestStatus = &iStatus;
+ User::RequestComplete(requestStatus,KErrNone);
+ SetActive();
+ }