homesync/contentmanager/mediaservant/src/msfillview.cpp
branchIOP_Improvements
changeset 40 08b5eae9f9ff
parent 39 6369bfd1b60d
child 41 b4d83ea1d6e2
equal deleted inserted replaced
39:6369bfd1b60d 40:08b5eae9f9ff
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  CMSFillView class implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <mediaservant.rsg>
       
    20 #include <StringLoader.h>
       
    21 #include <aknlistquerydialog.h>
       
    22 #include <hlplch.h>
       
    23 #include <utf.h>
       
    24 
       
    25 #include "cmfillrule.h"
       
    26 #include "msfillview.h"
       
    27 #include "msengine.h"
       
    28 #include "msfillcontainer.h"
       
    29 #include "msappui.h"
       
    30 #include "msconstants.h"
       
    31 #include "mediaservant.hrh"
       
    32 #include "msparameteragent.h"
       
    33 #include "msdebug.h"
       
    34 
       
    35 
       
    36 // CONSTANTS
       
    37 _LIT( KWildCard, "*" );
       
    38 _LIT( KSpace, " ");
       
    39 
       
    40 const TInt KImageListTemplate = 1;
       
    41 const TInt KVideoListTemplate = 2;
       
    42 const TInt KMusicListTemplate = 3;
       
    43 
       
    44 
       
    45 // --------------------------------------------------------------------------
       
    46 // CMSFillView::CMSFillView()
       
    47 // --------------------------------------------------------------------------
       
    48 //
       
    49 CMSFillView::CMSFillView( CMSAppUi& aAppUi )
       
    50     {
       
    51     LOG(_L("[MediaServant]\t CMSFillView::CMSFillView"));
       
    52 
       
    53     iAppUi = &aAppUi;
       
    54     }
       
    55 
       
    56 // --------------------------------------------------------------------------
       
    57 // CMSFillView::ConstructL()
       
    58 // --------------------------------------------------------------------------
       
    59 //
       
    60 void CMSFillView::ConstructL()
       
    61     {
       
    62     LOG(_L("[MediaServant]\t CMSFillView::ConstructL"));
       
    63 
       
    64     BaseConstructL( R_MS_FILL_VIEW );
       
    65     }
       
    66 
       
    67 // --------------------------------------------------------------------------
       
    68 // CMSFillView::~CMSFillView()
       
    69 // --------------------------------------------------------------------------
       
    70 //
       
    71 CMSFillView::~CMSFillView()
       
    72     {
       
    73     LOG(_L("[MediaServant]\t CMSFillView::~CMSFillView"));
       
    74     DoDeactivate();
       
    75     }
       
    76 
       
    77 // --------------------------------------------------------------------------
       
    78 // TUid CMSFillView::Id()
       
    79 // --------------------------------------------------------------------------
       
    80 //
       
    81 TUid CMSFillView::Id() const
       
    82     {
       
    83     LOG(_L("[MediaServant]\t CMSFillView::Id"));
       
    84 
       
    85     return KMSFillViewId;
       
    86     }
       
    87 
       
    88 
       
    89 // --------------------------------------------------------------------------
       
    90 // CMSFillView::HandleCommandL(TInt aCommand)
       
    91 // --------------------------------------------------------------------------
       
    92 //
       
    93 void CMSFillView::HandleCommandL(TInt aCommand)
       
    94     {
       
    95     LOG(_L("[MediaServant]\t CMSFillView::HandleCommandL"));
       
    96 
       
    97     CEikButtonGroupContainer* cba = Cba();
       
    98 
       
    99     switch (aCommand)
       
   100         {
       
   101         case EAknSoftkeyBack:
       
   102             {
       
   103             CancelAsyncOperation( iAppUi );
       
   104             iNextView = KMSMainViewId;
       
   105 
       
   106             CheckAndHandleChangesL();
       
   107 
       
   108             break;
       
   109             }
       
   110 
       
   111         case EAknSoftkeyDone:
       
   112             {
       
   113             CancelAsyncOperation(  iAppUi );
       
   114             iContainer->SetReorderStateL( EMSFillNormal );
       
   115             cba->SetCommandSetL( R_AVKON_SOFTKEYS_OPTIONS_BACK );
       
   116             cba->DrawNow();
       
   117 
       
   118             // Set title pane text
       
   119             SetTitlePaneTextL( R_MS_FILL_VIEW_TITLE );
       
   120             break;
       
   121             }
       
   122 
       
   123         case EMSCmdActivate: // fall through
       
   124         case EMSCmdDeActivate:
       
   125             {
       
   126             iContainer->ChangeListActivityL();
       
   127             SetListUnselected();
       
   128             break;
       
   129             }
       
   130         // Edit fill rule
       
   131         case EMSCmdEditRule:
       
   132             {
       
   133             CancelAsyncOperation(  iAppUi );
       
   134             TMSTemplate ruleTemplate;
       
   135             ruleTemplate.templateType = aCommand;
       
   136             ruleTemplate.selectedTemplate = EMSNoTemplate;
       
   137             iAppUi->ParameterAgent()->SetRuleTemplate( ruleTemplate );
       
   138 
       
   139             iNextView = KMSFillEditViewId;
       
   140             CheckAndHandleChangesL();
       
   141 
       
   142             break;
       
   143             }
       
   144 
       
   145         case EMSCmdBrowse:
       
   146             {
       
   147             CancelAsyncOperation(  iAppUi );
       
   148             iNextView = KMSFillBrowseViewId;
       
   149             CheckAndHandleChangesL();
       
   150 
       
   151             break;
       
   152             }
       
   153 
       
   154         case EMSCmdNewImageList: // fall through
       
   155         case EMSCmdNewVideoList: // fall through
       
   156         case EMSCmdNewMusicList:
       
   157             {
       
   158             CancelAsyncOperation(  iAppUi );
       
   159             ShowTemplateQueryL( aCommand );
       
   160             iNextView = KMSFillEditViewId;
       
   161             CheckAndHandleChangesL();
       
   162             break;
       
   163             }
       
   164 
       
   165         // Reorder fill rule
       
   166         case EMSCmdReorder:
       
   167             {
       
   168             iContainer->SetReorderStateL( EMSFillReorderActive );
       
   169             cba->SetCommandSetL( R_SOFTKEYS_DROP_EMPTY );
       
   170             cba->DrawNow();
       
   171             // Set title pane text
       
   172             SetTitlePaneTextL( R_MS_FILL_VIEW_TITLE_REORDER_MODE );
       
   173             break;
       
   174             }
       
   175 
       
   176         // Drop rule to new location
       
   177         case EMSCmdDrop:
       
   178             {
       
   179             iContainer->SetReorderStateL( EMSFillGrabActive );
       
   180             cba->SetCommandSetL( R_SOFTKEYS_GRAB_DONE );
       
   181             cba->DrawNow();
       
   182             break;
       
   183             }
       
   184         // Reorder mode active - grab item
       
   185         case EMSCmdGrab:
       
   186             {
       
   187             iContainer->SetReorderStateL( EMSFillReorderActive );
       
   188             cba->SetCommandSetL( R_SOFTKEYS_DROP_EMPTY );
       
   189             cba->DrawNow();
       
   190             break;
       
   191             }
       
   192         // Delete fill rule
       
   193         case EMSCmdDelete:
       
   194             {
       
   195             iContainer->DeleteRuleL();
       
   196             break;
       
   197             }
       
   198         case EAknCmdHelp :
       
   199             {
       
   200             TRAP_IGNORE( HlpLauncher::LaunchHelpApplicationL(
       
   201                         iEikonEnv->WsSession(),
       
   202             iEikonEnv->EikAppUi()->AppHelpContextL() ));
       
   203             break;
       
   204             }
       
   205         default:
       
   206             {
       
   207             CancelAsyncOperation(  iAppUi );
       
   208             AppUi()->HandleCommandL(aCommand);
       
   209             break;
       
   210             }
       
   211         }
       
   212     }
       
   213 
       
   214 
       
   215 // --------------------------------------------------------------------------
       
   216 // CMSFillView::DoActivateL()
       
   217 // --------------------------------------------------------------------------
       
   218 //
       
   219 void CMSFillView::DoActivateL(
       
   220    const TVwsViewId& /*aPrevViewId*/,TUid /*aCustomMessageId*/,
       
   221    const TDesC8& /*aCustomMessage*/)
       
   222     {
       
   223     LOG(_L("[MediaServant]\t CMSFillView::DoActivateL"));
       
   224 
       
   225     // Set engine observer
       
   226     iAppUi->MSEngine()->SetObserver( this );
       
   227 
       
   228     // Set title pane text
       
   229     SetTitlePaneTextL( R_MS_FILL_VIEW_TITLE );
       
   230 
       
   231     if ( !iContainer )
       
   232         {
       
   233         iContainer = new (ELeave) CMSFillContainer( *iAppUi, *this );
       
   234         iContainer->ConstructL( ClientRect() );
       
   235         iContainer->SetMopParent( this );
       
   236         AppUi()->AddToViewStackL( *this, iContainer );
       
   237         }
       
   238     SetListUnselected();
       
   239     }
       
   240 
       
   241 // --------------------------------------------------------------------------
       
   242 // CMSFillView::DoDeactivate()
       
   243 // --------------------------------------------------------------------------
       
   244 //
       
   245 void CMSFillView::DoDeactivate()
       
   246     {
       
   247     LOG(_L("[MediaServant]\t CMSFillView::DoDeactivate"));
       
   248 
       
   249     if ( iContainer )
       
   250         {
       
   251         AppUi()->RemoveFromStack( iContainer );
       
   252         }
       
   253 
       
   254     delete iContainer; // Deletes the container class object.
       
   255     iContainer = NULL;
       
   256     SetListUnselected();
       
   257     }
       
   258 
       
   259 // --------------------------------------------------------------------------
       
   260 // CMSFillView::FocusIndex()
       
   261 // --------------------------------------------------------------------------
       
   262 //
       
   263 TInt CMSFillView::FocusIndex() const
       
   264     {
       
   265     return iContainer->SelectedItemIndex();
       
   266     }
       
   267 
       
   268 // --------------------------------------------------------------------------
       
   269 // CMSFillView::DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane)
       
   270 // --------------------------------------------------------------------------
       
   271 //
       
   272 void CMSFillView::DynInitMenuPaneL( TInt aResourceId,
       
   273                                     CEikMenuPane* aMenuPane )
       
   274     {
       
   275     LOG(_L("[MediaServant]\t CMSFillView::DynInitMenuPaneL"));
       
   276     
       
   277     if ( aResourceId == R_FILL_VIEW_MENU && iContainer )
       
   278         {
       
   279         // check if the list is empty
       
   280         if ( iContainer->ListItemCount() <= 0 )
       
   281             {
       
   282             // Hide commands
       
   283             aMenuPane->SetItemDimmed(EMSCmdEditRule, ETrue);
       
   284             aMenuPane->SetItemDimmed(EMSCmdReorder, ETrue);
       
   285             aMenuPane->SetItemDimmed(EMSCmdDelete, ETrue);
       
   286             aMenuPane->SetItemDimmed(EMSCmdBrowse, ETrue);
       
   287             aMenuPane->SetItemDimmed(EMSCmdActivate, ETrue);
       
   288             aMenuPane->SetItemDimmed(EMSCmdDeActivate, ETrue);
       
   289             }
       
   290 
       
   291         if ( iContainer->IsCurrentListItemActive() )
       
   292             {
       
   293             aMenuPane->SetItemDimmed(EMSCmdActivate, ETrue);
       
   294             }
       
   295         else
       
   296             {
       
   297             aMenuPane->SetItemDimmed(EMSCmdDeActivate, ETrue);
       
   298             }
       
   299         }
       
   300     }
       
   301 
       
   302 // --------------------------------------------------------------------------
       
   303 // CMSFillView::ShowTemplateQueryL
       
   304 // shows template query
       
   305 // --------------------------------------------------------------------------
       
   306 //
       
   307 void CMSFillView::ShowTemplateQueryL( TInt aCommand )
       
   308     {
       
   309     LOG(_L("[MediaServant]\t CMSFillView::ShowTemplateQueryL"));
       
   310     
       
   311     HBufC* defaultListName = NULL;;
       
   312 
       
   313     TMSTemplate ruleTemplate;
       
   314     // set template info
       
   315     ruleTemplate.templateType = aCommand;
       
   316 
       
   317     switch ( aCommand )
       
   318         {
       
   319         case EMSCmdNewImageList:
       
   320             {
       
   321             defaultListName = StringLoader::LoadLC(
       
   322                                         R_MS_CUSTOM_LIST_IMAGE_NAME );
       
   323             ruleTemplate.selectedTemplate = KImageListTemplate;
       
   324             break;
       
   325             }
       
   326         case EMSCmdNewVideoList:
       
   327             {
       
   328             defaultListName = StringLoader::LoadLC(
       
   329                                         R_MS_CUSTOM_LIST_VIDEO_NAME );
       
   330             ruleTemplate.selectedTemplate = KVideoListTemplate;
       
   331             break;
       
   332             }
       
   333         case EMSCmdNewMusicList:
       
   334             {
       
   335             defaultListName = StringLoader::LoadLC(
       
   336                                         R_MS_CUSTOM_LIST_MUSIC_NAME );
       
   337             ruleTemplate.selectedTemplate = KMusicListTemplate;
       
   338             break;
       
   339             }
       
   340         default:
       
   341             {
       
   342             defaultListName = StringLoader::LoadLC(
       
   343                                         R_MS_CUSTOM_LIST_IMAGE_NAME );
       
   344             ruleTemplate.selectedTemplate = KImageListTemplate;
       
   345             // command not found
       
   346             break;
       
   347             }
       
   348         }
       
   349 
       
   350     // Create search string with wildcards
       
   351     HBufC* searchStr = HBufC::NewLC( KMaxFileName );
       
   352     searchStr->Des().Copy( KWildCard );
       
   353     searchStr->Des().Append( defaultListName->Des() );
       
   354     searchStr->Des().Append( KWildCard );
       
   355 
       
   356     // Check if fill list have dublicate names
       
   357     TInt count = iContainer->CheckIfDublicateNames( *searchStr );
       
   358 
       
   359     CleanupStack::PopAndDestroy( searchStr );
       
   360     // keep template name safe
       
   361     ruleTemplate.templateName.Copy( defaultListName->Des() );
       
   362                         
       
   363     // if existing items...
       
   364     searchStr = HBufC::NewLC( KMaxFileName );
       
   365     searchStr->Des().Append( defaultListName->Des() );
       
   366 
       
   367     TBool same = EFalse;
       
   368 
       
   369     RPointerArray<CMSFillList>* iFillListArray =
       
   370                     iAppUi->FillRuleController()->FillListArray();
       
   371 
       
   372     // if there are same name items
       
   373     for ( TInt index = 0; index < iFillListArray->Count(); ++index )
       
   374         {
       
   375         CCmFillRule* rule = (*iFillListArray)[index]->List();
       
   376         HBufC* listName =
       
   377                 CnvUtfConverter::ConvertToUnicodeFromUtf8L( rule->Name() );
       
   378         CleanupStack::PushL( listName );
       
   379         if ( *searchStr == *listName )
       
   380             {
       
   381             same = ETrue;
       
   382             }
       
   383         CleanupStack::PopAndDestroy( listName );
       
   384         }
       
   385 
       
   386     CleanupStack::PopAndDestroy( searchStr );
       
   387     // exist same name items
       
   388     if ( count > 0 && same )
       
   389         {
       
   390         TInt postfix;
       
   391         // calculate a postfix number to add the end of the name
       
   392         for ( postfix = 1; ; ++postfix )
       
   393             {
       
   394             HBufC* sameStr = HBufC::NewL( KMaxFileName );
       
   395             CleanupStack::PushL( sameStr );
       
   396             sameStr->Des().Copy( KWildCard );
       
   397             sameStr->Des().Append( defaultListName->Des() );
       
   398             sameStr->Des().Append( KSpace );
       
   399             sameStr->Des().AppendNum( postfix );
       
   400             sameStr->Des().Append( KWildCard );
       
   401                
       
   402             // do number conversion            
       
   403             TPtr ptr = sameStr->Des();
       
   404             AknTextUtils::
       
   405             DisplayTextLanguageSpecificNumberConversion( ptr );
       
   406                                 
       
   407             if ( 0 == iContainer->CheckIfDublicateNames( *sameStr ) )
       
   408                 {
       
   409                 // after append the current number, there are not
       
   410                 //same name items, so jump out the code block
       
   411                 CleanupStack::PopAndDestroy( sameStr );
       
   412                 break;
       
   413                 }
       
   414             CleanupStack::PopAndDestroy( sameStr );
       
   415             }
       
   416 
       
   417         // append order number to name
       
   418         ruleTemplate.templateName.Append( KSpace );
       
   419         ruleTemplate.templateName.AppendNum( postfix );
       
   420 
       
   421         // do number conversion            
       
   422         AknTextUtils::
       
   423             DisplayTextLanguageSpecificNumberConversion(
       
   424                 ruleTemplate.templateName );            
       
   425         }
       
   426 
       
   427     // store template info to parameter agent
       
   428     iAppUi->ParameterAgent()->SetRuleTemplate( ruleTemplate );
       
   429 
       
   430     CleanupStack::PopAndDestroy( defaultListName );
       
   431     }
       
   432 
       
   433 // ---------------------------------------------------------------------------
       
   434 // CMSFillView::ShowNaviTextL
       
   435 // ---------------------------------------------------------------------------
       
   436 //
       
   437 void CMSFillView::ShowNaviTextL()
       
   438     {
       
   439     LOG(_L("[MediaServant]\t CMSFillView::ShowNaviTextL"));
       
   440     
       
   441     HBufC* naviText = StringLoader::LoadLC( R_MS_PREPROCESSING_TEXT );
       
   442     SetNavigationPaneTextL( *naviText );
       
   443     CleanupStack::PopAndDestroy( naviText );
       
   444     }
       
   445 
       
   446 // ---------------------------------------------------------------------------
       
   447 // CMSFillView::SetListUnselected
       
   448 // ---------------------------------------------------------------------------
       
   449 //
       
   450 void CMSFillView::SetListUnselected( )
       
   451     {
       
   452     LOG(_L("[MediaServant]\t CMSFillView::SetListUnselected"));
       
   453     
       
   454     iListUnSelected =  iAppUi->FillRuleController()->
       
   455                                        HasSelectionsChanged( ECmUnSelected );
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------------------------
       
   459 // CMSFillView::CheckAndHandleChangesL
       
   460 // ---------------------------------------------------------------------------
       
   461 //
       
   462 void CMSFillView::CheckAndHandleChangesL()
       
   463     {
       
   464     LOG(_L("[MediaServant]\t CMSFillView::CheckAndHandleChangesL"));
       
   465     
       
   466     TBool priorityChanged( EFalse );
       
   467 
       
   468     // Check if priorities has been changed
       
   469     priorityChanged = iAppUi->FillRuleController()->
       
   470                                    HasPriorityChangedL();
       
   471 
       
   472     iNewListSelected = iAppUi->FillRuleController()->
       
   473                                    HasSelectionsChanged( ECmSelected );
       
   474     // check if there is deleted lists
       
   475     TBool listDeleted = iContainer->IsListDeleted();
       
   476 
       
   477     // set activity for all rules
       
   478     iContainer->SetFillRules();
       
   479 
       
   480     if ( iListUnSelected )
       
   481         {
       
   482         // unselected list(s) - show query
       
   483         DoDeleteQueryL();
       
   484         }
       
   485 
       
   486     // send rules to server
       
   487     iAppUi->FillRuleController()->SaveRulesL();
       
   488 
       
   489     // update lists if list(s) have been deleted, created or their selection
       
   490     // statuses or priorities have been changed
       
   491     if ( listDeleted ||
       
   492          priorityChanged ||
       
   493          iListUnSelected ||
       
   494          iNewListSelected )
       
   495         {
       
   496         // disable right softkey
       
   497         CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
       
   498         cba->SetCommandSetL( R_MS_SOFTKEYS_OPTIONS_EMPTY );
       
   499         cba->DrawDeferred();
       
   500 
       
   501         ShowNaviTextL();
       
   502         iAppUi->MSEngine()->UpdateFillListsL();
       
   503         }
       
   504     else // no list update needed
       
   505         {
       
   506         // retrieve new information
       
   507         iAppUi->FillRuleController()->UpdateArrayL();
       
   508         iAppUi->ChangeViewL( KMSFillViewId, iNextView );
       
   509         }
       
   510     }
       
   511 
       
   512 // ---------------------------------------------------------------------------
       
   513 // CMSFillView::DoDeleteQueryL
       
   514 // ---------------------------------------------------------------------------
       
   515 //
       
   516 void CMSFillView::DoDeleteQueryL()
       
   517     {
       
   518     LOG(_L("[MediaServant]\t CMSFillView::DoDeleteQueryL"));
       
   519 
       
   520     // Show delete files query
       
   521     CAknQueryDialog* query= CAknQueryDialog::NewL(
       
   522                                    CAknQueryDialog::ENoTone );
       
   523 
       
   524     if ( query->ExecuteLD( R_MSERV_DELETE_FILES_QUERY ) )
       
   525         {
       
   526         // do nothing
       
   527         }
       
   528     else // canceled
       
   529         {
       
   530         iAppUi->FillRuleController()->RestoreOriginalSelections();
       
   531         }
       
   532     }
       
   533 
       
   534 // --------------------------------------------------------------------------
       
   535 // CMSFillView::ReadyL()
       
   536 // engine observer callback
       
   537 // --------------------------------------------------------------------------
       
   538 //
       
   539 void CMSFillView::ReadyL( TCmService aService, TInt /*aError*/ )
       
   540     {
       
   541     LOG(_L("[MediaServant]\t CMSFillView::ReadyL"));
       
   542 
       
   543     switch ( aService )
       
   544         {
       
   545         case ECmServiceUpdateFillLists:
       
   546             {
       
   547             // set original softkeys back
       
   548             CEikButtonGroupContainer* cba =
       
   549                             CEikButtonGroupContainer::Current();
       
   550             cba->SetCommandSetL( R_AVKON_SOFTKEYS_OPTIONS_BACK );
       
   551             cba->DrawDeferred();
       
   552 
       
   553             // retrieve new information
       
   554             iAppUi->FillRuleController()->UpdateArrayL();
       
   555 
       
   556             ClearCurrentNaviPaneText();
       
   557             iAppUi->ChangeViewL( KMSFillViewId, iNextView );
       
   558             break;
       
   559             }
       
   560         case ECmServiceDeleteFilledFiles:
       
   561             {
       
   562             LOG(_L("[MediaServant]\t CMSFillView::ReadyL delete complete"));
       
   563             ClearCurrentNaviPaneText();
       
   564             // Set context pane icon
       
   565             iContainer->SetDefaultContextPaneIconL();
       
   566 
       
   567             iContainer->UpdateListBoxDataL();
       
   568             break;
       
   569             }
       
   570 
       
   571         default:
       
   572             {
       
   573             LOG(_L("[MediaServant]\t CMSFillView::ReadyL \
       
   574             service not found"));
       
   575             }
       
   576 
       
   577         }
       
   578     }
       
   579 
       
   580 // --------------------------------------------------------------------------
       
   581 // CMSFillView::SetCbaL()
       
   582 // Changes softkeys
       
   583 // --------------------------------------------------------------------------
       
   584 //
       
   585 void CMSFillView::SetCbaL( TBool aSelected )
       
   586     {
       
   587     LOG(_L("[MediaServant]\t CMSFillView::SetCbaL"));
       
   588     
       
   589     CEikButtonGroupContainer* cba = Cba();
       
   590 
       
   591     if ( aSelected )
       
   592         {
       
   593         cba->SetCommandSetL( R_MS_SOFTKEYS_OPTIONS_BACK__DEACTIVATE );
       
   594         }
       
   595     else
       
   596         {
       
   597         cba->SetCommandSetL( R_MS_SOFTKEYS_OPTIONS_BACK__ACTIVATE );
       
   598         }
       
   599     cba->DrawDeferred();
       
   600     }
       
   601 
       
   602 // End of File
       
   603