engine/collectionframework/thumbnailcreator/src/glxtnvolumedatabase.cpp
changeset 71 27f2d7aec52a
parent 69 45459746d5e8
child 72 0a8e959402e5
equal deleted inserted replaced
69:45459746d5e8 71:27f2d7aec52a
     1 /*
       
     2 * Copyright (c) 2008-2009 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:   Implementation of CGlxtnVolumeDatabase
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 /**
       
    21  * @internal reviewed 31/07/2007 by Simon Brooks
       
    22  */
       
    23 
       
    24 #include "glxtnvolumedatabase.h"
       
    25 
       
    26 #include <glxtracer.h>
       
    27 #include <glxpanic.h>
       
    28 #include <s32file.h>
       
    29 
       
    30 #include "glxtnfileinfo.h"
       
    31 #include "mglxtnvolumedatabaseobserver.h"
       
    32 
       
    33 #include <glxlog.h>
       
    34 _LIT(KGlxCreateTableIds, "CREATE TABLE Ids (MediaId UNSIGNED INTEGER NOT NULL, ThumbId UNSIGNED INTEGER NOT NULL)");
       
    35 _LIT(KGlxCreateTableItems, "CREATE TABLE Items (Uri VARCHAR NOT NULL, ThumbId UNSIGNED INTEGER NOT NULL, FileSize INTEGER, ModTime TIME)");
       
    36 _LIT(KGlxCreateTableThumbnails, "CREATE TABLE Thumbnails (ThumbId UNSIGNED INTEGER NOT NULL, Width INTEGER NOT NULL, Height INTEGER NOT NULL, Format INTEGER NOT NULL, ImageData LONG VARBINARY NOT NULL)");
       
    37 _LIT(KGlxCreateIndexIds, "CREATE UNIQUE INDEX IdIndex ON Ids (MediaId)");
       
    38 _LIT(KGlxCreateIndexItems, "CREATE UNIQUE INDEX ItemIndex ON Items (ThumbId ASC)");
       
    39 _LIT(KGlxCreateIndexThumbnails, "CREATE UNIQUE INDEX ThumbnailIndex ON Thumbnails (ThumbId, Width, Height)");
       
    40 
       
    41 _LIT(KGlxTableIds, "Ids");
       
    42 _LIT(KGlxTableItems, "Items");
       
    43 _LIT(KGlxTableThumbnails, "Thumbnails");
       
    44 _LIT(KGlxIndexItems, "ItemIndex");
       
    45 
       
    46 const TInt KGlxColIdMediaId = 1;
       
    47 const TInt KGlxColIdThumbId = 2;
       
    48 
       
    49 const TInt KGlxColItemUri = 1;
       
    50 const TInt KGlxColItemId = 2;
       
    51 const TInt KGlxColItemFileSize = 3;
       
    52 const TInt KGlxColItemModTime = 4;
       
    53 
       
    54 const TInt KGlxColThumbnailId = 1;
       
    55 const TInt KGlxColThumbnailWidth = 2;
       
    56 const TInt KGlxColThumbnailHeight = 3;
       
    57 const TInt KGlxColThumbnailFormat = 4;
       
    58 const TInt KGlxColThumbnailData = 5;
       
    59 
       
    60 _LIT(KGlxQueryThumbIdFromIds, "SELECT * FROM Ids WHERE MediaId = ");
       
    61 _LIT(KGlxQueryThumbIdFromItems, "SELECT * FROM Items WHERE Uri = ");
       
    62 _LIT(KGlxQueryThumbnail, "SELECT * FROM Thumbnails WHERE ThumbId = %d AND Width = %d AND Height = %d");
       
    63 _LIT(KGlxQueryAvailable, "SELECT ThumbId, Width, Height FROM Thumbnails WHERE ThumbId = %d AND Width = %d AND Height = %d");
       
    64 
       
    65 _LIT(KGlxDeleteId, "DELETE FROM Ids WHERE MediaId = %d");
       
    66 _LIT(KGlxDeleteThumbnails, "DELETE FROM Thumbnails WHERE ThumbId = %d");
       
    67 _LIT(KGlxDeleteItem, "DELETE FROM Items WHERE ThumbId = %d");
       
    68 
       
    69 const TInt KGlxTIntMaxDigits = 11;
       
    70 
       
    71 const TUint KGlxFirstThumbnailId = 1;
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // NewL
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 CGlxtnVolumeDatabase* CGlxtnVolumeDatabase::NewLC(
       
    78         MGlxtnVolumeDatabaseObserver& aObserver, RFs& aFs, const TDesC& aPath)
       
    79     {
       
    80     TRACER("CGlxtnVolumeDatabase* CGlxtnVolumeDatabase::NewLC( MGlxtnVolumeDatabaseObserver& aObserver, RFs& aFs, const TDesC& aPath)");
       
    81     CGlxtnVolumeDatabase* self = 
       
    82                         new (ELeave) CGlxtnVolumeDatabase(aObserver, aFs);
       
    83     CleanupStack::PushL(self);
       
    84     self->ConstructL(aPath);
       
    85     return self;
       
    86     }
       
    87 
       
    88 // -----------------------------------------------------------------------------
       
    89 // Constructor
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 CGlxtnVolumeDatabase::CGlxtnVolumeDatabase(
       
    93                                     MGlxtnVolumeDatabaseObserver& aObserver, 
       
    94                                     RFs& aFs)
       
    95     : CActive(EPriorityStandard), 
       
    96       iObserver(aObserver), iFs(aFs), iState(EStateIdle)
       
    97     {
       
    98     TRACER("CGlxtnVolumeDatabase::CGlxtnVolumeDatabase( MGlxtnVolumeDatabaseObserver& aObserver, RFs& aFs)");
       
    99     }
       
   100 
       
   101 // -----------------------------------------------------------------------------
       
   102 // ConstructL
       
   103 // -----------------------------------------------------------------------------
       
   104 //
       
   105 void CGlxtnVolumeDatabase::ConstructL(const TDesC& aPath)
       
   106     {
       
   107     TRACER("void CGlxtnVolumeDatabase::ConstructL(const TDesC& aPath)");
       
   108     iDrive = aPath.Left(KMaxDriveName);
       
   109 
       
   110     TRAPD(error, OpenDbL(iFs, aPath));
       
   111     if ( KErrNone != error )
       
   112         {
       
   113         iDatabase.Close();
       
   114         delete iStore;
       
   115         iStore = NULL;
       
   116         CreateDbL(iFs, aPath);
       
   117         }
       
   118 
       
   119     CActiveScheduler::Add(this);
       
   120     }
       
   121 
       
   122 // -----------------------------------------------------------------------------
       
   123 // Destructor
       
   124 // -----------------------------------------------------------------------------
       
   125 //
       
   126 CGlxtnVolumeDatabase::~CGlxtnVolumeDatabase() 
       
   127     {
       
   128     TRACER("CGlxtnVolumeDatabase::~CGlxtnVolumeDatabase()");
       
   129     Cancel();
       
   130     iView.Close();
       
   131     iTable.Close();
       
   132     iDbUpdater.Close();
       
   133     iDatabase.Close();
       
   134     delete iStore;
       
   135     }
       
   136 
       
   137 // -----------------------------------------------------------------------------
       
   138 // Drive
       
   139 // -----------------------------------------------------------------------------
       
   140 //
       
   141 const TDesC& CGlxtnVolumeDatabase::Drive() const
       
   142     {
       
   143     TRACER("TDesC& CGlxtnVolumeDatabase::Drive()");
       
   144     return iDrive;
       
   145     }
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // GetThumbnailIdL
       
   149 // Look up thumbnail ID from Ids table
       
   150 // -----------------------------------------------------------------------------
       
   151 //
       
   152 void CGlxtnVolumeDatabase::GetThumbnailIdL( const TGlxMediaId& aMediaId )
       
   153     {
       
   154     TRACER("void CGlxtnVolumeDatabase::GetThumbnailIdL( const TGlxMediaId& aMediaId )");
       
   155     if ( EStateIdle != iState )
       
   156         {
       
   157         User::Leave(KErrNotReady);
       
   158         }
       
   159 
       
   160     GLX_LOG_INFO1("CGlxtnVolumeDatabase::GetThumbnailIdL() Media Id= %d",aMediaId.Value());
       
   161     HBufC* sql = HBufC::NewLC(
       
   162                     KGlxQueryThumbIdFromIds().Length() + KGlxTIntMaxDigits );
       
   163     *sql = KGlxQueryThumbIdFromIds;
       
   164     sql->Des().AppendNum( aMediaId.Value() );
       
   165 
       
   166     EvaluateQueryL( *sql );
       
   167     iState = EStateGettingIdFromMediaId;
       
   168 
       
   169     CleanupStack::PopAndDestroy(sql);
       
   170     }
       
   171 
       
   172 // -----------------------------------------------------------------------------
       
   173 // GetThumbnailIdL
       
   174 // Look up thumbnail ID from Items table.  If not found, add new record.
       
   175 // -----------------------------------------------------------------------------
       
   176 //
       
   177 void CGlxtnVolumeDatabase::GetThumbnailIdL(const CGlxtnFileInfo* aInfo)
       
   178     {
       
   179     TRACER("void CGlxtnVolumeDatabase::GetThumbnailIdL(const CGlxtnFileInfo* aInfo)");
       
   180     if ( EStateIdle != iState )
       
   181         {
       
   182         User::Leave(KErrNotReady);
       
   183         }
       
   184 
       
   185     iInfo = aInfo;
       
   186     HBufC* uri = QuoteSqlStringLC(iInfo->FilePath());
       
   187     HBufC* sql = HBufC::NewLC(
       
   188                     KGlxQueryThumbIdFromItems().Length() + uri->Length());
       
   189     *sql = KGlxQueryThumbIdFromItems;
       
   190     sql->Des().Append(*uri);
       
   191 
       
   192     EvaluateQueryL( *sql );
       
   193     iState = EStateGettingIdFromFilename;
       
   194 
       
   195     CleanupStack::PopAndDestroy(sql);
       
   196     CleanupStack::PopAndDestroy(uri);
       
   197     }
       
   198 
       
   199 // -----------------------------------------------------------------------------
       
   200 // StoreThumbnailIdL
       
   201 // Add record to Ids table
       
   202 // -----------------------------------------------------------------------------
       
   203 //
       
   204 void CGlxtnVolumeDatabase::StoreThumbnailIdL( const TGlxMediaId& aMediaId,
       
   205                                         const TGlxtnThumbnailId& aThumbId )
       
   206     {
       
   207     TRACER("void CGlxtnVolumeDatabase::StoreThumbnailIdL( const TGlxMediaId& aMediaId, const TGlxtnThumbnailId& aThumbId )");
       
   208     if ( EStateIdle != iState )
       
   209         {
       
   210         User::Leave(KErrNotReady);
       
   211         }
       
   212     GLX_LOG_INFO1("StoreThumbnailIdL():- Media Id = %d",aMediaId.Value());
       
   213     GLX_LOG_INFO1("StoreThumbnailIdL():- aThumbId = %d",aThumbId.Value());
       
   214     RDbTable table;
       
   215     CleanupClosePushL(table);
       
   216     User::LeaveIfError( table.Open(
       
   217                         iDatabase, KGlxTableIds, RDbRowSet::EInsertOnly ) );
       
   218 
       
   219     table.InsertL();
       
   220     table.SetColL( KGlxColIdMediaId, aMediaId.Value() );
       
   221     table.SetColL( KGlxColIdThumbId, aThumbId.Value() );
       
   222     table.PutL();
       
   223 
       
   224     CleanupStack::PopAndDestroy(&table);
       
   225 
       
   226     iObserver.HandleThumbnailIdStoredL();
       
   227     }
       
   228 
       
   229 // -----------------------------------------------------------------------------
       
   230 // GetThumbnailL
       
   231 // Look up thumbnail from Thumbnails table
       
   232 // -----------------------------------------------------------------------------
       
   233 //
       
   234 void CGlxtnVolumeDatabase::GetThumbnailL( const TGlxtnThumbnailId& aThumbId,
       
   235                                             const TSize& aSize )
       
   236     {
       
   237     TRACER("void CGlxtnVolumeDatabase::GetThumbnailL( const TGlxtnThumbnailId& aThumbId, const TSize& aSize )");
       
   238     if ( EStateIdle != iState )
       
   239         {
       
   240         User::Leave(KErrNotReady);
       
   241         }
       
   242 
       
   243     GLX_LOG_INFO1("GetThumbnailL():- ThumbId Id = %d",aThumbId.Value());
       
   244     GLX_LOG_INFO2("GetThumbnailL Width=%d, Height=%d", aSize.iWidth, aSize.iHeight);
       
   245     HBufC* sql = HBufC::NewLC( KGlxQueryThumbnail().Length()
       
   246                                 + 3 * KGlxTIntMaxDigits);
       
   247     sql->Des().Format( KGlxQueryThumbnail,
       
   248                         aThumbId.Value(), aSize.iWidth, aSize.iHeight );
       
   249 
       
   250     EvaluateQueryL( *sql );
       
   251     iState = EStateGettingThumbnail;
       
   252 
       
   253     CleanupStack::PopAndDestroy(sql);
       
   254     }
       
   255 
       
   256 // -----------------------------------------------------------------------------
       
   257 // CheckAvailableL
       
   258 // Check if thumbnail is in Thumbnails table
       
   259 // -----------------------------------------------------------------------------
       
   260 //
       
   261 void CGlxtnVolumeDatabase::CheckAvailableL( const TGlxtnThumbnailId& aThumbId,
       
   262                                             const TSize& aSize )
       
   263     {
       
   264     TRACER("void CGlxtnVolumeDatabase::CheckAvailableL( const TGlxtnThumbnailId& aThumbId, const TSize& aSize )");
       
   265     if ( EStateIdle != iState )
       
   266         {
       
   267         User::Leave(KErrNotReady);
       
   268         }
       
   269     GLX_LOG_INFO1("CheckAvailableL():- ThumbId = %d", aThumbId.Value());
       
   270 
       
   271     HBufC* sql = HBufC::NewLC( KGlxQueryAvailable().Length()
       
   272                                 + 3 * KGlxTIntMaxDigits);
       
   273     sql->Des().Format( KGlxQueryAvailable,
       
   274                         aThumbId.Value(), aSize.iWidth, aSize.iHeight );
       
   275 
       
   276     EvaluateQueryL( *sql );
       
   277     iState = EStateCheckingAvailability;
       
   278 
       
   279     CleanupStack::PopAndDestroy(sql);
       
   280     }
       
   281 
       
   282 // -----------------------------------------------------------------------------
       
   283 // StoreThumbnailL
       
   284 // Add record to Thumbnails table
       
   285 // -----------------------------------------------------------------------------
       
   286 //
       
   287 void CGlxtnVolumeDatabase::StoreThumbnailL( const TGlxtnThumbnailId& aThumbId,
       
   288                                            const TSize& aSize,
       
   289                                            TGlxImageDataFormat aFormat,
       
   290                                            const TDesC8& aData )
       
   291     {
       
   292     TRACER("void CGlxtnVolumeDatabase::StoreThumbnailL( const TGlxtnThumbnailId& aThumbId, const TSize& aSize, TGlxImageDataFormat aFormat, const TDesC8& aData )");
       
   293     if ( EStateIdle != iState )
       
   294         {
       
   295         User::Leave(KErrNotReady);
       
   296         }
       
   297     GLX_LOG_INFO1("StoreThumbnailL():- aThumbId = %d",aThumbId.Value());
       
   298     GLX_LOG_INFO2("StoreThumbnailL Width=%d, Height=%d", aSize.iWidth, aSize.iHeight);
       
   299 
       
   300     RDbTable table;
       
   301     CleanupClosePushL(table);
       
   302     User::LeaveIfError( table.Open(
       
   303                 iDatabase, KGlxTableThumbnails, RDbRowSet::EInsertOnly ) );
       
   304 
       
   305     table.InsertL();
       
   306     table.SetColL( KGlxColThumbnailId, aThumbId.Value() );
       
   307     table.SetColL( KGlxColThumbnailWidth, aSize.iWidth );
       
   308     table.SetColL( KGlxColThumbnailHeight, aSize.iHeight );
       
   309     table.SetColL( KGlxColThumbnailFormat, aFormat );
       
   310     table.SetColL( KGlxColThumbnailData, aData );
       
   311     table.PutL();
       
   312 
       
   313     CleanupStack::PopAndDestroy(&table);
       
   314 
       
   315     iObserver.HandleThumbnailStored();
       
   316     }
       
   317 
       
   318 // -----------------------------------------------------------------------------
       
   319 // DeleteFromIdsL
       
   320 // Delete from IDs table
       
   321 // -----------------------------------------------------------------------------
       
   322 //
       
   323 void CGlxtnVolumeDatabase::DeleteIdL( const TGlxMediaId& aMediaId )
       
   324     {
       
   325     TRACER("void CGlxtnVolumeDatabase::DeleteIdL( const TGlxMediaId& aMediaId )");
       
   326     if ( EStateIdle != iState )
       
   327         {
       
   328         User::Leave(KErrNotReady);
       
   329         }
       
   330 
       
   331     GLX_LOG_INFO1("DeleteIdL():- Media Id = %d",aMediaId.Value());
       
   332     HBufC* sql = HBufC::NewLC( KGlxDeleteId().Length() + KGlxTIntMaxDigits);
       
   333     
       
   334     sql->Des().Format( KGlxDeleteId, aMediaId.Value() );
       
   335     
       
   336     UpdateDataL( *sql );
       
   337     iState = EStateDeletingId;
       
   338     
       
   339     CleanupStack::PopAndDestroy(sql);
       
   340     }
       
   341     
       
   342 // -----------------------------------------------------------------------------
       
   343 // DeleteThumbnailsL
       
   344 // Delete Thumbnails from Thumbnail table
       
   345 // -----------------------------------------------------------------------------
       
   346 //
       
   347 void CGlxtnVolumeDatabase::DeleteThumbnailsL(
       
   348                                         const TGlxtnThumbnailId& aThumbId )
       
   349     {
       
   350     TRACER("void CGlxtnVolumeDatabase::DeleteThumbnailsL( const TGlxtnThumbnailId& aThumbId )");
       
   351     if ( EStateIdle != iState )
       
   352         {
       
   353         User::Leave(KErrNotReady);
       
   354         }
       
   355     GLX_LOG_INFO1("DeleteThumbnailsL():- aThumbId = %d",aThumbId.Value());
       
   356 
       
   357     HBufC* sql = HBufC::NewLC(KGlxDeleteThumbnails().Length() + 
       
   358                                  KGlxTIntMaxDigits);
       
   359     
       
   360     sql->Des().Format( KGlxDeleteThumbnails, aThumbId.Value() );
       
   361     
       
   362     UpdateDataL( *sql );
       
   363     iState = EStateDeletingThumbnails;
       
   364     
       
   365     CleanupStack::PopAndDestroy(sql);
       
   366     }
       
   367     
       
   368 // -----------------------------------------------------------------------------
       
   369 // DeleteItemL
       
   370 // Delete Item from Items table
       
   371 // -----------------------------------------------------------------------------
       
   372 //
       
   373 void CGlxtnVolumeDatabase::DeleteItemL( const TGlxtnThumbnailId& aThumbId )
       
   374     {
       
   375     TRACER("void CGlxtnVolumeDatabase::DeleteItemL( const TGlxtnThumbnailId& aThumbId )");
       
   376     if ( EStateIdle != iState )
       
   377         {
       
   378         User::Leave(KErrNotReady);
       
   379         }
       
   380 
       
   381     GLX_LOG_INFO1("DeleteItemL():- aThumbId = %d",aThumbId.Value());
       
   382     HBufC* sql = HBufC::NewLC( KGlxDeleteItem().Length() + KGlxTIntMaxDigits);
       
   383     
       
   384     sql->Des().Format( KGlxDeleteItem, aThumbId.Value() );
       
   385     
       
   386     UpdateDataL( *sql );
       
   387     iState = EStateDeletingItem;
       
   388     
       
   389     CleanupStack::PopAndDestroy(sql);
       
   390     }
       
   391 
       
   392 // -----------------------------------------------------------------------------
       
   393 // CleanupDatabaseL
       
   394 // Clean from database entries that do not have a corresponding media file
       
   395 // -----------------------------------------------------------------------------
       
   396 //
       
   397 void CGlxtnVolumeDatabase::CleanupDatabaseL()
       
   398     {
       
   399     TRACER("void CGlxtnVolumeDatabase::CleanupDatabaseL()");
       
   400     if ( EStateIdle != iState )
       
   401         {
       
   402         User::Leave(KErrNotReady);
       
   403         }
       
   404     User::LeaveIfError( iTable.Open(
       
   405                         iDatabase, KGlxTableItems, RDbRowSet::EUpdatable ) );
       
   406     iTable.BeginningL();
       
   407 
       
   408     SetActive();
       
   409     TRequestStatus* ts = &iStatus;
       
   410     User::RequestComplete(ts, KErrNone);
       
   411 
       
   412     iState = EStateCleaning;
       
   413     }
       
   414 
       
   415     
       
   416 // -----------------------------------------------------------------------------
       
   417 // CleanupRowL
       
   418 // Test entry in one row in Items table to see if file is available. If it is
       
   419 // not, delete this row and start process of deleting corresponding entries 
       
   420 // from Ids table and Thumbnails table
       
   421 // -----------------------------------------------------------------------------
       
   422 //
       
   423 void CGlxtnVolumeDatabase::CleanupRowL()
       
   424     {
       
   425     TRACER("void CGlxtnVolumeDatabase::CleanupRowL()");
       
   426     // Get filename
       
   427     iTable.GetL();
       
   428     TPtrC filename = iTable.ColDes(KGlxColItemUri);
       
   429    
       
   430     // does file exist
       
   431     TTime time;
       
   432     TInt err = iFs.Modified(filename, time);
       
   433     if(err == KErrNone)
       
   434         {
       
   435         //yes, file exists, so complete to go to next row
       
   436         SetActive();
       
   437         TRequestStatus* ts = &iStatus;
       
   438         User::RequestComplete(ts, KErrNone);
       
   439         iState = EStateCleaning;
       
   440         }
       
   441     else
       
   442         {
       
   443         // Problem accessing file, so delete database entries
       
   444         // First delete row in Items table
       
   445         TUint thumbId = iTable.ColUint( KGlxColItemId );
       
   446         //Delete the row (entry in Items)
       
   447         iTable.DeleteL();
       
   448 
       
   449         // Now delete from Thumbnails
       
   450         HBufC* sql = HBufC::NewLC(KGlxDeleteThumbnails().Length() + 
       
   451                                      KGlxTIntMaxDigits);
       
   452 
       
   453         sql->Des().Format( KGlxDeleteThumbnails, thumbId );
       
   454         UpdateDataL( *sql );
       
   455         iState = EStateCleaningDeletingThumbnails;
       
   456         CleanupStack::PopAndDestroy(sql);
       
   457         }
       
   458     }
       
   459     
       
   460 // -----------------------------------------------------------------------------
       
   461 // DoCancel
       
   462 // -----------------------------------------------------------------------------
       
   463 //
       
   464 void CGlxtnVolumeDatabase::DoCancel()
       
   465     {
       
   466     TRACER("void CGlxtnVolumeDatabase::DoCancel()");
       
   467     iView.Cancel();
       
   468     iTable.Close();
       
   469     iDbUpdater.Close();
       
   470     iState = EStateIdle;
       
   471     }
       
   472 
       
   473 // -----------------------------------------------------------------------------
       
   474 // RunL
       
   475 // -----------------------------------------------------------------------------
       
   476 //
       
   477 void CGlxtnVolumeDatabase::RunL()
       
   478     {
       
   479     TRACER("void CGlxtnVolumeDatabase::RunL()");
       
   480     User::LeaveIfError(iStatus.Int());
       
   481 
       
   482     // Continue any database operations which aren't finished
       
   483     switch ( iState )
       
   484         {
       
   485         case EStateGettingIdFromMediaId:
       
   486         case EStateGettingIdFromFilename:
       
   487         case EStateGettingThumbnail:
       
   488         case EStateCheckingAvailability:
       
   489             if ( iView.Unevaluated() )
       
   490                 {
       
   491                 iView.Evaluate(iStatus);
       
   492                 SetActive();
       
   493                 return;
       
   494                 }
       
   495             break;
       
   496         case EStateDeletingId:
       
   497         case EStateDeletingThumbnails:
       
   498         case EStateDeletingItem:
       
   499         case EStateCleaningDeletingThumbnails:
       
   500             if(iStatus.Int() != 0)
       
   501                 {
       
   502                 iDbUpdater.Next(iStatus);
       
   503                 SetActive();
       
   504                 return;
       
   505                 }
       
   506             break;
       
   507         case EStateCleaning:
       
   508         // do nothing
       
   509             break;
       
   510         default:
       
   511             Panic(EGlxPanicIllegalState);
       
   512             break;
       
   513         }
       
   514 
       
   515     // Handle results of database operation
       
   516     switch ( iState )
       
   517         {
       
   518         case EStateGettingIdFromMediaId:
       
   519             {
       
   520             TGlxtnThumbnailId thumbId;
       
   521             if ( iView.FirstL() )
       
   522                 {
       
   523                 iView.GetL();
       
   524                 thumbId = iView.ColUint(KGlxColIdThumbId);
       
   525                 GLX_LOG_INFO1("RunL - EStateGettingIdFromMediaId  IF (iView.FirstL()): ThumbId = %d", thumbId.Value());
       
   526                 }
       
   527             iView.Close();
       
   528             iState = EStateIdle;
       
   529             GLX_LOG_INFO1("RunL - EStateGettingIdFromMediaId - aThumbId = %d", thumbId.Value());
       
   530             iObserver.HandleThumbnailIdFromMediaIdL(thumbId);
       
   531             }
       
   532             break;
       
   533 
       
   534         case EStateGettingIdFromFilename:
       
   535             {
       
   536             TGlxtnThumbnailId thumbId;
       
   537             if ( iView.FirstL() )
       
   538                 {
       
   539                 iView.GetL();
       
   540                 thumbId = iView.ColUint(KGlxColItemId);
       
   541                 iView.Close();
       
   542                 }
       
   543             else
       
   544                 {
       
   545                 iView.Close();
       
   546                 thumbId = DoAddItemL();
       
   547                 }
       
   548             iState = EStateIdle;
       
   549             iInfo = NULL;
       
   550             GLX_LOG_INFO1("RunL - EStateGettingIdFromFilename - aThumbId = %d", thumbId.Value());
       
   551             iObserver.HandleThumbnailIdFromFilenameL(thumbId);
       
   552             }
       
   553             break;
       
   554 
       
   555         case EStateGettingThumbnail:
       
   556             if ( iView.FirstL() )
       
   557                 {
       
   558                 iView.GetL();
       
   559                 TGlxImageDataFormat format = static_cast<TGlxImageDataFormat>(
       
   560                                         iView.ColInt(KGlxColThumbnailFormat));
       
   561                 TInt size = iView.ColSize(KGlxColThumbnailData);
       
   562 
       
   563                 RDbColReadStream stream;
       
   564                 stream.OpenLC(iView, KGlxColThumbnailData);
       
   565                 HBufC8* data = HBufC8::NewLC(size);
       
   566                 TPtr8 ptr(data->Des());
       
   567                 // Need to specify amount to read, as the HBufC8 can be bigger
       
   568                 // than requested
       
   569                 stream.ReadL(ptr, size);    
       
   570 
       
   571                 CleanupStack::Pop(data);
       
   572                 CleanupStack::PopAndDestroy(&stream);
       
   573 
       
   574                 iView.Close();
       
   575                 iState = EStateIdle;
       
   576                 iObserver.HandleThumbnail(format, data);
       
   577                 }
       
   578             else
       
   579                 {
       
   580                 iView.Close();
       
   581                 iState = EStateIdle;
       
   582                 GLX_LOG_INFO("RunL: HandleDatabaseError - KErrNotFound");
       
   583                 iObserver.HandleDatabaseError(KErrNotFound);
       
   584                 }
       
   585             break;
       
   586             
       
   587         case EStateDeletingId:
       
   588             iState = EStateIdle;
       
   589             iDbUpdater.Close();
       
   590             iObserver.HandleMediaIdDeletedL();
       
   591             break;
       
   592             
       
   593         case EStateDeletingThumbnails:
       
   594             iState = EStateIdle;
       
   595             iDbUpdater.Close();
       
   596             iObserver.HandleThumbnailsDeletedL();
       
   597             break;
       
   598             
       
   599         case EStateDeletingItem:
       
   600             iState = EStateIdle;
       
   601             iDbUpdater.Close();
       
   602             iObserver.HandleItemDeletedL();
       
   603             break;
       
   604 
       
   605         case EStateCheckingAvailability:
       
   606             {
       
   607             TInt result = KGlxThumbnailAvailable;
       
   608             if ( iView.IsEmptyL() )
       
   609                 {
       
   610                 result = KGlxThumbnailNotAvailable;
       
   611                 }
       
   612             iView.Close();
       
   613             iState = EStateIdle;
       
   614             GLX_LOG_INFO1("RunL - EStateCheckingAvailability - result = %d", result);
       
   615             iObserver.HandleAvailabilityChecked(result);
       
   616             }
       
   617             break;
       
   618             
       
   619         case EStateCleaningDeletingThumbnails:
       
   620             iState = EStateCleaning;
       
   621             iDbUpdater.Close();      // deliberate fall through to next row
       
   622         case EStateCleaning:
       
   623             if(iTable.NextL())
       
   624                 {
       
   625                 // next row
       
   626                 CleanupRowL();
       
   627                 }
       
   628             else
       
   629                 {
       
   630                 // no more rows
       
   631                 iTable.Close();
       
   632                 iState = EStateIdle;
       
   633                 iObserver.HandleDatabaseCleanedL();
       
   634                 }
       
   635             break;
       
   636         default:
       
   637             Panic(EGlxPanicIllegalState);
       
   638             break;
       
   639         }
       
   640     }
       
   641 
       
   642 // -----------------------------------------------------------------------------
       
   643 // RunError
       
   644 // -----------------------------------------------------------------------------
       
   645 //
       
   646 TInt CGlxtnVolumeDatabase::RunError(TInt aError)
       
   647     {
       
   648     TRACER("TInt CGlxtnVolumeDatabase::RunError(TInt aError)");
       
   649     iTable.Close();
       
   650     iView.Close();
       
   651     iDbUpdater.Close();
       
   652     iState = EStateIdle;
       
   653     iInfo = NULL;
       
   654     GLX_LOG_INFO1("RunL: HandleDatabaseError - error=%d", aError);
       
   655     iObserver.HandleDatabaseError(aError);
       
   656 
       
   657     return KErrNone;
       
   658     }
       
   659 
       
   660 // -----------------------------------------------------------------------------
       
   661 // OpenDbL
       
   662 // Open an existing database.
       
   663 // -----------------------------------------------------------------------------
       
   664 //
       
   665 void CGlxtnVolumeDatabase::OpenDbL(RFs& aFs, const TDesC& aFilename)
       
   666     {
       
   667     GLX_LOG_ENTRY_EXIT("void CGlxtnVolumeDatabase::OpenDbL(RFs& aFs, const TDesC& aFilename)");
       
   668     iStore = CFileStore::OpenL(aFs, aFilename, EFileRead | EFileWrite);
       
   669     iDatabase.OpenL(iStore, iStore->Root());
       
   670 
       
   671     // Get next available thumbnail ID (synchronous)
       
   672     RDbTable table;
       
   673     CleanupClosePushL(table);
       
   674     User::LeaveIfError( table.Open(
       
   675                         iDatabase, KGlxTableItems, RDbRowSet::EReadOnly ) );
       
   676     User::LeaveIfError(table.SetIndex(KGlxIndexItems));
       
   677 
       
   678     // Find highest thumbnail ID in use.  New entries are added to the Items
       
   679     // table first, and deleted from the Items table last, so all IDs in use
       
   680     // will always be found there.
       
   681     // Thumbnail IDs are only unique within a volume.
       
   682     if ( table.LastL() )
       
   683         {
       
   684         table.GetL();
       
   685         iNextThumbId = table.ColUint(KGlxColItemId) + 1;
       
   686         }
       
   687     else
       
   688         {
       
   689         // Database is empty
       
   690         iNextThumbId = KGlxFirstThumbnailId;
       
   691         }
       
   692 
       
   693     CleanupStack::PopAndDestroy(&table);
       
   694     }
       
   695     
       
   696 // -----------------------------------------------------------------------------
       
   697 // CreateDbL
       
   698 // Create a new database.
       
   699 // -----------------------------------------------------------------------------
       
   700 //
       
   701 void CGlxtnVolumeDatabase::CreateDbL(RFs& aFs, const TDesC& aFilename)
       
   702     {
       
   703     TRACER("void CGlxtnVolumeDatabase::CreateDbL(RFs& aFs, const TDesC& aFilename)");
       
   704     // Create database, overwriting any existing file
       
   705     TInt err = aFs.MkDirAll(aFilename);
       
   706     if ( err != KErrAlreadyExists )
       
   707         {
       
   708         User::LeaveIfError(err);
       
   709         }
       
   710     iStore = CPermanentFileStore::ReplaceL(aFs, aFilename,
       
   711                                             EFileRead | EFileWrite);
       
   712     iStore->SetTypeL(KPermanentFileStoreLayoutUid);
       
   713     iStore->SetRootL(iDatabase.CreateL(iStore));
       
   714     iStore->CommitL();
       
   715 
       
   716     User::LeaveIfError(iDatabase.Execute(KGlxCreateTableIds));
       
   717     User::LeaveIfError(iDatabase.Execute(KGlxCreateTableItems));
       
   718     User::LeaveIfError(iDatabase.Execute(KGlxCreateTableThumbnails));
       
   719     User::LeaveIfError(iDatabase.Execute(KGlxCreateIndexIds));
       
   720     User::LeaveIfError(iDatabase.Execute(KGlxCreateIndexItems));
       
   721     User::LeaveIfError(iDatabase.Execute(KGlxCreateIndexThumbnails));
       
   722     
       
   723     iNextThumbId = KGlxFirstThumbnailId;
       
   724     }
       
   725 
       
   726 // -----------------------------------------------------------------------------
       
   727 // DoAddItemL
       
   728 // -----------------------------------------------------------------------------
       
   729 //
       
   730 TGlxtnThumbnailId CGlxtnVolumeDatabase::DoAddItemL()
       
   731     {
       
   732     TRACER("TGlxtnThumbnailId CGlxtnVolumeDatabase::DoAddItemL()");
       
   733     __ASSERT_ALWAYS(iInfo, Panic(EGlxPanicNullPointer));
       
   734     RDbTable table;
       
   735     CleanupClosePushL(table);
       
   736     User::LeaveIfError(table.Open(iDatabase, KGlxTableItems, RDbRowSet::EInsertOnly));
       
   737     TGlxtnThumbnailId thumbId( iNextThumbId );
       
   738 
       
   739     table.InsertL();
       
   740     table.SetColL( KGlxColItemUri, iInfo->FilePath() );
       
   741     table.SetColL( KGlxColItemId, thumbId.Value() );
       
   742     table.SetColL( KGlxColItemFileSize, iInfo->iFileSize );
       
   743     table.SetColL( KGlxColItemModTime, iInfo->iFileTime );
       
   744     table.PutL();
       
   745 
       
   746     iNextThumbId++;
       
   747     CleanupStack::PopAndDestroy(&table);
       
   748 
       
   749     return thumbId;
       
   750     }
       
   751 
       
   752 // -----------------------------------------------------------------------------
       
   753 // EvaluateQueryL
       
   754 // -----------------------------------------------------------------------------
       
   755 //
       
   756 void CGlxtnVolumeDatabase::EvaluateQueryL( const TDbQuery &aQuery )
       
   757     {
       
   758     TRACER("void CGlxtnVolumeDatabase::EvaluateQueryL( const TDbQuery &aQuery )");
       
   759     User::LeaveIfError( iView.Prepare(
       
   760                                 iDatabase, aQuery, RDbRowSet::EReadOnly ) );
       
   761     iView.Evaluate( iStatus );
       
   762     SetActive();
       
   763     }
       
   764 
       
   765 // -----------------------------------------------------------------------------
       
   766 // UpdateDataL
       
   767 // -----------------------------------------------------------------------------
       
   768 //
       
   769 void CGlxtnVolumeDatabase::UpdateDataL( const TDesC& aSql )
       
   770     {
       
   771     TRACER("void CGlxtnVolumeDatabase::UpdateDataL( const TDesC& aSql )");
       
   772     TInt result = iDbUpdater.Execute( iDatabase, aSql );
       
   773 
       
   774     if ( result < KErrNone )
       
   775         {
       
   776         iDbUpdater.Close();
       
   777         User::Leave( result );
       
   778         }
       
   779 
       
   780     // According to documentation a result of 0 should indicate complete
       
   781     // but this does not seem to be the case
       
   782     iDbUpdater.Next( iStatus );
       
   783     SetActive();
       
   784     }
       
   785 
       
   786 // -----------------------------------------------------------------------------
       
   787 // QuoteSqlStringLC
       
   788 // -----------------------------------------------------------------------------
       
   789 //
       
   790 HBufC* CGlxtnVolumeDatabase::QuoteSqlStringLC(const TDesC& aText)
       
   791     {
       
   792     TRACER("HBufC* CGlxtnVolumeDatabase::QuoteSqlStringLC(const TDesC& aText)");
       
   793     const TText quote('\'');
       
   794     TInt length = aText.Length() + 2;
       
   795 
       
   796     for ( TInt i = 0; i < aText.Length(); i++ )
       
   797         {
       
   798         if ( quote == aText[i] )
       
   799             {
       
   800             length++;
       
   801             }
       
   802         }
       
   803 
       
   804     HBufC* text = HBufC::NewLC(length);
       
   805     TPtr ptr(text->Des());
       
   806 
       
   807     ptr.Append(quote);
       
   808     for ( TInt i = 0; i < aText.Length(); i++ )
       
   809         {
       
   810         TText chr = aText[i];
       
   811         ptr.Append(chr);
       
   812         if ( quote == chr )
       
   813             {
       
   814             ptr.Append(quote);
       
   815             }
       
   816         }
       
   817     ptr.Append(quote);
       
   818 
       
   819     return text;
       
   820     }