Symbian AO实现的全盘扫描

这个是基于AO实现的扫描引擎,使用timer来隔开每次AO,给点时间给进度条,保证显示流畅,如果性能要求高的话,建议使用多线程实现。

写 这个代码的时候,我对AO还一知半解,可能很多问题,大家自己review下。


这代码是比较完整的,功能是扫描指定路径,指定后缀的文件,并且添加到一个列表界面(列表如果需要的话,自己加把,这里只是一个传入参 数),并且显示进度条。

#include "ScanFolderEngine.h"

#define USE_TIMER_WHEN_SCANNING 1   // use timer to break some time to display progress bar

const TInt KFinalValue(100); //进度条最大值
const TInt KTimerStartDelay(1250000);//第一次开始任务的延迟,主要是给时间给progress的显示
const TInt KTimerInterval(0);//计时器的间隔
const TInt KIncrement(5); //进度条每次增长的值(或者减小)


_LIT(KFormatXxx, ".xxx");
_LIT(KFormatYyy, ".yyy");
_LIT(KFormatZzz, ".zzz");

CScanFolderEngine * CScanFolderEngine::NewLC( CUIListContainer *pUIListContainer )
{
 CScanFolderEngine* self = new (ELeave) CScanFolderEngine(pUIListContainer);
 CleanupStack::PushL(self);
 self->ConstructL();
 return self;
}

CScanFolderEngine * CScanFolderEngine::NewL( CUIListContainer *pUIListContainer )
{
 CScanFolderEngine* self = CScanFolderEngine::NewLC(pUIListContainer);
 CleanupStack::Pop(self);
 return self;
}

CScanFolderEngine::CScanFolderEngine(CUIListContainer *pUIListContainer)
: CActive(0)
, iErrorFlag(EFalse)
, iDestroyFlag(EFalse)
, m_pUIListContainer(pUIListContainer)
, m_bFinished(EFalse)
, m_nErrCount(0)
{
 
}


void CScanFolderEngine::ConstructL()
{
 m_nIncreaseDir = 0;
#ifdef USE_TIMER_WHEN_SCANNING
 iTimer.CreateLocal();
#endif // USE_TIMER_WHEN_SCANNING
 CActiveScheduler::Add(this);
 User::LeaveIfError(iFs.Connect());
}

CScanFolderEngine::~CScanFolderEngine()
{
#ifndef USE_TIMER_WHEN_SCANNING
 if(iStatus == KRequestPending)
 {
  TRequestStatus* status = &iStatus;
  User::RequestComplete( status, KErrCancel);
 }
 Cancel();
#else
 Cancel();
 iTimer.Close();
#endif // USE_TIMER_WHEN_SCANNING
 if(iProgressDialog) {
  delete iProgressDialog;
  iProgressDialog = 0;
 }
 iFs.Close();
}

/**
 * @brief 真正的扫描逻辑
 */
void CScanFolderEngine::DoScan()
{
#ifdef USE_TIMER_WHEN_SCANNING
 TInt delay = KTimerInterval;
 iTimer.After(iStatus, delay);
#endif // USE_TIMER_WHEN_SCANNING

 if(m_DirStack.Count() == 0) {
  m_bFinished = ETrue;
  return;
 }

 HBufC *buf = m_DirStack[m_DirStack.Count()-1];
 char *ansi_filename = new char[KMaxFileName*2+1];   // unicode
 TInt src_len = buf->Des().Length();
 TInt convert_len = 0;
 convert_len = PubFunction::U2A_char((const wchar_t*)buf->Des().Ptr(), src_len, ansi_filename);
 ansi_filename[convert_len] = 0;
 string sPath = string(ansi_filename, convert_len);   // bug 0027128
 delete ansi_filename;
 TBool bResult = ETrue;
 if(m_Mark.find(sPath) != m_Mark.end()) {   // 已经访问过,从上次位置开始
  // 访问目录
  CDir* dirs = NULL;
  CDir *files = NULL;
  TInt nErr = iFs.GetDir(buf->Des(), KEntryAttNormal, ESortByName, files, dirs);
  if(nErr != KErrNone) {   // 这个文件夹访问出错
   delete m_DirStack[m_DirStack.Count()-1];
   m_DirStack.Remove(m_DirStack.Count()-1);
  } else {
   CleanupStack::PushL(dirs);
   CleanupStack::PushL(files);

   TInt numberDirs = dirs->Count();
   //TraceLog("numberDirs %d/n", numberDirs);
   if(numberDirs <= m_Mark[sPath]) {   // 已经访问完了,把当前目录出栈
    delete m_DirStack[m_DirStack.Count()-1];
    m_DirStack.Remove(m_DirStack.Count()-1);
    IncreaseProgress();
   } else {   // 访问下一个目录
    // 添加要访问的目录

    if(m_DirStack.Count() >= STACK_DEPTH) {
     bResult = EFalse;
     m_nFinishReason = EFinishStackFull;
    } else {
     TBuf<KMaxPath> sBuf;
     sBuf.Append(buf->Des());
     sBuf.Append((*dirs)[m_Mark[sPath]].iName);
     sBuf.Append(_L("//"));   // - 这里要用//结尾,不然就当是文件
     m_DirStack.Append(sBuf.Alloc());
     m_Mark[sPath] ++;
     m_nFolderScanned ++;
    }
   }

   CleanupStack::PopAndDestroy(files);
   CleanupStack::PopAndDestroy(dirs);
  }

 } else {    // 未访问过,遍历文件与文件夹
  //TraceLog("new sPath %s/n", sPath.c_str());
  m_Mark[sPath] = 0;
  //TraceLog("test find %d %d/n", m_Mark.find(sPath) == m_Mark.end(), m_Mark[sPath]);

  CDir* dirs = NULL;
  CDir *files = NULL;
  //if(!buf->Compare(_L("e://PRIVATE//"))) { // TODO: 这里可以注释掉了
  // TraceLog("this is PRIVATE dir!!");
  //}
#ifdef __TUI_SUPPORTED__
  if(!buf->Compare(_L("c://resource//"))) {
   TraceLog("this is 5th c://resource// dir!!/n");
   delete m_DirStack[m_DirStack.Count()-1];
   m_DirStack.Remove(m_DirStack.Count()-1);
  } else {
#endif // __TUI_SUPPORTED__
   TInt nErr = iFs.GetDir(buf->Des(), KEntryAttNormal, ESortByName, files, dirs);
   if(nErr != KErrNone) {   // 这个文件夹访问出错
    //TraceLog(L"dir access error1 %s dir: %s/n", (TInt)nErr, buf->Des().Ptr());
    delete m_DirStack[m_DirStack.Count()-1];
    m_DirStack.Remove(m_DirStack.Count()-1);
   } else {
    CleanupStack::PushL(dirs);
    CleanupStack::PushL(files);

    //TraceLog("CScanFolderEngine start add files from " << buf->Des());
    TInt numberDirs = dirs->Count();
    TInt numberFiles = files->Count();
    //TraceLog("numberFiles %d/n", numberFiles);
    for(TInt a = 0; a < numberFiles; a++)
    {
     TraceLog("check file %d/n", a);
     const TEntry& file = (*files)[a];
     IncreaseProgress();  // 对于文件访问现在也会增加进度

     //TPtrC tptrRight = file.iName.Right(4);
     TBuf<KMaxPath> tbufLowerCase;
     //file.iName.Copy(tbufLowerCase, KMaxPath);
     tbufLowerCase.Append(file.iName.Ptr(), file.iName.Length());
     tbufLowerCase.LowerCase();
     TPtrC tptrRight = tbufLowerCase.Right(4);
     if(tptrRight.Compare(KFormatXxx()) && tptrRight.Compare(KFormatYyy()) && tptrRight.Compare(KFormatZzz())) {
      continue;
     }

     //TraceLog("add file " << file.iName);
     // 添加到列表
     //HBufC *sFilePath = file.iName.Alloc();
     //CleanupStack::PushL(sFilePath);

     TBuf<KMaxPath> sBuf;
     sBuf.Append(buf->Des());
     sBuf.Append(file.iName);
     HBufC *hTmp = sBuf.Alloc();
     CleanupStack::PushL(hTmp);
     StringW_t strFilePath = StringW_t(*hTmp);

     //StringW_t strFilePath = StringW_t(*sFilePath);
     m_pUIListContainer->DoAddItem(strFilePath, EFalse);   // 添加,但是先不写ini
     CleanupStack::PopAndDestroy(hTmp);
     //CleanupStack::PopAndDestroy(sFilePath);

     m_nFileAdded ++;
    }

    if(numberDirs) {
     // 添加第一个dir
     if(m_DirStack.Count() >= STACK_DEPTH) {
      bResult = EFalse;
      m_nFinishReason = EFinishStackFull;
     } else {
      TBuf<KMaxPath> sBuf;
      sBuf.Append(buf->Des());
      /// sBuf.Append(_L("//"));   - 列出的目录一定是//结尾的,这里不需要加了。
      sBuf.Append((*dirs)[0].iName);
      sBuf.Append(_L("//"));   // - 这里要用//结尾,不然就当是文件
      m_DirStack.Append(sBuf.Alloc());
      m_Mark[sPath] ++;
      m_nFolderScanned ++;
     }
    } else {   // 该目录没有子目录,出栈
     delete m_DirStack[m_DirStack.Count()-1];
     m_DirStack.Remove(m_DirStack.Count()-1);
     IncreaseProgress();
    }

    CleanupStack::PopAndDestroy(files);
    CleanupStack::PopAndDestroy(dirs);
   }  // end if access err
#ifdef __TUI_SUPPORTED__
  }  // end if skip
#endif // __TUI_SUPPORTED__
 }

 if(bResult == EFalse) {
  m_bFinished = ETrue;
 }
}

/**
* @brief 扫描文件夹下的文件
*/
void CScanFolderEngine::ScanFolderL( const TDesC &aRootPath )
{
 TraceLog("ScanFolder==========================================/n");
 // 初始化
 m_bFinished = EFalse;
 m_nFileAdded = 0;
 m_nFileScanned = 0;
 m_nFolderScanned = 0;
 iDestroyFlag = EFalse;
 iErrorFlag = EFalse;
 m_nFinishReason = EFinishSucc;
 m_nProgressNum = 0;
 m_nErrCount = 0;
 if(m_DirStack.Count()) {
  for(int i=0;i<m_DirStack.Count();++i) {
   delete m_DirStack[i];
  }
  m_DirStack.Reset();
 }  // TODO: 确定reset就释放了所有内存
 HBufC *bufPath = aRootPath.Alloc();  // TODO: 错误处理
 m_DirStack.Append(bufPath);
 m_Mark.clear();

 m_nIncreaseDir = 0;
 iProgressDialog = new (ELeave) CAknProgressDialog (reinterpret_cast<CEikDialog**>(&iProgressDialog));  //创建进度条框对象
#ifdef SDK_S60_3RD
 iProgressDialog->PrepareLC(R_PROGRESSNOTE_ADDING_FOLDER_NOTE_3RD);// 从资源中加载界面
#else
 iProgressDialog->PrepareLC(R_PROGRESSNOTE_ADDING_FOLDER_NOTE);// 从资源中加载界面
#endif // SDK_S60_3RD
 iProgressDialog->SetCallback (this); // calls DialogDismissL on completion
 CEikProgressInfo* progressBar = iProgressDialog->GetProgressInfoL(); // not taking ownership
 progressBar->SetFinalValue(KFinalValue);  // Set final value of progress bar
 iProgressDialog->RunLD(); // this doesn't actually delete the dialog despite the 'D' suffix
 //DoScan(); // make a synchronous request
 IncreaseProgress();
#ifdef USE_TIMER_WHEN_SCANNING
 iTimer.After(iStatus, KTimerStartDelay);
 SetActive(); // set the active object to be active
#else
 SetActive();
 TRequestStatus* status = &iStatus;
 User::RequestComplete( status, KErrNone );
#endif // USE_TIMER_WHEN_SCANNING
}

/**
* @brief 这里继续做文件夹扫描工作
*/
void CScanFolderEngine::RunL()
{
 TraceLog("RunL/n");
 if((iStatus == KErrNone) && !iDestroyFlag && !iErrorFlag) {
  TraceLog("iStatus ok/n");
  if (!IsProcessDone())
  {
   TraceLog("!IsProcessDone()/n");
   DoScan();
   //IncreaseProgress();
    SetActive();    // do scan里面会SetActive
#ifndef USE_TIMER_WHEN_SCANNING
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrNone );
#endif // USE_TIMER_WHEN_SCANNING
  }
  else
  {
   TraceLog("IsProcessDone/n");
   iProgressDialog->SetCallback(0);
   iProgressDialog->ProcessFinishedL();
   Final();
  }
 } else {
  TraceLog("not ok iStatus %d iDestroyFlag %d iErrorFlag %d/n", (int)iStatus.Int(), (int)iDestroyFlag, (int)iErrorFlag);
 }

 // 上次已经在Final里面设置destroy
 if(iDestroyFlag)
 {
  // 除非实在ExecuteLD里面运行这个AO才进行自我delete
  //if(iWait)
  // CAknEnv::StopSchedulerWaitWithBusyMessage(*iWait);
  //else
  // delete this;
 }
}

/**
 * @brief 如果RunL Leave了就 call该函数
 */
TInt CScanFolderEngine::RunError(TInt aError)
{
 TraceLog("RunError() %d/n", aError);
 iErrorFlag = ETrue;
 // since RunError() function may not leave we must trap
 TRAPD(error, iProgressDialog->ProcessFinishedL());

 if(error != KErrNone) {
  Final();

  HBufC* noteText;
  noteText = StringLoader::LoadLC(R_PROJECT_SOFTWARE_EXCEPTION);
  CAknErrorNote* note = new(ELeave)CAknErrorNote();
  note->ExecuteLD(*noteText);
  CleanupStack::PopAndDestroy(noteText);
 }

 return KErrNone;  // 表示已经处理了。
 //return aError;
}


/**
* @brief 取消文件夹扫描
*/
void CScanFolderEngine::DoCancel()
{
 TraceLog("DoCancel()/n");
 iTimer.Cancel();
}

/**
 * @brief 结束,保证再call一次RunL()
 * Since it is possible that this function is called when the class CProgressProcessor instance as active object is either active or inactive, it is necessary to ensure that function RunL() will be called once more.
 */
void CScanFolderEngine::Final()
{
 TraceLog("Final()/n");
 iDestroyFlag = ETrue;
 if(!IsActive())
 {
#ifdef USE_TIMER_WHEN_SCANNING
  iTimer.After(iStatus,0);
  SetActive();
#else
  SetActive();
  TRequestStatus* status = &iStatus;
  User::RequestComplete( status, KErrNone );
#endif // USE_TIMER_WHEN_SCANNING
 }
 else {
#ifdef USE_TIMER_WHEN_SCANNING
  iTimer.Cancel();
#endif // USE_TIMER_WHEN_SCANNING
 }

 CleanUpProgress();

}

/**
* @brief 进度条取消的callback
*/
void CScanFolderEngine::DialogDismissedL(TInt aButtonId)
{
 TraceLog("DialogDismissedL()/n");
 m_nFinishReason = EFinishUserCancel;
 if (!IsProcessDone())
 {
  CancelProgress();
 }
 else
 {
  CleanUpProgress();
 }

 //m_bFinished = EFalse;
 m_nFileAdded = 0;
 m_nFileScanned = 0;
 m_nFolderScanned = 0;
}

/**
* @brief 判断是否完成了扫描的处理
*/
TBool CScanFolderEngine::IsProcessDone() const
{
 //return m_nFolderScanned == 10;
 return m_bFinished;
}

/**
* @brief 取消扫描文件夹
*/
void CScanFolderEngine::CancelProgress()
{
 TraceLog("CancelProgress()/n");
 Cancel();

 CleanUpProgress();
}

/**
* @brief 取消或者正常完成扫描后的清除工作
*/
void CScanFolderEngine::CleanUpProgress()
{
 TraceLog("CleanUpProgress()/n");

 if(m_DirStack.Count()) {
  for(int i=0;i<m_DirStack.Count();++i) {
   delete m_DirStack[i];
  }
  m_DirStack.Reset();
 }

 // 写ini
 m_pUIListContainer->OnFinishScan(m_nFinishReason);
}

void CScanFolderEngine::IncreaseProgress()
{
 if(m_nIncreaseDir == 0) {
  if(m_nProgressNum + KIncrement <= 100) {
   m_nProgressNum += KIncrement;
   iProgressDialog->GetProgressInfoL()->SetAndDraw(m_nProgressNum);
  } else {
   m_nIncreaseDir = 1;
  }
 } else {
  if(m_nProgressNum - KIncrement >= 0) {
   m_nProgressNum -= KIncrement;
   iProgressDialog->GetProgressInfoL()->SetAndDraw(m_nProgressNum);
  } else {
   m_nIncreaseDir = 0;
  }
 }
 /*
 if(m_nProgressNum < 99) {
  iProgressDialog->GetProgressInfoL()->IncrementAndDraw(KIncrement); // increment the progress bar
  m_nProgressNum += KIncrement;
 }*/
}
#endif // USE_MINI_CORE

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值