notepad/notepad1/LibSrc/NpdCoreModel.cpp
branchRCL_3
changeset 66 bd7edf625bdd
child 67 1539a383d7b6
equal deleted inserted replaced
65:12af337248b1 66:bd7edf625bdd
       
     1 /*
       
     2 * Copyright (c) 2002 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 core part of Notepad Model.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <txtglobl.h>
       
    21 #include <barsread.h>
       
    22 #include <eikenv.h>
       
    23 #include "NpdModel_platsec.h"
       
    24 #include "NpdLib.hrh"
       
    25 #include "NpdLib.h"
       
    26 #include "NpdUtil.h"
       
    27 #include "NpdLibPanic.h"
       
    28 
       
    29 // next is for KNotepadPseudoKeyIdForNewNote.
       
    30 //
       
    31 #include "NpdApi.h"
       
    32 
       
    33 #include "AknUtils.h"
       
    34 // CONSTANTS
       
    35 _LIT(KNotepadKey, "key");
       
    36 _LIT(KNotepadUpdateTime, "time");
       
    37 _LIT(KNotepadMemo, "memo");
       
    38 _LIT(KNotepadTableName, "Table1");
       
    39 _LIT(KNotepadSqlInsert, "SELECT * FROM Table1");
       
    40 _LIT(KNotepadSqlFormatSeek, "SELECT * FROM Table1 WHERE key=%d");
       
    41 
       
    42 const TUid KSecureUid = {0x101F8878};
       
    43 _LIT(KSecure,	"SECURE");
       
    44 
       
    45 
       
    46 const TInt KNotepadSqlStringMaxLength(128);
       
    47 const TInt KNotepadLanguagePostfixWidth(2); // TLanuguage is 00 -- 99
       
    48 const TInt KNotepadModelMinimumEntrySize(24);
       
    49 const TInt KNotepadModelMinimumDataFileSize(300);
       
    50 const TInt KNotepadDiskSpaceNeededForSingleDeletion(8192);
       
    51 
       
    52 const TInt KNotepadListEntryLength ( 60 );
       
    53 // ============================ MEMBER FUNCTIONS ===============================
       
    54 
       
    55 // -----------------------------------------------------------------------------
       
    56 // CNotepadCoreModel::CNotepadCoreModel
       
    57 // C++ constructor
       
    58 // -----------------------------------------------------------------------------
       
    59 //
       
    60 CNotepadCoreModel::CNotepadCoreModel()
       
    61     : iEnv(CEikonEnv::Static()),
       
    62     iModeOp(ENotepadModelRowNop),
       
    63     iKey(-1),
       
    64     iNpdItemLastChanged(Time::MinTTime())
       
    65     {
       
    66     }
       
    67 
       
    68 // -----------------------------------------------------------------------------
       
    69 // CNotepadCoreModel::ConstructL
       
    70 // second phase constructor.
       
    71 // -----------------------------------------------------------------------------
       
    72 //
       
    73 void CNotepadCoreModel::ConstructL(TInt aResId)
       
    74     {
       
    75     iDataResourceId = aResId; // used by IsTemplates()
       
    76     iDataFile = iEnv->AllocReadResourceL(aResId);
       
    77     if ( IsTemplates() )
       
    78         {
       
    79         const TInt language( User::Language() );
       
    80         __ASSERT_DEBUG( language >= 0 && language <= 999, 
       
    81             User::Leave( KErrUnknown ) );
       
    82         __ASSERT_DEBUG( iDataFile->Length() >= KNotepadLanguagePostfixWidth,
       
    83             User::Leave( KErrUnknown ) );
       
    84         TInt width( KNotepadLanguagePostfixWidth );
       
    85         if ( language > 99 )
       
    86             {
       
    87             iDataFile = iDataFile->ReAllocL( iDataFile->Length() + 1 );
       
    88             width++;
       
    89             }
       
    90         TPtr ptr = iDataFile->Des();
       
    91         ptr.SetLength(iDataFile->Length() - KNotepadLanguagePostfixWidth);
       
    92         ptr.AppendNumFixedWidth( language, EDecimal, width );
       
    93         }
       
    94     User::LeaveIfError(iDbs.Connect());
       
    95     OpenDatabaseL();
       
    96     iDatabase.Compact();
       
    97     if ( iDatabase.IsDamaged() )
       
    98         {
       
    99         iDatabase.Recover();
       
   100         }
       
   101     }
       
   102 
       
   103 // -----------------------------------------------------------------------------
       
   104 // CNotepadCoreModel::~CNotepadCoreModel
       
   105 // Destructor.
       
   106 // -----------------------------------------------------------------------------
       
   107 //
       
   108 CNotepadCoreModel::~CNotepadCoreModel()
       
   109     {
       
   110     iDatabase.Close();
       
   111     iDbs.Close();
       
   112     delete iDataFile;
       
   113     }
       
   114 
       
   115 // -----------------------------------------------------------------------------
       
   116 // CNotepadCoreModel::ContentByKeyL
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 HBufC* CNotepadCoreModel::ContentByKeyL(const TInt aKey)
       
   120     {
       
   121     __ASSERT_DEBUG( aKey >= 0, Panic(ENotepadLibraryPanicInvalidKey) );
       
   122     TBuf<KNotepadSqlStringMaxLength> sql;
       
   123     sql.Format(KNotepadSqlFormatSeek, aKey);
       
   124     RDbView dbView;
       
   125     CleanupClosePushL(dbView);
       
   126     User::LeaveIfError( dbView.Prepare(
       
   127         iDatabase, TDbQuery(sql), RDbView::EReadOnly ) );
       
   128     User::LeaveIfError(dbView.EvaluateAll());
       
   129     HBufC* content = NULL;
       
   130     TInt isAtRow(dbView.FirstL());
       
   131     User::LeaveIfError(isAtRow);
       
   132     if ( isAtRow )
       
   133         {
       
   134         dbView.GetL();
       
   135         RDbColReadStream blob;
       
   136         blob.OpenLC(dbView, ENotepadMemo);
       
   137         TInt colLength( dbView.ColLength(ENotepadMemo) );
       
   138         content = HBufC::NewLC(colLength);
       
   139         TPtr ptr = content->Des();
       
   140 
       
   141         blob.ReadL(ptr, colLength);
       
   142         CleanupStack::Pop(); // content
       
   143         CleanupStack::PopAndDestroy(); // blob
       
   144         }
       
   145     CleanupStack::PopAndDestroy(); // dbView
       
   146     return content;
       
   147     }
       
   148 
       
   149 // -----------------------------------------------------------------------------
       
   150 // CNotepadCoreModel::CountL
       
   151 // -----------------------------------------------------------------------------
       
   152 //
       
   153 TInt CNotepadCoreModel::CountL()
       
   154     {
       
   155     RDbTable table;
       
   156     User::LeaveIfError( table.Open(
       
   157         iDatabase, KNotepadTableName, RDbRowSet::EReadOnly ) );
       
   158     CleanupClosePushL(table);
       
   159     TInt count( table.CountL() );
       
   160     CleanupStack::PopAndDestroy(); // table
       
   161     return count;
       
   162     }
       
   163 
       
   164 // -----------------------------------------------------------------------------
       
   165 // CNotepadCoreModel::InsertL
       
   166 // Never leave once the database has committed.
       
   167 // -----------------------------------------------------------------------------
       
   168 //
       
   169 TInt CNotepadCoreModel::InsertL(const TDesC& aDes, TInt& aKey)
       
   170     {
       
   171     if ( NotepadUtil::IsEmpty(aDes) )
       
   172         {
       
   173         return ENotepadModelRowNop;
       
   174         }
       
   175     aKey = KNotepadPseudoKeyIdForNewNote;
       
   176     return InsertOrUpdateL(aDes, aKey);
       
   177     }
       
   178 
       
   179 // -----------------------------------------------------------------------------
       
   180 // CNotepadCoreModel::UpdateL
       
   181 // Never leave once the database has committed.
       
   182 // -----------------------------------------------------------------------------
       
   183 //
       
   184 TInt CNotepadCoreModel::UpdateL(const TDesC& aDes, TInt& aKey)
       
   185     {
       
   186     __ASSERT_DEBUG( aKey >= 0, Panic(ENotepadLibraryPanicInvalidKey) );
       
   187     TInt resultStatus( NotepadUtil::IsEmpty(aDes) ? DeleteL(aKey) :
       
   188         InsertOrUpdateL(aDes, aKey) );
       
   189     if ( resultStatus == ENotepadModelRowDeleted )
       
   190         {
       
   191         aKey = KNotepadPseudoKeyIdForNewNote;
       
   192         }
       
   193     return resultStatus;
       
   194     }
       
   195 
       
   196 // -----------------------------------------------------------------------------
       
   197 // CNotepadCoreModel::DeleteL
       
   198 // Never leave once the database has committed.
       
   199 // -----------------------------------------------------------------------------
       
   200 //
       
   201 TInt CNotepadCoreModel::DeleteL(TInt aKey)
       
   202     {
       
   203     TInt resultStatus(ENotepadModelRowNop);
       
   204     iModeOp = ENotepadModelRowNop;
       
   205     RFs fileSession;
       
   206    	User::LeaveIfError(fileSession.Connect());
       
   207    	CleanupClosePushL(fileSession);
       
   208     TInt retval = fileSession.ReserveDriveSpace( KDefaultDrive, KNotepadDiskSpaceNeededForSingleDeletion );
       
   209     if ( retval == KErrNone )
       
   210     {
       
   211     	retval = fileSession.GetReserveAccess( KDefaultDrive );
       
   212     }
       
   213     TBuf<KNotepadSqlDeleteHeadSize> sql;
       
   214     sql.Append(KNotepadSqlDeleteHead);
       
   215     sql.AppendNum(aKey);
       
   216 
       
   217     TInt rowCount( iDatabase.Execute(sql) );
       
   218     User::LeaveIfError( rowCount );
       
   219     if ( rowCount > 0 ) 
       
   220         {
       
   221         resultStatus = ENotepadModelRowDeleted;
       
   222     	if ( !IsTemplates() )
       
   223     		{
       
   224         	iModeOp = ENotepadModelRowDeleted;
       
   225     		}
       
   226         TInt err(KErrNone);
       
   227         err = iDatabase.Compact();
       
   228         if ( err != KErrNone )
       
   229             {
       
   230             iEnv->HandleError(err);
       
   231             }
       
   232         }
       
   233     if ( retval == KErrNone )
       
   234     {
       
   235     	retval = fileSession.ReleaseReserveAccess( KDefaultDrive );
       
   236     }
       
   237 	fileSession.Close();
       
   238 	CleanupStack::PopAndDestroy();
       
   239     iKey = aKey;
       
   240     return resultStatus;
       
   241     }
       
   242 
       
   243 // -----------------------------------------------------------------------------
       
   244 // CNotepadCoreModel::Compact
       
   245 // -----------------------------------------------------------------------------
       
   246 //
       
   247 TInt CNotepadCoreModel::Compact()
       
   248     {
       
   249     return iDatabase.Compact();
       
   250     }
       
   251 
       
   252 // -----------------------------------------------------------------------------
       
   253 // CNotepadCoreModel::SetModeOp
       
   254 // -----------------------------------------------------------------------------
       
   255 //
       
   256 void CNotepadCoreModel::SetModeOp(CNotepadCoreModel::TNotepadModelRowResult aModeOp)
       
   257 	{
       
   258 	iModeOp = aModeOp;
       
   259 	}
       
   260 
       
   261 // -----------------------------------------------------------------------------
       
   262 // CNotepadCoreModel::AppendContentAsLabelL
       
   263 // -----------------------------------------------------------------------------
       
   264 //
       
   265 void CNotepadCoreModel::AppendContentAsLabelL(TDes& aDes, const TInt aKey)
       
   266     {
       
   267     __ASSERT_DEBUG( aKey >= 0, Panic(ENotepadLibraryPanicInvalidKey) );
       
   268 
       
   269     TBuf<KNotepadSqlStringMaxLength> sql;
       
   270     sql.Format(KNotepadSqlFormatSeek, aKey);
       
   271     RDbView dbView;
       
   272     CleanupClosePushL(dbView);
       
   273     User::LeaveIfError( dbView.Prepare(
       
   274         iDatabase, TDbQuery(sql), RDbView::EReadOnly ) );
       
   275     User::LeaveIfError(dbView.EvaluateAll());
       
   276     dbView.FirstL();
       
   277     dbView.GetL();
       
   278     AppendContentAsLabelL(aDes, dbView);
       
   279     CleanupStack::PopAndDestroy(); // dbView
       
   280     }
       
   281 
       
   282 // -----------------------------------------------------------------------------
       
   283 // CNotepadCoreModel::AppendContentAsLabelL
       
   284 // -----------------------------------------------------------------------------
       
   285 //
       
   286 void CNotepadCoreModel::AppendContentAsLabelL(TDes& aDes, RDbView& aDbView)
       
   287     {
       
   288     __ASSERT_DEBUG( aDbView.AtRow(), 
       
   289         Panic(ENotepadLibraryPanicInvalidRowInView) );
       
   290 
       
   291     HBufC* hbuf = HBufC::NewLC(aDes.MaxLength());
       
   292     TPtr buf = hbuf->Des();
       
   293     RDbColReadStream blob;
       
   294     blob.OpenLC(aDbView, ENotepadMemo);
       
   295     const TInt colLength( aDbView.ColLength(ENotepadMemo) );
       
   296     TInt unreadLength( colLength );
       
   297     TInt orgLength(aDes.Length());
       
   298     while ( aDes.Length() < aDes.MaxLength() && unreadLength > 0 )
       
   299         {
       
   300         blob.ReadL(buf, 
       
   301             unreadLength < buf.MaxLength() ? unreadLength : buf.MaxLength() );
       
   302         unreadLength -= buf.Length();
       
   303         NotepadUtil::AppendLabel(aDes, buf, (aDes.Length() == orgLength));
       
   304         }
       
   305     CleanupStack::PopAndDestroy(2); // blob, hbuf
       
   306     }
       
   307 
       
   308 // -----------------------------------------------------------------------------
       
   309 // CNotepadCoreModel::ModeOp
       
   310 // -----------------------------------------------------------------------------
       
   311 //
       
   312 CNotepadCoreModel::TNotepadModelRowResult CNotepadCoreModel::ModeOp()
       
   313 	{
       
   314 	return iModeOp;
       
   315 	}
       
   316 
       
   317 // -----------------------------------------------------------------------------
       
   318 // CNotepadCoreModel::DoUpdateNotepadItemArrayAndKeyArrayL
       
   319 // -----------------------------------------------------------------------------
       
   320 //
       
   321 void CNotepadCoreModel::DoUpdateNotepadItemArrayAndKeyArrayL(CDesCArray& aItemArray,
       
   322 															RArray<TInt>& aKeyArray,
       
   323 															HBufC& aTimeFormat)
       
   324 	{
       
   325 	switch(iModeOp)
       
   326 		{
       
   327 		//delete the items from list arrays
       
   328 		case ENotepadModelRowDeleted:
       
   329 			{
       
   330 			TInt index = aKeyArray.Find(iKey);
       
   331 			if(index != KErrNotFound) //if found
       
   332 				{
       
   333 				aItemArray.Delete(index);
       
   334 				aItemArray.Compress();
       
   335 				aKeyArray.Remove(index);
       
   336 				}
       
   337 			iModeOp = ENotepadModelRowNop;
       
   338 			}
       
   339 			break;
       
   340 		//add new item in list arrays			
       
   341 		case ENotepadModelRowAdded:
       
   342 			{
       
   343 			TTime time;
       
   344 			time = iNpdItemLastChanged;
       
   345     		TTimeIntervalMinutes offset;
       
   346     		TTime now;
       
   347     		now.HomeTime();
       
   348     		TTime gmt;
       
   349     		gmt.UniversalTime();
       
   350     		now.MinutesFrom(gmt, offset);
       
   351     		time += offset; // including summertime adjustment
       
   352 	 		HBufC* hbuf = HBufC::NewLC(KNotepadListEntryLength);
       
   353 	    	TPtr lBuf = hbuf->Des();
       
   354 	        lBuf.SetLength(0);
       
   355 	        time.FormatL( lBuf, aTimeFormat);
       
   356 	        AknTextUtils::LanguageSpecificNumberConversion(lBuf);
       
   357 	        lBuf.Append(KColumnListSeparator);
       
   358 	        AppendContentAsLabelL(lBuf, iKey);
       
   359 	        TInt lIndex = GetInsertionIndex(lBuf,aItemArray);
       
   360 	        aItemArray.InsertL(lIndex,lBuf);
       
   361 	        User::LeaveIfError(aKeyArray.Insert(iKey,lIndex));
       
   362 	        CleanupStack::PopAndDestroy(); // hbuf
       
   363 			iModeOp = ENotepadModelRowNop;
       
   364 			}
       
   365 			break;
       
   366 		//update the existing item.
       
   367 		case ENotepadModelRowUpdated:
       
   368 			{
       
   369 			TTime time = iNpdItemLastChanged;
       
   370     		TTimeIntervalMinutes offset;
       
   371     		TTime now;
       
   372     		now.HomeTime();
       
   373     		TTime gmt;
       
   374     		gmt.UniversalTime();
       
   375     		now.MinutesFrom(gmt, offset);
       
   376     		time += offset; // including summertime adjustment
       
   377 	 		HBufC* hbuf = HBufC::NewLC(KNotepadListEntryLength);
       
   378 	    	TPtr lBuf = hbuf->Des();
       
   379 	        lBuf.SetLength(0);
       
   380 	        time.FormatL( lBuf, aTimeFormat);
       
   381 	        lBuf.Append(KColumnListSeparator);
       
   382 	        AppendContentAsLabelL(lBuf, iKey);
       
   383 	        AknTextUtils::LanguageSpecificNumberConversion(lBuf);
       
   384 	        TInt index = aKeyArray.Find(iKey);
       
   385 	        if(index != KErrNotFound) //if found
       
   386 				{
       
   387 				aItemArray.Delete(index);
       
   388 				aItemArray.Compress();
       
   389 				aKeyArray.Remove(index);
       
   390 				}
       
   391 	        TInt lIndex = GetInsertionIndex(lBuf,aItemArray);
       
   392 	        aItemArray.InsertL(lIndex,lBuf);
       
   393 	        User::LeaveIfError(aKeyArray.Insert(iKey,lIndex));
       
   394 	        CleanupStack::PopAndDestroy(); // hbuf
       
   395 			iModeOp = ENotepadModelRowNop;	        
       
   396 			}
       
   397 			break;
       
   398 		default:
       
   399 			iModeOp = ENotepadModelRowNop;
       
   400 			break;
       
   401 		}
       
   402 	}
       
   403 
       
   404 // -----------------------------------------------------------------------------
       
   405 // CNotepadCoreModel::OpenDatabaseL
       
   406 // -----------------------------------------------------------------------------
       
   407 //
       
   408 void CNotepadCoreModel::OpenDatabaseL()
       
   409     {
       
   410     __ASSERT_DEBUG(iDataFile, Panic(ENotepadLibraryPanicNullDataFileName));
       
   411     __ASSERT_DEBUG(iDbs.ResourceCount() == 0, 
       
   412         Panic(ENotepadLibraryPanicDatabaseAlreadyOpened));
       
   413         
       
   414        TBuf<32> format;
       
   415        format.Copy(KSecure);
       
   416        format.Append(KSecureUid.Name());
       
   417 
       
   418     TInt err(iDatabase.Open(iDbs, *iDataFile,format));
       
   419     if ( err == KErrNone && IsInvalidTableL() )
       
   420         {
       
   421         err = KErrCorrupt;
       
   422         }
       
   423     switch ( err )
       
   424         {
       
   425         case KErrArgument: // when the datafile is empty
       
   426         case KErrNotSupported: // UID mismatch, corrupted
       
   427         case KErrEof: // read error, corrupted
       
   428         case KErrCorrupt:
       
   429             // delete corrupted file
       
   430             NotepadUtil::ShowCorruptedNoteL(*iEnv);
       
   431             DeleteFileL();
       
   432             // go through into next case
       
   433         case KErrNotFound:
       
   434             // try to create a new data file
       
   435             iDatabase.Close();
       
   436             CreateDataFileL();
       
   437             User::LeaveIfError(iDatabase.Open(iDbs, *iDataFile,format));
       
   438             // go through into next case
       
   439         case KErrNone: // database open succeed
       
   440             break;
       
   441         default:
       
   442             User::Leave(err);
       
   443             break;
       
   444         }
       
   445     }
       
   446 
       
   447 // -----------------------------------------------------------------------------
       
   448 // CNotepadCoreModel::CreateDataFileL
       
   449 // -----------------------------------------------------------------------------
       
   450 //
       
   451 void CNotepadCoreModel::CreateDataFileL()
       
   452     {
       
   453     NotepadUtil::LeaveIfCriticalLevelL(*iEnv, 
       
   454         KNotepadModelMinimumDataFileSize );
       
   455     iDatabase.Close(); // for safty
       
   456     //User::LeaveIfError(iDatabase.Create(iEnv->FsSession(), *iDataFile));
       
   457     TBuf<32> format;
       
   458        format.Copy(KSecure);
       
   459        format.Append(KSecureUid.Name());
       
   460 	TInt rr(0);
       
   461     TRAP(rr,iDatabase.Create(iDbs,*iDataFile,format); )
       
   462 
       
   463     TRAP(rr, InitDataFileL(); );
       
   464     if ( rr != KErrNone )
       
   465         {
       
   466         DeleteFileL(); // including iDatabase.Close()
       
   467         User::Leave(rr);
       
   468         }
       
   469     iDatabase.Close();
       
   470     }
       
   471 
       
   472 // -----------------------------------------------------------------------------
       
   473 // CNotepadCoreModel::InitDataFileL
       
   474 //
       
   475 // [Q] CreateIndex is needed?
       
   476 // [A] No.
       
   477 // We made a comparison experiment whether the data file with the index 
       
   478 // has better performance than without it.
       
   479 // 
       
   480 // Pre-condition: The "C:\System\Data\Notepad.dat" does not exist and 
       
   481 //     the folder "C:\System\favorites" should be empty.
       
   482 // 
       
   483 //                             Without Index         With Index   
       
   484 // 1. Create 300 memos             200 sec             218 sec
       
   485 //   (using NpdTest.app)
       
   486 // 2. Notepad.dat size             9546 b              9546 b
       
   487 //    after 1.
       
   488 // 3. Boot up time of Notepad      2.2 sec             2.4 sec
       
   489 //    with the 300 memos.
       
   490 // 4. Delete the 300 memos.         18 sec              18 sec
       
   491 //
       
   492 // So our conclusion is that the data file without the index is better.
       
   493 // -----------------------------------------------------------------------------
       
   494 //
       
   495 void CNotepadCoreModel::InitDataFileL()
       
   496     {
       
   497     // create table
       
   498     CDbColSet* columns = CreateDbColSetLC();
       
   499     User::LeaveIfError(iDatabase.CreateTable(KNotepadTableName, *columns));
       
   500     CleanupStack::PopAndDestroy(); // columns
       
   501     if ( IsTemplates() )
       
   502         {
       
   503         SetDefaultTemplatesL();
       
   504         }
       
   505     }
       
   506 
       
   507 // -----------------------------------------------------------------------------
       
   508 // CNotepadCoreModel::SetDefaultTemplatesL
       
   509 // -----------------------------------------------------------------------------
       
   510 //
       
   511 void CNotepadCoreModel::SetDefaultTemplatesL()
       
   512     {
       
   513     CDesCArray* data = iEnv->ReadDesCArrayResourceL(
       
   514         R_NOTEPAD_DEFAULT_TEMPLATES );
       
   515     CleanupStack::PushL(data);
       
   516     const TInt count(data->Count());
       
   517 
       
   518     TInt estimatedSize(0);
       
   519     for (TInt i(0); i < count; i++)
       
   520         {
       
   521         estimatedSize += KNotepadModelMinimumEntrySize + (*data)[i].Size();
       
   522         }
       
   523     NotepadUtil::LeaveIfCriticalLevelL(*iEnv, estimatedSize);
       
   524 
       
   525     TTime gmt;
       
   526     gmt.UniversalTime();
       
   527     gmt.RoundUpToNextMinute();
       
   528     gmt -= TTimeIntervalMinutes(1);
       
   529 
       
   530     RDbView dbView;
       
   531     CleanupClosePushL(dbView);
       
   532     User::LeaveIfError( dbView.Prepare(
       
   533         iDatabase, TDbQuery(KNotepadSqlInsert), RDbView::EInsertOnly ) );
       
   534 
       
   535     User::LeaveIfError(iDatabase.Begin());
       
   536     TRAPD(r,
       
   537         for ( TInt i(0); i < count; i++ )
       
   538             {
       
   539             TPtrC entry((*data)[i]);
       
   540             if ( !NotepadUtil::IsEmpty(entry) )
       
   541                 {
       
   542                 dbView.InsertL();
       
   543                 dbView.SetColL(ENotepadUpdateTime, gmt);
       
   544                 dbView.SetColL(ENotepadMemo, entry);
       
   545                 dbView.PutL();
       
   546                 }
       
   547             }
       
   548         User::LeaveIfError(iDatabase.Commit());
       
   549         );
       
   550     if (r != KErrNone)
       
   551         {
       
   552         Rollback();
       
   553         User::Leave(r);
       
   554         } 
       
   555     CleanupStack::PopAndDestroy(2); // dbView, data
       
   556     User::LeaveIfError(iDatabase.Compact()); 
       
   557     }
       
   558 
       
   559 // -----------------------------------------------------------------------------
       
   560 // CNotepadCoreModel::CreateDbColSetLC
       
   561 // -----------------------------------------------------------------------------
       
   562 //
       
   563 CDbColSet* CNotepadCoreModel::CreateDbColSetLC() const
       
   564     {
       
   565     CDbColSet* columns = CDbColSet::NewLC(); 
       
   566     TDbCol col(KNotepadKey, EDbColInt32);
       
   567     col.iAttributes = TDbCol::ENotNull | TDbCol::EAutoIncrement;
       
   568     columns->AddL(col);
       
   569 
       
   570     col.iName = KNotepadUpdateTime;
       
   571     col.iType = EDbColDateTime;
       
   572     col.iAttributes = TDbCol::ENotNull;
       
   573     columns->AddL(col);
       
   574 
       
   575     col.iName = KNotepadMemo;
       
   576     col.iType = EDbColLongText;
       
   577     col.iAttributes = TDbCol::ENotNull;
       
   578     columns->AddL(col);
       
   579 
       
   580     return columns; // columns keeps on CleanupStack
       
   581     }
       
   582 
       
   583 // -----------------------------------------------------------------------------
       
   584 // CNotepadCoreModel::Rollback
       
   585 // -----------------------------------------------------------------------------
       
   586 //
       
   587 void CNotepadCoreModel::Rollback()
       
   588     {
       
   589     iDatabase.Rollback();
       
   590     if ( iDatabase.IsDamaged() )
       
   591         {
       
   592         iDatabase.Recover();
       
   593         }
       
   594     }
       
   595 
       
   596 // -----------------------------------------------------------------------------
       
   597 // CNotepadCoreModel::InsertOrUpdateL
       
   598 // Never leave once the database has committed.
       
   599 // Including: FFS-full check.
       
   600 // Not including: empty check.
       
   601 // -----------------------------------------------------------------------------
       
   602 //
       
   603 TInt CNotepadCoreModel::InsertOrUpdateL(const TDesC& aDes, TInt& aKey)
       
   604     {
       
   605     NotepadUtil::LeaveIfCriticalLevelL(*iEnv, 
       
   606         KNotepadModelMinimumEntrySize + aDes.Size());
       
   607 
       
   608     RDbView dbView;
       
   609     CleanupClosePushL(dbView);
       
   610     TBool doInsert( aKey == KNotepadPseudoKeyIdForNewNote );
       
   611     if ( !doInsert )
       
   612         {
       
   613         TBuf<KNotepadSqlStringMaxLength> sql;
       
   614         sql.Format(KNotepadSqlFormatSeek, aKey);
       
   615         User::LeaveIfError( dbView.Prepare(
       
   616             iDatabase, TDbQuery(sql) ) );
       
   617         User::LeaveIfError(dbView.EvaluateAll());
       
   618         TInt isAtRow(dbView.FirstL());
       
   619         User::LeaveIfError(isAtRow);
       
   620         if ( !isAtRow )
       
   621             {
       
   622             doInsert = ETrue;
       
   623             }
       
   624         }
       
   625     if ( doInsert )
       
   626         {
       
   627         User::LeaveIfError( dbView.Prepare(
       
   628             iDatabase, TDbQuery(KNotepadSqlInsert) ) );
       
   629         }
       
   630 
       
   631     TTime gmt;
       
   632     gmt.UniversalTime();
       
   633     gmt.RoundUpToNextMinute();
       
   634     gmt -= TTimeIntervalMinutes(1);
       
   635 
       
   636     User::LeaveIfError(iDatabase.Begin());
       
   637     TRAPD(r,
       
   638         if ( doInsert )
       
   639             {
       
   640             dbView.InsertL();
       
   641             }
       
   642         else
       
   643             {
       
   644             dbView.UpdateL();
       
   645             }
       
   646         dbView.SetColL(ENotepadUpdateTime, gmt);
       
   647         dbView.SetColL(ENotepadMemo, aDes);
       
   648         dbView.PutL();
       
   649         dbView.GetL();
       
   650         User::LeaveIfError(iDatabase.Commit());
       
   651         );
       
   652     if (r != KErrNone)
       
   653         {
       
   654         dbView.Close();
       
   655         Rollback();
       
   656         User::Leave(r);
       
   657         } 
       
   658     // Database has committed
       
   659 
       
   660     aKey = dbView.ColInt32(ENotepadKey);
       
   661 
       
   662     CleanupStack::PopAndDestroy(); // dbView
       
   663 
       
   664     TInt err(iDatabase.Compact());
       
   665     if ( err != KErrNone )
       
   666         {
       
   667         iEnv->HandleError(err);
       
   668         }
       
   669 	iNpdItemLastChanged = gmt;
       
   670 	iKey = aKey;
       
   671     if ( !IsTemplates() )
       
   672     	{
       
   673 		iModeOp = (doInsert?ENotepadModelRowAdded : ENotepadModelRowUpdated);
       
   674     	}
       
   675     return ( doInsert ? ENotepadModelRowAdded : ENotepadModelRowUpdated );
       
   676     }
       
   677 
       
   678 // -----------------------------------------------------------------------------
       
   679 // CNotepadCoreModel::DeleteFileL
       
   680 // -----------------------------------------------------------------------------
       
   681 //
       
   682 void CNotepadCoreModel::DeleteFileL()
       
   683     {
       
   684     __ASSERT_DEBUG( iDataFile, Panic(ENotepadLibraryPanicNullDataFileName) );
       
   685     iDatabase.Close(); // indespensable for RFs::Delete()
       
   686     User::LeaveIfError( iEnv->FsSession().Delete( *iDataFile ) );
       
   687     }
       
   688 
       
   689 // -----------------------------------------------------------------------------
       
   690 // CNotepadCoreModel::IsInvalidTableL()
       
   691 // -----------------------------------------------------------------------------
       
   692 //
       
   693 TBool CNotepadCoreModel::IsInvalidTableL()
       
   694     {
       
   695     TBool isInvalid(EFalse);
       
   696     RDbTable table;
       
   697     TInt err(table.Open(iDatabase, KNotepadTableName, RDbRowSet::EReadOnly));
       
   698  
       
   699 	if ( err == KErrNotFound )
       
   700         {
       
   701         isInvalid = ETrue;
       
   702         }
       
   703     else if ( err == KErrNone )
       
   704         {
       
   705         if ( table.ColCount() > ENotepadColCountPlusOne - 1 )
       
   706             {
       
   707             table.Close();
       
   708             CDbColSet* cols = CreateDbColSetLC();
       
   709             TInt error(iDatabase.AlterTable(KNotepadTableName, *cols));
       
   710             CleanupStack::PopAndDestroy(); // cols
       
   711             if ( error == KErrArgument ) // for fail safe
       
   712                 {
       
   713                 isInvalid = ETrue;
       
   714                 error = KErrNone;
       
   715                 }
       
   716             User::LeaveIfError(error);
       
   717             }
       
   718         else if ( table.ColCount() < ENotepadColCountPlusOne - 1 )
       
   719             {
       
   720             isInvalid = ETrue;
       
   721             }
       
   722         else if ( table.ColType(ENotepadKey) != EDbColInt32 ||
       
   723             table.ColType(ENotepadUpdateTime) != EDbColDateTime ||
       
   724             table.ColType(ENotepadMemo) != EDbColLongText )
       
   725             {
       
   726             isInvalid = ETrue;
       
   727             }
       
   728         table.Close();
       
   729         }
       
   730     return isInvalid;
       
   731     }
       
   732 
       
   733 // -----------------------------------------------------------------------------
       
   734 // CNotepadCoreModel::GetInsertionIndex
       
   735 // -----------------------------------------------------------------------------
       
   736 //
       
   737 TInt CNotepadCoreModel::GetInsertionIndex(const TDesC& aDes,
       
   738 										CDesCArray& aItemArray)
       
   739 	{
       
   740 	_LIT(KCmpColumnListSeparator,"*\t*");
       
   741 	TBuf<255> timeBuf;
       
   742 	TBuf<255> contentBuf;
       
   743 	TBuf<255> actualTimeBuf;
       
   744 	timeBuf.Copy(aDes.Left( aDes.Match(KCmpColumnListSeparator) ));
       
   745 	TBuf<255> cmpBuf;
       
   746     cmpBuf.Copy(_L("*"));
       
   747     cmpBuf.Append(timeBuf);
       
   748     cmpBuf.Append(_L("*"));
       
   749     TBuf<255> actualBuf;
       
   750     TInt insertIndex=0;
       
   751     TInt offset = KErrNotFound;
       
   752     TInt cmpOffsetListItem = KErrNotFound;
       
   753     if ( IsTemplates() )
       
   754     	{
       
   755         insertIndex = 0;
       
   756     	}
       
   757     else
       
   758     	{
       
   759         insertIndex = 1;
       
   760     	}
       
   761     for(;insertIndex<aItemArray.MdcaCount();insertIndex++)
       
   762     	{
       
   763     	actualBuf.Copy(aItemArray.MdcaPoint(insertIndex));
       
   764 		actualTimeBuf.Copy(actualBuf.Left( actualBuf.Match(KCmpColumnListSeparator) ));
       
   765     	offset = actualBuf.Match(cmpBuf);
       
   766     	if(offset!=KErrNotFound)
       
   767     		{
       
   768     		cmpOffsetListItem = actualBuf.Match(KCmpColumnListSeparator);
       
   769     		if(cmpOffsetListItem!=KErrNotFound)
       
   770     			{
       
   771     			actualBuf.Copy(actualBuf.Right(actualBuf.Length()-cmpOffsetListItem-1));	
       
   772     			contentBuf.Copy(aDes.Right( aDes.Length()-aDes.Match(KCmpColumnListSeparator)-1 ));
       
   773     			if(actualBuf.Compare(contentBuf)>0)
       
   774     				{
       
   775     				break;
       
   776     				}
       
   777     			}
       
   778     		}
       
   779     	else
       
   780     		{
       
   781     		TTime time1;
       
   782     		time1.Parse(timeBuf);
       
   783     		TTime time2;
       
   784     		time2.Parse(actualTimeBuf);
       
   785     		TDateTime dateTime2 = time2.DateTime();
       
   786     		if ( !dateTime2.Year() )
       
   787     			{
       
   788     			if ( time1 > time2 )
       
   789     				break;
       
   790     			}
       
   791     		else
       
   792     			{
       
   793     			TTime now;
       
   794     			now.HomeTime();
       
   795     			if ( now > time2 )
       
   796     				break;
       
   797     			}
       
   798     		}
       
   799     	}
       
   800     return insertIndex;
       
   801 	}
       
   802 // End of File