symhelp/helpmodel/src/HLPDB.CPP
changeset 0 1f04cf54edd8
equal deleted inserted replaced
-1:000000000000 0:1f04cf54edd8
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "HLPDB.H"
       
    17 
       
    18 // System includes
       
    19 #include <fbs.h>
       
    20 
       
    21 // User includes
       
    22 #include "HLPMODEL.H"
       
    23 #include "hlppanic.h"
       
    24 #include "Hlpsqlconsts.h"
       
    25 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    26 #include "hlpmodel_internal.h"
       
    27 #endif
       
    28 
       
    29 // Constants
       
    30 const TInt KHlpModelNumberOfImageTableColumnsForV6Point0HelpFile = 2;
       
    31 const TInt KHlpModelNumberOfImagesInV6Point0HelpFile = 1;
       
    32 
       
    33 
       
    34 //
       
    35 // ----> CHlpDatabase  
       
    36 //
       
    37 
       
    38 CHlpDatabase::CHlpDatabase(RFs& aFs)
       
    39 :	iFs(aFs)
       
    40 	{
       
    41 	}
       
    42 
       
    43 CHlpDatabase::~CHlpDatabase()
       
    44 	{
       
    45 	Close();
       
    46 	iImageTable.Close();
       
    47 
       
    48 	delete iView;
       
    49 	delete iDatabase;
       
    50 	delete iStore;
       
    51 	delete iUids;
       
    52 	}
       
    53 
       
    54 void CHlpDatabase::ConstructL()
       
    55 	{
       
    56 	iView = new(ELeave) RDbView;
       
    57 	iUids = new(ELeave) CArrayFixFlat<TUid>(2);
       
    58 	iDatabase = new(ELeave) RDbStoreDatabase;
       
    59 	}
       
    60 
       
    61 CHlpDatabase* CHlpDatabase::NewLC(RFs& aFs)
       
    62 	{
       
    63 	CHlpDatabase* self = new(ELeave) CHlpDatabase(aFs);
       
    64 	CleanupStack::PushL(self);
       
    65 	self->ConstructL();
       
    66 	return self;
       
    67 	}
       
    68 
       
    69 CHlpDatabase* CHlpDatabase::NewLC(RFs& aFs, const TDesC& aFileName)
       
    70 	{
       
    71 	CHlpDatabase* self = CHlpDatabase::NewLC(aFs);
       
    72 	self->OpenL(aFileName);
       
    73 	return self;
       
    74 	}
       
    75 
       
    76 //
       
    77 //
       
    78 //
       
    79 
       
    80 void CHlpDatabase::OpenL(const TDesC& aFileName)
       
    81 	{
       
    82 	iFileName = aFileName;
       
    83 	iStore = CPermanentFileStore::OpenL(iFs, aFileName, EFileRead);
       
    84 
       
    85 	// Restore the dictionary
       
    86 	CStreamDictionary* dictionary = CStreamDictionary::NewLC();
       
    87 	RStoreReadStream in;
       
    88 	in.OpenLC(*iStore, iStore->Root());
       
    89 	dictionary->InternalizeL(in);
       
    90 	CleanupStack::PopAndDestroy(); // in
       
    91 
       
    92 	// Restore the database
       
    93 	iDatabase->OpenL(iStore, dictionary->At(KUidHlpDbStream));
       
    94 
       
    95 	// Open image table
       
    96 	_LIT(KImageTable, "IMAGE");
       
    97 	_LIT(KImageIndex, "IMAGEIDX");
       
    98 	User::LeaveIfError(iImageTable.Open(*iDatabase, KImageTable, RDbRowSet::EReadOnly));
       
    99 	User::LeaveIfError(iImageTable.SetIndex(KImageIndex));
       
   100 
       
   101 	// Fetch the image row
       
   102 	CDbColSet* columnSet = iImageTable.ColSetL();
       
   103 
       
   104 	// We can identify v6 help files by the number of columns in the image table.
       
   105 	// Since v6 help files only have one image for all zoom sizes, then we 
       
   106 	// can identify this via the number of columns being 2.
       
   107 	iOldHelpFileFormat = (columnSet->Count() == KHlpModelNumberOfImageTableColumnsForV6Point0HelpFile);
       
   108 	delete columnSet;
       
   109 
       
   110 	// Restore the Uid list
       
   111 	TStreamId uidStream = dictionary->At(KUidHlpUidStream);
       
   112 	in.OpenLC(*iStore, uidStream);
       
   113 
       
   114 	TUid uid;
       
   115 	TKeyArrayFix key(_FOFF(TUid, iUid), ECmpTUint32);
       
   116 	const TInt count = in.ReadInt32L();
       
   117 	for (TInt i=0; i < count; i++)
       
   118 		{
       
   119 		uid.iUid = in.ReadInt32L();
       
   120 #ifdef _DEBUG
       
   121 		iUids->InsertIsqL(uid, key);
       
   122 #else
       
   123 		iUids->InsertIsqAllowDuplicatesL(uid, key);
       
   124 #endif
       
   125 		}
       
   126 	CleanupStack::PopAndDestroy(2); // in, dictionary
       
   127 
       
   128 	TEntry entry;
       
   129 	User::LeaveIfError(iFs.Entry(aFileName, entry));
       
   130 	iHelpFileUid = entry.MostDerivedUid();
       
   131 	}
       
   132 
       
   133 void CHlpDatabase::Close()
       
   134 	{
       
   135 	if	(iView)
       
   136 		iView->Close();
       
   137 	if	(iDatabase)
       
   138 		iDatabase->Close();
       
   139 	}
       
   140 
       
   141 //
       
   142 //
       
   143 //
       
   144 
       
   145 void CHlpDatabase::AppendCategoryListL(CDesCArray& aList)
       
   146 	{
       
   147 	_LIT(KCategoryTable, "TOPIC");
       
   148 
       
   149 	// Open the topic table so that we can use it to build the category list
       
   150 	RDbTable table;
       
   151 	User::LeaveIfError(table.Open(*iDatabase, KCategoryTable, RDbRowSet::EReadOnly));
       
   152 	CleanupClosePushL(table);
       
   153 
       
   154 	// Now build the list
       
   155 	if (table.FirstL())
       
   156 		{
       
   157 		// Get the column of the category
       
   158 		CDbColSet* columnSet = table.ColSetL();
       
   159 		TDbColNo categoryColumn = columnSet->ColNo(KSQLCategoryColumn);
       
   160 		delete columnSet;
       
   161 
       
   162 		TInt posNotReferenced = KErrNotFound;
       
   163 		TBuf<KMaxTitleColumn> title;
       
   164 		do
       
   165 			{
       
   166 			// Add the stuff
       
   167 			table.GetL();
       
   168 			title = table.ColDes(categoryColumn);
       
   169 			if	(aList.Find(title, posNotReferenced)) // Returns something other than 0 if not found
       
   170 				aList.AppendL(title); // Not found, so append
       
   171 			}
       
   172 		while (table.NextL());
       
   173 		}
       
   174 
       
   175 	// Finally, close the table
       
   176 	CleanupStack::PopAndDestroy(&table);
       
   177 	}
       
   178 
       
   179 TInt CHlpDatabase::TopicIdSearchL(const TUid aCategoryUid, const TUint aTopicId)
       
   180 	{
       
   181 	const TInt KNumLength = 20;
       
   182 	const TInt KMaxParamLength = (2*KNumLength) + 20; // 20 for numbers, + 20 for ' = ' and ' AND ' etc.
       
   183 	TBuf<KNumLength> num;
       
   184 
       
   185 	HBufC* sqlStatement = HBufC::NewLC(KSQLTopicSearchProlog().Length() + KMaxParamLength);
       
   186 	TPtr pSql(sqlStatement->Des());
       
   187 	pSql.Append(KSQLTopicSearchProlog);
       
   188 
       
   189 	pSql.Append(KSQLTopicIdColumn);
       
   190 	pSql.Append(KSQLEqualOperator);
       
   191 	num.Num(aTopicId);
       
   192 	pSql.Append(num);
       
   193 
       
   194 	pSql.Append(KSQLAndOperator);
       
   195 	pSql.Append(KSQLCategoryUidColumn);
       
   196 	pSql.Append(KSQLEqualOperator);
       
   197 	num.Num(STATIC_CAST(TUint, aCategoryUid.iUid));
       
   198 	pSql.Append(num);
       
   199 
       
   200 	iView->Close();
       
   201 	User::LeaveIfError(iView->Prepare(Database(), TDbQuery(pSql, EDbCompareFolded), TDbWindow::EUnlimited, RDbRowSet::EReadOnly));
       
   202 	User::LeaveIfError(iView->EvaluateAll());
       
   203 	CleanupStack::PopAndDestroy(); // sqlStatement
       
   204 	if	(iView->CountL())
       
   205 		{
       
   206 		iView->FirstL();
       
   207 		iView->GetL();
       
   208 		return ETopicAvailable; // View is prepared
       
   209 		}
       
   210 
       
   211 	return ETopicNotFound;
       
   212 	}
       
   213 
       
   214 TInt CHlpDatabase::ContextSearchL(const TDesC& aContext)
       
   215 	{
       
   216 	_LIT(KContextSearch,	"SELECT CONTEXT, TOPICID FROM CONTEXT");
       
   217 	_LIT(KSpecificContext,	" WHERE CONTEXT='%S'");
       
   218 
       
   219 	TInt specificContextLength = aContext.Length();
       
   220 	HBufC* sqlStatement = HBufC::NewLC(KContextSearch().Length() + KSpecificContext().Length() + specificContextLength);
       
   221 	TPtr pStatement = sqlStatement->Des();
       
   222 	pStatement.Append(KContextSearch);
       
   223 	if	(specificContextLength)
       
   224 		{
       
   225 		HBufC* specificContext = HBufC::NewLC(KSpecificContext().Length() + specificContextLength);
       
   226 		TPtr pContext = specificContext->Des();
       
   227 		pContext.Format(KSpecificContext, &aContext);
       
   228 		pStatement.Append(pContext);
       
   229 		CleanupStack::PopAndDestroy(specificContext);
       
   230 		}
       
   231 
       
   232 	iView->Close();
       
   233 	User::LeaveIfError(iView->Prepare(Database(), TDbQuery(pStatement, EDbCompareFolded), TDbWindow::EUnlimited, RDbRowSet::EReadOnly));
       
   234 	User::LeaveIfError(iView->EvaluateAll());
       
   235 	CleanupStack::PopAndDestroy(sqlStatement);
       
   236 
       
   237 	if	(iView->CountL())
       
   238 		{
       
   239 		// Get the topic id from the context table
       
   240 		CDbColSet* columnSet = iView->ColSetL();
       
   241 		TDbColNo topicIdCol = columnSet->ColNo(KSQLTopicIdColumn);
       
   242 		delete columnSet;
       
   243 
       
   244 		// Get the topic id as a descriptor
       
   245 		iView->FirstL();
       
   246 		iView->GetL();
       
   247 		TUint topicId = iView->ColUint(topicIdCol);
       
   248 		
       
   249 		_LIT(KTopicSearch, "SELECT TOPICTITLE, TOPICID, CATEGORY, TOPICTEXT, TOPICMARKUP FROM TOPIC WHERE TOPICID=%d");
       
   250 		sqlStatement = HBufC::NewLC(KTopicSearch().Length() + 16); // 16 for the topic id
       
   251 		pStatement.Set(sqlStatement->Des());
       
   252 		pStatement.Format(KTopicSearch, topicId);
       
   253 
       
   254 		// Prepare the topic table with the correct record...
       
   255 		iView->Close(); // Finished with this view now
       
   256 		User::LeaveIfError(iView->Prepare(Database(), TDbQuery(pStatement, EDbCompareFolded), TDbWindow::EUnlimited, RDbRowSet::EReadOnly));
       
   257 		User::LeaveIfError(iView->EvaluateAll());
       
   258 		CleanupStack::PopAndDestroy(); // sqlStatement
       
   259 
       
   260 		return ETopicAvailable;
       
   261 		}
       
   262 
       
   263 	return ETopicNotFound;
       
   264 	}
       
   265 
       
   266 /** This method is called within the CHlpPicture::RestoreL() method and 
       
   267 is responsible for finding the right bitmap to be retrieved and for reading 
       
   268 in a pointer to that bitmap.
       
   269 
       
   270 @param aImageId The ID of the bitmap to be retrieved.
       
   271 @param aZoomState The current zoom state.
       
   272 @return A pointer to a CFbsBitmap object.
       
   273 @pre A valid zoom state is passed to the function.
       
   274 @post A pointer to the referenced bitmap is returned. */
       
   275 CFbsBitmap* CHlpDatabase::ImageForIdLC(TInt aImageId, THlpZoomState aZoomState)
       
   276 {
       
   277 	if	(!iImageTable.FirstL())
       
   278 		User::Leave(KErrNotFound);
       
   279 
       
   280 	if	(!iImageTable.SeekL(aImageId))
       
   281 		User::Leave(KErrNotFound);
       
   282 
       
   283 	// Fetch the image row
       
   284 	iImageTable.GetL();
       
   285 
       
   286 	// Work out which column the image is in
       
   287 	CDbColSet* columnSet = iImageTable.ColSetL();
       
   288 	CleanupStack::PushL(columnSet);
       
   289 
       
   290 	TDbColNo imageColumn = KDbNullColNo;
       
   291 	if	(iOldHelpFileFormat)
       
   292 		{
       
   293 		// OLD HELP FILE FORMAT
       
   294 		// Retrieve bitmap from bitmap column in image table
       
   295 		// and store it in the 'imageColumn variable'
       
   296 		imageColumn = columnSet->ColNo(KSQLImageColumn);
       
   297 		}
       
   298 	else
       
   299 		{
       
   300 		// NEW HELP FILE FORMAT
       
   301 		// Depending on whether the number of bitmaps is 1 or 3,
       
   302 		// the bitmap from the appropriate column is retrieved 
       
   303 		// and stored in the 'imageColumn' variable
       
   304 
       
   305 		// Stores the number of bitmaps per image table row.
       
   306 		const TInt bitmapCount = ImageCountForIdL(aImageId);
       
   307 		__ASSERT_DEBUG(bitmapCount <= KHlpModelMaximumNumberOfImagesForV6Point2Files, User::Invariant());
       
   308 
       
   309 		if	(bitmapCount == KHlpModelDefaultNumberOfImagesForV6Point2Files)
       
   310 			imageColumn = columnSet->ColNo(KSQLImage0Column);
       
   311 		else if (bitmapCount == KHlpModelMaximumNumberOfImagesForV6Point2Files)
       
   312 			{
       
   313 			switch(aZoomState) 
       
   314 				{
       
   315 				case EHlpZoomStateSmall:
       
   316 					imageColumn = columnSet->ColNo(KSQLImage0Column);
       
   317 					break;
       
   318 				default:
       
   319 				case EHlpZoomStateMedium:
       
   320 					imageColumn = columnSet->ColNo(KSQLImage1Column);
       
   321 					break;
       
   322 				case EHlpZoomStateLarge:
       
   323 					imageColumn = columnSet->ColNo(KSQLImage2Column);
       
   324 					break;
       
   325 				}
       
   326 			}
       
   327 		}
       
   328 	CleanupStack::PopAndDestroy(columnSet);
       
   329 
       
   330 	// Load the image from the blob
       
   331 	CFbsBitmap* bitmap = new(ELeave) CFbsBitmap();
       
   332 	CleanupStack::PushL(bitmap);
       
   333 
       
   334 	// Read the column from the blob
       
   335 	RDbColReadStream blob;
       
   336 	blob.OpenLC(iImageTable, imageColumn);
       
   337 	blob >> *bitmap;
       
   338 	CleanupStack::PopAndDestroy(); // blob
       
   339 	return bitmap;
       
   340 	}
       
   341 
       
   342 /** This method is called within the CHlpDatabase::ImageForIdLC() 
       
   343 method and is responsible for returning the number of bitmaps stored 
       
   344 in the image-table row, as referenced by the aImageId argument.
       
   345 
       
   346 @param aImageId The ID of the bitmap, used for retrieving image-table 
       
   347 column information.
       
   348 @return An integer value that reflects the number of bitmaps within a 
       
   349 particular image-table row.
       
   350 @pre None.
       
   351 @post The integer number at the image-table row referenced by 
       
   352 aImageId is returned.
       
   353 @see RDbTable::GetL()
       
   354 @see RDbTable::ColSetL() */
       
   355 TInt CHlpDatabase::ImageCountForIdL(TInt aImageId)
       
   356 	{
       
   357 	if	(!iImageTable.FirstL())
       
   358 		User::Leave(KErrNotFound);
       
   359 
       
   360 	if	(!iImageTable.SeekL(aImageId))
       
   361 		User::Leave(KErrNotFound);
       
   362 
       
   363 	// Fetch the image row
       
   364 	iImageTable.GetL();
       
   365 
       
   366 	TInt count = KErrNotFound;
       
   367 	if	(iOldHelpFileFormat)
       
   368 		count = KHlpModelNumberOfImagesInV6Point0HelpFile;
       
   369 	else
       
   370 		{
       
   371 		// Work out which column the image count is in, 
       
   372 		// and assign it to 'imageCountColumn'.
       
   373 		CDbColSet* columnSet = iImageTable.ColSetL();
       
   374 		TDbColNo imageCountColumn = columnSet->ColNo(KSQLImageCountColumn);
       
   375 		delete columnSet;
       
   376 		//
       
   377 		count = iImageTable.ColUint(imageCountColumn);
       
   378 		}
       
   379 	return count;
       
   380 	}
       
   381 
       
   382 //
       
   383 //
       
   384 //
       
   385 
       
   386 TBool CHlpDatabase::MatchUidL(TUid aUid)
       
   387 	{
       
   388 	__ASSERT_ALWAYS(iUids, Panic(EHlpFault));
       
   389 	TInt index = KErrNotFound;
       
   390 	TKeyArrayFix key(_FOFF(TUid, iUid), ECmpTUint32);
       
   391 	// For some bizare reason, findisq returns 0 when the item was found.
       
   392 	return (iUids->FindIsq(aUid, key, index) == KErrNone);
       
   393 	}