1 /////////////////////////////////////////////////////////////////////////////
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or (at
6 // your option) any later version.
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 /////////////////////////////////////////////////////////////////////////////
18 * @file FileActionScript.cpp
20 * @brief Implementation of FileActionScript and related classes
22 // ID line follows -- this is updated by SVN
26 #include "FileActionScript.h"
28 #include "UnicodeString.h"
30 #include "OptionsDef.h"
31 #include "OptionsMgr.h"
33 #include "ShellFileOperations.h"
35 #include "SourceControl.h"
40 * @brief Standard constructor.
42 FileActionScript::FileActionScript()
43 : m_bUseRecycleBin(TRUE)
44 , m_bHasCopyOperations(FALSE)
45 , m_bHasMoveOperations(FALSE)
46 , m_bHasRenameOperations(FALSE)
47 , m_bHasDelOperations(FALSE)
48 , m_hParentWindow(NULL)
49 , m_pCopyOperations(new ShellFileOperations())
50 , m_pMoveOperations(new ShellFileOperations())
51 , m_pRenameOperations(new ShellFileOperations())
52 , m_pDelOperations(new ShellFileOperations())
57 * @brief Standard destructor.
59 FileActionScript::~FileActionScript()
64 * @brief Remove last action item from the list.
65 * @return Item removed from the list.
67 FileActionItem FileActionScript::RemoveTailActionItem()
69 FileActionItem item = m_actions.back();
75 * @brief Set parent window used for showing MessageBoxes.
76 * @param [in] hWnd Handle to parent window.
78 void FileActionScript::SetParentWindow(HWND hWnd)
80 m_hParentWindow = hWnd;
84 * @brief Does user want to move deleted files to Recycle Bin?
85 * @param [in] bUseRecycleBin If TRUE deleted files are moved to Recycle Bin.
87 void FileActionScript::UseRecycleBin(BOOL bUseRecycleBin)
89 m_bUseRecycleBin = bUseRecycleBin;
93 * @brief Return amount of actions (copy, move, etc) in script.
94 * @return Amount of actions.
96 size_t FileActionScript::GetActionItemCount() const
98 return m_actions.size();
102 * @brief Checkout file from VSS before synching (copying) it.
103 * @param [in] path Full path to a file.
104 * @param [in,out] bApplyToAll Apply user selection to all (selected)files?
105 * @return One of CreateScriptReturn values.
107 int FileActionScript::VCSCheckOut(const String &path, BOOL &bApplyToAll)
110 int retVal = SCRIPT_SUCCESS;
112 if (GetOptionsMgr()->GetInt(OPT_VCS_SYSTEM) == SourceControl::VCS_NONE)
115 // TODO: First param is not used!
116 int nRetVal = theApp.SyncFileToVCS(path.c_str(), bApplyToAll, strErr);
119 retVal = SCRIPT_FAIL; // So we exit without file operations done
120 AfxMessageBox(strErr.c_str(), MB_OK | MB_ICONERROR);
122 else if (nRetVal == IDCANCEL)
124 retVal = SCRIPT_USERCANCEL; // User canceled, so we don't continue
126 else if (nRetVal == IDNO)
128 retVal = SCRIPT_USERSKIP; // User wants to skip this item
135 * @brief Create ShellFileOperations operation lists from our scripts.
137 * We use ShellFileOperations internally to do actual file operations.
138 * ShellFileOperations can do only one type of operation (copy, move, delete)
139 * with one instance at a time, so we use own instance for every
141 * @return One of CreateScriptReturn values.
143 int FileActionScript::CreateOperationsScripts()
146 FILEOP_FLAGS operFlags = 0;
147 BOOL bApplyToAll = FALSE;
148 BOOL bContinue = TRUE;
150 // Copy operations first
152 operFlags |= FOF_NOCONFIRMMKDIR | FOF_MULTIDESTFILES | FOF_NOCONFIRMATION;
153 if (m_bUseRecycleBin)
154 operFlags |= FOF_ALLOWUNDO;
156 vector<FileActionItem>::const_iterator iter = m_actions.begin();
157 while (iter != m_actions.end() && bContinue == TRUE)
160 if ((*iter).atype == FileAction::ACT_COPY && !(*iter).dirflag)
162 // Handle VCS checkout
163 // Before we can write over destination file, we must unlock
164 // (checkout) it. This also notifies VCS system that the file
165 // has been modified.
166 if (GetOptionsMgr()->GetInt(OPT_VCS_SYSTEM) != SourceControl::VCS_NONE)
168 int retVal = VCSCheckOut((*iter).dest, bApplyToAll);
169 if (retVal == SCRIPT_USERCANCEL)
171 else if (retVal == SCRIPT_USERSKIP)
173 else if (retVal == SCRIPT_FAIL)
179 if (!theApp.CreateBackup(TRUE, (*iter).dest.c_str()))
181 String strErr = _("Error backing up file");
182 AfxMessageBox(strErr.c_str(), MB_OK | MB_ICONERROR);
188 if ((*iter).atype == FileAction::ACT_COPY &&
189 bSkip == FALSE && bContinue == TRUE)
191 m_pCopyOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
192 m_bHasCopyOperations = TRUE;
196 if (bContinue == FALSE)
198 m_bHasCopyOperations = FALSE;
199 m_pCopyOperations->Reset();
200 return SCRIPT_USERCANCEL;
203 if (m_bHasCopyOperations)
204 m_pCopyOperations->SetOperation(operation, operFlags, m_hParentWindow);
206 // Move operations next
208 operFlags = FOF_MULTIDESTFILES;
209 if (m_bUseRecycleBin)
210 operFlags |= FOF_ALLOWUNDO;
212 iter = m_actions.begin();
213 while (iter != m_actions.end())
215 if ((*iter).atype == FileAction::ACT_MOVE)
217 m_pMoveOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
218 m_bHasMoveOperations = TRUE;
222 if (m_bHasMoveOperations)
223 m_pMoveOperations->SetOperation(operation, operFlags, m_hParentWindow);
225 // Rename operations nextbbbb
226 operation = FO_RENAME;
227 operFlags = FOF_MULTIDESTFILES;
228 if (m_bUseRecycleBin)
229 operFlags |= FOF_ALLOWUNDO;
231 iter = m_actions.begin();
232 while (iter != m_actions.end())
234 if ((*iter).atype == FileAction::ACT_RENAME)
236 m_pRenameOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
237 m_bHasRenameOperations = TRUE;
241 if (m_bHasRenameOperations)
242 m_pRenameOperations->SetOperation(operation, operFlags, m_hParentWindow);
244 // Delete operations last
245 operation = FO_DELETE;
247 if (m_bUseRecycleBin)
248 operFlags |= FOF_ALLOWUNDO;
250 iter = m_actions.begin();
251 while (iter != m_actions.end())
253 if ((*iter).atype == FileAction::ACT_DEL)
255 m_pDelOperations->AddSource((*iter).src);
256 if (!(*iter).dest.empty())
257 m_pDelOperations->AddSource((*iter).dest);
258 m_bHasDelOperations = TRUE;
262 if (m_bHasDelOperations)
263 m_pDelOperations->SetOperation(operation, operFlags, m_hParentWindow);
264 return SCRIPT_SUCCESS;
268 * @brief Run one operation set.
269 * @param [in] oplist List of operations to run.
270 * @param [out] userCancelled Did user cancel the operation?
271 * @return true if the operation succeeded and finished.
273 bool FileActionScript::RunOp(ShellFileOperations *oplist, bool & userCancelled)
275 bool fileOpSucceed = false;
278 fileOpSucceed = oplist->Run();
279 userCancelled = oplist->IsCanceled();
281 __except (EXCEPTION_EXECUTE_HANDLER)
283 fileOpSucceed = false;
285 return fileOpSucceed;
289 * @brief Execute fileoperations.
290 * @return TRUE if all actions were done successfully, FALSE otherwise.
292 BOOL FileActionScript::Run()
294 // Now process files/directories that got added to list
295 bool bFileOpSucceed = true;
296 bool bUserCancelled = false;
299 CreateOperationsScripts();
301 if (m_bHasCopyOperations)
303 vector<FileActionItem>::const_iterator iter = m_actions.begin();
304 while (iter != m_actions.end())
307 paths_CreateIfNeeded((*iter).dest);
310 bFileOpSucceed = RunOp(m_pCopyOperations.get(), bUserCancelled);
313 if (m_bHasMoveOperations)
315 if (bFileOpSucceed && !bUserCancelled)
317 bFileOpSucceed = RunOp(m_pMoveOperations.get(), bUserCancelled);
323 if (m_bHasRenameOperations)
325 if (bFileOpSucceed && !bUserCancelled)
327 bFileOpSucceed = RunOp(m_pRenameOperations.get(), bUserCancelled);
333 if (m_bHasDelOperations)
335 if (bFileOpSucceed && !bUserCancelled)
337 bFileOpSucceed = RunOp(m_pDelOperations.get(), bUserCancelled);
343 if (!bFileOpSucceed || bUserCancelled)