notepad/notepad1/LibSrc/NpdModel.cpp
changeset 0 f979ecb2b13e
child 20 21239b3bcd78
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     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 Notepad engine.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <e32std.h>
       
    21 #include <gulutil.h>
       
    22 #include <sysutil.h>
       
    23 #include <eikenv.h>
       
    24 #include <barsread.h>
       
    25 #include "NpdLib.hrh"
       
    26 #include "NpdModel_platsec.h"
       
    27 #include "NpdApi.h"
       
    28 #include "NpdLibPanic.h"
       
    29 #include "AknUtils.h"
       
    30 
       
    31 // CONSTANTS
       
    32 _LIT(KNotepadMceFirstColumnData, "1");
       
    33 _LIT(KNotepadSqlSelect, 
       
    34     "SELECT * FROM Table1 ORDER BY time DESC");
       
    35 _LIT(KNotepadSqlMceSelect, 
       
    36     "SELECT * FROM Table1 ORDER BY memo ASC,key DESC");
       
    37 _LIT(KNotepadSqlDeleteByKeysAppend, " OR key="); // 8 chars
       
    38 const TInt KNotepadSqlDeleteByKeysAppendSize(18); // %d costs 10 chars in max
       
    39 const TInt KNotepadItemArrayGranularity(10);
       
    40 const TInt KNotepadMaxRunIntervalInMicroSeconds(500000); // 0.5 sec
       
    41 const TInt KNotepadBuildItemArrayProgressCount(10);
       
    42 const TInt KNotepadMaxDeleteCountInStep(300);
       
    43 const TInt KNotepadDiskSpaceNeededForMultipleDeletion(8192);
       
    44 const TInt KNotepadMaxCharactersForSort(100);
       
    45 
       
    46 // assert KNotepadListEntryLength >= KNotepadMaxCharactersForSort + length of
       
    47 //     1st column
       
    48 const TInt KNotepadListEntryLength( 60 ); 
       
    49 
       
    50 // ============================ MEMBER FUNCTIONS ===============================
       
    51 
       
    52 // -----------------------------------------------------------------------------
       
    53 // CNotepadModel::NewL
       
    54 // Constructor.
       
    55 // -----------------------------------------------------------------------------
       
    56 //
       
    57 EXPORT_C CNotepadModel* CNotepadModel::NewL(RFs& /*aFs*/, TInt aResId)
       
    58     {
       
    59     CNotepadModel* self = new(ELeave) CNotepadModel();
       
    60     CleanupStack::PushL(self);
       
    61     self->ConstructL(aResId);
       
    62     CleanupStack::Pop(); //self
       
    63     return self;
       
    64     }
       
    65 
       
    66 // -----------------------------------------------------------------------------
       
    67 // CNotepadModel::~CNotepadModel
       
    68 // Destructor.
       
    69 // -----------------------------------------------------------------------------
       
    70 //
       
    71 EXPORT_C CNotepadModel::~CNotepadModel()
       
    72     {
       
    73     delete iDatabaseChangeNotifier;
       
    74     delete iExecuter;
       
    75     iSavedDeleteKeys.Close();
       
    76     iDbUpdate.Close();
       
    77     iDbView.Close();
       
    78     iKeyArray.Close(); //delete iKeyArray;
       
    79     delete iItemArray;
       
    80     delete iTimeFormat;
       
    81     delete iDateFormat;
       
    82     }
       
    83 
       
    84 // -----------------------------------------------------------------------------
       
    85 // CNotepadModel::AddContentL
       
    86 // API. CNotepadApi call this.
       
    87 // -----------------------------------------------------------------------------
       
    88 //
       
    89 EXPORT_C void CNotepadModel::AddContentL(const TDesC& aText)
       
    90     {
       
    91     TInt key(KNotepadPseudoKeyIdForNewNote);
       
    92     InsertL(aText, key);
       
    93     }
       
    94 
       
    95 // -----------------------------------------------------------------------------
       
    96 // CNotepadModel::OpenL
       
    97 // deprecated. (only for BC).
       
    98 // -----------------------------------------------------------------------------
       
    99 //
       
   100 EXPORT_C void CNotepadModel::OpenL()
       
   101     {
       
   102     }
       
   103 
       
   104 // -----------------------------------------------------------------------------
       
   105 // CNotepadModel::Close
       
   106 // deprecated. (only for BC).
       
   107 // -----------------------------------------------------------------------------
       
   108 //
       
   109 EXPORT_C void CNotepadModel::Close() 
       
   110     {
       
   111     }
       
   112 
       
   113 // -----------------------------------------------------------------------------
       
   114 // CNotepadModel::IsOpen
       
   115 // deprecated. (only for BC).
       
   116 // -----------------------------------------------------------------------------
       
   117 //
       
   118 EXPORT_C TBool CNotepadModel::IsOpen() 
       
   119     {
       
   120     return ETrue;
       
   121     } 
       
   122 
       
   123 // -----------------------------------------------------------------------------
       
   124 // CNotepadModel::SeekKey
       
   125 // -----------------------------------------------------------------------------
       
   126 //
       
   127 EXPORT_C TInt CNotepadModel::SeekKey(const TInt aKey)
       
   128     {
       
   129     return iKeyArray.Find(aKey) >= 0 ? // found?
       
   130         0 : 1;
       
   131     }
       
   132 
       
   133 // -----------------------------------------------------------------------------
       
   134 // CNotepadModel::ContentL
       
   135 // -----------------------------------------------------------------------------
       
   136 //
       
   137 HBufC* CNotepadModel::ContentL(TInt aItemIndex)
       
   138     {
       
   139     return ContentByKeyL(iKeyArray[aItemIndex]);
       
   140     }
       
   141 
       
   142 // -----------------------------------------------------------------------------
       
   143 // CNotepadModel::IndexOf
       
   144 // -----------------------------------------------------------------------------
       
   145 //
       
   146 TInt CNotepadModel::IndexOf(const TInt aKey) const
       
   147     {
       
   148     TInt returnIndex(KNotepadModelInvalidIndex);
       
   149     if ( aKey != KNotepadPseudoKeyIdForNewNote )
       
   150         {
       
   151         TInt index(iKeyArray.Find(aKey));
       
   152         if ( index >= 0 )
       
   153             {
       
   154             returnIndex = index;
       
   155             }
       
   156         }
       
   157     return returnIndex;
       
   158     }
       
   159 
       
   160 // -----------------------------------------------------------------------------
       
   161 // CNotepadModel::HandleDateChangedL
       
   162 // -----------------------------------------------------------------------------
       
   163 //
       
   164 void CNotepadModel::HandleDateChangedL(TBool aSyncNow)
       
   165     {
       
   166     iFlag |= ENotepadRequireDbViewUpdate | ENotepadRequireItemArrayUpdate;
       
   167     if ( aSyncNow )
       
   168         {
       
   169         SyncL(EFalse);
       
   170         }
       
   171     }
       
   172 
       
   173 // -----------------------------------------------------------------------------
       
   174 // CNotepadModel::DeleteByKeysL
       
   175 // -----------------------------------------------------------------------------
       
   176 //
       
   177 void CNotepadModel::DeleteByKeysL(const RArray<TInt>& aKeys)
       
   178     {
       
   179     __ASSERT_DEBUG( aKeys.Count() > 0, 
       
   180         Panic(ENotepadLibraryPanicInvalidArgument) );
       
   181     TRAPD( err, PrepareToDeleteByKeysL(aKeys); ); // execute RDbUpdate
       
   182     if ( err != KErrNone )
       
   183         {
       
   184         AbortDeletionL();
       
   185         User::Leave(err);
       
   186         }
       
   187     iFlag |= ENotepadIsDeleting;
       
   188     iFlag &= ~ENotepadIsRemovingLinks;
       
   189     iExecuter->Start(TCallBack(DeleteCallBack, this));
       
   190     }
       
   191 
       
   192 // -----------------------------------------------------------------------------
       
   193 // CNotepadModel::CancelDeletion
       
   194 // -----------------------------------------------------------------------------
       
   195 //
       
   196 void CNotepadModel::CancelDeletion()
       
   197     {
       
   198     iDbUpdate.Close();
       
   199     delete iExecuter;
       
   200     iExecuter = NULL;
       
   201     iFlag &= ~ENotepadIsDeleting;
       
   202     iFlag &= ~ENotepadIsRemovingLinks;
       
   203     iFlag |= ENotepadRequireDbViewUpdate;
       
   204     if ( iDatabase.IsDamaged() )
       
   205         {
       
   206         iDatabase.Recover();
       
   207         }
       
   208     iSavedDeleteKeys.Reset();
       
   209 	}
       
   210 
       
   211 // -----------------------------------------------------------------------------
       
   212 // CNotepadModel::SyncL
       
   213 // Sync non-updated data.
       
   214 // -----------------------------------------------------------------------------
       
   215 //
       
   216 void CNotepadModel::SyncL( const TBool aForceSync )
       
   217     {
       
   218     // If iExecuter is creating iDbView, cancel the process and restart 
       
   219     // to create iDbView. If iExecuter is deleting items, this method does nothing.
       
   220     // (ie. Creating iDbView is postponed until the deleting process 
       
   221     // will be finished.
       
   222 	if ( !aForceSync && (iFlag & ENotepadItemArrayUpdateOnly) )
       
   223 	    {
       
   224 	    iFlag |= ENotepadItemArrayUpdateOnly;
       
   225     	if ( iModelObserver )
       
   226         	{
       
   227         	iModelObserver->HandleNotepadModelEventL(
       
   228           			MNotepadModelObserver::EStartItemArrayChange );
       
   229         	}
       
   230 	    TInt err(KErrNone);
       
   231 		TRAP(err,DoUpdateNotepadItemArrayAndKeyArrayL(*iItemArray,
       
   232 													  iKeyArray,
       
   233 													  *iTimeFormat));
       
   234 		if ( err != KErrNone)
       
   235 			{
       
   236 			iItemArray->Reset();
       
   237 			iKeyArray.Reset();
       
   238 			if ( iModelObserver )
       
   239 				{
       
   240 			    iModelObserver->HandleNotepadModelEventL(
       
   241 			        MNotepadModelObserver::EAbortItemArrayChange ); // not leave
       
   242 			    }
       
   243 			User::Leave(err);
       
   244 		    }
       
   245 		iFlag &= ~ENotepadItemArrayUpdateOnly; // now iItemArray is up to date
       
   246 		if ( iModelObserver )
       
   247 			{
       
   248 			iModelObserver->HandleNotepadModelEventL(
       
   249 			        MNotepadModelObserver::ECompleteItemArrayChange );
       
   250 		    }
       
   251 	    }
       
   252     else if(aForceSync || ( iFlag & ENotepadRequireDbViewUpdate ))
       
   253         {
       
   254         iFlag |= (ENotepadRequireDbViewUpdate | ENotepadRequireItemArrayUpdate);
       
   255         iDbView.Close();
       
   256         TDbTextComparison textComparison(EDbCompareCollated);
       
   257         User::LeaveIfError( iDbView.Prepare( iDatabase, 
       
   258             ( IsTemplates() ? TDbQuery(KNotepadSqlMceSelect, textComparison)
       
   259                 : TDbQuery(KNotepadSqlSelect, textComparison) ), 
       
   260         RDbView::EReadOnly ) );
       
   261         User::LeaveIfError( iDbView.EvaluateAll() );
       
   262         iFlag &= ~ENotepadRequireDbViewUpdate; // iDbView is now up to date
       
   263         BuildItemArrayL(ETrue); // force update
       
   264         }
       
   265     else 
       
   266         {
       
   267         BuildItemArrayL(aForceSync);
       
   268         }
       
   269     return;
       
   270     }
       
   271 
       
   272 // -----------------------------------------------------------------------------
       
   273 // CNotepadModel::HandleDatabaseChangedL
       
   274 // -----------------------------------------------------------------------------
       
   275 //
       
   276 void CNotepadModel::HandleDatabaseChangedL(TInt aStatus)
       
   277     {
       
   278     if ( ( ModeOp() == CNotepadCoreModel::ENotepadModelRowDeleted ) ||
       
   279     	 ( ModeOp() == CNotepadCoreModel::ENotepadModelRowAdded ) ||
       
   280     	 ( ModeOp() == CNotepadCoreModel::ENotepadModelRowUpdated ) )
       
   281     	{
       
   282  	  	iFlag |=ENotepadItemArrayUpdateOnly;
       
   283     	}
       
   284     else
       
   285     	{
       
   286     	iFlag |= ENotepadRequireDbViewUpdate; // delayed sync	
       
   287     	}
       
   288     if ( iModelObserver 
       
   289         && !(IsDeleting() && !(iFlag & ENotepadIsRemovingLinks)) )
       
   290         {
       
   291         iModelObserver->HandleNotepadModelEventL(
       
   292             MNotepadModelObserver::EDatabaseChanged, aStatus );
       
   293         }
       
   294     }
       
   295 
       
   296 // -----------------------------------------------------------------------------
       
   297 // CNotepadModel::SetNotepadModelObserver
       
   298 // -----------------------------------------------------------------------------
       
   299 //
       
   300 void CNotepadModel::SetNotepadModelObserver(
       
   301     MNotepadModelObserver* aObserver )
       
   302     {
       
   303     iModelObserver = aObserver;
       
   304     }
       
   305 
       
   306 // -----------------------------------------------------------------------------
       
   307 // CNotepadModel::MdcaCount
       
   308 // from MDesCArray
       
   309 // -----------------------------------------------------------------------------
       
   310 //
       
   311 EXPORT_C TInt CNotepadModel::MdcaCount() const
       
   312     {
       
   313     return iItemArray->Count();
       
   314     }
       
   315 
       
   316 // -----------------------------------------------------------------------------
       
   317 // CNotepadModel::MdcaPoint
       
   318 // from MDesCArray
       
   319 // -----------------------------------------------------------------------------
       
   320 //
       
   321 EXPORT_C TPtrC CNotepadModel::MdcaPoint(TInt aIndex) const
       
   322     {
       
   323     return (*iItemArray)[aIndex];
       
   324     }
       
   325 
       
   326 // -----------------------------------------------------------------------------
       
   327 // CNotepadModel::CNotepadModel
       
   328 // C++ constructor
       
   329 // -----------------------------------------------------------------------------
       
   330 //
       
   331 CNotepadModel::CNotepadModel()
       
   332     : CNotepadCoreModel(),
       
   333     iListingStyle(ENotepadListingStyleNone)
       
   334     {
       
   335     }
       
   336 
       
   337 // -----------------------------------------------------------------------------
       
   338 // CNotepadModel::ConstructL
       
   339 // second phase constructor.
       
   340 // -----------------------------------------------------------------------------
       
   341 //
       
   342 void CNotepadModel::ConstructL(TInt aResId)
       
   343     {
       
   344     TResourceReader rr;
       
   345     iEnv->CreateResourceReaderLC(rr, aResId); // Push rr
       
   346     CNotepadCoreModel::ConstructL(rr.ReadInt32()); // LLINK data_file
       
   347     iListingStyle 
       
   348         = rr.ReadInt16(); // WORD  listing_style;
       
   349     TInt dateResId(rr.ReadInt32());               // LLINK date_format
       
   350     TInt timeResId(rr.ReadInt32());               // LLINK time_format
       
   351     CleanupStack::PopAndDestroy(); // rr
       
   352     if (dateResId)
       
   353         {
       
   354         iDateFormat = iEnv->AllocReadResourceL(dateResId);
       
   355         }
       
   356     if (timeResId)
       
   357         {
       
   358         iTimeFormat = iEnv->AllocReadResourceL(timeResId);
       
   359         }
       
   360     iItemArray = new(ELeave) CDesCArrayFlat(KNotepadItemArrayGranularity);
       
   361     iDatabaseChangeNotifier = 
       
   362         CNotepadModel::CDatabaseChangeNotifier::NewL(iDatabase, *this);
       
   363 
       
   364     SyncL(ETrue);
       
   365     }
       
   366 
       
   367 // -----------------------------------------------------------------------------
       
   368 // CNotepadModel::PrepareToDeleteByKeysL
       
   369 // -----------------------------------------------------------------------------
       
   370 //
       
   371 void CNotepadModel::PrepareToDeleteByKeysL(const RArray<TInt>& aKeys)
       
   372     {
       
   373     CancelDeletion();
       
   374     User::LeaveIfError(iFileSession.Connect());
       
   375    	CleanupClosePushL(iFileSession);
       
   376     iRetval = iFileSession.ReserveDriveSpace( KDefaultDrive, KNotepadDiskSpaceNeededForMultipleDeletion );
       
   377     if ( iRetval == KErrNone )
       
   378     {
       
   379     	iRetval = iFileSession.GetReserveAccess( KDefaultDrive );
       
   380     }
       
   381     // the priority of iExecuter must be lower than that of CAknProgressDialog
       
   382     iExecuter = CIdle::NewL(CActive::EPriorityLow); 
       
   383     const TInt count( aKeys.Count() );
       
   384     for (TInt i(0); i < count; i++)
       
   385         {
       
   386         User::LeaveIfError(iSavedDeleteKeys.Append(aKeys[i]));
       
   387         }
       
   388     ExecuteDeleteStepL();
       
   389     iRetval = iFileSession.ReleaseReserveAccess( KDefaultDrive );
       
   390     iFileSession.Close();
       
   391 	CleanupStack::PopAndDestroy();
       
   392     }
       
   393 
       
   394 // -----------------------------------------------------------------------------
       
   395 // CNotepadModel::ExecuteDeleteStepL
       
   396 // -----------------------------------------------------------------------------
       
   397 //
       
   398 void CNotepadModel::ExecuteDeleteStepL()
       
   399     {
       
   400     iProgressCount = 0;
       
   401     iStepCount = iSavedDeleteKeys.Count();
       
   402     if ( iStepCount > KNotepadMaxDeleteCountInStep )
       
   403         {
       
   404         iStepCount = KNotepadMaxDeleteCountInStep;
       
   405         }
       
   406     HBufC* hbuf = HBufC::NewLC( KNotepadSqlDeleteHeadSize + 
       
   407         ( iStepCount - 1 )* KNotepadSqlDeleteByKeysAppendSize);
       
   408     TPtr sql = hbuf->Des();
       
   409     sql.Append(KNotepadSqlDeleteHead);
       
   410     sql.AppendNum(iSavedDeleteKeys[0]);
       
   411     if ( IsTemplates() )
       
   412         {
       
   413         iSavedDeleteKeys.Remove(0);
       
   414         for (TInt i(0); i < iStepCount - 1; i++)
       
   415             {
       
   416             sql.Append(KNotepadSqlDeleteByKeysAppend);
       
   417             sql.AppendNum(iSavedDeleteKeys[0]);
       
   418             iSavedDeleteKeys.Remove(0);
       
   419             }
       
   420         }
       
   421     else // If Notepad, Remove is postponed until remove link phase
       
   422         {
       
   423         for (TInt i(1); i < iStepCount; i++)
       
   424             {
       
   425             sql.Append(KNotepadSqlDeleteByKeysAppend);
       
   426             sql.AppendNum(iSavedDeleteKeys[i]);
       
   427             }
       
   428         }
       
   429     User::LeaveIfError(iDbUpdate.Execute(iDatabase, sql));
       
   430     CleanupStack::PopAndDestroy(); // hbuf
       
   431     }
       
   432 
       
   433 // -----------------------------------------------------------------------------
       
   434 // CNotepadModel::AbortDeletionL
       
   435 // -----------------------------------------------------------------------------
       
   436 //
       
   437 void CNotepadModel::AbortDeletionL()
       
   438     {
       
   439     CancelDeletion();
       
   440     if ( iModelObserver )
       
   441         {
       
   442         iModelObserver->HandleNotepadModelEventL(
       
   443             MNotepadModelObserver::EAbortDeletion );
       
   444         }
       
   445     }
       
   446 
       
   447 // -----------------------------------------------------------------------------
       
   448 // CNotepadModel::CompleteDeletionL
       
   449 // -----------------------------------------------------------------------------
       
   450 //
       
   451 void CNotepadModel::CompleteDeletionL()
       
   452     {
       
   453     CancelDeletion();
       
   454     if ( iModelObserver )
       
   455         {
       
   456         iModelObserver->HandleNotepadModelEventL(
       
   457             MNotepadModelObserver::ECompleteDeletion);
       
   458         }
       
   459     SyncL(ETrue);
       
   460     iItemArray->Compress();
       
   461     }
       
   462 
       
   463 // -----------------------------------------------------------------------------
       
   464 // CNotepadModel::DeleteCallBack
       
   465 //
       
   466 // be sure that this function never leave after AbortDeletionL
       
   467 // because iExecuter is deleted in AbortDeletionL.
       
   468 // -----------------------------------------------------------------------------
       
   469 //
       
   470 TInt CNotepadModel::DeleteCallBack(TAny *aSelf)
       
   471     {
       
   472     TInt needsRepeat(FALSE);
       
   473     CNotepadModel* self = STATIC_CAST(CNotepadModel*, aSelf);
       
   474     TRAPD(err, 
       
   475         needsRepeat = ( self->iFlag & ENotepadIsRemovingLinks ) ? 
       
   476             self->DoRemoveLinkCallBackL() : 
       
   477             self->DoDeleteCallBackL(); 
       
   478         );
       
   479     if ( err != KErrNone )
       
   480         {
       
   481         self->iEnv->HandleError(err);
       
   482         TRAP(err, self->AbortDeletionL(););
       
   483         if ( err != KErrNone )
       
   484             {
       
   485             self->iEnv->HandleError(err);
       
   486             }
       
   487         }
       
   488     return needsRepeat;
       
   489     }
       
   490 
       
   491 // -----------------------------------------------------------------------------
       
   492 // CNotepadModel::DoDeleteCallBackL
       
   493 // -----------------------------------------------------------------------------
       
   494 //
       
   495 TInt CNotepadModel::DoDeleteCallBackL()
       
   496     {
       
   497     TInt needsRepeat(TRUE);
       
   498     TInt increment(0);
       
   499     TBool deleteFinished(EFalse);
       
   500     const TInt stat(iDbUpdate.Next());
       
   501     if ( stat == 0 ) // current step has completed
       
   502         {
       
   503         iDbUpdate.Close();
       
   504         if ( IsTemplates() )
       
   505             {
       
   506             if ( iSavedDeleteKeys.Count() == 0 ) // MCE, finish all
       
   507                 {
       
   508                 needsRepeat = FALSE;
       
   509                 CompleteDeletionL();
       
   510                 deleteFinished = ETrue;
       
   511                 }
       
   512             else // do next step
       
   513                 {
       
   514                 increment = iStepCount - iProgressCount;
       
   515                 ExecuteDeleteStepL();
       
   516                 }
       
   517             }
       
   518         else
       
   519             {
       
   520             // switch to remove link phase
       
   521             iFlag |= ENotepadIsRemovingLinks; 
       
   522             increment = iStepCount - iProgressCount;
       
   523             if ( iSavedDeleteKeys.Count() == iStepCount ) // final step
       
   524                 {
       
   525                 deleteFinished = ETrue;
       
   526                 }
       
   527             }
       
   528         }
       
   529     if ( stat > 0 )
       
   530         {
       
   531         increment = iDbUpdate.RowCount() - iProgressCount;
       
   532         }            
       
   533     if ( increment > 0 )
       
   534         {
       
   535         iProgressCount += increment;
       
   536         if ( iModelObserver )
       
   537             {
       
   538             iModelObserver->HandleNotepadModelEventL(
       
   539                 MNotepadModelObserver::EProgressDeletion, increment);
       
   540             }
       
   541         }
       
   542     if ( deleteFinished || ( stat == 0 && 
       
   543         SysUtil::FFSSpaceBelowCriticalLevelL(&(iEnv->FsSession())) ) )
       
   544         {
       
   545         User::LeaveIfError(iDatabase.Compact());
       
   546         }
       
   547     User::LeaveIfError(stat);
       
   548     return needsRepeat;
       
   549     }
       
   550 
       
   551 // -----------------------------------------------------------------------------
       
   552 // CNotepadModel::DoRemoveLinkCallBackL
       
   553 // -----------------------------------------------------------------------------
       
   554 //
       
   555 TInt CNotepadModel::DoRemoveLinkCallBackL()
       
   556     {
       
   557     TInt needsRepeat(TRUE);
       
   558     TBool hasFinished(EFalse);
       
   559     TBool timeUp(EFalse);
       
   560     TInt count(0);
       
   561     TTime beginning;
       
   562     TTime now;
       
   563     TTimeIntervalMicroSeconds maxInterval(
       
   564         KNotepadMaxRunIntervalInMicroSeconds );
       
   565     beginning.UniversalTime();
       
   566     while ( !hasFinished && !timeUp )
       
   567         {
       
   568         if ( iStepCount == 0 ) // current step has completed
       
   569             {
       
   570             hasFinished = ETrue;
       
   571             }
       
   572         else
       
   573             {
       
   574             iSavedDeleteKeys.Remove(0);
       
   575             count++;
       
   576             iStepCount--;
       
   577             now.UniversalTime();
       
   578             timeUp = ( now.MicroSecondsFrom(beginning) > maxInterval );
       
   579             }
       
   580         }
       
   581     if ( hasFinished ) // current step has finished
       
   582         {
       
   583         if ( iSavedDeleteKeys.Count() == 0 ) // finish all
       
   584             {
       
   585             needsRepeat = FALSE;
       
   586             CompleteDeletionL();
       
   587             }
       
   588         else // switch to delete phase again
       
   589             {
       
   590             iFlag &= ~ENotepadIsRemovingLinks;
       
   591             ExecuteDeleteStepL();
       
   592             }
       
   593         }
       
   594     if ( needsRepeat && count > 0 )
       
   595         {
       
   596         iModelObserver->HandleNotepadModelEventL(
       
   597             MNotepadModelObserver::EProgressDeletion, count); 
       
   598         }
       
   599     return needsRepeat;
       
   600     }
       
   601 
       
   602 // -----------------------------------------------------------------------------
       
   603 // CNotepadModel::BuildItemArrayL
       
   604 // -----------------------------------------------------------------------------
       
   605 //
       
   606 void CNotepadModel::BuildItemArrayL( const TBool aForceSync )
       
   607     {
       
   608     if ( !aForceSync && !(iFlag & ENotepadRequireItemArrayUpdate) )
       
   609         {
       
   610         return;
       
   611         }
       
   612 
       
   613     iFlag |= ENotepadRequireItemArrayUpdate;
       
   614     if ( iModelObserver )
       
   615         {
       
   616         iModelObserver->HandleNotepadModelEventL(
       
   617             MNotepadModelObserver::EStartItemArrayChange );
       
   618         }
       
   619     iItemArray->Reset();
       
   620     iKeyArray.Reset();
       
   621     TRAPD( err, DoBuildItemArrayL() );
       
   622     if ( err != KErrNone)
       
   623         {
       
   624         iItemArray->Reset();
       
   625         iKeyArray.Reset();
       
   626         if ( iModelObserver )
       
   627             {
       
   628             iModelObserver->HandleNotepadModelEventL(
       
   629                 MNotepadModelObserver::EAbortItemArrayChange ); // not leave
       
   630             }
       
   631         User::Leave(err);
       
   632         }
       
   633     iFlag &= ~ENotepadRequireItemArrayUpdate; // now iItemArray is up to date
       
   634     if ( iModelObserver )
       
   635         {
       
   636         iModelObserver->HandleNotepadModelEventL(
       
   637             MNotepadModelObserver::ECompleteItemArrayChange );
       
   638         }
       
   639     }
       
   640 
       
   641 // -----------------------------------------------------------------------------
       
   642 // CNotepadModel::DoBuildItemArrayL
       
   643 // -----------------------------------------------------------------------------
       
   644 //
       
   645 void CNotepadModel::DoBuildItemArrayL()
       
   646     {
       
   647     HBufC* hbuf = HBufC::NewLC(KNotepadListEntryLength);
       
   648     TPtr buf = hbuf->Des();
       
   649     if ( IsTemplates() )
       
   650         {
       
   651         DoBuildTemplateItemArrayL(buf);
       
   652         }
       
   653     else
       
   654         {
       
   655         DoBuildNotepadItemArrayL(buf);
       
   656         }
       
   657     CleanupStack::PopAndDestroy(); // hbuf
       
   658     }
       
   659 
       
   660 // -----------------------------------------------------------------------------
       
   661 // CNotepadModel::DoBuildNotepadItemArrayL
       
   662 // -----------------------------------------------------------------------------
       
   663 //
       
   664 void CNotepadModel::DoBuildNotepadItemArrayL(
       
   665     TPtr& aBuf)
       
   666     {
       
   667     TTimeIntervalMinutes offset;
       
   668     TTime now;
       
   669     now.HomeTime();
       
   670     TTime gmt;
       
   671     gmt.UniversalTime();
       
   672     now.MinutesFrom(gmt, offset);
       
   673     TInt currentDay(now.DateTime().Day());
       
   674     TInt currentMonth(now.DateTime().Month());
       
   675     TInt currentYear(now.DateTime().Year());
       
   676 
       
   677     RArray<TInt> minutesArrayOfToday;
       
   678     CleanupClosePushL(minutesArrayOfToday);
       
   679     TInt minutesInToday(0);
       
   680 
       
   681     TInt firstIndexOfTheDay(KNotepadModelInvalidIndex);
       
   682     TDateTime prevDateTime;
       
   683 
       
   684     RArray<TPtrC> textArrayOfTheDay;
       
   685     CleanupClosePushL(textArrayOfTheDay);
       
   686     iDbView.FirstL();
       
   687     while (iDbView.AtRow())
       
   688         {
       
   689         iDbView.GetL();
       
   690         TInt thisKey(iDbView.ColInt(ENotepadKey));
       
   691         TTime time = iDbView.ColTime(ENotepadUpdateTime);
       
   692         time += offset; // including summertime adjustment
       
   693         TDateTime dateTime = time.DateTime(); // cache
       
   694         TBool isToday( dateTime.Day() == currentDay
       
   695              && dateTime.Month() == currentMonth
       
   696              && dateTime.Year() == currentYear );
       
   697         if ( isToday )
       
   698             {
       
   699             minutesInToday = dateTime.Hour() * 60 + dateTime.Minute();
       
   700             }
       
   701         aBuf.SetLength(0);
       
   702         TInt textOffset(0);
       
   703         switch (iListingStyle)
       
   704             {
       
   705             case ENotepadListingStyleNP: // list of memos
       
   706                 time.FormatL( aBuf, isToday ? *iTimeFormat : *iDateFormat );
       
   707                 aBuf.Append(KColumnListSeparator);
       
   708                 textOffset = aBuf.Length();
       
   709                 // through into next case
       
   710             case ENotepadListingStyleFetch: // fetch a memo
       
   711                 AppendContentAsLabelL(aBuf, iDbView);
       
   712                 break;
       
   713             default:
       
   714                 break;
       
   715             }
       
   716 
       
   717         TPtrC thisText = 
       
   718             aBuf.Mid(textOffset).Left(KNotepadMaxCharactersForSort);
       
   719         if ( iItemArray->Count() == 0 || 
       
   720              dateTime.Day() != prevDateTime.Day() ||
       
   721              dateTime.Month() != prevDateTime.Month() ||
       
   722              dateTime.Year() != prevDateTime.Year() )
       
   723             {
       
   724             // first entry or date of the item has changed
       
   725             firstIndexOfTheDay = iItemArray->Count();
       
   726             textArrayOfTheDay.Reset();
       
   727             if ( isToday )
       
   728                 {
       
   729                 User::LeaveIfError(minutesArrayOfToday.Append(minutesInToday));
       
   730                 }
       
   731             // INSERT POINT
       
   732             AknTextUtils::LanguageSpecificNumberConversion(aBuf);
       
   733             iItemArray->AppendL(aBuf);
       
   734             User::LeaveIfError( textArrayOfTheDay.Append(
       
   735                 (*iItemArray)[firstIndexOfTheDay].Mid(textOffset).Left(
       
   736                     KNotepadMaxCharactersForSort) ) );
       
   737             User::LeaveIfError(iKeyArray.Append(thisKey));
       
   738             }
       
   739         else
       
   740             {
       
   741             // calculate an insertion point
       
   742             TInt low(0); // this will be result insertion point
       
   743             TInt high( textArrayOfTheDay.Count() - 1 );
       
   744             TInt mid(0);
       
   745             while ( high >= low )
       
   746                 {
       
   747                 mid = (high + low) / 2;
       
   748                 if ( isToday ? ( minutesInToday < minutesArrayOfToday[mid] ||
       
   749                     ( minutesInToday == minutesArrayOfToday[mid] &&
       
   750                         thisText.CompareC(textArrayOfTheDay[mid]) > 0 ) ) :
       
   751                     thisText.CompareC(textArrayOfTheDay[mid]) > 0 )
       
   752                     {
       
   753                     low = mid + 1;
       
   754                     }
       
   755                 else
       
   756                     {
       
   757                     high = mid - 1;
       
   758                     }
       
   759                 }
       
   760             // low is result
       
   761             if ( isToday )
       
   762                 {
       
   763                 User::LeaveIfError(minutesArrayOfToday.Insert(
       
   764                     minutesInToday, low ) );
       
   765                 }
       
   766             // INSERT POINT
       
   767             AknTextUtils::LanguageSpecificNumberConversion(aBuf);
       
   768             iItemArray->InsertL(firstIndexOfTheDay + low, aBuf);
       
   769             User::LeaveIfError( textArrayOfTheDay.Insert(
       
   770                 (*iItemArray)[firstIndexOfTheDay + low].Mid(textOffset).Left(
       
   771                     KNotepadMaxCharactersForSort), 
       
   772                 low ) );
       
   773             User::LeaveIfError(
       
   774                 iKeyArray.Insert(thisKey, firstIndexOfTheDay + low) );
       
   775             }
       
   776         if ( iModelObserver && 
       
   777             iItemArray->Count() == KNotepadBuildItemArrayProgressCount )
       
   778             {
       
   779             iModelObserver->HandleNotepadModelEventL(
       
   780                 MNotepadModelObserver::EProgressItemArrayChange );
       
   781             }
       
   782         prevDateTime = dateTime;
       
   783         iDbView.NextL();
       
   784         }
       
   785     CleanupStack::PopAndDestroy(2); // minutesArrayOfToday, textArrayOfTheDay
       
   786     }
       
   787 
       
   788 // -----------------------------------------------------------------------------
       
   789 // CNotepadModel::DoBuildTemplateItemArrayL
       
   790 // -----------------------------------------------------------------------------
       
   791 //
       
   792 void CNotepadModel::DoBuildTemplateItemArrayL(
       
   793     TPtr& aBuf)
       
   794     {
       
   795     iDbView.FirstL();
       
   796     while (iDbView.AtRow())
       
   797         {
       
   798         iDbView.GetL();
       
   799         TInt thisKey(iDbView.ColInt(ENotepadKey));
       
   800         aBuf.SetLength(0);
       
   801         switch (iListingStyle)
       
   802             {
       
   803             case ENotepadListingStyleMC:
       
   804                 aBuf.Append(KNotepadMceFirstColumnData);
       
   805                 aBuf.Append(KColumnListSeparator);
       
   806                 // pass through into next case
       
   807             case ENotepadListingStyleFetchMC: // fetch template
       
   808                 AppendContentAsLabelL(aBuf, iDbView);
       
   809                 break;
       
   810             default:
       
   811                 break;
       
   812             }
       
   813         // INSERT POINT
       
   814         iItemArray->AppendL(aBuf);
       
   815         User::LeaveIfError(iKeyArray.Append(thisKey));
       
   816         if ( iModelObserver && 
       
   817             iItemArray->Count() == KNotepadBuildItemArrayProgressCount )
       
   818             {
       
   819             iModelObserver->HandleNotepadModelEventL(
       
   820                 MNotepadModelObserver::EProgressItemArrayChange );
       
   821             }
       
   822         iDbView.NextL();
       
   823         }
       
   824     }
       
   825 
       
   826 // -----------------------------------------------------------------------------
       
   827 // CNotepadModel::CNotepadModel_Reserved
       
   828 // -----------------------------------------------------------------------------
       
   829 //
       
   830 EXPORT_C void CNotepadModel::CNotepadModel_Reserved()
       
   831     {
       
   832     }
       
   833 
       
   834 // -----------------------------------------------------------------------------
       
   835 // CNotepadModel::SetItemArrayFlags
       
   836 // -----------------------------------------------------------------------------
       
   837 //
       
   838 void CNotepadModel::SetItemArrayFlags()
       
   839 	{
       
   840 	if(iFlag&ENotepadItemArrayUpdateOnly)
       
   841 		{
       
   842 
       
   843 		iFlag |= ENotepadRequireDbViewUpdate;
       
   844 		iFlag |= ENotepadRequireItemArrayUpdate;
       
   845 		}
       
   846 	}
       
   847 
       
   848 // -----------------------------------------------------------------------------
       
   849 // CNotepadModel::ItemArrayFlags
       
   850 // -----------------------------------------------------------------------------
       
   851 //
       
   852 TUint CNotepadModel::ItemArrayFlags()
       
   853 	{
       
   854 	return iFlag;
       
   855 	}
       
   856 
       
   857 // -----------------------------------------------------------------------------
       
   858 // CNotepadModel::CDatabaseChangeNotifier::NewL
       
   859 // -----------------------------------------------------------------------------
       
   860 //
       
   861 CNotepadModel::CDatabaseChangeNotifier* 
       
   862     CNotepadModel::CDatabaseChangeNotifier::NewL(
       
   863     RDbDatabase& aDatabase,
       
   864     CNotepadModel& aModel )
       
   865     {
       
   866     CDatabaseChangeNotifier* self = 
       
   867         new(ELeave) CDatabaseChangeNotifier(aModel);
       
   868     CleanupStack::PushL(self);
       
   869     self->ConstructL(aDatabase);
       
   870     CleanupStack::Pop(); // self
       
   871     return self; 
       
   872     }
       
   873 
       
   874 // -----------------------------------------------------------------------------
       
   875 // CNotepadModel::CDatabaseChangeNotifier::~CDatabaseChangeNotifier
       
   876 // -----------------------------------------------------------------------------
       
   877 //
       
   878 CNotepadModel::CDatabaseChangeNotifier::~CDatabaseChangeNotifier()
       
   879     {
       
   880     Cancel();
       
   881     iDbNotifier.Close(); 
       
   882     }
       
   883 
       
   884 // -----------------------------------------------------------------------------
       
   885 // CNotepadModel::CDatabaseChangeNotifier::CDatabaseChangeNotifier
       
   886 // -----------------------------------------------------------------------------
       
   887 //
       
   888 CNotepadModel::CDatabaseChangeNotifier::CDatabaseChangeNotifier(
       
   889     CNotepadModel& aModel )
       
   890     :CActive(CActive::EPriorityLow), iModel(aModel)
       
   891     {
       
   892     CActiveScheduler::Add(this);
       
   893     }
       
   894 
       
   895 // -----------------------------------------------------------------------------
       
   896 // CNotepadModel::CDatabaseChangeNotifier::ConstructL
       
   897 // -----------------------------------------------------------------------------
       
   898 //
       
   899 void CNotepadModel::CDatabaseChangeNotifier::ConstructL(
       
   900     RDbDatabase& aDatabase ) 
       
   901     { 
       
   902     User::LeaveIfError(iDbNotifier.Open(aDatabase)); 
       
   903     iDbNotifier.NotifyChange(iStatus);
       
   904     SetActive();
       
   905     }
       
   906 
       
   907 // -----------------------------------------------------------------------------
       
   908 // CNotepadModel::CDatabaseChangeNotifier::DoCancel
       
   909 // -----------------------------------------------------------------------------
       
   910 //
       
   911 void CNotepadModel::CDatabaseChangeNotifier::DoCancel()
       
   912     { 
       
   913     iDbNotifier.Cancel(); 
       
   914     }
       
   915 
       
   916 // -----------------------------------------------------------------------------
       
   917 // CNotepadModel::CDatabaseChangeNotifier::RunL
       
   918 // -----------------------------------------------------------------------------
       
   919 //
       
   920 void CNotepadModel::CDatabaseChangeNotifier::RunL()
       
   921     {
       
   922     // enum TEvent {EClose,EUnlock,ECommit,ERollback,ERecover};
       
   923     TInt status(iStatus.Int());
       
   924     TInt err(KErrNone);
       
   925     if (status == RDbNotifier::ECommit)
       
   926         {
       
   927         TRAP(err, iModel.HandleDatabaseChangedL(status););
       
   928         }
       
   929     // Restart this even if err != KErrNone
       
   930     iDbNotifier.NotifyChange(iStatus);
       
   931     SetActive();
       
   932     User::LeaveIfError(err);
       
   933     }
       
   934 
       
   935 // End of File