#include "BCMenu.h"
#include "DirCmpReportDlg.h"
#include "DirCmpReport.h"
-#include "DirCompProgressBar.h"
#include "CompareStatisticsDlg.h"
#include "LoadSaveCodepageDlg.h"
#include "ConfirmFolderCopyDlg.h"
#include "PatchTool.h"
#include "SyntaxColors.h"
#include "Shell.h"
+#include "DirTravel.h"
#include <numeric>
#include <functional>
CDirView::CDirView()
: m_pList(nullptr)
- , m_nHiddenItems(0)
- , m_pCmpProgressBar(nullptr)
, m_compareStart(0)
+ , m_elapsed(0)
, m_bTreeMode(false)
, m_dirfilter(std::bind(&COptionsMgr::GetBool, GetOptionsMgr(), _1))
, m_pShellContextMenuLeft(nullptr)
ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_LEFT2_RIGHT1, OnUpdateMergeCompare2<SELECTIONTYPE_LEFT2RIGHT1>)
ON_COMMAND(ID_MERGE_COMPARE_NONHORIZONTALLY, OnMergeCompareNonHorizontally)
// Context menu -> Compare As
- ON_COMMAND_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_IMAGE, OnMergeCompareAs)
+ ON_COMMAND_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_WEBPAGE, OnMergeCompareAs)
ON_COMMAND_RANGE(ID_UNPACKERS_FIRST, ID_UNPACKERS_LAST, OnMergeCompareAs)
- ON_UPDATE_COMMAND_UI_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_IMAGE, OnUpdateMergeCompare)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_WEBPAGE, OnUpdateMergeCompare)
ON_UPDATE_COMMAND_UI(ID_NO_UNPACKER, OnUpdateNoUnpacker)
// Context menu -> Copy
ON_COMMAND(ID_DIR_COPY_LEFT_TO_RIGHT, (OnCtxtDirCopy<SIDE_LEFT, SIDE_RIGHT>))
ON_UPDATE_COMMAND_UI(ID_STATUS_RIGHTDIR_RO, OnUpdateStatusRightRO)
ON_UPDATE_COMMAND_UI(ID_STATUS_MIDDLEDIR_RO, OnUpdateStatusMiddleRO)
ON_UPDATE_COMMAND_UI(ID_STATUS_LEFTDIR_RO, OnUpdateStatusLeftRO)
- // Progress dialog
- ON_BN_CLICKED(IDC_COMPARISON_STOP, OnBnClickedComparisonStop)
- ON_BN_CLICKED(IDC_COMPARISON_PAUSE, OnBnClickedComparisonPause)
- ON_BN_CLICKED(IDC_COMPARISON_CONTINUE, OnBnClickedComparisonContinue)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
*/
void CDirView::StartCompare(CompareStats *pCompareStats)
{
- if (m_pCmpProgressBar == nullptr)
- m_pCmpProgressBar.reset(new DirCompProgressBar());
-
- if (!::IsWindow(m_pCmpProgressBar->GetSafeHwnd()))
- m_pCmpProgressBar->Create(GetParentFrame());
-
- m_pCmpProgressBar->SetCompareStat(pCompareStats);
- m_pCmpProgressBar->StartUpdating();
-
- GetParentFrame()->ShowControlBar(m_pCmpProgressBar.get(), TRUE, FALSE);
-
m_compareStart = clock();
}
try {
// First we build a list of desired actions
FileActionScript actionScript;
- actionScript.m_destBase = destPath;
+ actionScript.m_destBase = std::move(destPath);
DirItemWithIndexIterator begin(m_pIList.get(), -1, true);
DirItemWithIndexIterator end;
FileActionScript *rsltScript;
//sort using static CompareFunc comparison function
CompareState cs(&GetDiffContext(), m_pColItems.get(), sortCol, bSortAscending, m_bTreeMode);
std::stable_sort(m_listViewItems.begin(), m_listViewItems.end(), [&cs](const ListViewOwnerDataItem& a, const ListViewOwnerDataItem& b)
- { return CompareState::CompareFunc(a.lParam, b.lParam, reinterpret_cast<LPARAM>(&cs)) > 0; });
+ { return CompareState::CompareFunc(a.lParam, b.lParam, reinterpret_cast<LPARAM>(&cs)) < 0; });
m_firstDiffItem.reset();
m_lastDiffItem.reset();
}
CListView::OnDestroy();
-
- GetMainFrame()->ClearStatusbarItemCount();
}
/**
{
// Open subfolders
// Don't add folders to MRU
- GetMainFrame()->DoFileOrFolderOpen(&paths, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive, (GetAsyncKeyState(VK_CONTROL) & 0x8000) ? nullptr : pDoc);
+ GetMainFrame()->DoFileOrFolderOpen(&paths, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive,
+ ((GetAsyncKeyState(VK_CONTROL) & 0x8000) || GetDiffContext().m_bRecursive) ? nullptr : pDoc);
}
else if (HasZipSupport() && std::count_if(paths.begin(), paths.end(), ArchiveGuessFormat) == paths.GetSize())
{
GetDiffContext().FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer);
}
- GetMainFrame()->ShowAutoMergeDoc(GetDocument(), paths.GetSize(), fileloc,
+ GetMainFrame()->ShowAutoMergeDoc(0, GetDocument(), paths.GetSize(), fileloc,
dwFlags, strDesc, _T(""), infoUnpacker);
}
}
{
PackingInfo infoUnpacker(
CMainFrame::GetPluginPipelineByMenuId(id, FileTransform::UnpackerEventNames, ID_UNPACKERS_FIRST));
- GetMainFrame()->ShowAutoMergeDoc(pDoc, paths.GetSize(), fileloc, dwFlags, strDesc, _T(""), &infoUnpacker);
+ GetMainFrame()->DoFileOrFolderOpen(&paths, dwFlags, strDesc, _T(""),
+ ctxt.m_bRecursive, nullptr, &infoUnpacker, nullptr, 0);
}
else
{
m_pList->SetItemState(currentInd, 0, LVIS_SELECTED);
m_pList->SetItemState(currentInd, 0, LVIS_FOCUSED);
m_pList->SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
+ m_pList->SetSelectionMark(i);
}
// Move focus to specified item
// Check if we got 'ESC pressed' -message
if (pMsg->wParam == VK_ESCAPE)
{
- if (m_pCmpProgressBar != nullptr)
+ if (GetDocument()->m_diffThread.GetThreadState() == CDiffThread::THREAD_COMPARING)
{
- OnBnClickedComparisonStop();
+ GetDocument()->AbortCurrentScan();
return TRUE;
}
CDirDoc * pDoc = GetDocument();
ASSERT(pDoc != nullptr);
+ // Since the Collect thread deletes the DiffItems in the rescan by "Update selection",
+ // the UI update process should not be executed until the Collect thread process is completed
+ // to avoid accessing the deleted DiffItem.
+ if (pDoc->m_diffThread.IsMarkedRescan() && pDoc->m_diffThread.GetCollectThreadState() != CDiffThread::THREAD_COMPLETED)
+ {
+ ASSERT(0);
+ return 0; // return value unused
+ }
+
if (wParam == CDiffThread::EVENT_COMPARE_COMPLETED)
{
if (pDoc->GetDiffContext().m_pPropertySystem && pDoc->GetDiffContext().m_pPropertySystem->HasHashProperties())
pDoc->GetDiffContext().CreateDuplicateValueMap();
- // Close and destroy the dialog after compare
- if (m_pCmpProgressBar != nullptr)
- GetParentFrame()->ShowControlBar(m_pCmpProgressBar.get(), FALSE, FALSE);
- m_pCmpProgressBar.reset();
-
pDoc->CompareReady();
if (!pDoc->GetGeneratingReport())
MoveFocus(0, 0, 0);
// If compare took more than TimeToSignalCompare seconds, notify user
- clock_t elapsed = clock() - m_compareStart;
- GetParentFrame()->SetStatus(
- strutils::format(_("Elapsed time: %ld ms"), elapsed).c_str()
- );
- if (elapsed > TimeToSignalCompare * CLOCKS_PER_SEC)
+ m_elapsed = clock() - m_compareStart;
+ SetTimer(STATUSBAR_UPDATE, 150, nullptr);
+ if (m_elapsed > TimeToSignalCompare * CLOCKS_PER_SEC)
MessageBeep(IDOK);
GetMainFrame()->StartFlashing();
}
else
Redisplay();
}
+
+ HideItems(GetDiffContext().m_vCurrentlyHiddenItems);
}
return 0; // return value unused
{
KillTimer(STATUSBAR_UPDATE);
int items = GetSelectedCount();
- String msg = (items == 1) ? _("1 item selected") : strutils::format_string1(_("%1 items selected"), strutils::to_str(items));
+ String msg;
+ if (m_elapsed != 0)
+ {
+ msg = strutils::format(_("Elapsed time: %ld ms"), m_elapsed);
+ m_elapsed = 0;
+ }
+ else
+ {
+ msg = (items == 1) ? _("1 item selected") : strutils::format_string1(_("%1 items selected"), strutils::to_str(items));
+ }
GetParentFrame()->SetStatus(msg.c_str());
}
return false;
}
- sLinkPath = di.diffFileInfo[0].GetFile();
+ sLinkPath = strutils::format(_T("%d_"), nIndex) + di.diffFileInfo[0].GetFile();
strutils::replace(sLinkPath, _T("\\"), _T("_"));
sLinkPath += _T(".html");
{
case ID_PREDIFFER_SETTINGS_NONE:
case ID_UNPACKER_SETTINGS_NONE:
- pluginPipeline = _T("");
+ pluginPipeline.clear();
break;
case ID_PREDIFFER_SETTINGS_AUTO:
case ID_UNPACKER_SETTINGS_AUTO:
void CDirView::OnUpdateItemRename(CCmdUI* pCmdUI)
{
bool bEnabled = (1 == m_pList->GetSelectedCount());
- pCmdUI->Enable(bEnabled && SelBegin() != SelEnd());
+ if (bEnabled)
+ {
+ Counts counts = Count(&DirActions::IsItemRenamable);
+ bEnabled = (counts.count > 0 && counts.total == 1);
+ }
+ pCmdUI->Enable(bEnabled);
}
/**
*/
void CDirView::OnHideFilenames()
{
+ CDiffContext& ctxt = GetDiffContext();
+ int selection_index;
+ String hiddden_item_path;
+
m_pList->SetRedraw(FALSE); // Turn off updating (better performance)
DirItemIterator it;
+
while ((it = SelRevBegin()) != SelRevEnd())
{
DIFFITEM &di = *it;
+ selection_index = it.m_sel;
+ hiddden_item_path = di.getItemRelativePath();
SetItemViewFlag(di, ViewCustomFlags::HIDDEN, ViewCustomFlags::VISIBILITY);
- DeleteItem(it.m_sel);
- m_nHiddenItems++;
+ DeleteItem(selection_index);
+ ctxt.m_vCurrentlyHiddenItems.push_back(hiddden_item_path);
}
m_pList->SetRedraw(TRUE); // Turn updating back on
}
/**
+ * @brief determine if an item-relative-path is contained in the list of items to hide
+ */
+bool CDirView::IsItemToHide(const String& currentItem, const std::vector<String>& ItemsToHide) const
+{
+ return std::find(ItemsToHide.begin(), ItemsToHide.end(), currentItem) != ItemsToHide.end();
+}
+
+/**
+ * @brief hides items specified in the .winmerge file
+ */
+
+void CDirView::HideItems(const std::vector<String>& ItemsToHide)
+{
+ CDiffContext& ctxt = GetDiffContext();
+ DIFFITEM *diffpos = ctxt.GetFirstDiffPosition();
+ while (diffpos != nullptr)
+ {
+ DIFFITEM &di = ctxt.GetNextDiffRefPosition(diffpos);
+ if (IsItemToHide(di.getItemRelativePath(), ItemsToHide))
+ SetItemViewFlag(di, ViewCustomFlags::HIDDEN, ViewCustomFlags::VISIBILITY);
+ }
+
+ m_pList->SetRedraw(FALSE); // Turn off updating (better performance)
+
+ int num_hidden = 0;
+ const size_t num_to_hide = ItemsToHide.size();
+ DirItemIterator it = RevBegin();
+ while((num_hidden < num_to_hide) && (it != RevEnd()))
+ {
+ DIFFITEM& di = *it;
+ if (di.customFlags & ViewCustomFlags::HIDDEN)
+ {
+ DeleteItem(it.m_sel);
+ num_hidden++;
+ }
+ ++it;
+ }
+
+ m_pList->SetRedraw(TRUE); // Turn updating back on
+}
+
+/**
* @brief update menu item
*/
void CDirView::OnUpdateHideFilenames(CCmdUI* pCmdUI)
if ((pNMListView->uOldState & LVIS_SELECTED) !=
(pNMListView->uNewState & LVIS_SELECTED))
{
- if ((pNMListView->iItem % 5000) > 0)
- SetTimer(STATUSBAR_UPDATE, 100, nullptr);
- else
- OnTimer(STATUSBAR_UPDATE);
+ SetTimer(STATUSBAR_UPDATE, 100, nullptr);
}
*pResult = 0;
}
*/
afx_msg void CDirView::OnBeginLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
- *pResult = (SelBegin() == SelEnd());
+ Counts counts = Count(&DirActions::IsItemRenamable);
+ *pResult = !(counts.count > 0 && counts.total == 1);
// If label edit is allowed.
if (*pResult == FALSE)
CString sText;
pEdit->GetWindowText(sText);
- if (!sText.IsEmpty())
+ if (!sText.IsEmpty() && paths::IsValidName(String(sText)))
{
try {
DirItemIterator it(m_pIList.get(), reinterpret_cast<NMLVDISPINFO *>(pNMHDR)->item.iItem);
+ DIFFITEM& di = *it;
+ unsigned sideFlags = (di.diffcode.diffcode & DIFFCODE::SIDEFLAGS);
*pResult = DoItemRename(it, GetDiffContext(), String(sText));
+ // Rescan the item if side flags change due to renaming.
+ if (*pResult)
+ {
+ if ((di.diffcode.diffcode & DIFFCODE::SIDEFLAGS) != sideFlags)
+ {
+ // Delete the item with the same file name as after renaming.
+ if (di.HasParent())
+ {
+ for (DIFFITEM* pItem = di.GetParentLink()->GetFirstChild(); pItem != nullptr; pItem = pItem->GetFwdSiblingLink())
+ {
+ if ((pItem != &di) && (pItem->diffcode.isDirectory() == di.diffcode.isDirectory()) && (collstr(pItem->diffFileInfo[0].filename, di.diffFileInfo[0].filename, false) == 0))
+ {
+ pItem->DelinkFromSiblings();
+ delete pItem;
+ break;
+ }
+ }
+ }
+ // Rescan the item.
+ MarkForRescan(di);
+ m_pSavedTreeState.reset(SaveTreeState(GetDiffContext()));
+ GetDocument()->SetMarkedRescan();
+ GetDocument()->Rescan();
+ }
+ else {
+ int nDirs = GetDiffContext().GetCompareDirs();
+ assert(nDirs == 2 || nDirs == 3);
+ UpdatePaths(nDirs, di);
+
+ int nIdx = reinterpret_cast<NMLVDISPINFO*>(pNMHDR)->item.iItem;
+ UpdateDiffItemStatus(nIdx);
+ }
+ }
} catch (ContentsChangedException& e) {
AfxMessageBox(e.m_msg.c_str(), MB_ICONWARNING);
}
}
+ else
+ {
+ LangMessageBox(IDS_ERROR_INVALID_DIR_FILE_NAME, MB_ICONWARNING);
+ }
}
}
*/
void CDirView::OnViewShowHiddenItems()
{
+ CDiffContext& ctxt = GetDiffContext();
SetItemViewFlag(GetDiffContext(), ViewCustomFlags::VISIBLE, ViewCustomFlags::VISIBILITY);
- m_nHiddenItems = 0;
+ ctxt.m_vCurrentlyHiddenItems.clear();
Redisplay();
}
*/
void CDirView::OnUpdateViewShowHiddenItems(CCmdUI* pCmdUI)
{
- pCmdUI->Enable(m_nHiddenItems > 0);
+ const CDiffContext& ctxt = GetDiffContext();
+ pCmdUI->Enable(ctxt.m_vCurrentlyHiddenItems.size() > 0);
}
/**
void CDirView::OnUpdateMergeCompare(CCmdUI *pCmdUI)
{
- bool openableForDir = !((pCmdUI->m_nID >= ID_MERGE_COMPARE_TEXT && pCmdUI->m_nID <= ID_MERGE_COMPARE_IMAGE) ||
+ bool openableForDir = !((pCmdUI->m_nID >= ID_MERGE_COMPARE_TEXT && pCmdUI->m_nID <= ID_MERGE_COMPARE_WEBPAGE) ||
(pCmdUI->m_nID >= ID_UNPACKERS_FIRST && pCmdUI->m_nID <= ID_UNPACKERS_LAST));
DoUpdateOpen(SELECTIONTYPE_NORMAL, pCmdUI, openableForDir);
}
}
-void CDirView::OnBnClickedComparisonStop()
-{
- if (m_pCmpProgressBar != nullptr)
- m_pCmpProgressBar->EndUpdating();
- GetDocument()->AbortCurrentScan();
-}
-
-void CDirView::OnBnClickedComparisonPause()
-{
- if (m_pCmpProgressBar != nullptr)
- m_pCmpProgressBar->SetPaused(true);
- GetDocument()->PauseCurrentScan();
-}
-
-void CDirView::OnBnClickedComparisonContinue()
-{
- if (m_pCmpProgressBar != nullptr)
- m_pCmpProgressBar->SetPaused(false);
- GetDocument()->ContinueCurrentScan();
-}
-
/**
* @brief Populate colors for items in view, depending on difference status
*/
CDirDoc *pDoc = GetDocument();
m_pList->SetRedraw(FALSE); // Turn off updating (better performance)
int nRows = m_pList->GetItemCount();
+ CDiffContext& ctxt = GetDiffContext();
+
for (int currRow = nRows - 1; currRow >= 0; currRow--)
{
DIFFITEM *pos = GetItemKey(currRow);
bool bFound = false;
DIFFITEM &di = GetDiffItem(currRow);
PathContext paths;
+
for (int i = 0; i < pDoc->m_nDirs; i++)
{
if (di.diffcode.exists(i) && !di.diffcode.isDirectory())
}
if (!bFound)
{
+ String hiddden_item_path = di.getItemRelativePath();
SetItemViewFlag(di, ViewCustomFlags::HIDDEN, ViewCustomFlags::VISIBILITY);
DeleteItem(currRow);
- m_nHiddenItems++;
+ ctxt.m_vCurrentlyHiddenItems.push_back(hiddden_item_path);
}
}
m_pList->SetRedraw(TRUE); // Turn updating back on
*/
void CDirView::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
- COleDataSource *DropData = new COleDataSource();
-
std::list<String> list;
CopyPathnamesForDragAndDrop(SelBegin(), SelEnd(), std::back_inserter(list), GetDiffContext());
String filesForDroping = strutils::join(list.begin(), list.end(), _T("\n")) + _T("\n");
HGLOBAL hMem = GlobalReAlloc(file.Detach(), (filesForDroping.length() + 1) * sizeof(TCHAR), 0);
if (hMem != nullptr)
{
+ COleDataSource* DropData = new COleDataSource();
DropData->CacheGlobalData(CF_UNICODETEXT, hMem);
DROPEFFECT de = DropData->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE, nullptr);
}
int i = m_pColItems->ColPhysToLog(pParam->item.iSubItem);
if (IsDiffItemSpecial(key))
{
+ pParam->item.iImage = m_listViewItems[nIdx].iImage;
if (m_pColItems->IsColName(i))
{
pParam->item.pszText = _T("..");