From aac2ffa394e0a052c87f02dfde6edb60a5d573e5 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Sun, 29 Jan 2017 15:48:43 +0100 Subject: [PATCH] RenameDlg: Improve error reporting for already existing files Signed-off-by: Sven Strickroth --- src/TortoiseProc/Commands/DropCopyCommand.cpp | 31 +++++++++++++++++------- src/TortoiseProc/Commands/DropMoveCommand.cpp | 34 +++++++++++++++++---------- src/TortoiseProc/Commands/RenameCommand.cpp | 28 +++++++++++++++------- src/TortoiseProc/RenameDlg.cpp | 22 +++++++++-------- src/TortoiseProc/RenameDlg.h | 4 ++-- src/Utils/IInputValidator.h | 14 ++--------- 6 files changed, 79 insertions(+), 54 deletions(-) diff --git a/src/TortoiseProc/Commands/DropCopyCommand.cpp b/src/TortoiseProc/Commands/DropCopyCommand.cpp index 6cae1360f..01f2fa272 100644 --- a/src/TortoiseProc/Commands/DropCopyCommand.cpp +++ b/src/TortoiseProc/Commands/DropCopyCommand.cpp @@ -40,16 +40,20 @@ bool DropCopyCommand::Execute() if (parser.HasKey(L"rename") && pathList.GetCount() == 1) { // ask for a new name of the source item - do + CRenameDlg renDlg; + renDlg.SetInputValidator([&](const int /*nID*/, const CString& input) -> CString { - CRenameDlg renDlg; - renDlg.m_sBaseDir = sDroppath; - renDlg.m_windowtitle.LoadString(IDS_PROC_COPYRENAME); - renDlg.m_name = pathList[0].GetFileOrDirectoryName(); - if (renDlg.DoModal() != IDOK) - return FALSE; - sNewName = renDlg.m_name; - } while (PathFileExists(sDroppath + L'\\' + sNewName)); + if (PathFileExists(sDroppath + L'\\' + input)) + return CString(CFormatMessageWrapper(ERROR_FILE_EXISTS)); + + return{}; + }); + renDlg.m_sBaseDir = sDroppath; + renDlg.m_windowtitle.LoadString(IDS_PROC_COPYRENAME); + renDlg.m_name = pathList[0].GetFileOrDirectoryName(); + if (renDlg.DoModal() != IDOK) + return FALSE; + sNewName = renDlg.m_name; } CSysProgressDlg progress; progress.SetTitle(IDS_PROC_COPYING); @@ -73,6 +77,15 @@ bool DropCopyCommand::Execute() // Offer a rename progress.Stop(); CRenameDlg dlg; + dlg.SetInputValidator([&](const int /*nID*/, const CString& input) -> CString + { + CTGitPath newPath(sDroppath); + newPath.AppendPathString(input); + if (newPath.Exists()) + return CString(CFormatMessageWrapper(ERROR_FILE_EXISTS)); + + return{}; + }); dlg.m_sBaseDir = fullDropPath.GetContainingDirectory().GetWinPathString(); dlg.m_name = fullDropPath.GetFileOrDirectoryName(); dlg.m_windowtitle.Format(IDS_PROC_NEWNAMECOPY, (LPCTSTR)sourcePath.GetUIFileOrDirectoryName()); diff --git a/src/TortoiseProc/Commands/DropMoveCommand.cpp b/src/TortoiseProc/Commands/DropMoveCommand.cpp index 877107afa..9bd72be35 100644 --- a/src/TortoiseProc/Commands/DropMoveCommand.cpp +++ b/src/TortoiseProc/Commands/DropMoveCommand.cpp @@ -53,16 +53,21 @@ bool DropMoveCommand::Execute() if (parser.HasKey(L"rename") && pathList.GetCount() == 1) { // ask for a new name of the source item - do + CRenameDlg renDlg; + renDlg.SetRenameRequired(pathList[0].GetContainingDirectory().IsEquivalentToWithoutCase(droppath)); + renDlg.SetInputValidator([&](const int /*nID*/, const CString& input) -> CString { - CRenameDlg renDlg; - renDlg.m_sBaseDir = g_Git.CombinePath(droppath); - renDlg.m_windowtitle.LoadString(IDS_PROC_MOVERENAME); - renDlg.m_name = pathList[0].GetFileOrDirectoryName(); - if (renDlg.DoModal() != IDOK) - return FALSE; - sNewName = renDlg.m_name; - } while(PathFileExists(droppath + L'\\' + sNewName)); + if (PathFileExists(g_Git.CombinePath(droppath + L'\\' + input))) + return CString(CFormatMessageWrapper(ERROR_FILE_EXISTS)); + + return{}; + }); + renDlg.m_sBaseDir = g_Git.CombinePath(droppath); + renDlg.m_windowtitle.LoadString(IDS_PROC_MOVERENAME); + renDlg.m_name = pathList[0].GetFileOrDirectoryName(); + if (renDlg.DoModal() != IDOK) + return FALSE; + sNewName = renDlg.m_name; } CSysProgressDlg progress; if (progress.IsValid()) @@ -83,11 +88,16 @@ bool DropMoveCommand::Execute() { progress.Stop(); - CString name = pathList[nPath].GetFileOrDirectoryName(); - if (!sNewName.IsEmpty()) - name = sNewName; + CString name = destPath.GetFileOrDirectoryName(); progress.Stop(); CRenameDlg dlg; + dlg.SetInputValidator([&](const int /*nID*/, const CString& input) -> CString + { + if (PathFileExists(g_Git.CombinePath(droppath + L'\\' + input))) + return CString(CFormatMessageWrapper(ERROR_FILE_EXISTS)); + + return{}; + }); dlg.m_sBaseDir = g_Git.CombinePath(destPath); dlg.m_name = name; dlg.m_windowtitle.Format(IDS_PROC_NEWNAMEMOVE, (LPCTSTR)name); diff --git a/src/TortoiseProc/Commands/RenameCommand.cpp b/src/TortoiseProc/Commands/RenameCommand.cpp index 6401b1ff9..14d20c9bd 100644 --- a/src/TortoiseProc/Commands/RenameCommand.cpp +++ b/src/TortoiseProc/Commands/RenameCommand.cpp @@ -34,18 +34,28 @@ bool RenameCommand::Execute() // show the rename dialog until the user either cancels or enters a new // name (one that's different to the original name CString sNewName; - do + CRenameDlg dlg; + dlg.SetInputValidator([&](const int /*nID*/, const CString& input) -> CString { - CRenameDlg dlg; - dlg.m_sBaseDir = g_Git.CombinePath(basePath); - dlg.m_name = filename; - if (dlg.DoModal() != IDOK) - return FALSE; + CString newName; if (!basePath.IsEmpty()) - sNewName = basePath + "/" + dlg.m_name; + newName = basePath + "/" + input; else - sNewName = dlg.m_name; - } while (sNewName.Compare(cmdLinePath.GetGitPathString()) == 0); + newName = input; + + if (newName.CompareNoCase(cmdLinePath.GetGitPathString()) != 0 && PathFileExists(g_Git.CombinePath(newName))) + return CString(CFormatMessageWrapper(ERROR_FILE_EXISTS)); + + return{}; + }); + dlg.m_sBaseDir = g_Git.CombinePath(basePath); + dlg.m_name = filename; + if (dlg.DoModal() != IDOK) + return FALSE; + if (!basePath.IsEmpty()) + sNewName = basePath + "/" + dlg.m_name; + else + sNewName = dlg.m_name; CString force; // if the filenames only differ in case, we have to pass "-f" diff --git a/src/TortoiseProc/RenameDlg.cpp b/src/TortoiseProc/RenameDlg.cpp index 8bc9d219d..7584c6201 100644 --- a/src/TortoiseProc/RenameDlg.cpp +++ b/src/TortoiseProc/RenameDlg.cpp @@ -90,16 +90,6 @@ void CRenameDlg::OnOK() { UpdateData(); m_name.Trim(); - if (m_pInputValidator) - { - CString sError = m_pInputValidator->Validate(IDC_NAME, m_name); - if (!sError.IsEmpty()) - { - m_bBalloonVisible = true; - ShowEditBalloon(IDC_NAME, sError, CString(MAKEINTRESOURCE(IDS_ERR_ERROR)), TTI_ERROR); - return; - } - } bool nameAllowed = ((m_originalName != m_name) || !m_renameRequired) && !m_name.IsEmpty(); if (!nameAllowed) { @@ -115,6 +105,18 @@ void CRenameDlg::OnOK() ShowEditBalloon(IDC_NAME, IDS_WARN_NOVALIDPATH, IDS_ERR_ERROR, TTI_ERROR); return; } + + if (m_pInputValidator) + { + CString sError = m_pInputValidator(IDC_NAME, m_name); + if (!sError.IsEmpty()) + { + m_bBalloonVisible = true; + ShowEditBalloon(IDC_NAME, sError, CString(MAKEINTRESOURCE(IDS_ERR_ERROR)), TTI_ERROR); + return; + } + } + CHorizontalResizableStandAloneDialog::OnOK(); } diff --git a/src/TortoiseProc/RenameDlg.h b/src/TortoiseProc/RenameDlg.h index 21785730c..e7bed256b 100644 --- a/src/TortoiseProc/RenameDlg.h +++ b/src/TortoiseProc/RenameDlg.h @@ -33,7 +33,7 @@ public: CRenameDlg(CWnd* pParent = nullptr); virtual ~CRenameDlg(); - void SetInputValidator(IInputValidator * validator) { m_pInputValidator = validator; } + void SetInputValidator(IInputValidator validator) { m_pInputValidator = validator; } void SetRenameRequired(bool renameRequired) { m_renameRequired = renameRequired; } enum { IDD = IDD_RENAME }; @@ -59,5 +59,5 @@ private: bool m_bBalloonVisible; bool m_renameRequired; CString m_originalName; - IInputValidator * m_pInputValidator; + IInputValidator m_pInputValidator; }; diff --git a/src/Utils/IInputValidator.h b/src/Utils/IInputValidator.h index e590f9596..038900c36 100644 --- a/src/Utils/IInputValidator.h +++ b/src/Utils/IInputValidator.h @@ -1,5 +1,6 @@ // TortoiseGit - a Windows shell extension for easy version control +// Copyright (C) 2017 - TortoiseGit // Copyright (C) 2010, 2013 - TortoiseSVN // This program is free software; you can redistribute it and/or @@ -18,15 +19,4 @@ // #pragma once -class IInputValidator -{ -public: - /** - * Method is called to validate the user input, usually an edit control. - * Return an empty string if the input is valid. If the input is not valid, - * return an error string which is then shown in an error balloon. - * \param nID the id of the edit control, or 0 if it's not for a specific control - * \param input the user input - */ - virtual CString Validate(const int nID, const CString& input) = 0; -}; +typedef std::function IInputValidator; -- 2.11.4.GIT