📄 engine.cpp
字号:
TInt CAppEngine::EntryListCount() const
// Report number of TFolderEntry's we have
{
return(iFolderEntryList->Count());
}
TFolderEntry& CAppEngine::EntryListAt(const TInt aIndex) const
// Report the TFolderEntry at the indicated place within the
{
return((*iFolderEntryList)[aIndex]);
}
CArrayFixFlat<TInt>* CAppEngine::BuildIndexL(RArray<TFolderEntry>* aList,const TInt aCategory)
//
// Create an index into the list of entries. Indicies often have many superior properties, in this
// case we can easily filter and sort our underlying content simply by changing the index. Sorting
// entries consists of moving single TInts, compared to sizeof(TFolderEntry). Filtering is performed
// by putting a value in the index (or not as the case may be)
//
{
TInt count=aList->Count();
TInt granularity=count;
if (!count)
granularity=1; // ensure we cant generate a granularity of zero
// by creating the array at the granularity of the primary list we will only cause one
// alloc to occur when we add entries = signficantly faster adding entries.
CArrayFixFlat<TInt>* index=new(ELeave)CArrayFixFlat<TInt>(granularity);
CleanupStack::PushL(index);
for (TInt i=0;i<count;i++)
{
if (aCategory==EAppCategoryAll || (*aList)[i].EntryCategory()==aCategory)
index->AppendL(i);
}
// reduce ram used if not all entries are added to the index
index->Compress();
// caller is expected to take ownership of the created list
CleanupStack::Pop(index);
return(index);
}
_LIT(KWildCardName,"*");
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);
// add a set of entries to our new container
TFolderEntry entry;
TInt count=dirList->Count();
for (TInt i=0;i<count;i++)
{
// construct a new entry
entry.Construct((*dirList)[i]);
// 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;
}
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);
User::LeaveIfError(iFs.Delete(name));
// 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++)
{
if (iFolderEntryIndex->At(i)==whichEntry)
{
iCurrentEntry=i;
break;
}
}
}
TInt CAppEngine::CategoryListCount() const
// Report the number of items we have in the category list
{
return(iCategoryList->Count());
}
TAppCategoryEntry& CAppEngine::CategoryListAt(const TInt aIndex) const
// Report the aIndex'th item in the category list
{
return((*iCategoryList)[aIndex]);
}
void CAppEngine::AddCategoryL(const TInt aHandle,const TDesC& aName)
// Add a new category.
{
TAppCategoryEntry category;
category.iCategoryId=aHandle;
category.iCategoryName=aName;
iCategoryList->AppendL(category);
}
void CAppEngine::UpdateCategoryName(const TInt aHandle,const TDesC& aNewName)
// Update the textual name of the category identified by the aHandle value.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -