⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 engine.cpp

📁 《UIQ 3 The Complete Guide》书的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
_LIT(KBackupRegistrationFileName,"backup_registration.xml");
_LIT(KIniFileName,"SignedApp_0x20000462.ini");
_LIT(KExtensionGif,".gif");
_LIT(KExtensionWav,".wav");
_LIT(KExtension3gp,".3gp");
_LIT(KExtensionAvi,".avi");

void CAppEngine::BuildDirectoryListL(const TDesC& aPath)
//
// Get a list of the files and folders within the indicated folder
//
	{
	TParse parse;
	parse.Set(KWildCardName,&aPath,NULL);
	CDir *dirList;
	User::LeaveIfError(iFs.GetDir(parse.FullName(),KEntryAttNormal|KEntryAttReadOnly|
									KEntryAttHidden|KEntryAttSystem|KEntryAttDir,0,dirList));

	// ensure some part of the app takes ownership of the dirList before we can leave later on
	CleanupStack::PushL(dirList);

	// create a new container to store the entries
	RArray<TFolderEntry>* folderEntryList=new(ELeave)RArray<TFolderEntry>(8);

	// not only do we need to ensure we delete the actual allocated Rarray
	CleanupDeletePushL(folderEntryList);

	// but we also have to ensure we call Close() before the delete to release any resources
	CleanupClosePushL(*folderEntryList);
	
	TInt i,count;

	// see which of the original categories still remain - so we dont assign entries to
	// categories that have now been deleted.
	TAppCategoryIds existingIds[EAppCategoryLastItem];
	for (i=0;i<EAppCategoryLastItem;i++)
		existingIds[i]=EAppCategoryUnfiled;
	count=CategoryListCount();
	for (i=0;i<count;i++)
		{
		TInt catId=CategoryListAt(i).iCategoryId;
		if (catId<EAppCategoryLastItem)
			existingIds[catId]=(TAppCategoryIds)catId;
		}

	// add a set of entries to our new container
	TFolderEntry entry;
	count=dirList->Count();
	for (i=0;i<count;i++)
		{
		// dont list our backup_registration or INI files = stop user causing possible issues 
		// if they attempt to delete them. 
		if (!(*dirList)[i].iName.CompareF(KBackupRegistrationFileName))
			continue;
		if (!(*dirList)[i].iName.CompareF(KIniFileName))
			continue;

		// construct a new entry
		entry.Construct((*dirList)[i]);
		
		// assign to default categories....
		parse.Set(entry.EntryName(),&aPath,NULL);
		if (!parse.Ext().CompareF(KExtensionGif))
			entry.UpdateCategory(existingIds[EAppCategoryImage]);
		if (!parse.Ext().CompareF(KExtensionWav))
			entry.UpdateCategory(existingIds[EAppCategorySound]);
		if (!parse.Ext().CompareF(KExtension3gp))
			entry.UpdateCategory(existingIds[EAppCategoryVideo]);
		if (!parse.Ext().CompareF(KExtensionAvi))
			entry.UpdateCategory(existingIds[EAppCategoryVideo]);

		// add to the new list of entries
		folderEntryList->AppendL(entry);
		}

	// we need an index onto the entries to perform efficient processing
	CArrayFixFlat<TInt>* index=BuildIndexL(folderEntryList,iCurrentCategory);

	// now sort the array of TInts dependant on the content they refer to, in the current
	// mode + ascending/descending order
	TKeyEntryList key(folderEntryList,iSortType,iSortOrder);
	index->Sort(key);

	// replace any existing list with the new list
	if (iFolderEntryList)
		{
		iFolderEntryList->Close();
		delete(iFolderEntryList);
		}
	iFolderEntryList=folderEntryList;

	// firstly the Cleanup stack item that calls close()
	CleanupStack::Pop(folderEntryList);	

	// then the cleanup stack item that deletes the actual object
	CleanupStack::Pop(folderEntryList);	

	// replace the index
	delete(iFolderEntryIndex);
	iFolderEntryIndex=index;

	// we have a new list, display from the top, if there is a top item
	iCurrentEntry=0;
	LimitCurrentEntryVal();

	// update the path our entries exist within now all constructed
	iPath=aPath;

	// whilst it may have been tempting to perform this immedately after the end of the loop above
	// it is very important to match Push/Pops on the cleanup stack, so we simply defer to here
	CleanupStack::PopAndDestroy(dirList);

	// Perform a self test to verify our internal structure is still self consistent
	__TEST_INVARIANT;
	}

void CAppEngine::UpdateCurrentEntryL(const TFolderEntry& aUpdate)
//
// The current entry is being updated. Apply the changes. Update the index as appropriate.
// The expectation is that upon completion of this function the UI will return to a list view.
//
	{
	TFolderEntry& curEntry=EntryListAt(iFolderEntryIndex->At(iCurrentEntry));

	TParse srcName;
	srcName.Set(curEntry.EntryName(),&iPath,NULL);

	TBool sortReqd=EFalse;
	if (curEntry.EntryName()!=aUpdate.EntryName())
		{ // names being changed
		TParse destName;
		destName.Set(aUpdate.EntryName(),&iPath,NULL);

		// attempt to rename the file on disk
		User::LeaveIfError(iFs.Rename(srcName.FullName(),destName.FullName()));

		// now update the internal representation
		curEntry.UpdateName(aUpdate.EntryName());

		// whilst not strictly true in all circumstances, in majority of cases it is requried
		// so we ignore a possible optimization here
		sortReqd=ETrue;
		}

	if (curEntry.EntryModified()!=aUpdate.EntryModified())
		{ // file last modification date being updated
		User::LeaveIfError(iFs.SetModified(srcName.FullName(),aUpdate.EntryModified()));

		// update the internal representation
		curEntry.UpdateModified(aUpdate.EntryModified());

		// modification dates only involved in EFolderEntrySortByModified sorts 
		// so we can optimize quite easily.
		if (iSortType==EFolderEntrySortByModified)
			sortReqd=ETrue;
		}

	if (curEntry.EntryCategory()!=aUpdate.EntryCategory())
		{
		// firstly update the category associated with the current item
		TInt oldCategory=curEntry.EntryCategory();
		curEntry.UpdateCategory(aUpdate.EntryCategory());

		if (iCurrentCategory==oldCategory)
			{ // the index shows items from the categry weve just left, remove our entry
			iFolderEntryIndex->Delete(iCurrentEntry);

			// ensure we are still referencing a valid entry within the index
			LimitCurrentEntryVal();
			}

		// in our model it is not possible to move an entry from outside our category to within the
		// current category - as its not possible to select such an item within the UI..
		}

	if (sortReqd)
		SortEntries(iSortType,iSortOrder);

	// Perform a self test to verify our internal structure is still self consistent
	__TEST_INVARIANT;
	}

void CAppEngine::AddEntryL(const TDesC& aName,const TInt aCategoryId)
//
// Add a new entry to the list of entries we know about
//
	{
	// firstly check that the category we propose the entry be added to still exists.
	TInt catId=aCategoryId;
	TInt i;
	TInt count=CategoryListCount();
	for (i=0;i<count;i++)
		{
		if (CategoryListAt(i).iCategoryId==catId)
			break;
		}
	if (i==count) // the proposed category is missing, place in the unfiled category
		catId=EAppCategoryUnfiled;

	// create the new TFolderEntry, obtaining required info from the file stored on disk
	TFolderEntry entry;
	TEntry fileEntry;
	User::LeaveIfError(iFs.Entry(aName,fileEntry));
	entry.Construct(fileEntry);

	// update the entry category to propsed one
	entry.UpdateCategory(catId);

	// now attempt to add the entry to our list of entries.
	// firstly check to see if weve already got the same named entry in our list
	count=EntryListCount();
	for (i=0;i<count;i++)
		{
		TFolderEntry& existing=EntryListAt(i);
		if (!entry.EntryName().CompareF(existing.EntryName()))
			break;
		}

	if (i==count)
		{	// cant find the entry - append this one
		iFolderEntryList->AppendL(entry);

		if (iCurrentCategory==EAppCategoryAll || iCurrentCategory==catId)
			{ // we want to be able to see the entry as its in the currently chosen users list
	
			// the index of the entry weve appended will be the value 'count'.
			// since we always append to the iFolderEntryList, none of the other index values have
			// to change. 
			TRAPD(err,
				TKeyEntryList key(iFolderEntryList,iSortType,iSortOrder);
				iCurrentEntry=iFolderEntryIndex->InsertIsqAllowDuplicatesL(count,key);
				);

			if (err!=KErrNone)
				{ // roll back, remove the entry from the primary list
				iFolderEntryList->Remove(count);
				User::Leave(err);
				}
			}
		}
	else
		{ // see if the entry currently displayed in the index, if so move hlight to that entry
		TInt index=i;
		count=iFolderEntryIndex->Count();
		for (i=0;i<count;i++)
			{
			if (iFolderEntryIndex->At(i)==index)
				{ // entry represented by 'index' is being displayed to the user...
				iCurrentEntry=i;
				break;
				}
			}
		}

	// Perform a self test to verify our internal structure is still self consistent
	__TEST_INVARIANT;
	}

TInt CAppEngine::EntryCount() const
//
// Report the number of entries visible to the UI = number of entries in our filtered list
// 
	{
	return(iFolderEntryIndex->Count());
	}

const TFolderEntry& CAppEngine::Entry(const TInt aIndex) const
//
// Report the aIndex'th entry visible to the UI. 
//
	{
	return(EntryListAt(iFolderEntryIndex->At(aIndex)));
	}

const TFolderEntry& CAppEngine::CurrentEntry() const
//
// Return the current TFolderEntry as visible to the UI
//
	{
	return(EntryListAt(iFolderEntryIndex->At(iCurrentEntry)));
	}

void CAppEngine::LimitCurrentEntryVal()
// Limit the iCurrentEntry value so its within the valid range. Set to -1 if no entries left.
	{
	if (iCurrentEntry>=iFolderEntryIndex->Count())
		iCurrentEntry--;
	}

void CAppEngine::SetCurrentEntry(const TInt aIndex)
//
// Set the current entry to the aIndex'th entry visible to the UI. 
// Note that its entirely possible for aIndex to be -ve (-1), e.g. if no
// entries in the currently filtered list. 
// 
	{
	__ASSERT_DEBUG(aIndex<iFolderEntryIndex->Count(),Panic(10));
	iCurrentEntry=aIndex;
	}

void CAppEngine::EntryFullName(TDes& aName)
// Report the full name of the currently selected entry
	{
	TParse parse;
	parse.Set(CurrentEntry().EntryName(),&iPath,NULL);
	aName=parse.FullName();
	}

void CAppEngine::DeleteCurrentEntryL()
//
// Delete the current entry. 
// i) remove from disk, ii) remove from internal representation of disk entry, iii) from index
//
	{
	// remove the file from the file store
	TFileName name;
	EntryFullName(name);
	TInt err=iFs.Delete(name);
	if (err!=KErrNotFound)
		User::LeaveIfError(err);

	// remove the entry from our list of all entries
	TInt index=iFolderEntryIndex->At(iCurrentEntry);
	iFolderEntryList->Remove(index);
	
	// remove the entry from the index + adjust all index values so they take into account
	// the fact that the iFolderEntryList contains one less entry. Any entries after the
	// 'index' th entry have moved up the list.
	iFolderEntryIndex->Delete(iCurrentEntry);
	const TInt count=EntryCount();
	for (TInt i=0;i<count;i++)
		{
		TInt val=iFolderEntryIndex->At(i);
		if (val>=index)
			(*iFolderEntryIndex)[i]=val-1;
		}

	// as an alternative to the above index updating we could have chosen to rebuild the entire
	// index, however the above is significantly more efficient + no OOM to contend with. 

	// limit the current entry index to the existing entries
	LimitCurrentEntryVal();

	// Perform a self test to verify our internal structure is still self consistent
	__TEST_INVARIANT;
	}

void CAppEngine::SortEntries(const TFolderEntrySortType aSortType,const TFolderEntrySortOrder aOrder)
//
// Sort the current entries in the index into specified order
// The engine design explitly ensures that we can sort entries without leaving being possible. This
// is to ensure we can handle any UI rollback that may be required.
//
// We also track the current entry so when the UI displays the newly sorted list the selected item
// remains the same. 
//
	{
	// as an optimization we could check to see if only the aOrder is varying. If so we can
	// generate the sorted list by simply swapping all entries in our index - which is much faster
	// than actually performing a sort. That is not implmented at this time. 

	// we want to track where the current entry has got to so when we return to the list view
	// the hlight remains on the item that was changed...
	TInt whichEntry=iFolderEntryIndex->At(iCurrentEntry);

	TKeyEntryList key(iFolderEntryList,aSortType,aOrder);
	iFolderEntryIndex->Sort(key);
	iSortType=aSortType;
	iSortOrder=aOrder;

	// scan the index to locate the original entry, so we can determine the new iCurrentEntry
	const TInt count=EntryCount();
	for (TInt i=0;i<count;i++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -