OSDN Git Service

PATCH: [ 903670 ] Copy Folder (and convert to CShellFileOp)
authorKimmo Varis <kimmov@gmail.com>
Thu, 26 Feb 2004 12:39:52 +0000 (12:39 +0000)
committerKimmo Varis <kimmov@gmail.com>
Thu, 26 Feb 2004 12:39:52 +0000 (12:39 +0000)
Src/DirActions.cpp
Src/DirView.h
Src/MainFrm.cpp
Src/MainFrm.h
Src/readme.txt

index 63b7a38..e94b4b4 100644 (file)
@@ -287,7 +287,10 @@ void CDirView::ConfirmAndPerformActions(ActionList & actionList)
        PerformActionList(actionList);
 }
 
-// Confirm actions with user as appropriate (type, whether single or multiple)
+/**
+ * @brief Confirm actions with user as appropriate
+ * (type, whether single or multiple).
+ */
 BOOL CDirView::ConfirmActionList(const ActionList & actionList)
 {
        // special handling for the single item case, because it is probably the most common,
@@ -307,165 +310,198 @@ BOOL CDirView::ConfirmActionList(const ActionList & actionList)
                                return FALSE;
                }
                break;
-       default: // deletes
-               if (actionList.GetCount()==1 && actionList.atype!=ACT_DEL_BOTH)
-               {
-                       const action & act = actionList.actions.GetHead();
-                       if (!ConfirmSingleDelete(act.src))
-                               return FALSE;
-               }
-               else
-               {
-                       if (!ConfirmMultipleDelete(actionList.GetCount(), actionList.selcount))
-                               return FALSE;
-               }
+               
+       // Deleting does not need confirmation, CShellFileOp takes care of it
+       case ACT_DEL_LEFT:
+       case ACT_DEL_RIGHT:
+       case ACT_DEL_BOTH:
+               break;
+
+       // Invalid operation
+       default: 
+               LogErrorString(_T("Unknown fileoperation in CDirView::ConfirmActionList()"));
+               _RPTF0(_CRT_ERROR, "Unknown fileoperation in CDirView::ConfirmActionList()");
                break;
        }
        return TRUE;
 }
 
-// Perform an array of actions
+/**
+ * @brief Perform an array of actions
+ * @note There can be only COPY or DELETE actions, not both!
+ */
 void CDirView::PerformActionList(ActionList & actionList)
 {
+       CShellFileOp fileOp;
+       CString destPath;
+       CString startPath;
+       CString strErr;
+       UINT operation = 0;
+
        // Set mainframe variable (VSS):
        mf->m_CheckOutMulti = FALSE;
        mf->m_bVCProjSync = TRUE;
-
-       while (actionList.GetCount()>0)
+       
+       switch (actionList.atype)
        {
-               PerformAndRemoveTopAction(actionList);
+       case ACT_COPY:
+               operation = FO_COPY;
+               break;
+       case ACT_DEL_LEFT:
+               operation = FO_DELETE;
+               break;
+       case ACT_DEL_RIGHT:
+               operation = FO_DELETE;
+               break;
+       case ACT_DEL_BOTH:
+               operation = FO_DELETE;
+               break;
+       default:
+               LogErrorString(_T("Unknown fileoperation in CDirView::PerformActionList()"));
+               _RPTF0(_CRT_ERROR, "Unknown fileoperation in CDirView::PerformActionList()");
+               break;
        }
+       
+       // TODO: option for putting deleted items into recycle bin!
+       int operFlags = FOF_NOCONFIRMMKDIR | FOF_MULTIDESTFILES;
+       fileOp.SetOperationFlags(operation, this, operFlags);
+       
+       // Add files/directories
+       POSITION pos = actionList.actions.GetHeadPosition();
+       while (pos != NULL)
+       {
+               const action act = actionList.actions.GetNext(pos);
+               switch (actionList.atype)
+               {
+               case ACT_COPY:
+                       fileOp.AddSourceFile(act.src);
+                       fileOp.AddDestFile(act.dest);
+                       if (!act.dirflag)
+                       {
+                               mf->SyncFilesToVCS(act.src, act.dest, &strErr);
+                       }
+                       gLog.Write(_T("Copy file(s) from: %s\n\tto: %s"), act.src, act.dest);
+                       break;
+               case ACT_DEL_LEFT:
+                       fileOp.AddSourceFile(act.src);
+                       gLog.Write(_T("Delete file(s) from LEFT: %s"), act.src);
+                       break;
+               case ACT_DEL_RIGHT:
+                       fileOp.AddSourceFile(act.src);
+                       gLog.Write(_T("Delete file(s) from RIGHT: %s"), act.src);
+                       break;
+               case ACT_DEL_BOTH:
+                       fileOp.AddSourceFile(act.src);
+                       fileOp.AddSourceFile(act.dest);
+                       gLog.Write(_T("Delete BOTH file(s) from: %s\n\tto: %s"), act.src, act.dest);
+                       break;
+               }
+       } 
 
-       // must process deleted items in reverse order
-       // ie, work our way *up* the display list
-       // so we don't invalidate indices of items not done yet
-       while (!actionList.deletedItems.IsEmpty())
+       BOOL bOpStarted = FALSE;
+       int apiRetVal = 0;
+       BOOL bUserCancelled = FALSE; 
+       BOOL bFileOpSucceed = fileOp.Go(&bOpStarted, &apiRetVal, &bUserCancelled);
+
+       // All succeeded
+       if (bFileOpSucceed && !bUserCancelled)
        {
-               int idx = actionList.deletedItems.RemoveTail();
-               POSITION diffpos = GetItemKey(idx);
-               GetDiffContext()->RemoveDiff(diffpos);
-               m_pList->DeleteItem(idx);
+               gLog.Write(_T("Fileoperation succeeded."));
+               UpdateCopiedItems(actionList);
+               UpdateDeletedItems(actionList);
        }
-
-       if (!actionList.errors.IsEmpty())
+       else if (!bOpStarted)
        {
-               CString sTitle, sText;
-               AfxFormatString1(sTitle, IDS_ERRORS_TITLE, NumToStr(actionList.errors.GetCount()));
-               while (!actionList.errors.IsEmpty())
-               {
-                       sText += actionList.errors.RemoveHead() + _T("\r\n\r\n");
-               }
-               gLog.Write(LOGLEVEL::LERROR, sText);
-               OutputBox(sTitle, sText);
+               // Invalid parameters - is this programmer error only?
+               LogErrorString(_T("Invalid usage of CShellFileOp in "
+                       "CDirView::PerformActionList()"));
+               _RPTF0(_CRT_ERROR, "Invalid usage of CShellFileOp in "
+                       "CDirView::PerformActionList()");
+       }
+       else if (bUserCancelled)
+       {
+               // User cancelled, we have a problem as we don't know which
+               // items were processed!
+               // User could cancel operation before it was done or during operation
+               gLog.Write(LOGLEVEL::LWARNING, _T("User cancelled fileoperation!"));
+       }
+       else
+       {
+               // CShellFileOp shows errors to user, so just write log
+               LogErrorString(Fmt(_T("File operation failed: %s"),
+                       GetSysError(GetLastError())));
        }
 }
 
-static void NormalizeFilepath(CString * pstr)
-{
-       pstr->Replace('/', '\\');
-}
-
-void CDirView::PerformAndRemoveTopAction(ActionList & actionList)
+/**
+ * @brief Update copied items after fileactions
+ */
+void CDirView::UpdateCopiedItems(ActionList & actionList)
 {
-       action act = actionList.actions.RemoveHead();
-       if (actionList.atype == ACT_COPY)
+       while (actionList.GetCount()>0)
        {
-               // copy
-               if (act.dirflag)
+               action act = actionList.actions.RemoveHead();
+
+#ifdef _DEBUG
+               // Sometimes its nice to see flags...
+               POSITION diffpos = GetItemKey(act.idx);
+               const DIFFITEM & di = GetDiffContext()->GetDiffAt(diffpos);
+#endif
+
+               if (actionList.atype == ACT_COPY)
                {
-                       // TODO: copy directory
-                       // add new entries to an append list to be added to list at end
+                       // Copy files and folders
+                       CDirDoc *pDoc = GetDocument();
+                       pDoc->SetDiffSide(DIFFCODE::BOTH, act.idx);
+                       
+                       // Folders don't have compare flag set!!
+                       if (act.dirflag)
+                               pDoc->SetDiffCompare(DIFFCODE::NOCMP, act.idx);
+                       else
+                               pDoc->SetDiffCompare(DIFFCODE::SAME, act.idx);
+                       pDoc->ReloadItemStatus(act.idx);
                }
                else
                {
-                       CString s;
-                       // copy single file, and update status immediately
-                       if (mf->SyncFiles(act.src, act.dest, &s))
+                       // Delete files and folders
+                       CDirDoc *pDoc = GetDocument();
+                       if (actionList.atype == ACT_DEL_LEFT)
                        {
-                               GetDocument()->SetDiffSide(DIFFCODE::BOTH, act.idx);
-                               GetDocument()->SetDiffCompare(DIFFCODE::SAME, act.idx);
-                               GetDocument()->ReloadItemStatus(act.idx);
+                               pDoc->SetDiffSide(DIFFCODE::RIGHT, act.idx);
+                               pDoc->SetDiffCompare(DIFFCODE::NOCMP, act.idx);
+                               pDoc->ReloadItemStatus(act.idx);
                        }
-                       else
+                       
+                       if (actionList.atype == ACT_DEL_RIGHT)
                        {
-                               actionList.errors.AddTail(s);
+                               pDoc->SetDiffSide(DIFFCODE::LEFT, act.idx);
+                               pDoc->SetDiffCompare(DIFFCODE::NOCMP, act.idx);
+                               pDoc->ReloadItemStatus(act.idx);
                        }
-               }
-       }
-       else
-       {
-               // delete
-               if (act.dirflag)
-               {
-                       // delete directory
-                       CString s;
-                       if (DeleteDirSilently(act.src, &s))
+
+                       if (actionList.atype == ACT_DEL_BOTH)
                        {
-                               ASSERT(actionList.atype != ACT_DEL_BOTH); // directories are all unique
                                actionList.deletedItems.AddTail(act.idx);
                        }
-                       else
-                       {
-                               actionList.errors.AddTail(s);
-                       }
-               }
-               else
-               {
-                       // delete file
-                       CString s;
-                       if (actionList.atype==ACT_DEL_LEFT || actionList.atype==ACT_DEL_BOTH)
-                       {
-                               CString sFile = act.src;
-                               if (DeleteFileSilently(sFile, &s))
-                               {
-                                       // figure out if copy on right
-                                       POSITION diffpos = GetItemKey(act.idx);
-                                       const DIFFITEM & di = GetDiffContext()->GetDiffAt(diffpos);
-                                       if (di.isSideLeft())
-                                       {
-                                               actionList.deletedItems.AddTail(act.idx);
-                                       }
-                                       else
-                                       {
-                                               GetDocument()->SetDiffSide(DIFFCODE::RIGHT, act.idx);
-                                               GetDocument()->SetDiffCompare(DIFFCODE::NOCMP, act.idx);
-                                               GetDocument()->ReloadItemStatus(act.idx);
-                                       }
-                               }
-                               else
-                               {
-                                       actionList.errors.AddTail(s);
-                               }
-                       }
-                       s.Empty();
-                       if (actionList.atype==ACT_DEL_RIGHT || actionList.atype==ACT_DEL_BOTH)
-                       {
-                               CString sFile = act.dest.IsEmpty() ? act.src : act.dest;
-                               if (DeleteFileSilently(sFile, &s))
-                               {
-                                       // figure out if copy on right
-                                       POSITION diffpos = GetItemKey(act.idx);
-                                       const DIFFITEM & di = GetDiffContext()->GetDiffAt(diffpos);
-                                       if (di.isSideRight())
-                                       {
-                                               actionList.deletedItems.AddTail(act.idx);
-                                       }
-                                       else
-                                       {
-                                               GetDocument()->SetDiffSide(DIFFCODE::LEFT, act.idx);
-                                               GetDocument()->SetDiffCompare(DIFFCODE::NOCMP, act.idx);
-                                               GetDocument()->ReloadItemStatus(act.idx);
-                                       }
-                               }
-                               else
-                               {
-                                       actionList.errors.AddTail(s);
-                               }
-                       }
                }
        }
 }
 
+/**
+ * @brief Update deleted items after fileactions
+ */
+void CDirView::UpdateDeletedItems(ActionList & actionList)
+{
+       while (!actionList.deletedItems.IsEmpty())
+       {
+               int idx = actionList.deletedItems.RemoveTail();
+               POSITION diffpos = GetItemKey(idx);
+               GetDiffContext()->RemoveDiff(diffpos);
+               m_pList->DeleteItem(idx);
+       }
+
+}
+
 /// Get directories of first selected item
 BOOL CDirView::GetSelectedDirNames(CString& strLeft, CString& strRight) const
 {
@@ -484,8 +520,6 @@ BOOL CDirView::IsItemCopyableToLeft(const DIFFITEM & di)
 {
        // don't let them mess with error items
        if (di.isResultError()) return FALSE;
-       // no directory copying right now
-       if (di.isDirectory()) return FALSE;
        // can't copy same items
        if (di.isResultSame()) return FALSE;
        // impossible if only on left
@@ -499,8 +533,6 @@ BOOL CDirView::IsItemCopyableToRight(const DIFFITEM & di)
 {
        // don't let them mess with error items
        if (di.isResultError()) return FALSE;
-       // no directory copying right now
-       if (di.isDirectory()) return FALSE;
        // can't copy same items
        if (di.isResultSame()) return FALSE;
        // impossible if only on right
@@ -661,4 +693,3 @@ void CDirView::DoOpenWithEditor(SIDE_TYPE stype)
 
        mf->OpenFileToExternalEditor(file);
 }
-
index 21c75d5..15a7e82 100644 (file)
@@ -139,7 +139,8 @@ private:
        void ConfirmAndPerformActions(ActionList & actions);
        BOOL ConfirmActionList(const ActionList & actions);
        void PerformActionList(ActionList & actions);
-       void PerformAndRemoveTopAction(ActionList & actions);
+       void UpdateCopiedItems(ActionList & actions);
+       void UpdateDeletedItems(ActionList & actions);
 // End DirActions.cpp
 
 // Implementation in DirViewCols.cpp
index 286630e..cd58e0d 100644 (file)
@@ -1358,96 +1358,23 @@ BOOL CMainFrame::CreateBackup(LPCTSTR pszPath)
        return TRUE;
 }
 
-// trim trailing line returns
+/**
+ * @brief Trim trailing line returns.
+ */
 static void RemoveLineReturns(CString & str)
 {
        str.Remove('\n');
        str.Remove('\r');
 }
 
-// TODO: Can we move this into DirActions.cpp ?
-// Delete file (return TRUE if deleted, else put up error & return FALSE)
-BOOL CMainFrame::DeleteFileOrError(LPCTSTR szFile)
-{
-       if (!DeleteFile(szFile))
-       {
-               CString sError = GetSysError(GetLastError());
-               RemoveLineReturns(sError);
-               sError += (CString)_T(" [") + szFile + _T("]");
-               CString s;
-               AfxFormatString1(s, IDS_DELETE_FILE_FAILED, sError);
-               AfxMessageBox(s, MB_OK|MB_ICONSTOP);
-               return FALSE;
-       }
-       return TRUE;
-}
-
-// Delete file (return TRUE if successful, else sets error string & returns FALSE)
-BOOL DeleteFileSilently(LPCTSTR szFile, CString * psError)
-{
-       if (!DeleteFile(szFile))
-       {
-               CString sError = GetSysError(GetLastError());
-               RemoveLineReturns(sError);
-               AfxFormatString2(*psError, IDS_DELETE_FILE_FAILED, szFile, sError);
-               return FALSE;
-       }
-       return TRUE;
-}
-
-
-// delete directory by recursively deleting all contents
-// gives up on first error
-BOOL DeleteDirSilently(LPCTSTR szDir, CString * psError)
-{
-       CFileFind finder;
-       CString sSpec = szDir;
-       sSpec += _T("\\*.*");
-       if (finder.FindFile(sSpec))
-       {
-               BOOL done=FALSE;
-               while (!done)
-               {
-                       done = !finder.FindNextFile();
-                       if (finder.IsDots()) continue;
-                       if (finder.IsDirectory())
-                       {
-                               if (!DeleteDirSilently(finder.GetFilePath(), psError))
-                                       return FALSE;
-                       }
-                       else
-                       {
-                               if (!DeleteFileSilently(finder.GetFilePath(), psError))
-                                       return FALSE;
-                       }
-               }
-       }
-       finder.Close(); // must close the handle or RemoveDirectory will fail
-       if (!RemoveDirectory(szDir))
-       {
-               CString sError = GetSysError(GetLastError());
-               RemoveLineReturns(sError);
-               AfxFormatString2(*psError, IDS_DELETE_FILE_FAILED, szDir, sError);
-               return FALSE;
-       }
-       return TRUE;
-}
-
-// wrapper for DoSyncFiles which adds filename to error string reported
-BOOL CMainFrame::SyncFiles(LPCTSTR pszSrc, LPCTSTR pszDest, CString * psError)
-{
-       if (!DoSyncFiles(pszSrc, pszDest, psError))
-       {
-               CString msg;
-               AfxFormatString2(msg, IDS_COPY_FILE_FAILED, *psError, pszSrc);
-               *psError = msg;
-               return FALSE;
-       }
-       return TRUE;
-}
-
-// (error string reported does not include filename
-BOOL CMainFrame::DoSyncFiles(LPCTSTR pszSrc, LPCTSTR pszDest, CString * psError)
+/**
+ * @brief Sync file to Version Control System
+ * @param [in] pszSrc File to copy
+ * @param [in] pszDest Where to copy (incl. filename)
+ * @param [out] psError Error string that can be shown to user in caller func.
+ * Does not contain filename.
+ */
+BOOL CMainFrame::SyncFilesToVCS(LPCTSTR pszSrc, LPCTSTR pszDest, CString * psError)
 {
        CString sActionError;
        CString strSavePath(pszDest);
@@ -1464,13 +1391,6 @@ BOOL CMainFrame::DoSyncFiles(LPCTSTR pszSrc, LPCTSTR pszDest, CString * psError)
                return FALSE;
        }
        
-       // Now it's just a matter of copying the right file to the left
-       if (!CopyFile(pszSrc, strSavePath, FALSE))
-       {
-               *psError = GetSysError(GetLastError());
-               return FALSE;
-       }
-       
        // If VC project opened from VSS sync first
        if (m_bVCProjSync)
                return ReLinkVCProj(strSavePath, psError);
index 7786347..98c1b16 100644 (file)
@@ -80,8 +80,7 @@ public:
 // Operations
 public:
        BOOL DeleteFileOrError(LPCTSTR szFile);
-       BOOL SyncFiles(LPCTSTR pszSrc, LPCTSTR pszDest, CString * psError);
-       BOOL DoSyncFiles(LPCTSTR pszSrc, LPCTSTR pszDest, CString * psError);
+       BOOL SyncFilesToVCS(LPCTSTR pszSrc, LPCTSTR pszDest, CString * psError);
        BOOL DoFileOpen(LPCTSTR pszLeft = NULL, LPCTSTR pszRight = NULL,
                DWORD dwLeftFlags = 0, DWORD dwRightFlags = 0, BOOL bRecurse = FALSE);
        void ShowMergeDoc(CDirDoc * pDirDoc, LPCTSTR szLeft, LPCTSTR szRight, BOOL bROLeft, BOOL bRORight, int cpleft, int cpright, PackingInfo * infoUnpacker = NULL);
@@ -202,9 +201,6 @@ private:
 
 extern CMainFrame *mf;
 
-BOOL DeleteFileSilently(LPCTSTR szFile, CString * psError);
-BOOL DeleteDirSilently(LPCTSTR szDir, CString * psError);
-
 /////////////////////////////////////////////////////////////////////////////
 
 //{{AFX_INSERT_LOCATION}}
index 52bedf6..69d756d 100644 (file)
@@ -1,3 +1,7 @@
+2004-02-26 Kimmo
+ PATCH: [ 903670 ] Copy Folder (and convert to CShellFileOp)
+  Src: DirActions.cpp DirView.h MainFrm.cpp MainFrm.h
+
 2004-02-23 Kimmo
  PATCH: [ 902738 ] Two errors in resource (Whitespaces and Hilight)
   Also RFE [ 837773 ] fix all about boxes