From: sdottaka Date: Sun, 4 Aug 2013 21:43:22 +0000 (+0900) Subject: Add DirItemIterator.h and use it X-Git-Tag: 2.16.4+-jp-10~1007 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=a02ed1011d05df47abf3d8563adec5045e28eb78;p=winmerge-jp%2Fwinmerge-jp.git Add DirItemIterator.h and use it --- diff --git a/Src/7zCommon.cpp b/Src/7zCommon.cpp index fc29e809f..32a7c5e18 100644 --- a/Src/7zCommon.cpp +++ b/Src/7zCommon.cpp @@ -104,6 +104,7 @@ DATE: BY: DESCRIPTION: #include "DirDoc.h" #include "MainFrm.h" #include "7zCommon.h" +#include "DirActions.h" //#include "ExternalArchiveFormat.h" #include "version.h" #include @@ -1092,7 +1093,7 @@ void CDirView::DirItemEnumerator::CollectFiles(String &strBuffer) for (i = Open() ; i-- ; ) { const DIFFITEM &di = Next(); - if (m_bRight ? m_pView->IsItemOpenableOnRightWith(di) : m_pView->IsItemOpenableOnLeftWith(di)) + if (m_bRight ? IsItemOpenableOnRightWith(di) : IsItemOpenableOnLeftWith(di)) { cchBuffer += ( @@ -1105,7 +1106,7 @@ void CDirView::DirItemEnumerator::CollectFiles(String &strBuffer) for (i = Open() ; i-- ; ) { const DIFFITEM &di = Next(); - if (m_bRight ? m_pView->IsItemOpenableOnRightWith(di) : m_pView->IsItemOpenableOnLeftWith(di)) + if (m_bRight ? IsItemOpenableOnRightWith(di) : IsItemOpenableOnLeftWith(di)) { pchBuffer += wsprintf ( diff --git a/Src/DirActions.cpp b/Src/DirActions.cpp index 95c109523..6f9de04bb 100644 --- a/Src/DirActions.cpp +++ b/Src/DirActions.cpp @@ -16,6 +16,7 @@ // #include "stdafx.h" +#include "DirActions.h" #include "Merge.h" #include "UnicodeString.h" #include "DirView.h" @@ -34,6 +35,8 @@ #include "FileOrFolderSelect.h" #include "ConfirmFolderCopyDlg.h" #include "SourceControl.h" +#include "DirItemIterator.h" +#include "IListCtrlImpl.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -228,7 +231,7 @@ static bool CheckPathsExist(const String& orig, const String& dest, int allowOri * @brief Format warning message about invalid folder compare contents. * @param [in] failedPath Path that failed (didn't exist). */ -void CDirView::WarnContentsChanged(const String & failedPath) +static void WarnContentsChanged(const String & failedPath) { String msg = string_format_string1( _("Operation aborted!\n\nFolder contents at disks has changed, path\n%1\nwas not found.\n\nPlease refresh the compare."), @@ -236,233 +239,188 @@ void CDirView::WarnContentsChanged(const String & failedPath) AfxMessageBox(msg.c_str(), MB_ICONWARNING); } -/// Prompt & copy item from right to left, if legal -void CDirView::DoCopyRightToLeft() +struct ContentsChangedException { - WaitStatusCursor waitstatus(_("Copying files...")); + ContentsChangedException(const String& failpath) : m_failpath(failpath) {} + String m_failpath; +}; - // First we build a list of desired actions - FileActionScript actionScript; - int sel = -1; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) +struct CopyRightToLeftFunctor +{ + CopyRightToLeftFunctor(const CDiffContext *pctxt, FileActionScript& actionScript) : m_pctxt(pctxt), m_actionScript(actionScript) {} + + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemCopyableToLeft(di)) { FileActionItem act; - GetItemFileNames(sel, act.dest, act.src); + ::GetItemFileNames(m_pctxt, di, act.dest, act.src); // We must check that paths still exists String failpath; - bool succeed = CheckPathsExist(act.src, act.dest, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (!CheckPathsExist(act.src, act.dest, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); - act.context = sel; + act.context = it.first; act.dirflag = di.diffcode.isDirectory(); act.atype = FileAction::ACT_COPY; act.UIResult = FileActionItem::UI_SYNC; act.UIOrigin = FileActionItem::UI_RIGHT; act.UIDestination = FileActionItem::UI_LEFT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} + const CDiffContext *m_pctxt; + FileActionScript& m_actionScript; +}; -/// Prompt & copy item from left to right, if legal -void CDirView::DoCopyLeftToRight() +struct CopyLeftToRightFunctor { - WaitStatusCursor waitstatus(_("Copying files...")); + CopyLeftToRightFunctor(const CDiffContext *pctxt, FileActionScript& actionScript) : m_pctxt(pctxt), m_actionScript(actionScript) {} - // First we build a list of desired actions - FileActionScript actionScript; - int sel = -1; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemCopyableToRight(di)) { FileActionItem act; - GetItemFileNames(sel, act.src, act.dest); + ::GetItemFileNames(m_pctxt, di, act.src, act.dest); // We must first check that paths still exists String failpath; - bool succeed = CheckPathsExist(act.src, act.dest, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(act.src, act.dest, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); - act.context = sel; + act.context = it.first; act.dirflag = di.diffcode.isDirectory(); act.atype = FileAction::ACT_COPY; act.UIResult = FileActionItem::UI_SYNC; act.UIOrigin = FileActionItem::UI_LEFT; act.UIDestination = FileActionItem::UI_RIGHT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} + const CDiffContext *m_pctxt; + FileActionScript& m_actionScript; +}; -/// Prompt & delete left, if legal -void CDirView::DoDelLeft() + +struct DelLeftFunctor { - WaitStatusCursor waitstatus(_("Deleting files...")); + DelLeftFunctor(const CDiffContext *pctxt, FileActionScript& actionScript) : m_pctxt(pctxt), m_actionScript(actionScript) {} - // First we build a list of desired actions - FileActionScript actionScript; - int sel=-1; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemDeletableOnLeft(di)) { String dmy; FileActionItem act; - GetItemFileNames(sel, act.src, dmy); + GetItemFileNames(m_pctxt, di, act.src, dmy); // We must check that path still exists String failpath; - bool succeed = CheckPathsExist(act.src, dmy, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(act.src, dmy, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); - act.context = sel; + act.context = it.first; act.dirflag = di.diffcode.isDirectory(); act.atype = FileAction::ACT_DEL; act.UIResult = FileActionItem::UI_DEL_LEFT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} -/// Prompt & delete right, if legal -void CDirView::DoDelRight() + const CDiffContext *m_pctxt; + FileActionScript& m_actionScript; +}; + + +struct DelRightFunctor { - WaitStatusCursor waitstatus(_("Deleting files...")); + DelRightFunctor(const CDiffContext *pctxt, FileActionScript& actionScript) : m_pctxt(pctxt), m_actionScript(actionScript) {} - // First we build a list of desired actions - FileActionScript actionScript; - int sel = -1; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); - + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemDeletableOnRight(di)) { FileActionItem act; String dmy; - GetItemFileNames(sel, dmy, act.src); + GetItemFileNames(m_pctxt, di, dmy, act.src); // We must first check that path still exists String failpath; - bool succeed = CheckPathsExist(act.src, dmy, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(act.src, dmy, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); - act.context = sel; + act.context = it.first; act.dirflag = di.diffcode.isDirectory(); act.atype = FileAction::ACT_DEL; act.UIResult = FileActionItem::UI_DEL_RIGHT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} + const CDiffContext *m_pctxt; + FileActionScript& m_actionScript; +}; -/** - * @brief Prompt & delete both, if legal. - */ -void CDirView::DoDelBoth() +struct DelBothFunctor { - WaitStatusCursor waitstatus(_("Deleting files...")); + DelBothFunctor(const CDiffContext *pctxt, FileActionScript& actionScript) : m_pctxt(pctxt), m_actionScript(actionScript) {} - // First we build a list of desired actions - FileActionScript actionScript; - int sel = -1; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemDeletableOnBoth(di)) { FileActionItem act; - GetItemFileNames(sel, act.dest, act.src); + ::GetItemFileNames(m_pctxt, di, act.dest, act.src); // We must first check that paths still exists String failpath; - bool succeed = CheckPathsExist(act.src, act.dest, ALLOW_ALL, - ALLOW_ALL, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(act.src, act.dest, ALLOW_ALL, + ALLOW_ALL, failpath)) + throw ContentsChangedException(failpath); - act.context = sel; + act.context = it.first; act.dirflag = di.diffcode.isDirectory(); act.atype = FileAction::ACT_DEL; act.UIResult = FileActionItem::UI_DEL_BOTH; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} -/** - * @brief Delete left, right or both items. - * @note Usually we don't need to check for read-only in this level of code. - * Usually we can disable handling read-only items/sides by disabling GUI - * element. But in this case the GUI element effects to both sides and can - * be selected when another side is read-only. - */ -void CDirView::DoDelAll() + const CDiffContext *m_pctxt; + FileActionScript& m_actionScript; +}; + +struct DelAllFunctor { - WaitStatusCursor waitstatus(_("Deleting files...")); + DelAllFunctor(const CDiffContext *pctxt, bool leftRO, bool rightRO, FileActionScript& actionScript) : + m_pctxt(pctxt), m_leftRO(leftRO), m_rightRO(rightRO), m_actionScript(actionScript) {} - // First we build a list of desired actions - FileActionScript actionScript; - int sel = -1; - String slFile, srFile; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); - + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0) { - GetItemFileNames(sel, slFile, srFile); + String slFile, srFile; + GetItemFileNames(m_pctxt, di, slFile, srFile); int leftFlags = ALLOW_DONT_CARE; int rightFlags = ALLOW_DONT_CARE; - bool leftRO = GetDocument()->GetReadOnly(true); - bool rightRO = GetDocument()->GetReadOnly(false); FileActionItem act; - if (IsItemDeletableOnBoth(di) && !leftRO && !rightRO) + if (IsItemDeletableOnBoth(di) && !m_leftRO && !m_rightRO) { leftFlags = ALLOW_ALL; rightFlags = ALLOW_ALL; @@ -470,13 +428,13 @@ void CDirView::DoDelAll() act.dest = slFile; act.UIResult = FileActionItem::UI_DEL_BOTH; } - else if (IsItemDeletableOnLeft(di) && !leftRO) + else if (IsItemDeletableOnLeft(di) && !m_leftRO) { leftFlags = ALLOW_ALL; act.src = slFile; act.UIResult = FileActionItem::UI_DEL_LEFT; } - else if (IsItemDeletableOnRight(di) && !rightRO) + else if (IsItemDeletableOnRight(di) && !m_rightRO) { rightFlags = ALLOW_ALL; act.src = srFile; @@ -488,258 +446,332 @@ void CDirView::DoDelAll() { // We must first check that paths still exists String failpath; - bool succeed = CheckPathsExist(slFile, srFile, leftFlags, - rightFlags, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(slFile, srFile, leftFlags, + rightFlags, failpath)) + throw ContentsChangedException(failpath); act.dirflag = di.diffcode.isDirectory(); - act.context = sel; + act.context = it.first; act.atype = FileAction::ACT_DEL; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} + bool m_leftRO, m_rightRO; + const CDiffContext *m_pctxt; + FileActionScript& m_actionScript; +}; -/** - * @brief Copy selected left-side files to user-specified directory - * - * When copying files from recursive compare file subdirectory is also - * read so directory structure is preserved. - */ -void CDirView::DoCopyLeftTo() +struct CopyLeftToFunctor { - String destPath; - String startPath(m_lastCopyFolder); - - if (!SelectFolder(destPath, startPath.c_str(), _("Left side - select destination folder:"))) - return; - - m_lastCopyFolder = destPath; - WaitStatusCursor waitstatus(_("Copying files...")); + CopyLeftToFunctor(const CDiffContext *pctxt, const String& destPath, FileActionScript& actionScript) : + m_pctxt(pctxt), m_destPath(destPath), m_actionScript(actionScript) {} - FileActionScript actionScript; - int sel = -1; - String slFile, srFile; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemCopyableToOnLeft(di)) { - GetItemFileNames(sel, slFile, srFile); + String slFile, srFile; + GetItemFileNames(m_pctxt, di, slFile, srFile); // We must check that path still exists String failpath; - bool succeed = CheckPathsExist(slFile, srFile, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(slFile, srFile, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); FileActionItem act; - String sFullDest = paths_AddTrailingSlash(destPath); + String sFullDest = paths_AddTrailingSlash(m_destPath); - actionScript.m_destBase = sFullDest; + m_actionScript.m_destBase = sFullDest; sFullDest += di.diffFileInfo[0].filename; act.dest = sFullDest; act.src = slFile; act.dirflag = di.diffcode.isDirectory(); - act.context = sel; + act.context = it.first; act.atype = FileAction::ACT_COPY; act.UIResult = FileActionItem::UI_DONT_CARE; act.UIOrigin = FileActionItem::UI_LEFT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} - -/** - * @brief Copy selected righ-side files to user-specified directory - * - * When copying files from recursive compare file subdirectory is also - * read so directory structure is preserved. - */ -void CDirView::DoCopyRightTo() -{ - String destPath; - String startPath(m_lastCopyFolder); - if (!SelectFolder(destPath, startPath.c_str(), _("Right side - select destination folder:"))) - return; + const CDiffContext *m_pctxt; + String m_destPath; + FileActionScript& m_actionScript; +}; - m_lastCopyFolder = destPath; - WaitStatusCursor waitstatus(_("Copying files...")); +struct CopyRightToFunctor +{ + CopyRightToFunctor(const CDiffContext *pctxt, const String& destPath, FileActionScript& actionScript) : + m_pctxt(pctxt), m_destPath(destPath), m_actionScript(actionScript) {} - FileActionScript actionScript; - int sel = -1; - String slFile, srFile; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemCopyableToOnRight(di)) { - GetItemFileNames(sel, slFile, srFile); + String slFile, srFile; + + ::GetItemFileNames(m_pctxt, di, slFile, srFile); // We must check that path still exists String failpath; - bool succeed = CheckPathsExist(srFile, slFile, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(srFile, slFile, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); FileActionItem act; - String sFullDest = paths_AddTrailingSlash(destPath); + String sFullDest = paths_AddTrailingSlash(m_destPath); - actionScript.m_destBase = sFullDest; + m_actionScript.m_destBase = sFullDest; sFullDest += di.diffFileInfo[1].filename; act.dest = sFullDest; act.src = srFile; act.dirflag = di.diffcode.isDirectory(); - act.context = sel; + act.context = it.first; act.atype = FileAction::ACT_COPY; act.UIResult = FileActionItem::UI_DONT_CARE; act.UIOrigin = FileActionItem::UI_RIGHT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} - -/** - * @brief Move selected left-side files to user-specified directory - * - * When moving files from recursive compare file subdirectory is also - * read so directory structure is preserved. - */ -void CDirView::DoMoveLeftTo() -{ - String destPath; - String startPath(m_lastCopyFolder); - if (!SelectFolder(destPath, startPath.c_str(), _("Left side - select destination folder:"))) - return; + const CDiffContext *m_pctxt; + String m_destPath; + FileActionScript& m_actionScript; +}; - m_lastCopyFolder = destPath; - WaitStatusCursor waitstatus(_("Moving files...")); +struct MoveLeftToFunctor +{ + MoveLeftToFunctor(const CDiffContext *pctxt, const String& destPath, FileActionScript& actionScript) : + m_pctxt(pctxt), m_destPath(destPath), m_actionScript(actionScript) {} - FileActionScript actionScript; - int sel = -1; - String slFile, srFile; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemCopyableToOnLeft(di) && IsItemDeletableOnLeft(di)) { - GetItemFileNames(sel, slFile, srFile); + String slFile, srFile; + ::GetItemFileNames(m_pctxt, di, slFile, srFile); // We must check that path still exists String failpath; - bool succeed = CheckPathsExist(slFile, srFile, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(slFile, srFile, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); FileActionItem act; - String sFullDest = paths_AddTrailingSlash(destPath); - actionScript.m_destBase = sFullDest; + String sFullDest = paths_AddTrailingSlash(m_destPath); + m_actionScript.m_destBase = sFullDest; sFullDest += di.diffFileInfo[0].filename; act.dest = sFullDest; act.src = slFile; act.dirflag = di.diffcode.isDirectory(); - act.context = sel; + act.context = it.first; act.atype = FileAction::ACT_MOVE; act.UIOrigin = FileActionItem::UI_LEFT; act.UIResult = FileActionItem::UI_DEL_LEFT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); -} -/** - * @brief Move selected right-side files to user-specified directory - * - * When moving files from recursive compare file subdirectory is also - * read so directory structure is preserved. - */ -void CDirView::DoMoveRightTo() -{ - String destPath; - String startPath(m_lastCopyFolder); + const CDiffContext *m_pctxt; + String m_destPath; + FileActionScript& m_actionScript; +}; - if (!SelectFolder(destPath, startPath.c_str(), _("Right side - select destination folder:"))) - return; - - m_lastCopyFolder = destPath; - WaitStatusCursor waitstatus(_("Moving files...")); +struct MoveRightToFunctor +{ + MoveRightToFunctor(const CDiffContext *pctxt, const String& destPath, FileActionScript& actionScript) : + m_pctxt(pctxt), m_destPath(destPath), m_actionScript(actionScript) {} - FileActionScript actionScript; - int sel = -1; - String slFile, srFile; - while ((sel = m_pList->GetNextItem(sel, LVNI_SELECTED)) != -1) + void operator()(const std::pair it) { - const DIFFITEM& di = GetDiffItem(sel); + const DIFFITEM& di = *it.second; if (di.diffcode.diffcode != 0 && IsItemCopyableToOnRight(di) && IsItemDeletableOnRight(di)) { - GetItemFileNames(sel, slFile, srFile); + String slFile, srFile; + ::GetItemFileNames(m_pctxt, di, slFile, srFile); // We must check that path still exists String failpath; - bool succeed = CheckPathsExist(srFile, slFile, ALLOW_ALL, - ALLOW_DONT_CARE, failpath); - if (succeed == false) - { - WarnContentsChanged(failpath); - return; - } + if (CheckPathsExist(srFile, slFile, ALLOW_ALL, + ALLOW_DONT_CARE, failpath)) + throw ContentsChangedException(failpath); FileActionItem act; - String sFullDest = paths_AddTrailingSlash(destPath); - actionScript.m_destBase = sFullDest; + String sFullDest = paths_AddTrailingSlash(m_destPath); + m_actionScript.m_destBase = sFullDest; sFullDest += di.diffFileInfo[1].filename; act.dest = sFullDest; act.src = srFile; act.dirflag = di.diffcode.isDirectory(); - act.context = sel; + act.context = it.first; act.atype = FileAction::ACT_MOVE; act.UIOrigin = FileActionItem::UI_RIGHT; act.UIResult = FileActionItem::UI_DEL_RIGHT; - actionScript.AddActionItem(act); + m_actionScript.AddActionItem(act); } } - // Now we prompt, and execute actions - ConfirmAndPerformActions(actionScript); + + const CDiffContext *m_pctxt; + String m_destPath; + FileActionScript& m_actionScript; +}; + +template +void CDirView::DoDirAction(const String& status_message) +{ + WaitStatusCursor waitstatus(status_message); + + try { + // First we build a list of desired actions + FileActionScript actionScript; + std::for_each(SelectedDirItemIterator(&IListCtrlImpl(m_pList->m_hWnd)), SelectedDirItemIterator(), + Functor(&GetDocument()->GetDiffContext(), actionScript)); + // Now we prompt, and execute actions + ConfirmAndPerformActions(actionScript); + } catch (ContentsChangedException& e) { + WarnContentsChanged(e.m_failpath); + } +} + +template +void CDirView::DoDirActionTo(const String& status_message, const String& selectfolder_title) +{ + String destPath; + String startPath(m_lastCopyFolder); + + if (!SelectFolder(destPath, startPath.c_str(), selectfolder_title)) + return; + + m_lastCopyFolder = destPath; + WaitStatusCursor waitstatus(status_message); + + try { + // First we build a list of desired actions + FileActionScript actionScript; + std::for_each(SelectedDirItemIterator(&IListCtrlImpl(m_pList->m_hWnd)), SelectedDirItemIterator(), + Functor(&GetDocument()->GetDiffContext(), destPath, actionScript)); + // Now we prompt, and execute actions + ConfirmAndPerformActions(actionScript); + } catch (ContentsChangedException& e) { + WarnContentsChanged(e.m_failpath); + } +} + +/// Prompt & copy item from right to left, if legal +void CDirView::DoCopyRightToLeft() +{ + DoDirAction(_("Copying files...")); +} + +/// Prompt & copy item from left to right, if legal +void CDirView::DoCopyLeftToRight() +{ + DoDirAction(_("Copying files...")); +} + +/// Prompt & delete left, if legal +void CDirView::DoDelLeft() +{ + DoDirAction(_("Deleting files...")); +} + +/// Prompt & delete right, if legal +void CDirView::DoDelRight() +{ + DoDirAction(_("Deleting files...")); +} + +/** + * @brief Prompt & delete both, if legal. + */ +void CDirView::DoDelBoth() +{ + DoDirAction(_("Deleting files...")); +} + +/** + * @brief Delete left, right or both items. + * @note Usually we don't need to check for read-only in this level of code. + * Usually we can disable handling read-only items/sides by disabling GUI + * element. But in this case the GUI element effects to both sides and can + * be selected when another side is read-only. + */ +void CDirView::DoDelAll() +{ + WaitStatusCursor waitstatus(_("Deleting files...")); + + try { + // First we build a list of desired actions + FileActionScript actionScript; + std::for_each(SelectedDirItemIterator(&IListCtrlImpl(m_pList->m_hWnd)), SelectedDirItemIterator(), + DelAllFunctor(&GetDocument()->GetDiffContext(), GetDocument()->GetReadOnly(0), GetDocument()->GetReadOnly(1), actionScript)); + // Now we prompt, and execute actions + ConfirmAndPerformActions(actionScript); + } catch (ContentsChangedException& e) { + WarnContentsChanged(e.m_failpath); + } +} + +/** + * @brief Copy selected left-side files to user-specified directory + * + * When copying files from recursive compare file subdirectory is also + * read so directory structure is preserved. + */ +void CDirView::DoCopyLeftTo() +{ + DoDirActionTo(_("Copying files..."), _("Left side - select destination folder:")); +} + +/** + * @brief Copy selected righ-side files to user-specified directory + * + * When copying files from recursive compare file subdirectory is also + * read so directory structure is preserved. + */ +void CDirView::DoCopyRightTo() +{ + DoDirActionTo(_("Copying files..."), _("Right side - select destination folder:")); +} + +/** + * @brief Move selected left-side files to user-specified directory + * + * When moving files from recursive compare file subdirectory is also + * read so directory structure is preserved. + */ +void CDirView::DoMoveLeftTo() +{ + DoDirActionTo(_("Moving files..."), _("Left side - select destination folder:")); +} + +/** + * @brief Move selected right-side files to user-specified directory + * + * When moving files from recursive compare file subdirectory is also + * read so directory structure is preserved. + */ +void CDirView::DoMoveRightTo() +{ + DoDirActionTo(_("Moving files..."), _("Right side - select destination folder:")); } // Confirm with user, then perform the action list @@ -1009,7 +1041,7 @@ bool CDirView::GetSelectedDirNames(String& strLeft, String& strRight) const } /// is it possible to copy item to left ? -bool CDirView::IsItemCopyableToLeft(const DIFFITEM & di) const +bool IsItemCopyableToLeft(const DIFFITEM & di) { // don't let them mess with error items if (di.diffcode.isResultError()) return false; @@ -1022,7 +1054,7 @@ bool CDirView::IsItemCopyableToLeft(const DIFFITEM & di) const return true; } /// is it possible to copy item to right ? -bool CDirView::IsItemCopyableToRight(const DIFFITEM & di) const +bool IsItemCopyableToRight(const DIFFITEM & di) { // don't let them mess with error items if (di.diffcode.isResultError()) return false; @@ -1035,7 +1067,7 @@ bool CDirView::IsItemCopyableToRight(const DIFFITEM & di) const return true; } /// is it possible to delete left item ? -bool CDirView::IsItemDeletableOnLeft(const DIFFITEM & di) const +bool IsItemDeletableOnLeft(const DIFFITEM & di) { // don't let them mess with error items if (di.diffcode.isResultError()) return false; @@ -1045,7 +1077,7 @@ bool CDirView::IsItemDeletableOnLeft(const DIFFITEM & di) const return true; } /// is it possible to delete right item ? -bool CDirView::IsItemDeletableOnRight(const DIFFITEM & di) const +bool IsItemDeletableOnRight(const DIFFITEM & di) { // don't let them mess with error items if (di.diffcode.isResultError()) return false; @@ -1056,7 +1088,7 @@ bool CDirView::IsItemDeletableOnRight(const DIFFITEM & di) const return true; } /// is it possible to delete both items ? -bool CDirView::IsItemDeletableOnBoth(const DIFFITEM & di) const +bool IsItemDeletableOnBoth(const DIFFITEM & di) { // don't let them mess with error items if (di.diffcode.isResultError()) return false; @@ -1075,9 +1107,9 @@ bool CDirView::IsItemDeletableOnBoth(const DIFFITEM & di) const * @param [in] di DIFFITEM for item to check. * @return true if the item can be opened, false otherwise. */ -bool CDirView::IsItemOpenable(const DIFFITEM & di) const +bool IsItemOpenable(const CDiffContext *pctx, const DIFFITEM & di, bool treemode) { - if (m_bTreeMode && GetDocument()->GetRecursive()) + if (treemode && pctx->m_bRecursive) { if (di.diffcode.isDirectory() || (!di.diffcode.isExistsFirst() || !di.diffcode.isExistsSecond())) /* FIXME: 3-pane */ @@ -1145,11 +1177,11 @@ bool CDirView::AreItemsOpenable(SELECTIONTYPE selectionType, const DIFFITEM & di return false; } /// is it possible to compare these three items? -bool CDirView::AreItemsOpenable(const DIFFITEM & di1, const DIFFITEM & di2, const DIFFITEM & di3) const +bool AreItemsOpenable(const CDiffContext *pctxt, const DIFFITEM & di1, const DIFFITEM & di2, const DIFFITEM & di3) { - String sLeftBasePath = GetDocument()->GetBasePath(0); - String sMiddleBasePath = GetDocument()->GetBasePath(1); - String sRightBasePath = GetDocument()->GetBasePath(2); + String sLeftBasePath = pctxt->GetPath(0); + String sMiddleBasePath = pctxt->GetPath(1); + String sRightBasePath = pctxt->GetPath(2); String sLeftPath1 = paths_ConcatPath(di1.getFilepath(0, sLeftBasePath), di1.diffFileInfo[0].filename); String sLeftPath2 = paths_ConcatPath(di2.getFilepath(0, sLeftBasePath), di2.diffFileInfo[0].filename); String sLeftPath3 = paths_ConcatPath(di3.getFilepath(0, sLeftBasePath), di3.diffFileInfo[0].filename); @@ -1203,7 +1235,7 @@ bool CDirView::AreItemsOpenable(const DIFFITEM & di1, const DIFFITEM & di2, cons return false; } /// is it possible to open left item ? -bool CDirView::IsItemOpenableOnLeft(const DIFFITEM & di) const +bool IsItemOpenableOnLeft(const DIFFITEM & di) { // impossible if only on right if (di.diffcode.isSideSecondOnly()) return false; @@ -1212,7 +1244,7 @@ bool CDirView::IsItemOpenableOnLeft(const DIFFITEM & di) const return true; } /// is it possible to open right item ? -bool CDirView::IsItemOpenableOnRight(const DIFFITEM & di) const +bool IsItemOpenableOnRight(const DIFFITEM & di) { // impossible if only on left if (di.diffcode.isSideFirstOnly()) return false; @@ -1221,17 +1253,17 @@ bool CDirView::IsItemOpenableOnRight(const DIFFITEM & di) const return true; } /// is it possible to open left ... item ? -bool CDirView::IsItemOpenableOnLeftWith(const DIFFITEM & di) const +bool IsItemOpenableOnLeftWith(const DIFFITEM & di) { return (!di.diffcode.isDirectory() && IsItemOpenableOnLeft(di)); } /// is it possible to open with ... right item ? -bool CDirView::IsItemOpenableOnRightWith(const DIFFITEM & di) const +bool IsItemOpenableOnRightWith(const DIFFITEM & di) { return (!di.diffcode.isDirectory() && IsItemOpenableOnRight(di)); } /// is it possible to copy to... left item? -bool CDirView::IsItemCopyableToOnLeft(const DIFFITEM & di) const +bool IsItemCopyableToOnLeft(const DIFFITEM & di) { // impossible if only on right if (di.diffcode.isSideSecondOnly()) return false; @@ -1240,7 +1272,7 @@ bool CDirView::IsItemCopyableToOnLeft(const DIFFITEM & di) const return true; } /// is it possible to copy to... right item? -bool CDirView::IsItemCopyableToOnRight(const DIFFITEM & di) const +bool IsItemCopyableToOnRight(const DIFFITEM & di) { // impossible if only on left if (di.diffcode.isSideFirstOnly()) return false; @@ -1269,6 +1301,20 @@ String CDirView::GetSelectedFileName(SIDE_TYPE stype) const * @brief Get the file names on both sides for specified item. * @note Return empty strings if item is special item. */ +void GetItemFileNames(const CDiffContext* pctx, const DIFFITEM & di, String& strLeft, String& strRight) +{ + const String leftrelpath = paths_ConcatPath(di.diffFileInfo[0].path, di.diffFileInfo[0].filename); + const String rightrelpath = paths_ConcatPath(di.diffFileInfo[1].path, di.diffFileInfo[1].filename); + const String & leftpath = pctx->GetPath(0); + const String & rightpath = pctx->GetPath(1); + strLeft = paths_ConcatPath(leftpath, leftrelpath); + strRight = paths_ConcatPath(rightpath, rightrelpath); +} + +/** + * @brief Get the file names on both sides for specified item. + * @note Return empty strings if item is special item. + */ void CDirView::GetItemFileNames(int sel, String& strLeft, String& strRight) const { UINT_PTR diffpos = GetItemKey(sel); @@ -1279,13 +1325,17 @@ void CDirView::GetItemFileNames(int sel, String& strLeft, String& strRight) cons } else { - const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos); - const String leftrelpath = paths_ConcatPath(di.diffFileInfo[0].path, di.diffFileInfo[0].filename); - const String rightrelpath = paths_ConcatPath(di.diffFileInfo[1].path, di.diffFileInfo[1].filename); - const String & leftpath = GetDocument()->GetBasePath(0); - const String & rightpath = GetDocument()->GetBasePath(1); - strLeft = paths_ConcatPath(leftpath, leftrelpath); - strRight = paths_ConcatPath(rightpath, rightrelpath); + ::GetItemFileNames(&GetDocument()->GetDiffContext(), GetDocument()->GetDiffByKey(diffpos), strLeft, strRight); + } +} + +void GetItemFileNames(const CDiffContext *pctxt, const DIFFITEM & di, PathContext * paths) +{ + for (int nIndex = 0; nIndex < pctxt->GetCompareDirs(); nIndex++) + { + const String relpath = paths_ConcatPath(di.diffFileInfo[nIndex].path, di.diffFileInfo[nIndex].filename); + const String & path = pctxt->GetPath(nIndex); + paths->SetPath(nIndex, paths_ConcatPath(path, relpath)); } } @@ -1304,13 +1354,7 @@ void CDirView::GetItemFileNames(int sel, PathContext * paths) const } else { - const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos); - for (int nIndex = 0; nIndex < GetDocument()->m_nDirs; nIndex++) - { - const String relpath = paths_ConcatPath(di.diffFileInfo[nIndex].path, di.diffFileInfo[nIndex].filename); - const String & path = GetDocument()->GetBasePath(nIndex); - paths->SetPath(nIndex, paths_ConcatPath(path, relpath)); - } + ::GetItemFileNames(&GetDocument()->GetDiffContext(), GetDocument()->GetDiffByKey(diffpos), paths); } } @@ -1375,7 +1419,7 @@ void CDirView::ApplyPluginPrediffSetting(int newsetting) if (!di.diffcode.isDirectory() && !di.diffcode.isSideFirstOnly() && !di.diffcode.isSideSecondOnly()) { - GetItemFileNames(sel, slFile, srFile); + ::GetItemFileNames(&GetDocument()->GetDiffContext(), di, slFile, srFile); String filteredFilenames = slFile + _T("|") + srFile; GetDocument()->SetPluginPrediffSetting(filteredFilenames, newsetting); } @@ -1579,11 +1623,11 @@ bool CDirView::DoItemRename(const String& szNewItemName) int nSelItem = m_pList->GetNextItem(-1, LVNI_SELECTED); ASSERT(-1 != nSelItem); - GetItemFileNames(nSelItem, &paths); // We must check that paths still exists String failpath; DIFFITEM &di = GetDiffItemRef(nSelItem); + ::GetItemFileNames(&GetDocument()->GetDiffContext(), di, &paths); bool succeed = CheckPathsExist(paths.GetLeft(), paths.GetRight(), di.diffcode.isExistsFirst() ? ALLOW_FILE | ALLOW_FOLDER : ALLOW_DONT_CARE, di.diffcode.isExistsSecond() ? ALLOW_FILE | ALLOW_FOLDER : ALLOW_DONT_CARE, diff --git a/Src/DirActions.h b/Src/DirActions.h new file mode 100644 index 000000000..2f44c202b --- /dev/null +++ b/Src/DirActions.h @@ -0,0 +1,23 @@ +#pragma once + +#include "UnicodeString.h" + +struct DIFFITEM; +class CDiffContext; +class PathContext; + +void GetItemFileNames(const CDiffContext *pctxt, const DIFFITEM& di, String& strLeft, String& strRight); +void GetItemFileNames(const CDiffContext *pctxt, const DIFFITEM& di, PathContext * paths); +bool IsItemCopyableToLeft(const DIFFITEM & di); +bool IsItemCopyableToRight(const DIFFITEM & di); +bool IsItemDeletableOnLeft(const DIFFITEM & di); +bool IsItemDeletableOnRight(const DIFFITEM & di); +bool IsItemDeletableOnBoth(const DIFFITEM & di); +bool IsItemOpenable(const CDiffContext *pctx, const DIFFITEM & di, bool treemode); +bool AreItemsOpenable(const CDiffContext *pctx, const DIFFITEM & di1, const DIFFITEM & di2, const DIFFITEM & di3); +bool IsItemOpenableOnLeft(const DIFFITEM & di); +bool IsItemOpenableOnRight(const DIFFITEM & di); +bool IsItemOpenableOnLeftWith(const DIFFITEM & di); +bool IsItemOpenableOnRightWith(const DIFFITEM & di); +bool IsItemCopyableToOnLeft(const DIFFITEM & di); +bool IsItemCopyableToOnRight(const DIFFITEM & di); diff --git a/Src/DirItemIterator.h b/Src/DirItemIterator.h new file mode 100644 index 000000000..6db179da1 --- /dev/null +++ b/Src/DirItemIterator.h @@ -0,0 +1,62 @@ +/** + * @file DirItemIterator.h + * + * @brief Declaration DirItemIterator classes. + */ +// ID line follows -- this is updated by SVN +// $Id$ + +#pragma once + +#include +#include +#include "IListCtrl.h" + +struct DIFFITEM; + +class SelectedDirItemIterator : public std::iterator > +{ +public: + SelectedDirItemIterator(IListCtrl *pList) : m_pList(pList) + { + m_sel = m_pList->GetNextSelectedItem(-1); + } + + SelectedDirItemIterator() : m_sel(-1), m_pList(NULL) + { + } + + ~SelectedDirItemIterator() {} + + SelectedDirItemIterator& operator=(const SelectedDirItemIterator& it) + { + m_sel = it.m_sel; + m_pList = it.m_pList; + } + + SelectedDirItemIterator& operator++() + { + m_sel = m_pList->GetNextSelectedItem(m_sel); + return *this; + } + + std::pair operator*() + { + return std::make_pair(m_sel, reinterpret_cast(m_pList->GetItemData(m_sel))); + } + + bool operator==(const SelectedDirItemIterator& it) const + { + return m_sel == it.m_sel; + } + + bool operator!=(const SelectedDirItemIterator& it) const + { + return m_sel != it.m_sel; + } + + int m_sel; + +private: + IListCtrl *m_pList; +}; diff --git a/Src/DirView.cpp b/Src/DirView.cpp index fd3a97af7..2a0cc59ca 100644 --- a/Src/DirView.cpp +++ b/Src/DirView.cpp @@ -30,6 +30,7 @@ #include "Constants.h" #include "Merge.h" #include "ClipBoard.h" +#include "DirActions.h" #include "DirView.h" #include "DirViewColItems.h" #include "DirFrame.h" // StatePane @@ -1483,7 +1484,8 @@ bool CDirView::OpenThreeItems(UIntPtr pos1, UIntPtr pos2, UIntPtr pos3, DIFFITEM *di2 = &pDoc->GetDiffRefByKey(pos2); // Check for binary & side compatibility & file/dir compatibility - if (!AreItemsOpenable(**di1, **di2, **di2) && !AreItemsOpenable(**di1, **di1, **di2)) + if (!::AreItemsOpenable(&GetDocument()->GetDiffContext(), **di1, **di2, **di2) && + !::AreItemsOpenable(&GetDocument()->GetDiffContext(), **di1, **di1, **di2)) { return false; } @@ -1537,7 +1539,7 @@ bool CDirView::OpenThreeItems(UIntPtr pos1, UIntPtr pos2, UIntPtr pos3, DIFFITEM *di3 = &pDoc->GetDiffRefByKey(pos3); // Check for binary & side compatibility & file/dir compatibility - if (!AreItemsOpenable(**di1, **di2, **di3)) + if (!::AreItemsOpenable(&GetDocument()->GetDiffContext(), **di1, **di2, **di3)) { return false; } @@ -2202,7 +2204,7 @@ void CDirView::DoUpdateOpen(SELECTIONTYPE selectionType, CCmdUI* pCmdUI) { // One item selected const DIFFITEM& di = GetDiffItem(sel1); - if (selectionType != SELECTIONTYPE_NORMAL || !IsItemOpenable(di)) + if (selectionType != SELECTIONTYPE_NORMAL || !::IsItemOpenable(&GetDocument()->GetDiffContext(), di, m_bTreeMode)) { pCmdUI->Enable(FALSE); return; @@ -2225,7 +2227,7 @@ void CDirView::DoUpdateOpen(SELECTIONTYPE selectionType, CCmdUI* pCmdUI) const DIFFITEM& di1 = GetDiffItem(sel1); const DIFFITEM& di2 = GetDiffItem(sel2); const DIFFITEM& di3 = GetDiffItem(sel3); - if (!AreItemsOpenable(di1, di2, di3)) + if (!::AreItemsOpenable(&GetDocument()->GetDiffContext(), di1, di2, di3)) { pCmdUI->Enable(FALSE); return; diff --git a/Src/DirView.h b/Src/DirView.h index 73f6764a9..e52a0dffb 100644 --- a/Src/DirView.h +++ b/Src/DirView.h @@ -150,20 +150,9 @@ private: void FormatEncodingDialogDisplays(CLoadSaveCodepageDlg * dlg); bool IsItemLeftOnly(int code); bool IsItemRightOnly(int code); - bool IsItemCopyableToLeft(const DIFFITEM & di) const; - bool IsItemCopyableToRight(const DIFFITEM & di) const; - bool IsItemDeletableOnLeft(const DIFFITEM & di) const; - bool IsItemDeletableOnRight(const DIFFITEM & di) const; - bool IsItemDeletableOnBoth(const DIFFITEM & di) const; - bool IsItemOpenable(const DIFFITEM & di) const; bool AreItemsOpenable(SELECTIONTYPE selectionType, const DIFFITEM & di1, const DIFFITEM & di2) const; - bool AreItemsOpenable(const DIFFITEM & di1, const DIFFITEM & di2, const DIFFITEM & di3) const; - bool IsItemOpenableOnLeft(const DIFFITEM & di) const; - bool IsItemOpenableOnRight(const DIFFITEM & di) const; - bool IsItemOpenableOnLeftWith(const DIFFITEM & di) const; - bool IsItemOpenableOnRightWith(const DIFFITEM & di) const; - bool IsItemCopyableToOnLeft(const DIFFITEM & di) const; - bool IsItemCopyableToOnRight(const DIFFITEM & di) const; + template void DoDirAction(const String& status_message); + template void DoDirActionTo(const String& status_message, const String& selectfolder_title); void DoCopyLeftToRight(); void DoCopyRightToLeft(); void DoDelLeft(); @@ -248,7 +237,6 @@ protected: int GetColImage(const DIFFITEM & di) const; int AddSpecialItems(); void GetCurrentColRegKeys(std::vector& colKeys); - void WarnContentsChanged(const String & failedPath); void OpenSpecialItems(Poco::UIntPtr pos1, Poco::UIntPtr pos2, Poco::UIntPtr pos3); bool OpenOneItem(Poco::UIntPtr pos1, DIFFITEM **di1, DIFFITEM **di2, DIFFITEM **di3, PathContext &paths, int & sel1, bool & isDir); diff --git a/Src/IListCtrl.h b/Src/IListCtrl.h index 34cc84dae..71838cb11 100644 --- a/Src/IListCtrl.h +++ b/Src/IListCtrl.h @@ -9,7 +9,9 @@ struct IListCtrl virtual int GetRowCount() const = 0; virtual String GetColumnName(int col) const = 0; virtual String GetItemText(int row, int col) const = 0; + virtual void *GetItemData(int row) const = 0; virtual int GetBackColor(int row) const = 0; + virtual int GetNextSelectedItem(int sel) const = 0; }; #endif diff --git a/Src/IListCtrlImpl.h b/Src/IListCtrlImpl.h index a78d09d0b..5713f06a7 100644 --- a/Src/IListCtrlImpl.h +++ b/Src/IListCtrlImpl.h @@ -36,6 +36,11 @@ public: return text; } + void *GetItemData(int row) const + { + return (void *)SendMessage(m_hwndListCtrl, CB_GETITEMDATA, row, 0); + } + int GetBackColor(int row) const { NMLVCUSTOMDRAW nmlvcd = {0}; @@ -48,6 +53,11 @@ public: return nmlvcd.clrTextBk; } + int GetNextSelectedItem(int sel) const + { + return ListView_GetNextItem(m_hwndListCtrl, sel, LVNI_SELECTED); + } + protected: HWND m_hwndListCtrl; }; diff --git a/Src/Merge.vcxproj b/Src/Merge.vcxproj index 3eec1a84d..162c22534 100644 --- a/Src/Merge.vcxproj +++ b/Src/Merge.vcxproj @@ -8564,6 +8564,7 @@ + @@ -8571,6 +8572,7 @@ + diff --git a/Src/Merge.vcxproj.filters b/Src/Merge.vcxproj.filters index c90680ad5..5558622a7 100644 --- a/Src/Merge.vcxproj.filters +++ b/Src/Merge.vcxproj.filters @@ -1383,6 +1383,12 @@ MFCGui\Header Files + + Header Files + + + MFCGui\Header Files +