mpxplugins/viewplugins/views/metadataeditordialog/src/mpxmetadataeditordialog.cpp
changeset 0 ff3acec5bc43
child 1 8118492f1bdf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxplugins/viewplugins/views/metadataeditordialog/src/mpxmetadataeditordialog.cpp	Thu Dec 17 08:45:05 2009 +0200
@@ -0,0 +1,2821 @@
+/*
+* Copyright (c) 2006 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:  Music Player metadata editor dialog implementation
+*
+*/
+
+
+// INCLUDE FILES
+#include <eikmenub.h>
+#include <eikcapc.h>
+#include <eikdialg.h> // for dialog functions
+#include <eikedwin.h> // for edwins
+#include <eikmfne.h>  // for number editor
+#include <AknPopupFieldText.h>
+#include <AknQueryValueText.h>
+#include <aknappui.h>
+#include <eikspane.h> // for status pane update/restore
+#include <akntitle.h> // for title pane
+#include <aknnavilabel.h> // for navi label
+#include <aknnavi.h>
+#include <aknnavide.h>
+#include <StringLoader.h>
+#include <aknnotewrappers.h>
+#include <aknlists.h>
+#include <aknclearer.h>
+#include <hlplch.h>
+#include <bautils.h>
+#include <data_caging_path_literals.hrh>
+#include <drmrightsmanager.rsg>
+#include <centralrepository.h> // for podcasting cenrep key
+#include <tz.h>
+
+#include <aknSDData.h>
+#include <AknMediatorFacade.h>
+#include <mplayersecondarydisplayapi.h>
+#include <aknEditStateIndicator.h>
+#include <AknIndicatorContainer.h>
+#include <avkon.hrh>
+#include <avkon.rsg>
+#include <mpxmetadataeditordialog.rsg>
+#include <mpxcollectionutility.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxmediamusicdefs.h>
+#include <mpxmediaaudiodefs.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxmediadrmdefs.h>
+#include <mpxpodcastdefs.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxcollectioncommanddefs.h>
+
+#include <mpxcollectionframeworkdefs.h>
+#include <mpxcollectionmessage.h>
+#include <mpxcollectionpath.h>
+#include <mpxcollectionplaylist.h>
+#include <mpxconstants.h>
+#include <mpxcollectionhelperfactory.h>
+#include <mpxcollectionplugin.hrh>
+#include <mpxinternalcrkeys.h>
+#include <mpxuser.h>
+#include "mpxcommonuihelper.h"
+#include "mpxmetadataeditordialog.h"
+#include "mpxmetadataeditordialog.hrh"
+#include "mpxmetadataeditordialog.hlp.hrh"
+#include "mpxlog.h"
+
+// CONSTANTS
+const TInt KMPXFileDetailsMaxTitleLen = 32;
+const TInt KMPXFileDetailsMaxBufferLen = 255;
+const TInt KMPXMinNumDateTrack = 0;
+const TInt KMPXFileDetailsExtraBufferLen = 10;
+
+const TInt KMPXMaxTimeLength = 36;
+const TInt KMPXMaxVal = 512;
+const TInt KMPXOneDigit = 10;
+const TInt KMPXTwoDigits = 100;
+
+const TInt KMPXBitrateFactor = 1000;
+const TInt KSecondInMilliseconds = 1000;
+const TInt KOneHourInSeconds = 3600;
+
+
+
+const TInt KDigitFive = 5;
+const TInt KDigitNine = 9;
+const TInt KDigitTen = 10;
+const TInt KDigitEleven = 11;
+const TInt KDigitFourTeen = 14;
+const TInt KDigitHundred = 100;
+
+const TInt KMaxDaysInOneMonths = 31;
+const TInt KMaxDaysInTwoMonths = 62;
+const TInt KMaxDaysInThreeMonths = 92;
+const TInt KMaxDaysInFourMonths = 123;
+const TInt KMaxDaysInFiveMonths = 153;
+const TInt KMaxDaysInSixMonths = 184;
+const TInt KMaxDaysInSevenMonths= 215;
+const TInt KMaxDaysInEightMonths = 245;
+const TInt KMaxDaysInNineMonths = 276;
+const TInt KMaxDaysInTenMonths = 306;
+const TInt KMaxDaysInElevenMonths = 337;
+const TInt KMaxDaysInTwelveMonths = 366;
+
+// MACROS
+_LIT( KMPXMetadataEditorRscPath, "mpxmetadataeditordialog.rsc" );
+_LIT( KMPXDrmManagerRscPath, "drmrightsmanager.rsc" );
+_LIT( KMPXSpace, " ");
+
+const TInt KMPXDurationDisplayResvLen( 10 );
+const TInt64 KSecondInMicroSeconds( 1000000 );
+
+// FUNCTION PROTOTYPES
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// ----------------------------------------------------------------------------
+// CMPXQueryDialog::NewL
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXQueryDialog* CMPXQueryDialog::NewL()
+    {
+    CMPXQueryDialog* self = new (ELeave) CMPXQueryDialog();
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXQueryDialog::OfferKeyEventL
+// Keyevent handler.
+// ----------------------------------------------------------------------------
+//
+TKeyResponse CMPXQueryDialog::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
+    {
+    // exit from query dialog whever lost forground, currently implementing by mornitor
+    // application key and end key
+    if (( aKeyEvent.iScanCode == EStdKeyNo ||
+        aKeyEvent.iScanCode == EStdKeyApplication0  &&
+        aType == EEventKey ) ||
+        ( aKeyEvent.iScanCode == EStdKeyApplication6  &&
+        aType == EEventKeyDown ))
+        {
+        TryExitL(EEikBidCancel);
+        return EKeyWasNotConsumed;
+        }
+    else
+        {
+        return CAknQueryDialog::OfferKeyEventL( aKeyEvent,aType );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::NewL
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXMetadataEditorDialog* CMPXMetadataEditorDialog::NewL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::NewL" );
+    CMPXMetadataEditorDialog* self =
+          new (ELeave) CMPXMetadataEditorDialog();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::~CMPXMetadataEditorDialog
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXMetadataEditorDialog::~CMPXMetadataEditorDialog()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::~CMPXMetadataEditorDialog" );
+    delete iEmptyNaviDecorator;
+    delete iTitlePaneText;
+    delete iCommonUiHelper;
+    delete iParam;
+    delete iIdle;
+    delete iDrmInfo;
+    if ( iCollectionUtility )
+        {
+        iCollectionUtility->Close();
+        }
+    if ( iCollectionUiHelper )
+        {
+        iCollectionUiHelper->Close();
+        }
+    if ( iMedia )
+        {
+        delete iMedia;
+        }
+    if ( iTextValues )
+        {
+        delete iTextValues;
+        }
+    if ( iValueTextArray )
+        {
+        delete iValueTextArray;
+        }
+    if ( iGenreArr )
+        {
+        delete iGenreArr;
+        }
+    if ( iLibraryTextValues )
+        {
+        delete iLibraryTextValues;
+        }
+    if ( iLibraryValueTextArray )
+        {
+        delete iLibraryValueTextArray;
+        }
+    if ( iLibraryArr )
+        {
+        delete iLibraryArr;
+        }
+    if ( iResourceOffset )
+        {
+        iEikonEnv->DeleteResourceFile( iResourceOffset );
+        }
+    if ( iDrmResourceOffset )
+        {
+        iEikonEnv->DeleteResourceFile( iDrmResourceOffset );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SetParamL
+// parameter passed in from viewframework
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXMetadataEditorDialog::SetParamL( const TDesC* aParam )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SetParamL" );
+    delete iParam;
+    iParam = NULL;
+    iParam = aParam->AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::OkToExitL
+// This function ALWAYS returns ETrue
+// -----------------------------------------------------------------------------
+//
+TBool CMPXMetadataEditorDialog::OkToExitL(TInt aButtonId)
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::OkToExitL" );
+    TBool res = EFalse;
+
+    switch ( aButtonId )
+        {
+        case EAknSoftkeyDone:
+            {
+            SaveFormDataL();
+            RestoreNaviLabelL();
+            RestoreTitlePaneL();
+            res = ETrue;
+            break;
+            }
+        case EAknSoftkeyExit:
+            {
+            RestoreNaviLabelL();
+            RestoreTitlePaneL();
+            res = ETrue;
+            break;
+            }
+        case EAknSoftkeyOptions:
+        default:
+            {
+            // display the options menu
+            res = CAknForm::OkToExitL( aButtonId );
+            break;
+            }
+        }
+    return res;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::ExecuteLD
+// -----------------------------------------------------------------------------
+//
+TInt CMPXMetadataEditorDialog::ExecuteLD( TInt /*aResourceId*/ )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::ExecuteLD" );
+    TInt resId = R_MPX_CUI_SONG_DETAILS_DIALOG;
+    if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+        {
+        resId = R_MPX_CUI_PODCAST_DETAILS_DIALOG;
+        }
+    else if( iDisablePodcasting )
+        {
+        resId = R_MPX_CUI_SONG_DETAILS_DIALOG_NO_MOVE_LIBRARY;
+        }
+    return CAknForm::ExecuteLD( resId );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::ViewFileDetailsPopupL
+// Display file details popup window
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::ViewFileDetailsPopupL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::ViewFileDetailsPopupL" );
+    CAknDoublePopupMenuStyleListBox* listBox =
+        new (ELeave) CAknDoublePopupMenuStyleListBox();
+    CleanupStack::PushL( listBox );
+    CAknPopupList* popupList = CAknPopupList::NewL(
+                                listBox,
+                                R_AVKON_SOFTKEYS_OK_EMPTY,
+                                AknPopupLayouts::EMenuDoubleWindow );
+    CleanupStack::PushL( popupList );
+
+    listBox->ConstructL( popupList, CEikListBox::ELeftDownInViewRect );
+    listBox->CreateScrollBarFrameL( ETrue );
+    listBox->ScrollBarFrame()->SetScrollBarVisibilityL(
+        CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto );
+
+    // Enable Marquee
+    static_cast<CEikFormattedCellListBox*>
+        ( listBox )->ItemDrawer()->ColumnData()->EnableMarqueeL( ETrue );
+
+    // Retrieve heading array
+    CDesCArrayFlat* headingsArray = NULL;
+    TInt itemCount = 0;
+    if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+        {
+        headingsArray = iCoeEnv->ReadDesCArrayResourceL(
+            R_MPX_CUI_FD_HEADINGS_SONGS );
+        itemCount = EMPXSongsFileDetailsHeadingCount;
+        }
+    else if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+        {
+        headingsArray = iCoeEnv->ReadDesCArrayResourceL(
+            R_MPX_CUI_FD_HEADINGS_PODCASTS );
+        itemCount = EMPXPodcastsFileDetailsHeadingCount;
+        }
+    else
+        {
+        User::Leave( KErrArgument );
+        }
+    CleanupStack::PushL( headingsArray );
+
+    CAknLocalScreenClearer* clearer = CAknLocalScreenClearer::NewLC( EFalse );
+    CDesCArray* itemArray =
+        static_cast<CDesCArray*>( listBox->Model()->ItemTextArray() );
+    CDesCArrayFlat* dataArray =
+        new ( ELeave ) CDesCArrayFlat( itemCount );
+    CleanupStack::PushL( dataArray );
+
+    if ( iMedia )
+        {
+        PopulateFileDetailsL( headingsArray, dataArray );
+        // item count might have been updated due to addition of
+        // DRM content details
+        itemCount = headingsArray->MdcaCount();
+        }
+    else
+        {
+        // properties not available
+        for ( TInt i = 0; i < itemCount; i++ )
+            {
+            dataArray->AppendL( KNullDesC );
+            }
+        }
+
+    for ( TInt i = 0; i < itemCount; i++ )
+        {
+        AddItemToListBoxL( headingsArray->MdcaPoint( i ), dataArray->MdcaPoint( i ), itemArray );
+        }
+    CleanupStack::PopAndDestroy( dataArray );
+    CleanupStack::PopAndDestroy( clearer );
+    CleanupStack::PopAndDestroy( headingsArray );
+
+    // Set title
+    TBuf<KMPXFileDetailsMaxTitleLen> title;
+    iCoeEnv->ReadResourceL( title, R_MPX_CUI_FD_TITLE );
+    popupList->SetTitleL( title );
+
+    // Show popup list
+    popupList->ExecuteLD();
+    CleanupStack::Pop();
+    CleanupStack::PopAndDestroy( listBox );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handle collection message.
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::HandleCollectionMessage(
+    CMPXMessage* /*aMessage*/, TInt /*aError*/ )
+    {
+    // do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handles the collection entries being opened. Typically called
+// when client has Open()'d a folder
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::HandleOpenL(
+    const CMPXMedia& /*aEntries*/,
+    TInt /*aIndex*/, TBool /*aComplete*/, TInt /*aError*/ )
+    {
+    // do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handles the item being opened. Typically called
+// when client has Open()'d an item. Client typically responds by
+// 'playing' the item via the playlist
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::HandleOpenL(
+    const CMPXCollectionPlaylist& /*aPlaylist*/, TInt /*aError*/ )
+    {
+    // do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handle media properties.
+// Notes: The client is responsible for delete the object of aMedia.
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::HandleCollectionMediaL(
+    const CMPXMedia& aMedia,
+    TInt aError )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::HandleCollectionMediaL" );
+    TRAP_IGNORE( DoHandleMediaL( aMedia, aError ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::CMPXMetadataEditorDialog
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ----------------------------------------------------------------------------
+//
+CMPXMetadataEditorDialog::CMPXMetadataEditorDialog()
+    {
+    // do nothing
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::ConstructL
+// Symbian 2nd phase constructor can leave.
+// ----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::ConstructL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::ConstructL" );
+
+    CCoeEnv* coeEnv = iEikonEnv;
+    TParse parse;
+    parse.Set( KMPXMetadataEditorRscPath, &KDC_APP_RESOURCE_DIR, NULL );
+    TFileName resourceFile( parse.FullName() );
+    User::LeaveIfError( MPXUser::CompleteWithDllPath( resourceFile ) );
+    BaflUtils::NearestLanguageFile( coeEnv->FsSession(), resourceFile );
+    iResourceOffset = coeEnv->AddResourceFileL( resourceFile );
+
+    parse.Set( KMPXDrmManagerRscPath, &KDC_APP_RESOURCE_DIR, NULL );
+    TFileName drmResourceFile( parse.FullName() );
+    User::LeaveIfError( MPXUser::CompleteWithDllPath( drmResourceFile ) );
+    BaflUtils::NearestLanguageFile( coeEnv->FsSession(), drmResourceFile );
+    TRAPD(drmResourceError,iDrmResourceOffset = coeEnv->AddResourceFileL( drmResourceFile ));
+    iDrmDetails = (drmResourceError == KErrNone) ? ETrue: EFalse;
+
+    iCollectionUtility = MMPXCollectionUtility::NewL( this, KMcModeDefault );
+    iCommonUiHelper = CMPXCommonUiHelper::NewL();
+
+    CAknForm::ConstructL( R_MPX_CUI_SONG_DETAILS_MENUBAR );
+
+    iCurrentLibrary = EMPXMetadataEditorDlgCollection;
+    // check if it's podcast collection
+    CMPXCollectionPath* cpath = iCollectionUtility->Collection().PathL();
+    CleanupStack::PushL( cpath );
+    if ( cpath->Levels() > 0 )
+        {
+        RArray<TUid> ary;
+        CleanupClosePushL( ary );
+        ary.AppendL( TUid::Uid(EMPXCollectionPluginPodCast) );
+        TUid podcastUid = iCollectionUtility->CollectionIDL( ary.Array() );
+        CleanupStack::PopAndDestroy( &ary );
+
+        if ( cpath->Id( 0 ) == podcastUid.iUid )
+            {
+            MPX_DEBUG1( "CMPXMetadataEditorDialog::ConstructL Podcast collection" );
+            iCurrentLibrary = EMPXMetadataEditorDlgPodcast;
+            }
+        }
+    iCollectionUiHelper = CMPXCollectionHelperFactory::NewCollectionUiHelperL();
+    CleanupStack::PopAndDestroy( cpath );
+
+    // Get podcasting key
+    TInt val(0);
+    CRepository* repository = CRepository::NewL( KCRUidMPXMPFeatures );
+    repository->Get( KMPXMPLocalVariation, val );
+    iDisablePodcasting = val&KMPXDisablePodcastingOption ? ETrue : EFalse;
+    delete repository;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::CleanUpGenreText
+// Clean up function for genre related members.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::CleanUpGenreText()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::CleanUpGenreText" );
+
+    if ( iGenreArr )
+        {
+        delete iGenreArr;
+        iGenreArr = NULL;
+        }
+    if ( iValueTextArray )
+        {
+        delete iValueTextArray;
+        iValueTextArray = NULL;
+        }
+    if ( iTextValues )
+        {
+        delete iTextValues;
+        iTextValues = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::FetchGenreL
+// Populates genre popup with genre list for tracks.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::FetchGenreL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::FetchGenreL" );
+    RArray<TMPXAttribute> attrs;
+    CleanupClosePushL( attrs );
+    attrs.Append( KMPXMediaGeneralTitle );
+    CMPXMedia* criteria = CMPXMedia::NewL();
+    CleanupStack::PushL( criteria );
+    criteria->SetTObjectValueL<TUid>(
+        KMPXMediaGeneralCollectionId, TUid::Uid( 0x101FFC3A ) );
+    criteria->SetTObjectValueL<TMPXGeneralType>(
+        KMPXMediaGeneralType, EMPXGroup );
+    criteria->SetTObjectValueL<TMPXGeneralCategory>(
+        KMPXMediaGeneralCategory, EMPXGenre );
+    iCollectionUtility->Collection().FindAllL( *criteria, attrs.Array(), *this );
+    CleanupStack::PopAndDestroy( criteria );
+    CleanupStack::PopAndDestroy( &attrs );
+    }
+
+// ---------------------------------------------------------------------------
+// Handle media properties.
+// ---------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::DoHandleMediaL(
+    const CMPXMedia& aMedia,
+    TInt aError )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::DoHandleMediaL" );
+
+    if ( iCurrentMediaLOp == EMPXMetadataEditorGetSongInfo )
+        {
+        delete iMedia;
+        iMedia = NULL;
+        if ( aError == KErrNone )
+            {
+            iMedia = CMPXMedia::NewL( aMedia );
+            // common for both music and podcast
+            // Fetch the artist
+
+            if ( iMedia->IsSupported( KMPXMediaDrmProtected ) )
+                {
+                iIsDrmProtected = iMedia->ValueTObjectL<TBool>( KMPXMediaDrmProtected );
+                }
+
+            SetControlTextL( EMPXMetadataEditorDlgCtrlIdArtist,
+                iMedia->ValueText( KMPXMediaMusicArtist ), KNullDesC );
+
+            // Fetch the album
+            SetControlTextL( EMPXMetadataEditorDlgCtrlIdAlbum,
+                iMedia->ValueText( KMPXMediaMusicAlbum ), KNullDesC );
+
+            // Fetch the track number
+            SetControlNumberL( EMPXMetadataEditorDlgCtrlIdTrackNumber,
+                iMedia->ValueText( KMPXMediaMusicAlbumTrack ),
+                KMPXSongDetailsTrackNumMin, KMPXSongDetailsTrackNumMax );
+
+            // Fetch the year
+            TInt64 year(0);
+            if ( iMedia->IsSupported (KMPXMediaMusicYear ) )
+                {
+                year = iMedia->ValueTObjectL<TInt64>( KMPXMediaMusicYear );
+                }
+            TTime yearTime( year);
+            iYear = yearTime.DateTime().Year ( );
+            HBufC* yearBuf = HBufC::NewLC ( KMPXMaxTimeLength );
+            yearBuf->Des().AppendNum ( iYear );
+            SetControlNumberL ( EMPXMetadataEditorDlgCtrlIdYear, *yearBuf,
+                    KMPXSongDetailsYearMin, KMPXSongDetailsYearMax );
+            CleanupStack::PopAndDestroy ( yearBuf );
+
+            // Fetch genre
+            FetchGenreL();
+
+            // Fetch the comment
+            SetControlTextL( EMPXMetadataEditorDlgCtrlIdComment,
+                iMedia->ValueText( KMPXMediaGeneralComment ), KNullDesC );
+
+            // Fetch the song name
+            TParsePtrC fileDetail( iMedia->ValueText( KMPXMediaGeneralUri ) );
+            SetControlTextL( EMPXMetadataEditorDlgCtrlIdSongName,
+                iMedia->ValueText( KMPXMediaGeneralTitle ), fileDetail.Name() );
+
+            if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+                {
+                // Fetch the composer
+                SetControlTextL( EMPXMetadataEditorDlgCtrlIdComposer,
+                    iMedia->ValueText( KMPXMediaMusicComposer ), KNullDesC );
+                }
+            DrawNow();
+            }
+        else
+            {
+            // if error getting metadata, exit editor
+            iCommonUiHelper->HandleErrorL( aError );
+            if ( iIdle )
+                {
+                iIdle->Cancel();
+                delete iIdle;
+                iIdle = NULL;
+                }
+            iIdle = CIdle::NewL( CActive::EPriorityStandard );
+            iIdle->Start( TCallBack( CMPXMetadataEditorDialog::DeferredExitCallback, this ) );
+            }
+        }
+    else if ( iCurrentMediaLOp == EMPXMetadataEditorGetDrmInfo )
+        {
+        delete iDrmInfo;
+        iDrmInfo = NULL;
+        if ( aError == KErrNone )
+            {
+            iDrmInfo = CMPXMedia::NewL( aMedia );
+            }
+        else
+            {
+            iDrmInfo = CMPXMedia::NewL();
+            }
+        if ( iIdle )
+            {
+            iIdle->Cancel();
+            delete iIdle;
+            iIdle = NULL;
+            }
+        iIdle = CIdle::NewL( CActive::EPriorityStandard );
+        iIdle->Start( TCallBack( CMPXMetadataEditorDialog::DeferredFileDetailsCallback, this ) );
+        }
+    else
+        {
+        // Should not reach here
+        ASSERT( 0 );
+        }
+    iCurrentMediaLOp = EMPXMetadataEditorIdle;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SaveFormDataL
+// Save form data.
+// ----------------------------------------------------------------------------
+//
+TBool CMPXMetadataEditorDialog::SaveFormDataL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SaveFormDataL" );
+    if ( iMedia )
+        {
+        MPX_DEBUG1( "CMPXMetadataEditorDialog::SaveFormDataL Saving.." );
+        CMPXMedia* media = CMPXMedia::NewL();
+        CleanupStack::PushL( media );
+
+        TBool changed = EFalse;
+
+        // common to both music and podcast
+        // update local copy of media as well because getting media prop is slow
+        changed = UpdateMediaObjectWithControlL( EMPXMetadataEditorDlgCtrlIdSongName,
+            media, KMPXMediaGeneralTitle );
+
+        changed = UpdateMediaObjectWithControlL( EMPXMetadataEditorDlgCtrlIdArtist,
+            media, KMPXMediaMusicArtist ) || changed;
+
+        changed = UpdateMediaObjectWithControlL( EMPXMetadataEditorDlgCtrlIdAlbum,
+            media, KMPXMediaMusicAlbum ) || changed;
+
+        changed = UpdateMediaObjectWithControlL( EMPXMetadataEditorDlgCtrlIdTrackNumber,
+            media, KMPXMediaMusicAlbumTrack ) || changed;
+
+        changed = UpdateMediaObjectWithControlL( EMPXMetadataEditorDlgCtrlIdComment,
+            media, KMPXMediaGeneralComment ) || changed;
+
+        // special handling needed for year
+        CCoeControl* coeControl = ControlOrNull( EMPXMetadataEditorDlgCtrlIdYear );
+        if ( coeControl )
+            {
+            CEikNumberEditor* control = static_cast<CEikNumberEditor*>( coeControl );
+            if ( control )
+                {
+                TInt num = control->Number();
+                if ( num != iYear )
+                    {
+                    MPX_DEBUG3( "CMPXMetadataEditorDialog::SaveFormDataL year changed from %d to %d", iYear, num );
+                    TDateTime newYear;
+                    newYear.Set( num, EJanuary, 0, 0, 0, 0, 0 );
+                    TTime year( newYear );
+                    iMedia->SetTObjectValueL<TInt64>(
+                        KMPXMediaMusicYear, year.Int64() );
+                    media->SetTObjectValueL<TInt64>(
+                        KMPXMediaMusicYear, year.Int64() );
+                    iYear = num;
+                    changed = ETrue;
+                    }
+                else
+                    {
+                    MPX_DEBUG1( "CMPXMetadataEditorDialog::SaveFormDataL year not changed" );
+                    }
+                }
+            }
+
+        if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+            {
+            changed = UpdateMediaObjectWithControlL( EMPXMetadataEditorDlgCtrlIdComposer,
+                media, KMPXMediaMusicComposer ) || changed;
+            }
+        else if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+            {
+            // no special handling, all covered in common
+            }
+        if ( changed )
+            {
+            // save it back to collection engine
+            SaveMediaPropertiesL( media );
+            MPX_DEBUG1( "CMPXMetadataEditorDialog::SaveFormDataL Saved" );
+            }
+#ifdef _DEBUG
+        else
+            {
+            MPX_DEBUG1( "CMPXMetadataEditorDialog::SaveFormDataL All equal, not saved" );
+            }
+#endif
+        CleanupStack::PopAndDestroy( media );
+        }
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::DoNotSaveFormDataL
+// Does not save form data.
+// ----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::DoNotSaveFormDataL()
+    {
+    // Do nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SetTitlePane
+// Set Title Pane from descriptor.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::SetTitlePaneL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SetTitlePaneL" );
+    // Saving the current title before it's overwritten
+    CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
+
+    iTitlePane =
+        static_cast<CAknTitlePane*>
+            ( statusPane->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) );
+    const TDesC* text = iTitlePane->Text();
+    iTitlePaneText = text->AllocL();
+
+    HBufC* newText = NULL;
+    if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+        {
+        newText = StringLoader::LoadLC( R_MPX_CUI_SONG_DETAILS_TITLE );
+        }
+    else if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+        {
+        newText = StringLoader::LoadLC( R_MPX_CUI_SONG_DETAILS_EPISODE );
+        }
+
+    // Update Title Pane
+    if ( newText )
+        {
+        iTitlePane->SetTextL( *newText );
+        }
+    CleanupStack::PopAndDestroy( newText );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::RestoreTitlePane
+// Restore Title Pane from the member data.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::RestoreTitlePaneL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::RestoreTitlePaneL" );
+    // Update Title Pane
+    iTitlePane->SetTextL( *iTitlePaneText );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SetNaviLabelL
+// Set Navi Label from descriptor.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::SetNaviLabelL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SetNaviLabelL" );
+    MAknEditingStateIndicator *editingStateIndicator = CAknEnv::Static()->EditingStateIndicator();
+    CAknIndicatorContainer* indicContainerEditing = editingStateIndicator->IndicatorContainer();
+    indicContainerEditing->SetIndicatorValueL( TUid::Uid( EAknNaviPaneEditorIndicatorMessageInfo), KNullDesC );
+    // Saving the current title before it's overwritten
+    CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
+
+    iNaviPane = static_cast<CAknNavigationControlContainer*>
+        ( statusPane->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) );
+
+    // store the latest navi pane
+    iNaviDecorator = iNaviPane->Top();
+
+    // set the new navi label
+    iEmptyNaviDecorator =
+        iNaviPane->CreateNavigationLabelL(KNullDesC);
+
+    iNaviPane->PushL( *iEmptyNaviDecorator );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::RestoreNaviLabelL
+// Restore Navi Label from the member data.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::RestoreNaviLabelL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::RestoreNaviLabelL" );
+    iNaviPane->Pop( iEmptyNaviDecorator ); // pop out the empty navi
+    if ( iNaviDecorator )
+        {
+        iNaviPane->PushL( *iNaviDecorator );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::DynInitMenuPaneL
+// Dynamically initialises a menu pane.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::DynInitMenuPaneL(
+    TInt aResourceId,
+    CEikMenuPane* aMenuPane)
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::DynInitMenuPaneL" );
+    CAknForm::DynInitMenuPaneL(aResourceId, aMenuPane);
+
+    if ( aResourceId == R_AVKON_FORM_MENUPANE )
+        {
+        if ( ( IdOfFocusControl() == EMPXMetadataEditorDlgCtrlIdGenre ) ||
+            ( IdOfFocusControl() == EMPXMetadataEditorDlgCtrlIdLibrary ) )
+            {
+            aMenuPane->SetItemDimmed( EMPXCmdSongDetailsChange, EFalse );
+            }
+        else
+            {
+            aMenuPane->SetItemDimmed( EMPXCmdSongDetailsChange, ETrue );
+            }
+        // Dim out the Avkon menu items
+        aMenuPane->SetItemDimmed( EAknFormCmdEdit, ETrue );
+        aMenuPane->SetItemDimmed( EAknFormCmdAdd, ETrue );
+        aMenuPane->SetItemDimmed( EAknFormCmdSave, ETrue );
+        aMenuPane->SetItemDimmed( EAknFormCmdLabel, ETrue );
+        aMenuPane->SetItemDimmed( EAknFormCmdDelete, ETrue );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::ProcessCommandL
+// Act on the menu selection if menu is showing.
+// ----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::ProcessCommandL( TInt aCommandId )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::ProcessCommandL" );
+    CAknForm::ProcessCommandL(aCommandId);
+
+    switch (aCommandId)
+        {
+        case EMPXCmdSongDetailsChange:
+            {
+            if ( IdOfFocusControl() == EMPXMetadataEditorDlgCtrlIdGenre )
+                {
+                iPopup = static_cast<CAknPopupField*>
+                    ( ControlOrNull( EMPXMetadataEditorDlgCtrlIdGenre ) );
+                }
+            else if ( IdOfFocusControl() == EMPXMetadataEditorDlgCtrlIdLibrary )
+                {
+                iPopup = static_cast<CAknPopupField*>
+                    ( ControlOrNull( EMPXMetadataEditorDlgCtrlIdLibrary ) );
+                }
+            if ( iPopup )
+                {
+                iPopup->ActivateSelectionListL();
+                }
+
+            break;
+            }
+        case EMPXCmdSongDetails:
+            {
+            if ( iIsDrmProtected && !iDrmInfo )
+                {
+                CMPXCollectionPath* cpath = iCollectionUtility->Collection().PathL();
+                CleanupStack::PushL( cpath );
+                if ( iParam )
+                    {
+                    TLex yearLex( iParam->Des() );
+                    TInt lexToInt = NULL;
+                    if ( yearLex.Val( lexToInt ) == KErrNone )
+                        {
+                        cpath->Set( lexToInt );
+                        RArray<TMPXAttribute> attrs;
+                        CleanupClosePushL(attrs);
+                        attrs.Append( KMPXMediaGeneralUri );
+                        attrs.Append( KMPXMediaDrmAll );
+                        iCurrentMediaLOp = EMPXMetadataEditorGetDrmInfo;
+                        iCollectionUtility->Collection().MediaL( *cpath, attrs.Array() );
+                        CleanupStack::PopAndDestroy( &attrs );
+                        }
+                    }
+                CleanupStack::PopAndDestroy( cpath );
+                }
+            else
+                {
+                if( iMedia )
+                    {
+                    ViewFileDetailsPopupL();
+                    }
+                }
+            break;
+            }
+        case EAknCmdHelp:
+            {
+            TCoeHelpContext helpContext;
+            GetHelpContext( helpContext );
+
+            CArrayFixFlat<TCoeHelpContext>* array =
+                new(ELeave)CArrayFixFlat<TCoeHelpContext>( 1 );
+
+            CleanupStack::PushL( array );
+            array->AppendL( helpContext );
+            CleanupStack::Pop(); // array
+
+            // HlpLauncher deletes array
+            HlpLauncher::LaunchHelpApplicationL( iEikonEnv->WsSession(), array );
+            break;
+            }
+        case EAknCmdExit:
+            {
+            static_cast<MEikCommandObserver*>(iEikonEnv->EikAppUi())->
+                ProcessCommandL(aCommandId);
+            }
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::PopulateFileDetailsL
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::PopulateFileDetailsL(
+    CDesCArrayFlat* aHeadingsArray, CDesCArrayFlat* aDataArray )
+    {
+
+    MPX_FUNC( "CMPXMetadataEditorDialog::PopulateFileDetailsL" );
+
+    TBool drmProtected( iMedia->ValueTObjectL<TBool>( KMPXMediaDrmProtected ) );
+    MPX_DEBUG2( "CMPXMetadataEditorDialog::PopulateFileDetailsL drm protected: %d", drmProtected );
+
+    if ( drmProtected )
+        {
+        MakeDrmItemsL( aHeadingsArray, aDataArray );
+        }
+
+    // Get filename
+    const TDesC& uri = iMedia->ValueText( KMPXMediaGeneralUri );
+    TParsePtrC parse(uri);
+
+    AppendStringToArrayL( aDataArray, parse.Name() );
+
+    // Get mime type
+    const TDesC& mimeType = iMedia->ValueText( KMPXMediaGeneralMimeType );
+    AppendStringToArrayL( aDataArray, mimeType );
+
+    // Get duration
+    TInt duration( iMedia->ValueTObjectL<TInt>( KMPXMediaGeneralDuration ) );
+    if ( duration > 0 )
+        {
+        // convert milliseconds to seconds
+        duration = duration / KSecondInMilliseconds;
+        CMPXCommonUiHelper::TMPXDuratDisplayMode durationMode =
+            CMPXCommonUiHelper::EMPXDuratAuto;
+        if ( duration > KOneHourInSeconds )
+            {
+            durationMode = CMPXCommonUiHelper::EMPXDuratHMS;
+            }
+        HBufC* stringBuf = iCommonUiHelper->DisplayableDurationL(
+            duration, durationMode );
+        CleanupStack::PushL( stringBuf );
+        aDataArray->AppendL( *stringBuf );
+        CleanupStack::PopAndDestroy( stringBuf );
+        }
+    else
+        {
+        aDataArray->AppendL( KNullDesC );
+        }
+
+    // Get bitrate
+    TInt bitrate( iMedia->ValueTObjectL<TInt>( KMPXMediaAudioBitrate ) );
+    if ( bitrate > 0 )
+        {
+        // convert bitrate to kpbs
+        bitrate = bitrate / KMPXBitrateFactor;
+        HBufC* bitrateText = StringLoader::LoadLC(
+                        R_MPX_CUI_METADATAEDITOR_BITRATE_TXT, bitrate );
+        aDataArray->AppendL( bitrateText->Des() );
+        CleanupStack::PopAndDestroy( bitrateText );
+        }
+    else
+        {
+        aDataArray->AppendL( KNullDesC );
+        }
+
+    // Get sampling rate
+    TInt samplingRateNum( ( TInt )iMedia->ValueTObjectL<TInt>( KMPXMediaAudioSamplerate ) );
+    if ( samplingRateNum > 0 )
+        {
+        HBufC* stringBuf = HBufC::NewLC( KMPXFileDetailsMaxBufferLen );
+        TPtr stringBufPtr = stringBuf->Des();
+        stringBufPtr.AppendNum( samplingRateNum );
+        HBufC* samplingrate = StringLoader::LoadLC(
+                        R_MPX_CUI_METADATAEDITOR_SAMPLINGRATE_TXT, stringBufPtr );
+        aDataArray->AppendL( samplingrate->Des() );
+        CleanupStack::PopAndDestroy( samplingrate );
+        CleanupStack::PopAndDestroy( stringBuf );
+        }
+    else
+        {
+        aDataArray->AppendL( KNullDesC );
+        }
+
+    // Get size, not stored in collection, have to use RFile
+    //
+    RFs& fs = CEikonEnv::Static()->FsSession();
+    RFile file;
+    TInt sizeNum(0);
+    TInt err ( file.Open( fs, uri, EFileRead | EFileShareReadersOrWriters ) );
+    if ( err == KErrNone )
+        {
+        file.Size(sizeNum);
+        file.Close();
+        }
+
+    if ( sizeNum > 0 )
+        {
+        HBufC* stringBuf = iCommonUiHelper->UnitConversionL( sizeNum );
+        CleanupStack::PushL( stringBuf );
+        aDataArray->AppendL( *stringBuf );
+        CleanupStack::PopAndDestroy( stringBuf );
+        }
+    else
+        {
+        aDataArray->AppendL( KNullDesC );
+        }
+
+    if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+        {
+        PopulatePodcastFileDetailsL( aHeadingsArray, aDataArray );
+        }
+
+    // Get modified
+    if ( iMedia->IsSupported( KMPXMediaGeneralDate ) )
+        {
+        TInt64 timeInt( ( TInt64 )iMedia->ValueTObjectL<TInt64>(
+            KMPXMediaGeneralDate ) );
+        TTime time( timeInt );
+        ConvertToLocalTimeL(time);
+        HBufC* modDateTime = HBufC::NewLC(
+            KMPXMaxTimeLength + KMPXDurationDisplayResvLen );
+        HBufC* format = StringLoader::LoadLC(
+            R_QTN_DATE_USUAL_WITH_ZERO );
+        TPtr modDatePtr = modDateTime->Des();
+        MPX_TRAPD( err, time.FormatL( modDatePtr, *format ) );
+        CleanupStack::PopAndDestroy( format );
+        if (err != KErrNone)
+            {
+            aDataArray->AppendL( KNullDesC );
+            }
+        else
+            {
+            format = StringLoader::LoadLC(
+                R_QTN_TIME_USUAL_WITH_ZERO );
+            HBufC* modTime = HBufC::NewLC(
+                format->Length() + KMPXDurationDisplayResvLen );
+            TPtr modTimePtr = modTime->Des();
+            MPX_TRAPD( err, time.FormatL( modTimePtr, *format ) );
+            if ( err != KErrNone )
+                {
+                aDataArray->AppendL( KNullDesC );
+                }
+            else
+                {
+                modDatePtr.Append( KMPXSpace );
+                modDatePtr.Append( modTimePtr );
+                aDataArray->AppendL( modDatePtr );
+                }
+            CleanupStack::PopAndDestroy( modTime );
+            CleanupStack::PopAndDestroy( format );
+            }
+        CleanupStack::PopAndDestroy( modDateTime );
+        }
+    else
+        {
+        aDataArray->AppendL( KNullDesC );
+        }
+
+    // Get filename
+    AppendStringToArrayL( aDataArray, iMedia->ValueText(
+        KMPXMediaGeneralCopyright ) );
+
+    // Get URL
+    AppendStringToArrayL( aDataArray, iMedia->ValueText(
+        KMPXMediaMusicURL ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::PopulatePodcastFileDetailsL
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::PopulatePodcastFileDetailsL(
+    CDesCArrayFlat* /*aHeadingsArray*/, CDesCArrayFlat* aDataArray )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::PopulatePodcastFileDetailsL" );
+    // Get last playback position
+
+    TInt lastPbPosition( ( TInt )iMedia->ValueTObjectL<TInt>(
+        KMPXMediaGeneralLastPlaybackPosition ) );
+
+    if ( lastPbPosition > 0 )
+        {
+        // convert milliseconds to seconds
+        lastPbPosition = lastPbPosition / KSecondInMilliseconds;
+        CMPXCommonUiHelper::TMPXDuratDisplayMode lastPbPositionMode =
+            CMPXCommonUiHelper::EMPXDuratAuto;
+        if ( lastPbPosition > KOneHourInSeconds )
+            {
+            lastPbPositionMode = CMPXCommonUiHelper::EMPXDuratHMS;
+            }
+        HBufC* stringBuf = iCommonUiHelper->DisplayableDurationL(
+            lastPbPosition, lastPbPositionMode );
+        CleanupStack::PushL( stringBuf );
+        aDataArray->AppendL( *stringBuf );
+        CleanupStack::PopAndDestroy( stringBuf );
+        }
+    else if(lastPbPosition == 0 &&
+            iMedia->IsSupported(KMPXMediaGeneralPlayCount) &&
+            iMedia->ValueTObjectL<TInt>(KMPXMediaGeneralPlayCount) > 0 )
+        {
+        HBufC* stringBuf = StringLoader::LoadLC( R_MPX_CUI_METADATAEDITOR_PLAYBACK_COMPLETE );
+        aDataArray->AppendL( *stringBuf );
+        CleanupStack::PopAndDestroy( stringBuf );
+
+        }
+    else
+        {
+        aDataArray->AppendL( KNullDesC );
+        }
+
+
+    // Get published
+    if ( iMedia->IsSupported( TMPXAttribute( KMPXMediaIdPodcast,
+            EMPXMediaPodcastPubDate ) ) )
+        {
+        TInt64 timeInt( ( TInt64 )iMedia->ValueTObjectL<TInt64>(
+            TMPXAttribute( KMPXMediaIdPodcast, EMPXMediaPodcastPubDate ) ) );
+        TTime time( timeInt );
+        ConvertToLocalTimeL(time);
+        HBufC* modDateTime = HBufC::NewLC(
+            KMPXMaxTimeLength + KMPXDurationDisplayResvLen );
+        HBufC* format = StringLoader::LoadLC(
+            R_QTN_DATE_USUAL_WITH_ZERO );
+        TPtr modDatePtr = modDateTime->Des();
+        MPX_TRAPD( err, time.FormatL( modDatePtr, *format ) );
+        CleanupStack::PopAndDestroy( format );
+        if (err != KErrNone ||
+            time == 0)
+            {
+            aDataArray->AppendL( KNullDesC );
+            }
+        else
+            {
+            format = StringLoader::LoadLC(
+                R_QTN_TIME_USUAL_WITH_ZERO );
+            HBufC* modTime = HBufC::NewLC(
+                format->Length() + KMPXDurationDisplayResvLen );
+            TPtr modTimePtr = modTime->Des();
+            MPX_TRAPD( err, time.FormatL( modTimePtr, *format ) );
+            if ( err != KErrNone )
+                {
+                aDataArray->AppendL( KNullDesC );
+                }
+            else
+                {
+                modDatePtr.Append( KMPXSpace );
+                modDatePtr.Append( modTimePtr );
+                aDataArray->AppendL( modDatePtr );
+                }
+            CleanupStack::PopAndDestroy( modTime );
+            CleanupStack::PopAndDestroy( format );
+            }
+        CleanupStack::PopAndDestroy( modDateTime );
+        }
+    else
+        {
+        aDataArray->AppendL( KNullDesC );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::MakeDrmItemsL
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::MakeDrmItemsL(
+    CDesCArrayFlat* aHeadingsArray, CDesCArrayFlat* aDataArray )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::MakeDrmItemsL" );
+    if (iDrmDetails )
+        {
+        TInt itemCount( 0);
+        if ( iDrmInfo->IsSupported( KMPXMediaDrmType ) )
+            {
+            MPX_DEBUG2( "CMPXMetadataEditorDialog::MakeDrmItemsL drm type: %d",
+                    iDrmInfo->ValueTObjectL<TInt>( KMPXMediaDrmType ) );
+            TInt rightStatus( iDrmInfo->ValueTObjectL<TInt>( KMPXMediaDrmRightsStatus ) );
+            HBufC* rights( StringLoader::LoadLC( R_QTN_DRM_MGR_DET2_PLAY ) );
+            HBufC* heading( NULL);
+            HBufC* value( NULL);
+
+            switch ( rightStatus )
+                {
+                case EMPXDrmRightsFull:
+                    {
+                    // status
+                    heading = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_STAT );
+                    value = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_VALID );
+                    aHeadingsArray->InsertL ( itemCount, heading->Des ( ) );
+                    aDataArray->InsertL ( itemCount, value->Des ( ) );
+                    CleanupStack::PopAndDestroy ( value );
+                    CleanupStack::PopAndDestroy ( heading );
+                    itemCount++;
+
+                    // full rights
+                    heading = StringLoader::LoadLC (
+                        R_QTN_DRM_MGR_DET_FULL_X, *rights );
+                    value = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_UNLIMITED );
+                    aHeadingsArray->InsertL ( itemCount, heading->Des ( ) );
+                    aDataArray->InsertL ( itemCount, value->Des ( ) );
+                    CleanupStack::PopAndDestroy ( value );
+                    CleanupStack::PopAndDestroy ( heading );
+                    itemCount++;
+                    break;
+                    }
+                case EMPXDrmRightsRestricted:
+                case EMPXDrmRightsPreview:
+                    {
+                    // status
+                    heading = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_STAT );
+                    value = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_VALID );
+                    aHeadingsArray->InsertL ( itemCount, heading->Des ( ) );
+                    aDataArray->InsertL ( itemCount, value->Des ( ) );
+                    CleanupStack::PopAndDestroy ( value );
+                    CleanupStack::PopAndDestroy ( heading );
+                    itemCount++;
+                    // rights
+                    MakeRestrictedDrmItemsL(
+                        rights, itemCount, aHeadingsArray, aDataArray );
+                    break;
+                    }
+                case EMPXDrmRightsMissing:
+                    {
+                    // status
+                    heading = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_STAT );
+                    value = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_EXP );
+                    aHeadingsArray->InsertL ( itemCount, heading->Des ( ) );
+                    aDataArray->InsertL ( itemCount, value->Des ( ) );
+                    CleanupStack::PopAndDestroy ( value );
+                    CleanupStack::PopAndDestroy ( heading );
+                    itemCount++;
+                    break;
+                    }
+                case EMPXDrmRightsExpired:
+                    {
+                    // status
+                    heading = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_STAT );
+                    value = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_EXP );
+                    aHeadingsArray->InsertL ( itemCount, heading->Des ( ) );
+                    aDataArray->InsertL ( itemCount, value->Des ( ) );
+                    CleanupStack::PopAndDestroy ( value );
+                    CleanupStack::PopAndDestroy ( heading );
+                    itemCount++;
+                    // make rest of the drm items
+                    MakeRestrictedDrmItemsL(
+                        rights, itemCount, aHeadingsArray, aDataArray );
+                    break;
+                    }
+                default:
+                    {
+                    break;
+                    }
+                }
+
+            heading = NULL;
+            value = NULL;
+
+            // sending
+            heading = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_CS );
+            TBool forwardAllowed( iDrmInfo->ValueTObjectL<TBool>( KMPXMediaDrmSendingAllowed ) );
+            if ( forwardAllowed )
+                {
+                value = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_ALLOWED );
+                }
+            else
+                {
+                value = StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_FORBID );
+                }
+            aHeadingsArray->InsertL ( itemCount, heading->Des ( ) );
+            aDataArray->InsertL ( itemCount, value->Des ( ) );
+            CleanupStack::PopAndDestroy ( value );
+            CleanupStack::PopAndDestroy ( heading );
+            CleanupStack::PopAndDestroy ( rights ); // heading, value, rights
+            }
+        else
+            {
+            // if error getting drm info, drm type will not be valid
+            // by default assume the rights are invalid (since we can't read it)
+            MPX_DEBUG1( "CMPXMetadataEditorDialog::MakeDrmItemsL unable to get drm data" );
+            HBufC* heading( StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_STAT ));
+            HBufC* value( StringLoader::LoadLC ( R_QTN_DRM_MGR_DET_INVALID ));
+            aHeadingsArray->InsertL ( 0, heading->Des ( ) );
+            aDataArray->InsertL ( 0, value->Des ( ) );
+            CleanupStack::PopAndDestroy ( value );
+            CleanupStack::PopAndDestroy ( heading );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(
+    HBufC* aRights, TInt& aCurrentIndex,
+    CDesCArrayFlat* aHeadingsArray, CDesCArrayFlat* aDataArray )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL" );
+    TMPXMediaDrmRightsType expireConstraint( EMPXDrmRightsTypeNoRestriction );
+    if ( iDrmInfo->IsSupported( KMPXMediaDrmRightsType ) )
+        {
+        expireConstraint = iDrmInfo->ValueTObjectL<TMPXMediaDrmRightsType>(
+            KMPXMediaDrmRightsType );
+        }
+    MPX_DEBUG2("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): ExpireConstraint = %d", expireConstraint);
+    TInt64 intervalTime( KErrNotFound );
+    if ( iDrmInfo->IsSupported( KMPXMediaDrmIntervalStartTime ) )
+        {
+        MPX_DEBUG1("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): Interval Start Time");
+        intervalTime = (TInt64)iDrmInfo->ValueTObjectL<TInt64>( KMPXMediaDrmIntervalStartTime );
+        }
+    HBufC* heading = NULL;
+    HBufC* value = NULL;
+    // acculated time 
+    if ( expireConstraint ==  EMPXDrmRightsTypeAccTime )
+      	{
+      	MPX_DEBUG1("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): AccTime based");
+        heading = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_ACCUM_TIME_LEFT  );
+
+        TTimeIntervalSeconds  accTime = iDrmInfo->ValueTObjectL<TTimeIntervalSeconds>(  KMPXMediaDrmAccumulatedTime );
+        TInt years( 0 );
+        TInt months( 0 );
+        TInt days( 0 );
+        TInt hours( 0 );
+        TInt minutes( 0 );
+        TInt seconds( 0 );
+        SplitTime( accTime, years, months, days, hours, minutes, seconds );
+        value = AddPartsOfTimeLC( years, months, days, hours, minutes, seconds );      
+        
+        TPtr text = value->Des();
+        LanguageSpecificNumberConversion( text );   
+      	aHeadingsArray->InsertL( aCurrentIndex, heading->Des() );  
+        aDataArray->InsertL( aCurrentIndex, value->Des() ); 
+        
+        CleanupStack::PopAndDestroy( value );
+        CleanupStack::PopAndDestroy( heading );         
+        aCurrentIndex++;   
+      	}
+
+    // count
+    if ( expireConstraint == EMPXDrmRightsTypeCount ||
+         expireConstraint == EMPXDrmRightsTypeTimeCount )
+        {
+        MPX_DEBUG1("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): Count based");
+        heading = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_UTL_X, *aRights );
+
+        TInt counts( iDrmInfo->ValueTObjectL<TInt>( KMPXMediaDrmCount ) );
+        if ( counts == 1 )
+            {
+            value = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_1_COUNT );
+            }
+        else
+            {
+            value = StringLoader::LoadLC(
+                R_QTN_DRM_MGR_DET_N_COUNTS, counts );
+            }
+        TPtr text = value->Des();
+        LanguageSpecificNumberConversion( text );
+        aHeadingsArray->InsertL( aCurrentIndex, heading->Des() );
+        aDataArray->InsertL( aCurrentIndex, value->Des() );
+        CleanupStack::PopAndDestroy( value );
+        CleanupStack::PopAndDestroy( heading );
+        aCurrentIndex++;
+        }
+
+    if ( expireConstraint == EMPXDrmRightsTypeTime ||
+         expireConstraint == EMPXDrmRightsTypeTimeCount ||
+         ( expireConstraint == EMPXDrmRightsTypeInterval &&
+         intervalTime > 0 ) )
+        {
+        MPX_DEBUG1("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): Time based");
+        HBufC* dateFormatString = StringLoader::LoadLC(
+                R_QTN_DATE_USUAL_WITH_ZERO );
+        HBufC* timeFormatString = StringLoader::LoadLC( R_QTN_TIME_USUAL );
+
+        // from
+        if ( iDrmInfo->IsSupported( KMPXMediaDrmStartTime ) )
+            {
+            MPX_DEBUG1("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): Start time found");
+            TTime from( iDrmInfo->ValueTObjectL<TInt64>( KMPXMediaDrmStartTime ) );
+            heading = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_RVF_X, *aRights );
+            HBufC* datePointer = HBufC::NewLC( KMaxFileName );
+            TPtr date = datePointer->Des();
+            from.FormatL( date, *dateFormatString );
+            TBuf<KMPXMaxTimeLength> time;
+            from.FormatL( time, *timeFormatString );
+            date.Append( KMPXSpace );
+            date.Append( time );
+            LanguageSpecificNumberConversion( date );
+            aHeadingsArray->InsertL( aCurrentIndex, heading->Des() );
+            aDataArray->InsertL( aCurrentIndex, date );
+            CleanupStack::PopAndDestroy( datePointer );
+            CleanupStack::PopAndDestroy( heading );
+            aCurrentIndex++;
+            }
+
+        // until
+        if ( iDrmInfo->IsSupported( KMPXMediaDrmEndTime ) )
+            {
+            MPX_DEBUG1("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): End time found");
+            TTime until( iDrmInfo->ValueTObjectL<TInt64>( KMPXMediaDrmEndTime ) );
+            heading = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_RVT_X, *aRights );
+            HBufC* dateToPntr = HBufC::NewLC( KMaxFileName );
+            TPtr dateTo = dateToPntr->Des();
+            until.FormatL( dateTo, *dateFormatString );
+            TBuf<KMPXMaxTimeLength> timeTo;
+            until.FormatL( timeTo, *timeFormatString );
+            dateTo.Append( KMPXSpace );
+            dateTo.Append( timeTo );
+            LanguageSpecificNumberConversion( dateTo );
+            aHeadingsArray->InsertL( aCurrentIndex, heading->Des() );
+            aDataArray->InsertL( aCurrentIndex, dateTo );
+            CleanupStack::PopAndDestroy( dateToPntr );
+            CleanupStack::PopAndDestroy( heading );
+            aCurrentIndex++;
+            }
+        CleanupStack::PopAndDestroy( timeFormatString );
+        CleanupStack::PopAndDestroy( dateFormatString );
+        }
+    else if ( expireConstraint == EMPXDrmRightsTypeInterval &&
+         intervalTime < 0 )
+        {
+        MPX_DEBUG1("CMPXMetadataEditorDialog::MakeRestrictedDrmItemsL(): Time not activated");
+        // times not activated
+        heading = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_UTS_X, *aRights );
+        value  = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_NOT_ACT );
+        aHeadingsArray->InsertL( aCurrentIndex, heading->Des() );
+        aDataArray->InsertL( aCurrentIndex, value->Des() );
+        CleanupStack::PopAndDestroy( value );
+        CleanupStack::PopAndDestroy( heading );
+        aCurrentIndex++;
+
+        // query what the current time is
+        TTime currentTime;
+        currentTime.HomeTime();
+        // calculate rights end time
+        TTimeIntervalSeconds interval = iDrmInfo->ValueTObjectL<TInt64>( KMPXMediaDrmInterval );
+        TTime endTime( currentTime.Int64() + (TInt64) interval.Int() * KSecondInMicroSeconds );
+        TBuf<KMPXMaxVal> val;
+        TInt count = 0;
+
+        // years
+        TTimeIntervalYears years = endTime.YearsFrom( currentTime );
+        if ( years.Int() )
+            {
+            AddSinglePartOfTimeL( years.Int(),
+                R_QTN_DRM_NBR_OF_YEARS_ONE,
+                R_QTN_DRM_NBR_OF_YEARS_ONE_FINAL,
+                R_QTN_DRM_NBR_OF_YEARS_TWO_FOUR,
+                R_QTN_DRM_NBR_OF_YEARS_FIVE_ZERO,
+                value );
+            count++;
+            val.Append( *value );
+            endTime -= years;
+            CleanupStack::PopAndDestroy( value );
+            }
+
+        // months
+        TTimeIntervalMonths months = endTime.MonthsFrom( currentTime );
+        if ( months.Int() )
+            {
+            AddSinglePartOfTimeL( months.Int(),
+                R_QTN_DRM_NBR_OF_MONTHS_ONE,
+                0,
+                R_QTN_DRM_NBR_OF_MONTHS_TWO_FOUR,
+                R_QTN_DRM_NBR_OF_MONTHS_FIVE_ZERO,
+                value );
+             if ( count )
+                {
+                val.Append( KMPXSpace );
+                }
+
+            count++;
+            val.Append( *value );
+            endTime -= months;
+            CleanupStack::PopAndDestroy( value );
+            }
+
+        // days
+        TTimeIntervalDays days = endTime.DaysFrom( currentTime );
+        if ( days.Int() && count < 2 )
+            {
+            AddSinglePartOfTimeL( days.Int(),
+                R_QTN_DRM_NBR_OF_DAYS_ONE,
+                R_QTN_DRM_NBR_OF_DAYS_ONE_FINAL,
+                R_QTN_DRM_NBR_OF_DAYS_TWO_FOUR,
+                R_QTN_DRM_NBR_OF_DAYS_FIVE_ZERO,
+                value );
+            if ( count )
+                {
+                val.Append( KMPXSpace );
+                }
+
+            val.Append( *value );
+            endTime -= days;
+            CleanupStack::PopAndDestroy( value );
+            count++;
+            }
+
+        // hours
+        TTimeIntervalHours hours;
+        TInt ret = endTime.HoursFrom( currentTime, hours );
+        if ( ret == KErrNone && count < 2 && hours.Int() )
+            {
+            AddSinglePartOfTimeL( hours.Int(),
+                R_QTN_DRM_NBR_OF_HOURS_ONE,
+                R_QTN_DRM_NBR_OF_HOURS_ONE_FINAL,
+                R_QTN_DRM_NBR_OF_HOURS_TWO_FOUR,
+                R_QTN_DRM_NBR_OF_HOURS_FIVE_ZERO,
+                value );
+            if ( count )
+                {
+                val.Append( KMPXSpace );
+                }
+
+            val.Append( *value );
+            endTime -= hours;
+            CleanupStack::PopAndDestroy( value );
+            count++;
+            }
+
+        // mins
+        TTimeIntervalMinutes minutes;
+        ret = endTime.MinutesFrom( currentTime, minutes );
+        if ( ret == KErrNone && count < 2 && minutes.Int() )
+            {
+            AddSinglePartOfTimeL( minutes.Int(),
+                R_QTN_DRM_NBR_OF_MINS_ONE,
+                R_QTN_DRM_NBR_OF_MINS_ONE_FINAL,
+                R_QTN_DRM_NBR_OF_MINS_TWO_FOUR,
+                R_QTN_DRM_NBR_OF_MINS_FIVE_ZERO,
+                value );
+            if ( count )
+                {
+                val.Append( KMPXSpace );
+                }
+
+            val.Append( *value );
+            endTime -= minutes;
+            CleanupStack::PopAndDestroy( value );
+            count++;
+            }
+
+        // seconds
+        TTimeIntervalSeconds seconds;
+        ret = endTime.SecondsFrom( currentTime,seconds );
+        if ( ret == KErrNone && count < 2 && seconds.Int() )
+            {
+            AddSinglePartOfTimeL( seconds.Int(),
+                R_QTN_DRM_NBR_OF_SECS_ONE,
+                R_QTN_DRM_NBR_OF_SECS_ONE_FINAL,
+                R_QTN_DRM_NBR_OF_SECS_TWO_FOUR,
+                R_QTN_DRM_NBR_OF_SECS_FIVE_ZERO,
+                value );
+
+            if ( count )
+                {
+                val.Append( KMPXSpace );
+                }
+
+            val.Append( *value );
+            CleanupStack::PopAndDestroy(); // value
+            count++;
+            }
+
+        heading = StringLoader::LoadLC( R_QTN_DRM_MGR_DET_UDL_X, *aRights );
+        LanguageSpecificNumberConversion( val );
+        aHeadingsArray->InsertL( aCurrentIndex, heading->Des() );
+        aDataArray->InsertL( aCurrentIndex, val );
+        CleanupStack::PopAndDestroy( heading );
+        aCurrentIndex++;
+        }
+    }
+  
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::AddPartsOfTimeLC
+// -----------------------------------------------------------------------------
+//
+HBufC* CMPXMetadataEditorDialog::AddPartsOfTimeLC( TInt aIntYrs, TInt aIntMon, TInt aIntDay, 
+                         TInt aIntHrs, TInt aIntMin, TInt aIntSec )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::AddPartsOfTimeLC" );   
+    // Only the two most meaningful data will be showed
+    TInt numOfData( 0 );
+    const TInt KMaxDataItems = 2;
+
+    CDesCArrayFlat* strings = new ( ELeave ) CDesCArrayFlat( KMaxDataItems );
+    CleanupStack::PushL( strings );
+
+    if ( aIntYrs > 0 )
+        {
+        AddSinglePartOfTimeL( aIntYrs, 
+            R_QTN_DRM_NBR_OF_YEARS_ONE,
+            R_QTN_DRM_NBR_OF_YEARS_ONE_FINAL,
+            R_QTN_DRM_NBR_OF_YEARS_TWO_FOUR,
+            R_QTN_DRM_NBR_OF_YEARS_FIVE_ZERO,
+            strings );
+        numOfData++;
+        }
+
+    if ( aIntMon > 0 )
+        {
+        //  Second type not provided because 11 is the maximum
+        AddSinglePartOfTimeL( aIntMon, 
+            R_QTN_DRM_NBR_OF_MONTHS_ONE,
+            0,       
+            R_QTN_DRM_NBR_OF_MONTHS_TWO_FOUR, 
+            R_QTN_DRM_NBR_OF_MONTHS_FIVE_ZERO, 
+            strings );
+        numOfData++;
+        }
+
+    // Only if years or months were missing
+    if ( aIntDay > 0 && numOfData < KMaxDataItems )
+        {
+        AddSinglePartOfTimeL( aIntDay, 
+            R_QTN_DRM_NBR_OF_DAYS_ONE,
+            R_QTN_DRM_NBR_OF_DAYS_ONE_FINAL,
+            R_QTN_DRM_NBR_OF_DAYS_TWO_FOUR, 
+            R_QTN_DRM_NBR_OF_DAYS_FIVE_ZERO, 
+            strings );
+        numOfData++;
+        }
+
+    if ( aIntHrs > 0 && numOfData < KMaxDataItems )
+        {
+        AddSinglePartOfTimeL( aIntHrs, 
+            R_QTN_DRM_NBR_OF_HOURS_ONE, 
+            R_QTN_DRM_NBR_OF_HOURS_ONE_FINAL,
+            R_QTN_DRM_NBR_OF_HOURS_TWO_FOUR, 
+            R_QTN_DRM_NBR_OF_HOURS_FIVE_ZERO, 
+            strings );
+        numOfData++;
+        }
+
+    if ( aIntMin > 0 && numOfData < KMaxDataItems )
+        {
+        AddSinglePartOfTimeL( aIntMin, 
+            R_QTN_DRM_NBR_OF_MINS_ONE,
+            R_QTN_DRM_NBR_OF_MINS_ONE_FINAL,
+            R_QTN_DRM_NBR_OF_MINS_TWO_FOUR, 
+            R_QTN_DRM_NBR_OF_MINS_FIVE_ZERO, 
+            strings );
+        numOfData++;
+        }
+
+    // If interval is 0, then it shows "0 seconds" anyway
+    if ( ( aIntSec > 0 && numOfData < KMaxDataItems ) || numOfData == 0 )
+        {
+        AddSinglePartOfTimeL( aIntSec, 
+            R_QTN_DRM_NBR_OF_SECS_ONE, 
+            R_QTN_DRM_NBR_OF_SECS_ONE_FINAL,
+            R_QTN_DRM_NBR_OF_SECS_TWO_FOUR, 
+            R_QTN_DRM_NBR_OF_SECS_FIVE_ZERO, 
+            strings );
+        numOfData++;
+        }
+
+    HBufC* stringHolder = NULL;
+    if ( numOfData == 1 )
+        {
+        stringHolder = StringLoader::LoadL( R_QTN_DRM_MGR_DET_INTER,
+            strings->MdcaPoint(0) );
+        }
+    else
+        {
+        stringHolder = StringLoader::LoadL( R_QTN_DRM_MGR_DET_INTER_TWO,
+            *strings );
+        }
+
+    CleanupStack::PopAndDestroy( strings );
+    
+    CleanupStack::PushL( stringHolder );
+
+    return stringHolder;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::AddSinglePartOfTimeL
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::AddSinglePartOfTimeL( TInt aNumOfElements,
+        TInt aResourceIdSingle,
+        TInt aResourceIdOneFinal, 
+        TInt aResourceIdTwoFour,
+        TInt aResourceIdFiveZero, 
+        CDesCArrayFlat* aStrings )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::AddSinglePartOfTimeL" );   
+   
+    HBufC* stringHolder = NULL;
+    TInt finalOneDigit( aNumOfElements % KDigitTen );
+    TInt finalTwoDigits( aNumOfElements % KDigitHundred );
+
+    if ( aNumOfElements == 1 )
+        {
+        stringHolder = StringLoader::LoadLC( aResourceIdSingle );
+        }
+    else if ( finalOneDigit == 1 && finalTwoDigits != KDigitEleven )
+        {
+        stringHolder = StringLoader::LoadLC( aResourceIdOneFinal, 
+            aNumOfElements );
+        }
+    else if ( finalOneDigit == 0 || 
+             ( finalOneDigit >= KDigitFive && finalOneDigit <= KDigitNine ) ||
+             ( finalTwoDigits >= KDigitEleven && finalTwoDigits <= KDigitFourTeen ) )
+        {
+        stringHolder = StringLoader::LoadLC( aResourceIdFiveZero,
+            aNumOfElements );
+        }
+    else
+        {
+        stringHolder = StringLoader::LoadLC( aResourceIdTwoFour,
+            aNumOfElements );
+        }
+
+    if ( aStrings )
+        {
+        aStrings->AppendL( *stringHolder );
+        }
+
+    CleanupStack::PopAndDestroy ( stringHolder );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SplitTime
+// 
+// -----------------------------------------------------------------------------
+//
+
+void CMPXMetadataEditorDialog::SplitTime( const TTimeIntervalSeconds& aInterval,
+        TInt& aIntYrs, TInt& aIntMon, TInt& aIntDay,
+        TInt& aIntHrs, TInt& aIntMin, TInt& aIntSec )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SplitTime" );       
+    const TInt KSecsInMin( 60 );
+    const TInt KSecsInHour( KSecsInMin * 60 );
+    const TInt KSecsInDay( KSecsInHour * 24 );
+
+    // includes leap year day
+
+    const TInt KMaxDaysInMonths[] = {
+    		KMaxDaysInOneMonths,
+    		KMaxDaysInTwoMonths,
+    		KMaxDaysInThreeMonths,
+    		KMaxDaysInFourMonths,
+    		KMaxDaysInFiveMonths,
+    		KMaxDaysInSixMonths,
+    		KMaxDaysInSevenMonths,
+    		KMaxDaysInEightMonths,
+    		KMaxDaysInNineMonths,
+    		KMaxDaysInTenMonths,
+    		KMaxDaysInElevenMonths,
+    		KMaxDaysInEightMonths }; 
+
+    // calculate full days
+    TInt temp( aInterval.Int() / KSecsInDay );
+
+    // calculate full years, calculate without leap year for user to get the 
+    // longest time possible
+    aIntYrs = temp / ( KMaxDaysInMonths[KDigitEleven] - 1 );
+
+    // calc remainder days
+    temp = temp % ( KMaxDaysInMonths[KDigitEleven] - 1 );
+
+    aIntMon = 0;
+
+    TInt i( 0 );
+    if ( temp >= KMaxDaysInMonths[0] )
+        {
+        for ( i = 0; i < KDigitEleven; i++ )
+            {
+            // found correct amount of months
+            if ( temp >= KMaxDaysInMonths[i] && temp < KMaxDaysInMonths[i+1] )
+                {
+                // i now contains amount of full months (+1 because of table index)
+                aIntMon = i + 1;
+                break;
+                }
+            }
+        }
+
+    // calc remainder days = allSecs - secsInFullYears - secsInFullMonts
+    if( temp >= KMaxDaysInMonths[i] )
+        {
+        aIntDay = temp - KMaxDaysInMonths[i];
+        }
+    else
+        {
+        aIntDay = temp;
+        }
+
+    // calculate remainder secs
+    temp = aInterval.Int() % KSecsInDay;
+
+    aIntHrs = temp / KSecsInHour;
+
+    // calculate remainder secs
+    temp = temp % KSecsInHour;
+
+    aIntMin = temp / KSecsInMin;
+
+    // calculate remainder secs
+    aIntSec = temp % KSecsInMin;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::AddSinglePartOfTimeL
+// Language specific time formats
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::AddSinglePartOfTimeL(
+    TInt aNumOfElements,
+    TInt aResourceIdSingle,
+    TInt aResourceIdOneFinal,
+    TInt aResourceIdTwoFour,
+    TInt aResourceIdFiveZero,
+    HBufC*& aStrings )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::AddSinglePartOfTimeL" );
+    TInt finalOneDigit = aNumOfElements % KMPXOneDigit;
+    TInt finalTwoDigits = aNumOfElements % KMPXTwoDigits;
+
+    if ( aNumOfElements == 1 )
+        {
+        aStrings = StringLoader::LoadLC( aResourceIdSingle );
+        }
+    else if ( finalOneDigit == 1 && finalTwoDigits != KDigitEleven )
+        {
+        // Used for period of years ending with 1 from 21 (21, 31, 41, etc.)
+        aStrings = StringLoader::LoadLC( aResourceIdOneFinal, aNumOfElements );
+        }
+    else if ( finalOneDigit == 0 ||
+            ( finalOneDigit >= KDigitFive && finalOneDigit <= KDigitNine ) ||
+            ( finalTwoDigits >= KDigitEleven && finalTwoDigits <= KDigitFourTeen ) )
+        {
+        // Used for period of minutes ending from 5 to 0 plus range between 11
+        // and 14 (5-20, 25-30, 35-40, 45-50, 53-59)
+        aStrings = StringLoader::LoadLC( aResourceIdFiveZero, aNumOfElements );
+        }
+    else
+        {
+        // Used for period of minutes ending from 2 to 4, excluded 12-14 (2-4,
+        // 22-24, 32-34, 42-44, 52-54)
+        aStrings = StringLoader::LoadLC( aResourceIdTwoFour, aNumOfElements );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::LanguageSpecificNumberConversion
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::LanguageSpecificNumberConversion( TDes& aText ) const
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::LanguageSpecificNumberConversion" );
+    if ( AknTextUtils::DigitModeQuery( AknTextUtils::EDigitModeShownToUser ) )
+        {
+        AknTextUtils::DisplayTextLanguageSpecificNumberConversion( aText );
+        }
+    }
+
+
+// ----------------------------------------------------------------------------
+// Converts the time value to localtime
+// ----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::ConvertToLocalTimeL(TTime& aTime )
+    {
+    RTz timeConverter;
+    CleanupClosePushL(timeConverter);
+    User::LeaveIfError( timeConverter.Connect() );
+    User::LeaveIfError( timeConverter.ConvertToLocalTime( aTime ) );
+    CleanupStack::PopAndDestroy();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::AddItemToListBoxL
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::AddItemToListBoxL(
+    const TDesC& aHeading,
+    const TDesC& aValue,
+    CDesCArray* aItemArray )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::AddItemToListBoxL" );
+    CDesCArrayFlat* items = new (ELeave) CDesCArrayFlat( 2 );
+    CleanupStack::PushL( items );
+    items->AppendL( aHeading ); //First string (heading)
+    items->AppendL( aValue );   //Second string (value)
+    HBufC* headingAndValue =
+            StringLoader::LoadLC( R_MPX_CUI_METADATAEDITOR_FILE_DETAILS_ROW_FORMAT, *items );
+
+    aItemArray->AppendL( *headingAndValue );
+    CleanupStack::PopAndDestroy( headingAndValue );
+    CleanupStack::PopAndDestroy( items );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::HandleControlStateChangeL
+// Handle State Changes in Genre popup.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::HandleControlStateChangeL( TInt aControlId )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::HandleControlStateChangeL" );
+    if( !iTryingExit )
+        {
+        if ( aControlId == EMPXMetadataEditorDlgCtrlIdGenre )
+            {
+            // check to see if the genre pop has item custom selected
+            if ( iTextValues->CurrentValueIndex() == 0 )
+                {
+                HBufC* genreName = HBufC::NewLC( KMPXSongDetailsTextMaxLen );
+                TPtr genrePtr = genreName->Des();
+                CAknTextQueryDialog* queryDlg =
+                    CAknTextQueryDialog::NewL( genrePtr );
+                CleanupStack::PushL( queryDlg );
+                HBufC* promptTxt = NULL;
+                if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+                    {
+                    promptTxt = StringLoader::LoadLC( R_MPX_CUI_CUSTOM_GENRE_RENAME_TEXT );
+                    }
+                else
+                    {
+                    promptTxt = StringLoader::LoadLC( R_MPX_CUI_CUSTOM_CATEGORY_RENAME_TEXT );
+                    }
+                queryDlg->SetPromptL( *promptTxt );
+                queryDlg->SetPredictiveTextInputPermitted( ETrue );
+                CleanupStack::PopAndDestroy( promptTxt );
+                CleanupStack::Pop( queryDlg );
+                if ( queryDlg->ExecuteLD( R_MPX_CUI_CUSTOM_GENRE_NAME_QUERY_DLG ) )
+                    {
+                    TBool isHandled = EFalse;
+                    TBool tryExit = EFalse;
+                    if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+                        {
+                        // in music libray, if genre is set to podcast, ask user
+                        // to confirm move to podcast database
+                        HBufC* podcastText = StringLoader::LoadLC( R_MPX_QTN_NMP_GENRE_PODCAST );
+                        if ( genreName->Des().CompareF( *podcastText ) == 0 &&
+                             !iDisablePodcasting )
+                            {
+                            isHandled = ETrue;
+                            // genre is set to podcast
+                            if ( PromptForLibraryChangeL( EMPXMetadataEditorDlgPodcast ) )
+                                {
+                                MPX_DEBUG1( "CMPXMetadataEditorDialog::HandleControlStateChangeL Move to a different library" );
+                                iCollectionUiHelper->MoveL( iMedia, TUid::Uid(EMPXCollectionPluginPodCast) , this);
+                                tryExit = ETrue;
+                                iTryingExit = ETrue;
+                                }
+                            }
+                        CleanupStack::PopAndDestroy( podcastText );
+                        }
+                    if ( !isHandled )
+                        {
+                        // ok selected
+                        CMPXMedia* media = CMPXMedia::NewL();
+                        CleanupStack::PushL( media );
+                        iMedia->SetTextValueL(
+                            KMPXMediaMusicGenre, genreName->Des() );
+                        media->SetTextValueL(
+                            KMPXMediaMusicGenre, genreName->Des() );
+                        SaveMediaPropertiesL( media );
+                        CleanupStack::PopAndDestroy( media );
+                        }
+                    if ( !tryExit )
+                        {
+                        FetchGenreL();
+                        }
+                    }
+                else
+                    {
+                    // Text query cancelled.  Display popup list again.
+                    iTextValues->SetCurrentValueIndex( 0 );
+                    iPopup->ActivateSelectionListL();
+                    // genre is fetched so that "Custom..." isn't passed as the new genre
+                    FetchGenreL();
+                    }
+                CleanupStack::PopAndDestroy( genreName );
+                }
+            else
+                {
+                if ( iUnknownGenre &&
+                    ( iTextValues->CurrentValueIndex() == ( iTextValues->MdcArray()->MdcaCount() - 1 ) ) )
+                    {
+                    MPX_DEBUG1( "CMPXMetadataEditorDialog::HandleControlStateChangeL last entry with unknown genre, do nothing" );
+                    }
+                else
+                    {
+                    CMPXMedia* media = CMPXMedia::NewL();
+                    CleanupStack::PushL( media );
+                    HBufC* currentTxt = iTextValues->CurrentValueTextLC();
+                    iMedia->SetTextValueL( KMPXMediaMusicGenre, *currentTxt );
+                    media->SetTextValueL( KMPXMediaMusicGenre, *currentTxt );
+                    CleanupStack::PopAndDestroy( currentTxt );
+                    SaveMediaPropertiesL( media );
+                    CleanupStack::PopAndDestroy( media );
+                    FetchGenreL();
+                    }
+                }
+            }
+        else if ( aControlId == EMPXMetadataEditorDlgCtrlIdLibrary )
+            {
+            TInt currentIndex = iLibraryTextValues->CurrentValueIndex();
+            if ( iCurrentLibrary != currentIndex )
+                {
+                if ( PromptForLibraryChangeL( currentIndex ) )
+                    {
+                    MPX_DEBUG1( "CMPXMetadataEditorDialog::HandleControlStateChangeL Move to a different library" );
+                    TUid targetCollection = TUid::Uid( EMPXCollectionPluginMusic );
+                    if ( currentIndex == EMPXMetadataEditorDlgPodcast )
+                        {
+                        targetCollection = TUid::Uid(EMPXCollectionPluginPodCast);
+                        }
+                    // before moving, save current data
+                    SaveFormDataL();
+                    iCurrentLibrary = currentIndex; // Fix for ELWG-7AACMS prevent the if clause to be reentried.
+                    iCollectionUiHelper->MoveL( iMedia, targetCollection, this );
+                    iTryingExit = ETrue;
+                    }
+                else
+                    {
+                    iLibraryTextValues->SetCurrentValueIndex( iCurrentLibrary );
+                    // Fix EIZU-7QQAZN, Let it display back to "Music" immediately.
+                    if ( IdOfFocusControl() == EMPXMetadataEditorDlgCtrlIdLibrary )
+                        {
+                        iPopup = static_cast<CAknPopupField*>
+                                        ( ControlOrNull( EMPXMetadataEditorDlgCtrlIdLibrary ) );
+                        if ( iPopup )
+                            {
+                            iPopup->SetQueryValueL( iLibraryTextValues );
+                            iPopup->DrawDeferred();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    CAknForm::HandleControlStateChangeL( aControlId );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::PrepareForFocusTransitionL
+// Handle Focus changes for track and year controls.
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::PrepareForFocusTransitionL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::PrepareForFocusTransitionL" );
+    TInt err = KErrNone;
+
+    CEikNumberEditor* myTrackNumberEditor = static_cast<CEikNumberEditor*>
+            ( ControlOrNull( EMPXMetadataEditorDlgCtrlIdTrackNumber ) );
+
+    CEikNumberEditor* myYearNumberEditor = static_cast<CEikNumberEditor*>
+            ( ControlOrNull( EMPXMetadataEditorDlgCtrlIdYear ) );
+
+    if ( myTrackNumberEditor )
+        {
+        // if length 0 trap error and set to 0.
+        MPX_TRAP( err, myTrackNumberEditor->Number() );
+        if ( err )
+            {
+            myTrackNumberEditor->SetNumber( KMPXMinNumDateTrack );
+            }
+        }
+
+    if ( myYearNumberEditor )
+        {
+        // if length 0 trap error and set to 0.
+        MPX_TRAP( err, myYearNumberEditor->Number() );
+        if ( err )
+            {
+            myYearNumberEditor->SetNumber( KMPXMinNumDateTrack );
+            }
+        }
+
+    CAknForm::PrepareForFocusTransitionL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::GetHelpContext
+// Gets Help
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::GetHelpContext(
+    TCoeHelpContext& aContext ) const
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::GetHelpContext" );
+    aContext.iMajor = KAppUidMusicPlayerX;
+    aContext.iContext = KMUS_HLP_METADATA_EDITING;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::HandleFindAllL
+// Handle callback for "find" operation
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::HandleFindAllL(const CMPXMedia& aResults,
+                               TBool /*aComplete*/, TInt aError)
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::HandleFindAllL" );
+    iPopup = static_cast<CAknPopupField*>
+        ( ControlOrNull( EMPXMetadataEditorDlgCtrlIdGenre ) );
+    CleanUpGenreText();
+    // populate predefined genre
+    TResourceReader reader;
+    if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+        {
+        if( !iDisablePodcasting )
+            {
+            iEikonEnv->CreateResourceReaderLC( reader, R_MPX_MUSIC_GENRE_STRINGS );
+            }
+        else
+            {
+            iEikonEnv->CreateResourceReaderLC( reader, R_MPX_MUSIC_GENRE_STRINGS_PODCAST );
+            }
+        }
+    else if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+        {
+        iEikonEnv->CreateResourceReaderLC(
+            reader, R_MPX_PODCAST_CATEGORY_STRINGS );
+        }
+    iGenreArr = reader.ReadDesCArrayL( );
+    CleanupStack::PopAndDestroy(); // reader
+
+    // populate genres from database
+    if ( aError == KErrNone )
+        {
+        const CMPXMediaArray* mediaArray =
+            aResults.Value<CMPXMediaArray>( KMPXMediaArrayContents );
+        User::LeaveIfNull(const_cast<CMPXMediaArray*>(mediaArray));
+        
+        TInt entriesCount( mediaArray->Count() );
+        MPX_DEBUG2( "CMPXMetadataEditorDialog::HandleFindAllL genres from database count = %d", entriesCount );
+        for ( TInt i = 0; i < entriesCount; i++ )
+            {
+            CMPXMedia* media = mediaArray->AtL( i );
+            TInt location( 0 );
+            const TDesC& genre = media->ValueText( KMPXMediaGeneralTitle );
+            if ( i == entriesCount - 1)
+                {
+                if ( genre.Compare( KNullDesC ) != 0 )
+                    {
+                    // if last item is a null descriptor, don't append to array
+                    if ( iGenreArr->Find( genre, location ) != 0 )
+                        {
+                        // a match is not found
+                        MPX_DEBUG1( "CMPXMetadataEditorDialog::HandleFindAllL adding to genre list" );
+                        iGenreArr->AppendL( genre );
+                        }
+                    }
+                }
+            else
+                {
+                if ( iGenreArr->Find( genre, location ) != 0 )
+                    {
+                    // a match is not found
+                    MPX_DEBUG1( "CMPXMetadataEditorDialog::HandleFindAllL adding to genre list" );
+                    iGenreArr->AppendL( genre );
+                    }
+                }
+            }
+        }
+    iGenreArr->Sort(ECmpCollated);
+    
+    if ( iCurrentLibrary == EMPXMetadataEditorDlgCollection )
+        {
+            HBufC* custTxt =
+            StringLoader::LoadLC( R_MPX_CUI_CUSTOM_GENRE_PROMPT_TEXT );
+            iGenreArr->InsertL( 0, *custTxt );
+            CleanupStack::PopAndDestroy( custTxt );
+        }
+    else if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+        {
+            HBufC* custTxt =
+            StringLoader::LoadLC( R_MPX_CUI_PODCAST_CUSTOM_GENRE_PROMPT_TEXT );
+            iGenreArr->InsertL( 0, *custTxt );
+            CleanupStack::PopAndDestroy( custTxt );
+        }
+
+    iValueTextArray = CAknQueryValueTextArray::NewL();
+    iValueTextArray->SetArray( *iGenreArr );
+
+    iTextValues = CAknQueryValueText::NewL();
+    iTextValues->SetArrayL( iValueTextArray );
+    if ( iMedia->ValueText( KMPXMediaMusicGenre ).Length() == 0 )
+        {
+        // no genre
+        iUnknownGenre = ETrue;
+        HBufC* unknownGenre( StringLoader::LoadLC( R_MPX_CUI_UNKNOWN_GENRE_TEXT ) );
+        iGenreArr->AppendL( *unknownGenre );
+        CleanupStack::PopAndDestroy( unknownGenre );
+        iTextValues->SetCurrentValueIndex( iGenreArr->Count() - 1 );
+        }
+    else
+        {
+        // Find the genre
+        iUnknownGenre = EFalse;
+        TInt genreIndex;
+        iGenreArr->Find( iMedia->ValueText( KMPXMediaMusicGenre ), genreIndex );
+        iTextValues->SetCurrentValueIndex( genreIndex );
+        }
+    // Set values into popup fields.
+    iPopup->SetQueryValueL( iTextValues ); // Moved up from below.
+    iPopup->DrawDeferred();
+    }
+
+// ----------------------------------------------------------------------------
+// void CMPXMetadataEditorDialog::HandleOperationCompleteL
+// Handle callback for the ui helper.
+// ----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::HandleOperationCompleteL(
+    TCHelperOperation aOperation,
+    TInt aErr, void* aArgument )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::HandleOperationCompleteL" );
+    if ( aOperation == EMoveOp )
+        {
+        if ( aErr != KErrNone )
+            {
+            // TO-DO: error handling
+            }
+        // move complete, quit the editor
+        if ( iIdle )
+            {
+            iIdle->Cancel();
+            delete iIdle;
+            iIdle = NULL;
+            }
+        iIdle = CIdle::NewL( CActive::EPriorityStandard );
+        iIdle->Start( TCallBack( CMPXMetadataEditorDialog::DeferredExitCallback, this ) );
+        }
+    if ( aArgument )
+        {
+        delete (CBase*)aArgument;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// void CMPXMetadataEditorDialog::DeferredExitCallback
+// call back function for deferred exit.
+// ----------------------------------------------------------------------------
+//
+TInt CMPXMetadataEditorDialog::DeferredExitCallback( TAny* aPtr )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::DeferredExitCallback" );
+    CMPXMetadataEditorDialog* self =
+        static_cast<CMPXMetadataEditorDialog*>( aPtr );
+    TRAP_IGNORE( self->TryExitL( EAknSoftkeyExit ) );
+    return KErrNone;
+    }
+
+// ----------------------------------------------------------------------------
+// void CMPXMetadataEditorDialog::DeferredFileDetailsCallback
+// call back function for deferred file details dialog.
+// ----------------------------------------------------------------------------
+//
+TInt CMPXMetadataEditorDialog::DeferredFileDetailsCallback( TAny* aPtr )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::DeferredFileDetailsCallback" );
+    CMPXMetadataEditorDialog* self =
+        static_cast<CMPXMetadataEditorDialog*>( aPtr );
+    TRAP_IGNORE( self->ViewFileDetailsPopupL() );
+    return KErrNone;
+    }
+
+#ifdef __ENABLE_MSK
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::UpdateSoftkeyL()
+// Update softkey.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::UpdateSoftkeyL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::UpdateSoftkeyL" );
+    TInt resId( 0 );
+
+    if ( ( IdOfFocusControl() == EMPXMetadataEditorDlgCtrlIdGenre ) ||
+        ( IdOfFocusControl() == EMPXMetadataEditorDlgCtrlIdLibrary ) )
+        {
+        resId = R_MPX_CUI_SONG_DETAILS_SOFTKEYS_OPTIONS_CHANGE_DONE;
+        }
+    else
+        {
+        resId = R_MPX_CUI_SONG_DETAILS_SOFTKEYS_OPTIONS_EMPTY_DONE;
+        }
+
+    ButtonGroupContainer().SetCommandSetL( resId );
+    ButtonGroupContainer().DrawDeferred();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::OfferKeyEventL
+// Handles key-events.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CMPXMetadataEditorDialog::OfferKeyEventL(
+    const TKeyEvent& aKeyEvent,
+    TEventCode aType )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::OfferKeyEventL" );
+    TKeyResponse res = CAknForm::OfferKeyEventL( aKeyEvent, aType );
+
+    if ( aType == EEventKey )
+        {
+        switch ( aKeyEvent.iScanCode )
+            {
+            case EStdKeyUpArrow:
+            case EStdKeyDownArrow:
+                {
+                UpdateSoftkeyL();
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+
+    return res;
+    }
+#endif // __ENABLE_MSK
+
+// ----------------------------------------------------------------------------
+// void CMPXMetadataEditorDialog::PreLayoutDynInitL
+// Initialises the dialog's controls before the dialog is sized and layed out.
+// ----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::PreLayoutDynInitL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::PreLayoutDynInitL" );
+    SetTitlePaneL();
+    SetNaviLabelL();
+
+    _LIT( KZero, "0" );
+    
+    SetControlNumberL( EMPXMetadataEditorDlgCtrlIdTrackNumber, KZero,
+    	KMPXSongDetailsTrackNumMin, KMPXSongDetailsTrackNumMax );
+
+    SetControlNumberL ( EMPXMetadataEditorDlgCtrlIdYear, KZero,
+    	KMPXSongDetailsYearMin, KMPXSongDetailsYearMax );
+
+    // Get media property for the current song
+    CMPXCollectionPath* cpath = iCollectionUtility->Collection().PathL();
+    CleanupStack::PushL( cpath );
+    if ( iParam )
+        {
+        TLex yearLex( iParam->Des() );
+        TInt lexToInt = NULL;
+        if ( yearLex.Val( lexToInt ) == KErrNone )
+            {
+            cpath->Set( lexToInt );
+            RArray<TMPXAttribute> attrs;
+            CleanupClosePushL(attrs);
+            attrs.Append( KMPXMediaGeneralAll );
+            attrs.Append( KMPXMediaAudioAudioAll );
+            attrs.Append( KMPXMediaMusicAll );
+            attrs.Append( KMPXMediaDrmProtected );
+            if ( iCurrentLibrary == EMPXMetadataEditorDlgPodcast )
+                {
+                attrs.Append(
+                    TMPXAttribute( KMPXMediaIdPodcast, EMPXMediaPodcastAll ) );
+                }
+            iCurrentMediaLOp = EMPXMetadataEditorGetSongInfo;
+            iCollectionUtility->Collection().MediaL( *cpath, attrs.Array() );
+            CleanupStack::PopAndDestroy( &attrs );
+            }
+        }
+    CleanupStack::PopAndDestroy( cpath );
+
+    // Podcasting is enabled
+    if ( !iDisablePodcasting )
+        {
+        iPopup = static_cast<CAknPopupField*>
+            ( ControlOrNull( EMPXMetadataEditorDlgCtrlIdLibrary ) );
+        iLibraryArr = new (ELeave) CDesCArrayFlat( 1 );
+        HBufC* custTxt = StringLoader::LoadLC( R_MPX_CUI_GENRE_SELECTION_MUSIC_TEXT );
+        iLibraryArr->AppendL( *custTxt );
+        CleanupStack::PopAndDestroy( custTxt );
+        custTxt = StringLoader::LoadLC( R_MPX_CUI_GENRE_SELECTION_PODCAST_TEXT );
+        iLibraryArr->AppendL( *custTxt );
+        CleanupStack::PopAndDestroy( custTxt );
+        iLibraryValueTextArray = CAknQueryValueTextArray::NewL();
+        iLibraryValueTextArray->SetArray( *iLibraryArr );
+        iLibraryTextValues = CAknQueryValueText::NewL();
+        iLibraryTextValues->SetArrayL( iLibraryValueTextArray );
+        iLibraryTextValues->SetCurrentValueIndex( iCurrentLibrary );
+        // Set values into popup fields
+        iPopup->SetQueryValueL( iLibraryTextValues ); // Moved up from below
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::PostLayoutDynInitL
+// Set default field value to member data.
+// ----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::PostLayoutDynInitL()
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::PostLayoutDynInitL" );
+    CAknForm::PostLayoutDynInitL();
+    SetEditableL( ETrue );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SaveMediaPropertiesL
+// Saves media back to collection engine
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::SaveMediaPropertiesL( CMPXMedia* aMedia )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SaveMediaPropertiesL" );
+    if ( iMedia->IsSupported( KMPXMediaGeneralUri ) )
+        {
+        aMedia->SetTextValueL(
+            KMPXMediaGeneralUri, iMedia->ValueText( KMPXMediaGeneralUri ) );
+        }
+
+    if ( iMedia->IsSupported( KMPXMediaGeneralType ) )
+        {
+        aMedia->SetTObjectValueL<TInt>(
+            KMPXMediaGeneralType, iMedia->ValueTObjectL<TInt>( KMPXMediaGeneralType ) );
+        }
+
+    if ( iMedia->IsSupported( KMPXMediaGeneralCategory ) )
+        {
+        aMedia->SetTObjectValueL<TInt>(
+            KMPXMediaGeneralCategory,
+            iMedia->ValueTObjectL<TInt>( KMPXMediaGeneralCategory ) );
+        }
+
+    if ( iMedia->IsSupported( KMPXMediaGeneralId ) )
+        {
+        aMedia->SetTObjectValueL<TMPXItemId>(
+            KMPXMediaGeneralId, iMedia->ValueTObjectL<TMPXItemId>( KMPXMediaGeneralId ) );
+        }
+
+    if ( iMedia->IsSupported( KMPXMediaGeneralCollectionId ) )
+        {
+        aMedia->SetTObjectValueL<TUid>(
+            KMPXMediaGeneralCollectionId,
+            iMedia->ValueTObjectL<TUid>( KMPXMediaGeneralCollectionId ) );
+        }
+    
+    if ( iMedia->IsSupported( KMPXMediaMusicAlbumArtFileName ) )
+        {
+        aMedia->SetTextValueL(
+            KMPXMediaMusicAlbumArtFileName,
+            iMedia->ValueText( KMPXMediaMusicAlbumArtFileName ) );
+        }
+
+    // toggle the modified flag for the internal media reference
+    // or else any subsequent FindAllL calls won't be able to
+    // match against this object
+    iMedia->SetTObjectValueL<TBool>(KMPXMediaGeneralModified, ETrue);
+
+    // Set to collection via command
+    //
+    CMPXCommand* cmd = CMPXCommand::NewL();
+    CleanupStack::PushL( cmd );
+
+    cmd->SetTObjectValueL( KMPXCommandGeneralId, KMPXCommandIdCollectionSet );
+    cmd->SetTObjectValueL( KMPXCommandGeneralDoSync, ETrue );
+    TUid colId(iMedia->ValueTObjectL<TUid>(KMPXMediaGeneralCollectionId));
+    cmd->SetTObjectValueL( KMPXCommandGeneralCollectionId, colId.iUid );
+    cmd->SetCObjectValueL<CMPXMedia>( KMPXCommandColSetMedia, aMedia );
+
+    iCollectionUtility->Collection().CommandL( *cmd );
+    CleanupStack::PopAndDestroy( cmd );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::AppendStringToArrayL
+// Appends the value to the array, if the vaule has zero length,
+// appends "unavailable"
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::AppendStringToArrayL(
+    CDesCArrayFlat* aArray, const TDesC& aValue )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::AppendStringToArrayL" );
+    if ( aValue.Length() > 0 )
+        {
+        HBufC* stringBuf = HBufC::NewLC(
+            aValue.Length() + KMPXFileDetailsExtraBufferLen );
+        TPtr stringBufPtr = stringBuf->Des();
+        stringBufPtr.Append( aValue );
+        aArray->AppendL( stringBufPtr );
+        CleanupStack::PopAndDestroy( stringBuf );
+        }
+    else
+        {
+        aArray->AppendL( KNullDesC );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SetControlTextL
+// Sets control text
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::SetControlTextL( TInt aControlId,
+    const TDesC& aValue, const TDesC& aAlternateValue )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SetControlTextL" );
+    CEikEdwin* myEdwin = static_cast< CEikEdwin* >
+        ( ControlOrNull( aControlId ) );
+    if ( myEdwin )
+        {
+        if ( aValue.Length() > 0 )
+            {
+            myEdwin->SetTextL( &( aValue ) );
+            }
+        else if ( aAlternateValue.Length() > 0 )
+            {
+            myEdwin->SetTextL( &( aAlternateValue ) );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::SetControlNumberL
+// Sets control number
+// -----------------------------------------------------------------------------
+//
+void CMPXMetadataEditorDialog::SetControlNumberL( TInt aControlId,
+    const TDesC& aValue, TInt aMinValue, TInt aMaxValue )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::SetControlNumberL" );
+    CEikNumberEditor* myNumberEditor = static_cast< CEikNumberEditor* >
+        ( ControlOrNull( aControlId ) );
+
+    TInt defaultValue( 0 );
+    if ( aMinValue > 0  )
+        {
+        defaultValue = aMinValue;
+        }
+
+    if ( myNumberEditor )
+        {
+        if ( aValue.Length() > 0 )
+            {
+            TLex trackNumLex( aValue );
+            TInt LexToInt;
+            if ( trackNumLex.Val( LexToInt ) == KErrNone )
+                {
+                if ( LexToInt > aMaxValue )
+                    {
+                    LexToInt = aMaxValue;
+                    }
+                if ( LexToInt < aMinValue )
+                    {
+                    LexToInt = aMinValue;
+                    }
+                myNumberEditor->SetNumber( LexToInt );
+                }
+            else
+                {
+                myNumberEditor->SetNumber( defaultValue );
+                }
+            }
+        else
+            {
+            myNumberEditor->SetNumber( defaultValue );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::PromptForLibraryChangeL
+// prompt user for library change
+// -----------------------------------------------------------------------------
+//
+TBool CMPXMetadataEditorDialog::PromptForLibraryChangeL( TInt aMoveToLibrary )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::PromptForLibraryChangeL" );
+    CMPXQueryDialog* confirmationDlg = CMPXQueryDialog::NewL();
+    CleanupStack::PushL( confirmationDlg );
+    HBufC* libraryName = NULL;
+    if ( aMoveToLibrary == EMPXMetadataEditorDlgCollection )
+        {
+        libraryName =
+            StringLoader::LoadLC( R_MPX_CUI_GENRE_SELECTION_MUSIC_TEXT );
+        }
+    else if ( aMoveToLibrary == EMPXMetadataEditorDlgPodcast )
+        {
+        libraryName =
+            StringLoader::LoadLC( R_MPX_CUI_GENRE_SELECTION_PODCAST_TEXT );
+        }
+    else
+        {
+        // should not reach here
+        User::Leave( KErrArgument );
+        }
+    HBufC* promptTxt = StringLoader::LoadLC(
+        R_MPX_CUI_QUERY_MOVE_TO_LIBRARY, libraryName->Des() );
+    confirmationDlg->SetPromptL( *promptTxt );
+    CleanupStack::PopAndDestroy( promptTxt );
+
+
+    confirmationDlg->PublishDialogL(
+        EMPlayerQueryMoveToLibrary,
+        KMPlayerNoteCategory);
+
+    CAknMediatorFacade* covercl(
+        AknMediatorFacade( confirmationDlg ) );
+    if ( covercl )
+        {
+        covercl->BufStream() << libraryName->Des();
+        }
+    CleanupStack::PopAndDestroy( libraryName );
+    CleanupStack::Pop( confirmationDlg );
+    return confirmationDlg->ExecuteLD( R_MPX_CUI_MOVE_TO_LIBRARY_CONFIRMATION_QUERY );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXMetadataEditorDialog::UpdateMediaObjectWithControlL
+// Updates media object with current control text, this will also
+// update iMedia
+// -----------------------------------------------------------------------------
+//
+TBool CMPXMetadataEditorDialog::UpdateMediaObjectWithControlL(
+    TInt aControlId, CMPXMedia* aMedia, TMPXAttribute aAttribute )
+    {
+    MPX_FUNC( "CMPXMetadataEditorDialog::UpdateMediaObjectWithControlL" );
+    TBool ret = EFalse;
+    CCoeControl* coeControl = ControlOrNull( aControlId );
+    if ( coeControl )
+        {
+        HBufC* buf = NULL;
+        switch ( aControlId )
+            {
+            case EMPXMetadataEditorDlgCtrlIdSongName:
+            case EMPXMetadataEditorDlgCtrlIdArtist:
+            case EMPXMetadataEditorDlgCtrlIdAlbum:
+            case EMPXMetadataEditorDlgCtrlIdComment:
+            case EMPXMetadataEditorDlgCtrlIdComposer:
+                {
+                CEikEdwin* control = static_cast<CEikEdwin*>( coeControl );
+                if ( control )
+                    {
+                    buf = control->GetTextInHBufL();
+                    if ( !buf )
+                        {
+                        // the text contains nothing
+                        // special handling is needed for song name
+                        if ( aControlId == EMPXMetadataEditorDlgCtrlIdSongName && iMedia )
+                            {
+                            if ( iMedia->IsSupported( KMPXMediaGeneralUri ) )
+                                {
+                                // if URI is defined, use filename as song name
+                                TParsePtrC fn( iMedia->ValueText( KMPXMediaGeneralUri ) );
+                                buf = fn.Name().AllocL();
+                                }
+                            else
+                                {
+                                buf = HBufC::NewL( 0 );
+                                }
+                            }
+                        else
+                            {
+                            buf = HBufC::NewL( 0 );
+                            }
+                        }
+                    CleanupStack::PushL( buf );
+                    }
+                else
+                    {
+                    // should not reach here
+                    User::Leave( KErrArgument );
+                    }
+                break;
+                }
+            case EMPXMetadataEditorDlgCtrlIdTrackNumber:
+                {
+                CEikNumberEditor* control = static_cast<CEikNumberEditor*>( coeControl );
+                if ( control )
+                    {
+                    TInt num = control->Number();
+                    MPX_DEBUG2( "CMPXMetadataEditorDialog::UpdateMediaObjectWithControlL number from control %d", num );
+                    buf = HBufC::NewLC( KMPXFileDetailsMaxBufferLen );
+                    TPtr bufPtr = buf->Des();
+                    bufPtr.AppendNum( num );
+                    }
+                else
+                    {
+                    // should not reach here
+                    User::Leave( KErrArgument );
+                    }
+                break;
+                }
+            default:
+                {
+                // should not reach here
+                User::Leave( KErrArgument );
+                break;
+                }
+            }
+        if ( buf )
+            {
+            const TDesC& origValue = iMedia->ValueText( aAttribute );
+            if ( origValue.Compare( *buf ) != 0 )
+                {
+	                //check if the track number is actually changed
+	                if (aControlId == EMPXMetadataEditorDlgCtrlIdTrackNumber &&
+	                	origValue.Compare(_L("")) == 0 &&
+	                	buf->Compare(_L("0")) == 0)
+	                	{
+	                	//nothing to do
+	                	}
+	            	else
+	            		{
+		                ret = ETrue;
+		                iMedia->SetTextValueL( aAttribute , *buf );
+		                aMedia->SetTextValueL( aAttribute , *buf );
+	            		}
+                }
+            CleanupStack::PopAndDestroy( buf );
+            }
+        }
+    return ret;
+    }
+
+// End of File