--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/engine/collectionframework/datasource/plugins/glxdatasourcemde2.5/src/glxdatasourcetaskmdscommand.cpp Fri Mar 19 09:28:59 2010 +0200
@@ -0,0 +1,1172 @@
+/*
+* 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:
+*
+*/
+
+
+
+/**
+ * @internal reviewed 11/07/2007 by M Byrne
+ */
+
+
+#include "glxdatasourcetaskmdscommand.h"
+
+#include <bautils.h>
+#include <e32math.h>
+#include <glxcommandrequest.h>
+#include <glxpanic.h>
+#include <glxtndatabase.h>
+#include <glxtnthumbnailcreator.h>
+#include <glxtracer.h>
+#include <caf/manager.h>
+#include <mdeconstants.h>
+#include <mdeeventdef.h>
+#include <mdelogiccondition.h>
+#include <mdeobject.h>
+#include <mdeobjectdef.h>
+#include <mdeobjectquery.h>
+#include <mdepropertydef.h>
+#include <mderelationcondition.h>
+#include <mderelationdef.h>
+#include <mderelationquery.h>
+#include <mdesession.h>
+#include <mdetextproperty.h>
+#include <mpxcollectionmessagedefs.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxmediacollectiondetaildefs.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxmessageprogressdefs.h>
+#include <pathinfo.h>
+
+#include <glxstringcache.h>
+
+#include <glxcollectionplugincamera.hrh>
+#include <glxcollectionplugintags.hrh>
+#include <glxcollectionpluginalbums.hrh>
+#include <glxcollectionpluginall.hrh>
+
+#include "glxdatasourcemds.h"
+#include "glxdatasourcemdsutility.h"
+#include "glxdatasourcemds.hrh"
+
+#include <glxpluginalbums.rsg>
+
+#include <data_caging_path_literals.hrh>
+#include <f32file.h>
+#include <barsc.h>
+#include <bautils.h>
+
+// CONSTANTS
+_LIT(KPropertyDefNameDescription, "Comment");
+_LIT(KPropertyDefNameTitle, "Title" );
+_LIT(KPropertyDefNameSize, "Size");
+_LIT(KPropertyDefNameCreationDate, "CreationDate");
+_LIT(KPropertyDefNameLastModifiedDate, "LastModifiedDate");
+_LIT(KPropertyDefNameAlbumType, "Type");
+_LIT(KPropertyDefItemType, "ItemType");
+// Item type for Album
+_LIT( KAlbumItemType, "application/vnd.nokia.mde.album" );
+// Item type for Tag
+_LIT( KTagItemType, "application/vnd.nokia.mde.tag" );
+
+const TInt KDriveLetterLength = 1;
+_LIT(KColonBackslash, ":\\");
+_LIT(KFileNameFormatString, "(%+02u)");
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+CGlxDataSourceTaskMdeCommand::~CGlxDataSourceTaskMdeCommand()
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::~CGlxDataSourceTaskMdeCommand()")
+ iLeftIds.Close();
+ iRightIds.Close();
+ delete iTitle;
+ delete iObjectToRename;
+ delete iStringCache;
+ }
+
+
+// ----------------------------------------------------------------------------
+// Constructor
+// ----------------------------------------------------------------------------
+//
+CGlxDataSourceTaskMdeCommand::CGlxDataSourceTaskMdeCommand(
+ CGlxCommandRequest* aRequest, MGlxDataSourceRequestObserver& aObserver,
+ CGlxDataSource* aDataSource)
+ : CGlxDataSourceTaskMde(aRequest, aObserver, aDataSource)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::CGlxDataSourceTaskMdeCommand()")
+ // No implementation required
+ }
+
+// ----------------------------------------------------------------------------
+// Second phase constructor
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::ConstructL()
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::ConstructL()")
+ iResponse = CMPXCommand::NewL(static_cast<CGlxCommandRequest*>(iRequest)->Command());
+#ifdef USE_S60_TNM
+ DataSource()->CancelFetchThumbnail();
+#else
+ DataSource()->ThumbnailCreator().CancelRequest( TGlxMediaId(0) );
+#endif
+ }
+
+/// @todo minor: Rowland Cook 12/06/2007 Add method decription.
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::ExecuteRequestL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::ExecuteRequestL()
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::ExecuteRequestL()")
+ __ASSERT_DEBUG(DataSource()->NamespaceDef(), Panic(EGlxPanicIllegalState));
+
+ const CMPXCommand& command = static_cast<CGlxCommandRequest*>(iRequest)->Command();
+
+ if ( command.IsSupported(KMPXCommandGeneralCollectionId) )
+ {
+ iCollectionUid = command.ValueTObjectL<TUid>(KMPXCommandGeneralCollectionId);
+ }
+ else
+ {
+ // if the collection Uid has not been set on the command, use the Ud of the plugin in use.
+ iCollectionUid = iRequest->CollectionPluginUid();
+ }
+
+ TGlxCommandParser::ParseL(*this, command);
+ }
+
+// ----------------------------------------------------------------------------
+// Add container
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::AddContainerL(const TDesC& aContainerName)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::AddContainerL()")
+ iTitle = aContainerName.AllocL();
+ AppendContainerTitleCountQueryL(ECommandAddContainer, aContainerName);
+ ExecuteQueryL();
+ }
+
+// ----------------------------------------------------------------------------
+// Add items to container by id
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::AddToContainerL(const RArray<TGlxMediaId>& aSourceIds, const RArray<TGlxMediaId>& aTargetContainers)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::AddToContainerL(const RArray<TGlxMediaId>& aSourceIds, const RArray<TGlxMediaId>& aTargetContainers)")
+ __ASSERT_DEBUG(aSourceIds.Count() && aTargetContainers.Count(), Panic(EGlxPanicEmptyArray));
+
+ iLeftIds.Reset();
+ iRightIds.Reset();
+
+ CMdEQuery* query = DataSource()->Session().NewRelationQueryL(*DataSource()->NamespaceDef(), this);
+ AppendQueryL(query, ECommandAddToContainer);
+
+ CMdELogicCondition& rootCondition = query->Conditions();
+ CMdERelationCondition& containerRelationCondition = rootCondition.AddRelationConditionL(DataSource()->ContainsDef(), ERelationConditionSideLeft);
+ CMdELogicCondition& leftLogicCondition = containerRelationCondition.LeftL();
+ CMdELogicCondition& rightLogicCondition = containerRelationCondition.RightL();
+ leftLogicCondition.SetOperator(ELogicConditionOperatorOr);
+ rightLogicCondition.SetOperator(ELogicConditionOperatorOr);
+
+ TItemId containerId = ContainerItemId(aTargetContainers[0]);
+ // It is currenly a safe assumption that all containers are of the same type (either albums or tags)
+ // and thus they will either all be on the left or all be on the right of the logic condition. Therefore,
+ // we only need to test the first container to see if it is on the left or on the right.
+ CMdEObject* container = DataSource()->Session().GetObjectL(containerId);
+ if (!container)
+ {
+ User::Leave(KErrNotFound);
+ }
+ TBool containerIsLeft = DataSource()->ContainerIsLeft(container->Def());
+
+ delete container;
+ container = NULL;
+
+
+ if (containerIsLeft)
+ {
+ // the container is on the left
+ NGlxDataSourceMdsUtility::CopyMediaIdArrayL(iLeftIds, aTargetContainers);
+ NGlxDataSourceMdsUtility::CopyMediaIdArrayL(iRightIds, aSourceIds);
+ }
+ else
+ {
+ // the container is on the right
+ NGlxDataSourceMdsUtility::CopyMediaIdArrayL(iRightIds, aTargetContainers);
+ NGlxDataSourceMdsUtility::CopyMediaIdArrayL(iLeftIds, aSourceIds);
+ }
+
+ leftLogicCondition.AddObjectConditionL(iLeftIds);
+ rightLogicCondition.AddObjectConditionL(iRightIds);
+
+ query->SetResultMode(EQueryResultModeItem);
+
+ ExecuteQueryL();
+
+ }
+
+// ----------------------------------------------------------------------------
+// Add item to containers by URI.
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::AddToContainerL(const TDesC& aSourceUri,
+ const RArray< TGlxMediaId >& aTargetContainers)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::AddToContainerL()")
+ CMdEObject* sourceObject = DataSource()->Session().GetObjectL(aSourceUri);
+ if (!sourceObject)
+ {
+ User::Leave(KErrNotFound);
+ }
+ RArray<TGlxMediaId> sourceIds;
+ CleanupClosePushL(sourceIds);
+ sourceIds.AppendL(TGlxMediaId(sourceObject->Id()));
+
+ AddToContainerL(sourceIds, aTargetContainers);
+ CleanupStack::PopAndDestroy(&sourceIds);
+ }
+
+// ----------------------------------------------------------------------------
+// Copy files to another drive.
+// ----------------------------------------------------------------------------
+//
+/// @todo minor: Rowland Cook 12/06/2007 Has this method been tested? If so remove comments
+void CGlxDataSourceTaskMdeCommand::CopyL(const RArray<TGlxMediaId>& aSourceIds, const TDesC& aDrive)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::CopyL()")
+ FileOperationL(aSourceIds.Array(), aDrive, ECopy);
+ }
+
+// ----------------------------------------------------------------------------
+// Move files to another drive.
+// ----------------------------------------------------------------------------
+//
+/// @todo minor: Rowland Cook 12/06/2007 Has this method been tested? If so remove comments
+void CGlxDataSourceTaskMdeCommand::MoveL(const RArray<TGlxMediaId>& aSourceIds, const TDesC& aDrive)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::MoveL()")
+ FileOperationL(aSourceIds.Array(), aDrive, EMove);
+ }
+
+// ----------------------------------------------------------------------------
+// Remove items from a container.
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::RemoveFromContainerL(const RArray<TGlxMediaId>& aItemIds, const TGlxMediaId& aContainerId)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::RemoveFromContainerL()")
+ // Answer to question in @bug above: No
+
+ CMdEObject* object = NULL;
+ object = DataSource()->Session().GetObjectL(aContainerId.Value());
+ CleanupStack::PushL(object);
+ if (!object)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ CMdEQuery* query = DataSource()->Session().NewRelationQueryL(*DataSource()->NamespaceDef(), this);
+ AppendQueryL(query, ECommandRemoveFromContainer); // query is now owned by the query array.
+
+ CMdELogicCondition& rootCondition = query->Conditions();
+
+ CMdERelationCondition& containerRelationCondition = rootCondition.AddRelationConditionL(DataSource()->ContainsDef(), ERelationConditionSideLeft);
+ CMdELogicCondition* containerLogicCondition = NULL;
+ CMdELogicCondition* itemLogicCondition = NULL;
+ // Containers are on the left for albums, right for tags
+ if ( DataSource()->ContainerIsLeft(object->Def()) )
+ {
+ containerLogicCondition = &containerRelationCondition.LeftL();
+ itemLogicCondition = &containerRelationCondition.RightL();
+ }
+ else
+ {
+ containerLogicCondition = &containerRelationCondition.RightL();
+ itemLogicCondition = &containerRelationCondition.LeftL();
+ }
+
+ containerLogicCondition->AddObjectConditionL(aContainerId.Value());
+
+ itemLogicCondition->SetOperator(ELogicConditionOperatorOr);
+
+ NGlxDataSourceMdsUtility::AddObjectConditionL(*itemLogicCondition,aItemIds);
+
+ query->SetResultMode(EQueryResultModeId);
+ CleanupStack::PopAndDestroy(object);
+ ExecuteQueryL();
+ }
+
+// ----------------------------------------------------------------------------
+// Delete files, Remove container.
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DeleteL(const RArray<TGlxMediaId>& aItemIds)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DeleteL()")
+ CMdEObjectDef* containerObjectDef = NULL;
+ TInt err = ContainerObjectDef(containerObjectDef);
+ if (err == KErrNone)
+ {
+ QueueObjectQueryL(*containerObjectDef,
+ aItemIds, ECommandDeleteContainers);
+ }
+ // Assume that only items are left
+ QueueObjectQueryL(DataSource()->ObjectDef(),
+ aItemIds, ECommandDeleteItems);
+
+ ExecuteQueryL();
+ }
+
+// ----------------------------------------------------------------------------
+// Rename files, Rename container.
+//
+/// @todo test this method.
+//
+// ----------------------------------------------------------------------------
+//
+/// @todo minor: Rowland Cook 12/06/2007 Has this method been tested? If so remove comments
+void CGlxDataSourceTaskMdeCommand::RenameL(const TGlxMediaId& aSourceItemId, const TDesC& aTitle)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::RenameL()")
+ delete iTitle;
+ iTitle = NULL;
+ iTitle = aTitle.AllocL();
+
+ RArray<TGlxMediaId> sourceIdArray;
+ CleanupClosePushL(sourceIdArray);
+ sourceIdArray.AppendL(aSourceItemId);
+
+ QueueObjectQueryL(DataSource()->ObjectDef(), sourceIdArray , ECommandRename);
+ CleanupStack::PopAndDestroy(&sourceIdArray);
+
+ ExecuteQueryL();
+ }
+
+// ----------------------------------------------------------------------------
+// Set description.
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::SetDescriptionL(const RArray<TGlxMediaId>& aItemIds, const TDesC& aDescription)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::SetDescriptionL()")
+ CMdEPropertyDef& descriptionPropertyDef = DataSource()->MediaDef().GetPropertyDefL(KPropertyDefNameDescription);
+ if (descriptionPropertyDef.PropertyType() != EPropertyText)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ TInt count = aItemIds.Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ TItemId itemId = aItemIds[i].Value();
+ CMdEObject* object = DataSource()->Session().OpenFullObjectL(itemId);
+ if (!object)
+ {
+ User::Leave(KErrNotFound);
+ }
+ CleanupStack::PushL(object);
+ CMdEProperty* descriptionProperty = NULL;
+
+
+ TInt index = object->Property(descriptionPropertyDef, descriptionProperty);
+ if (index < KErrNotFound)
+ {
+ User::Leave(index);
+ }
+ if (index != KErrNotFound)
+ {
+ // Check whether the description string is empty
+ if( aDescription.Length() )
+ {
+ static_cast<CMdETextProperty*>(descriptionProperty)->SetValueL(aDescription);
+ }
+
+ //if entered description string is blank then remove the old property
+ else
+ {
+ object->RemoveProperty(index);
+ }
+ }
+ else
+ {
+ if( aDescription.Length() )
+ {
+ object->AddTextPropertyL(descriptionPropertyDef, aDescription);
+ }
+ }
+ DataSource()->Session().CommitObjectL(*object);
+ CleanupStack::PopAndDestroy(object);
+ }
+
+ HandleRequestComplete(KErrNone);
+ }
+
+
+// ----------------------------------------------------------------------------
+// Set capture location.
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::SetCaptureLocationL(const RArray<TGlxMediaId>& aItemIds, const TCoordinate& aCoordinate)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::SetCaptureLocationL()")
+ if (!Math::IsNaN(aCoordinate.Latitude()) || !Math::IsNaN(aCoordinate.Longitude()))
+ {
+ User::Leave(KErrArgument);
+ }
+
+ CMdEQuery* query = DataSource()->Session().NewRelationQueryL(*DataSource()->NamespaceDef(), this);
+ AppendQueryL(query, ECommandRemoveLocation); // query is now owned by the query array.
+
+ CMdELogicCondition& rootCondition = query->Conditions();
+
+ CMdERelationCondition& containerRelationCondition = rootCondition.AddRelationConditionL(ERelationConditionSideLeft);
+ CMdELogicCondition& locationLogicCondition = containerRelationCondition.RightL();
+ CMdELogicCondition& itemLogicCondition = containerRelationCondition.LeftL();
+ locationLogicCondition.AddObjectConditionL(DataSource()->LocationDef());
+
+ itemLogicCondition.SetOperator(ELogicConditionOperatorOr);
+
+
+ itemLogicCondition.AddObjectConditionL(reinterpret_cast<const RArray<TItemId>&>(aItemIds));
+
+ query->SetResultMode(EQueryResultModeId);
+ ExecuteQueryL();
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::ThumbnailCleanupL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::ThumbnailCleanupL()
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::ThumbnailCleanupL()")
+#ifndef USE_S60_TNM
+ CGlxDataSourceMde* ds = DataSource();
+ ds->ThumbnailCreator().CleanupThumbnailsL(&ds->ThumbnailDatabase());
+#endif
+ HandleRequestComplete(KErrNone);
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::HandleQueryCompletedL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoHandleQueryCompletedL(CMdEQuery& aQuery)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoHandleQueryCompletedL()")
+ TGlxQueryType queryType = iQueryTypes[0];
+
+ switch (queryType)
+ {
+
+ case ECommandRemoveFromContainer: // don't break
+ case ECommandRemoveLocation:
+ {
+ TInt queryCount = aQuery.Count();
+ RArray<TItemId> relationsToRemove;
+ CleanupClosePushL(relationsToRemove);
+ User::LeaveIfError(relationsToRemove.Reserve(queryCount));
+
+ RArray<TItemId> successfullyRemovedReleations;
+ CleanupClosePushL(successfullyRemovedReleations);
+ User::LeaveIfError(successfullyRemovedReleations.Reserve(queryCount));
+
+ for(TInt i = queryCount - 1; i >= 0; i--)
+ {
+ relationsToRemove.AppendL(aQuery.ResultId(i));
+ }
+
+ if (queryCount)
+ {
+ User::LeaveIfError(DataSource()->Session().RemoveRelationsL(relationsToRemove, successfullyRemovedReleations));
+ }
+
+ CleanupStack::PopAndDestroy(&successfullyRemovedReleations);
+ CleanupStack::PopAndDestroy(&relationsToRemove);
+ }
+ break;
+ case ECommandAddToContainer:
+ {
+ DoHandleAddToContainerQueryCompletedL(aQuery);
+ }
+ break;
+ case ECommandAddContainer:
+ {
+ DoHandleAddContainerQueryCompletedL(aQuery);
+ }
+ break;
+ case ECommandDeleteContainers:
+ {
+ DoHandleDeleteContainersQueryCompletedL(aQuery);
+ }
+ break;
+ case ECommandDeleteItems:
+ {
+ DoHandleDeleteItemsQueryCompletedL(aQuery);
+ }
+ break;
+ case ECommandRename:
+ {
+ DoHandleRenameQueryCompletedL(aQuery);
+ }
+ break;
+ case ECommandRenameContainer:
+ {
+ DoHandleRenameConainerQueryCompletedL(aQuery);
+ }
+ break;
+ }
+ }
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::DoNextQueryL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoNextQueryL()
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoNextQueryL()")
+ if (iQueries.Count())
+ {
+ ExecuteQueryL();
+ }
+ else
+ {
+ HandleRequestComplete(KErrNone);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::FileOperationL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::FileOperationL(const TArray<TGlxMediaId>& aSourceIds, const TDesC& aDrive, TFileOperation aFileOperation)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::FileOperationL()")
+ ContentAccess::CManager *manager = ContentAccess::CManager::NewL();
+ CleanupStack::PushL(manager);
+ // The following line causes a code scanner warning advising use of EikonEnv RFs instance.
+ // We don't have an EikonEnv as we are running in a server process.
+ RFs rfs; // used for BaflUtils::FileExists
+
+ CleanupClosePushL(rfs);
+ User::LeaveIfError(rfs.Connect());
+ for (TInt i = 0; i < aSourceIds.Count(); i++)
+ {
+ CMdEObject* sourceObject = DataSource()->Session().GetObjectL(aSourceIds[i].Value());
+ if (!sourceObject)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ CleanupStack::PushL(sourceObject);
+
+ const TDesC& sourceFileName = sourceObject->Uri();
+ TFileName sourceRootPath;
+
+ RootPath(sourceFileName, sourceRootPath);
+ TPtrC fileNameWithoutRoot(NULL,0);
+ if (sourceFileName.Left(sourceRootPath.Length()).CompareF(sourceRootPath) == 0)
+ // This is the expected case. The file to be copied is under the 'root' of
+ // the drive that it is located on. (For the C:, the root is C:\data,
+ // for the D: the root is D:\)
+ {
+ fileNameWithoutRoot.Set(sourceFileName.Right(sourceFileName.Length() - sourceRootPath.Length()));
+ }
+ else
+ {
+ fileNameWithoutRoot.Set(sourceFileName);
+ }
+
+ TFileName destinationFileName;
+ // Set destination file name to destination 'root' path
+ RootPath(aDrive, destinationFileName);
+ // Append the file name
+ destinationFileName.Append(fileNameWithoutRoot);
+
+/// @todo minor: Rowland Cook 12/06/2007 majic number.
+ if (destinationFileName.CompareF(sourceFileName) != 0)
+ {
+ // If source and destination are not identical, perform the copy.
+ if (BaflUtils::FileExists(rfs, destinationFileName))
+ {
+ // If the destination file name already exists find an available file name.
+ TParse destinationFileNameParse;
+ destinationFileNameParse.Set(destinationFileName,NULL,NULL); // this is a copy of the data
+ TInt destinationFileNameWithoutExtensionLength = destinationFileName.Length() - destinationFileNameParse.Ext().Length();
+ TInt i = 1;
+ do
+ {
+ destinationFileName.SetLength(destinationFileNameWithoutExtensionLength);
+ destinationFileName.AppendFormat(KFileNameFormatString,i++);
+ destinationFileName.Append(destinationFileNameParse.Ext());
+ }
+ while (BaflUtils::FileExists(rfs, destinationFileName));
+ }
+
+ // Ensure the path that we are copying to exists.
+ // Fixed error ID: ELLZ-798BP3 Lumiere 07.46.08_MC Photo:
+ // "System: System error." is displayed when copying/moving image which is saved in a user created folder.
+ BaflUtils::EnsurePathExistsL(rfs,destinationFileName);
+
+ if (aFileOperation == ECopy)
+ {
+ User::LeaveIfError(manager->CopyFile(sourceFileName, destinationFileName));
+ }
+ else
+ {
+ User::LeaveIfError(manager->RenameFile(sourceFileName, destinationFileName));
+ }
+
+ }
+
+ CleanupStack::PopAndDestroy(sourceObject);
+ }
+
+ CleanupStack::PopAndDestroy(&rfs);
+ CleanupStack::PopAndDestroy(manager);
+
+ HandleRequestComplete(KErrNone);
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::ContainerItemId
+// ----------------------------------------------------------------------------
+//
+TItemId CGlxDataSourceTaskMdeCommand::ContainerItemId(const TGlxMediaId& aMediaId)
+ {
+ TRACER("TMdEItemId CGlxDataSourceTaskMdeCommand::ContainerItemId()");
+ TItemId containerId = aMediaId.Value();
+ if (aMediaId == KGlxCollectionRootId)
+ {
+ // Check the collection plugin uid
+ if (iCollectionUid == TUid::Uid(KGlxCollectionPluginCameraImplementationUid))
+ {
+ // containerId = DataSource()->CameraAlbumId().Value();
+ }
+ }
+ return containerId;
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::ContainerItemId
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::RootPath(const TDesC& aDrive, TDes& aRootPath)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::RootPath()")
+ if (aDrive.Left(KDriveLetterLength).CompareF(PathInfo::PhoneMemoryRootPath().Left(KDriveLetterLength)) == 0)
+ {
+ aRootPath = PathInfo::PhoneMemoryRootPath();
+ }
+ else if (aDrive.Left(KDriveLetterLength).CompareF(PathInfo::MemoryCardRootPath().Left(KDriveLetterLength)) == 0)
+ {
+ aRootPath = PathInfo::MemoryCardRootPath();
+ }
+ else if (aDrive.Left(KDriveLetterLength).CompareF(PathInfo::RomRootPath().Left(KDriveLetterLength)) == 0)
+ {
+ aRootPath = PathInfo::RomRootPath();
+ }
+ else
+ {
+ aRootPath = aDrive.Left(KDriveLetterLength);
+ aRootPath.Append(KColonBackslash);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::SendProgressMessageL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::SendProgressMessageL(TInt aCurrentStep, TInt aStepCount)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::SendProgressMessageL()")
+ MGlxDataSourceUpdateObserver& observer = static_cast<CGlxCommandRequest*>(iRequest)->DataSourceUpdateObserver();
+
+ const CMPXCommand& command = static_cast<CGlxCommandRequest*>(iRequest)->Command();
+ __ASSERT_DEBUG(command.IsSupported(KMPXCommandGeneralSessionId), Panic(EGlxPanicCommandHasNoGeneralSessionId));
+
+ TAny* sessionId = command.ValueTObjectL<TAny*>(KMPXCommandGeneralSessionId);
+
+ CMPXMessage* progressMessage = CMPXMessage::NewL();
+ CleanupStack::PushL(progressMessage);
+ progressMessage->SetTObjectValueL<TInt>(KMPXMessageGeneralId, KMPXMessageContentIdProgress);
+ progressMessage->SetTObjectValueL<TInt>(TMPXAttribute(KMPXMessageContentIdProgress, EMPXMessageProgressCurrentCount), aCurrentStep);
+ progressMessage->SetTObjectValueL<TInt>(TMPXAttribute(KMPXMessageContentIdProgress, EMPXMessageProgressTotalCount), aStepCount);
+ progressMessage->SetTObjectValueL<TAny*>(KMPXCommandGeneralSessionId, sessionId);
+
+ observer.HandleMessage(*progressMessage);
+
+ CleanupStack::PopAndDestroy(progressMessage);
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::ContainerObjectDef
+// ----------------------------------------------------------------------------
+//
+TInt CGlxDataSourceTaskMdeCommand::ContainerObjectDef(CMdEObjectDef*& aContainerObjectDef)
+{
+ TRACER("CGlxDataSourceTaskMdeCommand::ContainerObjectDef()")
+ //__ASSERT_DEBUG( (iCollectionUid == TUid::Uid(KGlxTagCollectionPluginImplementationUid) || iCollectionUid == TUid::Uid(KGlxCollectionPluginAlbumsImplementationUid)), Panic(EGlxPanicInvalidCollectionUid));
+ TInt err = KErrNone;
+ if (iCollectionUid == TUid::Uid(KGlxTagCollectionPluginImplementationUid))
+ {
+ aContainerObjectDef = &DataSource()->TagDef();
+ }
+ else if (iCollectionUid == TUid::Uid(KGlxCollectionPluginAlbumsImplementationUid))
+ {
+ aContainerObjectDef = &DataSource()->AlbumDef();
+ }
+ else if(iCollectionUid == TUid::Uid(KGlxCollectionPluginAllImplementationUid))
+ {
+ aContainerObjectDef = &DataSource()->MediaDef();
+ }
+ else
+ {
+ err = KErrNotFound;
+ }
+ return err;
+}
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::DoHandleAddToContainerQueryCompletedL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoHandleAddToContainerQueryCompletedL
+ (CMdEQuery& aQuery)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoHandleAddToContainerQueryCompletedL()")
+ RPointerArray<CMdEInstanceItem> relations;
+ CleanupClosePushL(relations);
+
+ TInt leftCount = iLeftIds.Count();
+ User::LeaveIfError(relations.Reserve(leftCount)); // this is a bigest reservation that could be required.
+ for (TInt leftPos = 0; leftPos < leftCount; leftPos++)
+ {
+ TInt rightCount = iRightIds.Count();
+ for (TInt rightPos = 0; rightPos < rightCount; rightPos++)
+ {
+ // Check to see if id already exists
+ TBool alreadyExists = EFalse;
+ for(TInt queryPos = aQuery.Count() - 1; queryPos >= 0; queryPos--)
+ {
+ CMdERelation& relation = static_cast<CMdERelation&>(aQuery.ResultItem(queryPos));
+ if (relation.LeftObjectId() == iLeftIds[leftPos]
+ && relation.RightObjectId() == iRightIds[rightPos])
+ {
+ alreadyExists = ETrue;
+ break;
+ }
+ }
+
+ if (!alreadyExists)
+ {
+ CMdERelation* relation = DataSource()->Session().NewRelationL(DataSource()->ContainsDef(), iLeftIds[leftPos], iRightIds[rightPos]);
+ CleanupStack::PushL(relation);
+ relations.AppendL(relation);
+ CleanupStack::Pop(relation);
+ }
+ }
+
+ }
+
+ if (relations.Count())
+ {
+ User::LeaveIfError(DataSource()->Session().AddItemsL(relations));
+ }
+
+ CleanupStack::PopAndDestroy(&relations);
+
+ iLeftIds.Reset();
+ iRightIds.Reset();
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::DoHandleAddContainerQueryCompletedL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoHandleAddContainerQueryCompletedL
+ (CMdEQuery& aQuery)
+
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoHandleAddContainerQueryCompletedL()")
+
+ //Duplicate albums check for the default albums i.e. Favourites
+ //as title property is left blank in MDS 2.5
+ if(iCollectionUid == TUid::Uid(KGlxCollectionPluginAlbumsImplementationUid))
+ {
+ if(SearchStringL(R_ALBUM_FAVORITES_TITLE) == 0)
+ {
+ User::Leave(KErrAlreadyExists);
+ }
+ }
+
+ if (aQuery.Count())
+ {
+ // An object (or more strickly objects) with the given container name already exist
+ User::Leave(KErrAlreadyExists);
+ }
+
+ CMdEObject* object = NULL;
+ CMdEObjectDef* containerObjectDef = NULL;
+ TInt err = ContainerObjectDef(containerObjectDef );
+ __ASSERT_ALWAYS(err == KErrNone, Panic(EGlxPanicInvalidCollectionUid));
+
+ object = DataSource()->Session().NewObjectLC(*containerObjectDef, KNullDesC);
+
+ // A title property def of type text is required.
+ CMdEPropertyDef& titlePropertyDef = containerObjectDef->GetPropertyDefL(KPropertyDefNameTitle);
+ if (titlePropertyDef.PropertyType() != EPropertyText)
+ {
+ User::Leave(KErrCorrupt);
+ }
+ // Set the object title.
+ object->AddTextPropertyL(titlePropertyDef, *iTitle);
+
+ //ItemType property def of type text is required.
+ CMdEPropertyDef& itemTypePropertyDef = containerObjectDef->GetPropertyDefL(KPropertyDefItemType);
+ if (itemTypePropertyDef.PropertyType() != EPropertyText)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Checks the Container type whether it is Tag or Album
+ if (iCollectionUid == TUid::Uid(KGlxTagCollectionPluginImplementationUid))
+ {
+ object->AddTextPropertyL (itemTypePropertyDef, KTagItemType);
+ }
+ else
+ {
+ object->AddTextPropertyL (itemTypePropertyDef, KAlbumItemType);
+ }
+
+
+ // A size property is required.
+
+ CMdEPropertyDef& sizePropertyDef = containerObjectDef->GetPropertyDefL(KPropertyDefNameSize);
+ if (sizePropertyDef.PropertyType() != EPropertyUint32)
+ {
+ User::Leave(KErrCorrupt);
+ }
+ object->AddUint32PropertyL(sizePropertyDef,0);
+
+
+ // A creation date property is required.
+ CMdEPropertyDef& creationDateDef = containerObjectDef->GetPropertyDefL(KPropertyDefNameCreationDate);
+ if (creationDateDef.PropertyType() != EPropertyTime)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // A last modified date property is required.
+ CMdEPropertyDef& lmDateDef = containerObjectDef->GetPropertyDefL(KPropertyDefNameLastModifiedDate);
+ if (lmDateDef.PropertyType() != EPropertyTime)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ TTime uTime;
+ uTime.UniversalTime();
+ object->AddTimePropertyL(creationDateDef, uTime);
+ object->AddTimePropertyL(lmDateDef, uTime);
+
+ TItemId id = DataSource()->Session().AddObjectL(*object);
+ CleanupStack::PopAndDestroy(object);
+
+ iResponse->SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, id);
+ iResponse->SetTObjectValueL<TMPXItemId>(KMPXMessageMediaGeneralId, id);
+ iResponse->SetTObjectValueL<TMPXChangeEventType>(KMPXMessageChangeEventType, EMPXItemInserted);
+ }
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::DoHandleDeleteContainersQueryCompletedL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoHandleDeleteContainersQueryCompletedL
+ (CMdEQuery& aQuery)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoHandleDeleteContainersQueryCompletedL()")
+ CMdEPropertyDef& albumTypeProperty = DataSource()->AlbumDef().GetPropertyDefL(KPropertyDefNameAlbumType);
+ TInt queryCount = aQuery.Count();
+
+ RArray<TItemId> objectsForRemoval;
+ CleanupClosePushL(objectsForRemoval);
+ User::LeaveIfError(objectsForRemoval.Reserve(queryCount));
+
+ RArray<TItemId> sucessfullyRemovedObjects;
+ CleanupClosePushL(sucessfullyRemovedObjects);
+ User::LeaveIfError(sucessfullyRemovedObjects.Reserve(queryCount));
+
+ // Ensure that deletion is legal and that deletion
+ for(TInt queryPos = 0; queryPos < queryCount; queryPos++)
+ {
+ CMdEObject& object = static_cast<CMdEObject&>(aQuery.ResultItem(queryPos));
+
+ CMdEProperty* albumType;
+ TInt albumTypeIndex = object.Property(albumTypeProperty, albumType);
+ if (KErrNotFound != albumTypeIndex)
+ {
+ TInt albumTypeValue = static_cast<CMdEUint16Property*>(albumType)->Value();
+
+ if ((albumTypeValue == MdeConstants::Album::EAlbumSystemFavourite) || (albumTypeValue == MdeConstants::Album::EAlbumSystemCamera))
+ {
+ User::Leave(KErrAccessDenied);
+ }
+ }
+ objectsForRemoval.AppendL(object.Id());
+ }
+
+ if (queryCount)
+ {
+ User::LeaveIfError(DataSource()->Session().RemoveObjectsL(objectsForRemoval, sucessfullyRemovedObjects));
+ }
+
+ CleanupStack::PopAndDestroy(&sucessfullyRemovedObjects);
+ CleanupStack::PopAndDestroy(&objectsForRemoval);
+ }
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::DoHandleDeleteItemsContainersQueryCompletedL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoHandleDeleteItemsQueryCompletedL
+ (CMdEQuery& aQuery)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoHandleDeleteItemsQueryCompletedL()")
+ ContentAccess::CManager *manager = ContentAccess::CManager::NewL();
+ CleanupStack::PushL(manager);
+ TInt queryCount = aQuery.Count();
+ RArray<TItemId> objectsForRemoval;
+ CleanupClosePushL(objectsForRemoval);
+ User::LeaveIfError(objectsForRemoval.Reserve(queryCount));
+
+ RArray<TItemId> sucessfullyRemovedObjects;
+ CleanupClosePushL(sucessfullyRemovedObjects);
+ User::LeaveIfError(sucessfullyRemovedObjects.Reserve(queryCount));
+ //Handle to a file server session
+ RFs fs;
+ // Pushing the handle in Clean-up Stack to call Close() on file server session
+ CleanupClosePushL( fs );
+ //Connects a client to the file server
+ User::LeaveIfError( fs.Connect() );
+
+ TInt lastErr = KErrNone;
+ for(TInt queryPos = queryCount - 1; queryPos >= 0; queryPos--)
+ {
+ CMdEObject& object = static_cast<CMdEObject&>(aQuery.ResultItem(queryPos));
+ //Removes the Read Only attributes of the file
+ fs.SetAtt(object.Uri(), 0, KEntryAttReadOnly);
+ TInt err = manager->DeleteFile(object.Uri());
+ if (err != KErrNone)
+ {
+ lastErr = err;
+ }
+ objectsForRemoval.AppendL(object.Id());
+ }
+ // Calling Close() on file server session
+ CleanupStack::PopAndDestroy( &fs );
+
+ User::LeaveIfError(lastErr);
+
+ if (queryCount)
+ {
+ // Some objects may have already been removed by the harvester
+ DataSource()->Session().RemoveObjectsL(objectsForRemoval, sucessfullyRemovedObjects);
+ }
+
+ CleanupStack::PopAndDestroy(&sucessfullyRemovedObjects);
+ CleanupStack::PopAndDestroy(&objectsForRemoval);
+
+ CleanupStack::PopAndDestroy(manager);
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::DoHandleRenameConainerQueryCompletedL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoHandleRenameConainerQueryCompletedL
+ (CMdEQuery& aQuery)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoHandleRenameConainerQueryCompletedL()")
+ __ASSERT_DEBUG(iObjectToRename, Panic(EGlxPanicLogicError));
+ if (aQuery.Count())
+ {
+ User::Leave(KErrAlreadyExists);
+ }
+
+ CMdEObject* object = DataSource()->Session().OpenObjectL(iObjectToRename->Id(), iObjectToRename->Def());
+ CleanupStack::PushL(object);
+ CMdEProperty* albumType;
+ // @todo AB test this
+ CMdEPropertyDef* albumTypeProperty = NULL;
+ TRAP_IGNORE(albumTypeProperty = &object->Def().GetPropertyDefL(KPropertyDefNameAlbumType));
+ TInt albumTypeIndex = KErrNotFound;
+ // Must guard against non-existance of albumTypeProperty (e.g. when renaming a tag)
+ if (albumTypeProperty)
+ {
+ albumTypeIndex = object->Property(*albumTypeProperty, albumType);
+ }
+ if( KErrNotFound != albumTypeIndex )
+ {
+ TInt albumTypeValue = static_cast<CMdEUint16Property*>(albumType)->Value();
+ if ( albumTypeValue == MdeConstants::Album::EAlbumUserPredefined )
+ {
+ // Want to rename a predefined, localised album name so reclassify
+ // the type to be a non-localised user defined album
+ static_cast<CMdEUint16Property*>(albumType)->SetValueL(MdeConstants::Album::EAlbumUser);
+ }
+
+ else if ((albumTypeValue == MdeConstants::Album::EAlbumSystemFavourite) || (albumTypeValue == MdeConstants::Album::EAlbumSystemCamera))
+ {
+ // Cannot rename system albums
+ User::Leave(KErrAccessDenied);
+ }
+ }
+
+
+ CMdEPropertyDef& titlePropertyDef = object->Def().GetPropertyDefL(KPropertyDefNameTitle);
+ if (titlePropertyDef.PropertyType() != EPropertyText)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ CMdEProperty* titleProperty = NULL;
+ TInt index = object->Property(titlePropertyDef, titleProperty);
+ if (index < KErrNotFound)
+ {
+ User::Leave(index);
+ }
+ if (index != KErrNotFound)
+ {
+ // Remove the old property
+ object->RemoveProperty(index);
+ }
+ // Set the object title
+ object->AddTextPropertyL(titlePropertyDef, *iTitle);
+
+ // Get time propertydef of current session object
+ CMdEPropertyDef& timePropertyDef = object->Def().GetPropertyDefL(
+ KPropertyDefNameLastModifiedDate);
+
+ // Check the validty of the time def
+ if (timePropertyDef.PropertyType() != EPropertyTime)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Get index and check the validity
+ CMdEProperty* timeProperty = NULL;
+ index = object->Property(timePropertyDef, timeProperty);
+
+ if (index < KErrNotFound)
+ {
+ User::Leave(index);
+ }
+
+ if (index != KErrNotFound)
+ {
+ // Remove the old property
+ object->RemoveProperty(index);
+ }
+
+ // Take current universal time
+ TTime currentTime;
+ currentTime.UniversalTime();
+
+ // Set the object current time
+ object->AddTimePropertyL(timePropertyDef, currentTime);
+
+ DataSource()->Session().CommitObjectL(*object);
+ CleanupStack::PopAndDestroy(object);
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::DoHandleRenameConainerQueryCompletedL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::DoHandleRenameQueryCompletedL
+ (CMdEQuery& aQuery)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::DoHandleRenameQueryCompletedL()")
+ __ASSERT_DEBUG(aQuery.Count() == 1, Panic(EGlxPanicUnexpectedQueryResultCount ));
+ delete iObjectToRename;
+ iObjectToRename = static_cast<CMdEObject*>(aQuery.TakeOwnershipOfResult(0));
+
+ CMdEObjectDef* containerObjectDef = NULL;
+ TInt err = ContainerObjectDef(containerObjectDef);
+ if (err == KErrNone)
+ {
+ AppendContainerTitleCountQueryL(ECommandRenameContainer, *iTitle);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::AppendContainerTitleCountQueryL
+// ----------------------------------------------------------------------------
+//
+void CGlxDataSourceTaskMdeCommand::AppendContainerTitleCountQueryL
+ (const TGlxQueryType& aQueryType, const TDesC& aTitle)
+ {
+ TRACER("CGlxDataSourceTaskMdeCommand::AppendContainerTitleCountQueryL()")
+ // Test to see if a container alerady exists in the database with aContainerName
+ CMdEObjectDef* containerObjectDef = NULL;
+ TInt err = ContainerObjectDef(containerObjectDef);
+ __ASSERT_ALWAYS(err == KErrNone, Panic(EGlxPanicInvalidCollectionUid));
+
+ CMdEQuery* query = DataSource()->Session().NewObjectQueryL(*DataSource()->NamespaceDef(), *containerObjectDef, this);
+ CleanupStack::PushL(query);
+
+ CMdEPropertyDef& titlePropertyDef = DataSource()->ObjectDef().GetPropertyDefL(KPropertyDefNameTitle);
+
+ query->SetResultMode(EQueryResultModeCount);
+
+ query->Conditions().AddPropertyConditionL(titlePropertyDef, ETextPropertyConditionCompareEquals, aTitle);
+
+ CleanupStack::Pop(query);
+
+ AppendQueryL(query, aQueryType);
+ }
+
+// ----------------------------------------------------------------------------
+// CGlxDataSourceTaskMdeCommand::SearchString
+// ----------------------------------------------------------------------------
+//
+TInt CGlxDataSourceTaskMdeCommand::SearchStringL(TInt aResourceId)
+ {
+
+ _LIT(KResourceFile, "z:glxpluginalbums.rsc");
+
+ if (!iStringCache)
+ {
+ iStringCache = CGlxStringCache::NewL();
+ }
+ //Get the localized string from the cache
+ HBufC* string = iStringCache->LoadLocalizedStringLC(KResourceFile,aResourceId);
+
+ TInt result = string->CompareF(iTitle->Des());
+
+ CleanupStack::PopAndDestroy(string);
+
+ return result;
+
+ }