1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * @file FileActionScript.cpp
5 * @brief Implementation of FileActionScript and related classes
9 #include "FileActionScript.h"
11 #include "UnicodeString.h"
13 #include "OptionsDef.h"
14 #include "OptionsMgr.h"
15 #include "ShellFileOperations.h"
21 * @brief Standard constructor.
23 FileActionScript::FileActionScript()
24 : m_bUseRecycleBin(true)
25 , m_bHasCopyOperations(false)
26 , m_bHasMoveOperations(false)
27 , m_bHasRenameOperations(false)
28 , m_bHasDelOperations(false)
29 , m_hParentWindow(nullptr)
30 , m_pCopyOperations(new ShellFileOperations())
31 , m_pMoveOperations(new ShellFileOperations())
32 , m_pRenameOperations(new ShellFileOperations())
33 , m_pDelOperations(new ShellFileOperations())
39 * @brief Standard destructor.
41 FileActionScript::~FileActionScript() = default;
44 * @brief Remove last action item from the list.
45 * @return Item removed from the list.
47 FileActionItem FileActionScript::RemoveTailActionItem()
49 FileActionItem item = m_actions.back();
55 * @brief Create ShellFileOperations operation lists from our scripts.
57 * We use ShellFileOperations internally to do actual file operations.
58 * ShellFileOperations can do only one type of operation (copy, move, delete)
59 * with one instance at a time, so we use own instance for every
61 * @return One of CreateScriptReturn values.
63 int FileActionScript::CreateOperationsScripts()
66 FILEOP_FLAGS operFlags = 0;
67 bool bContinue = true;
69 // Copy operations first
71 operFlags |= FOF_NOCONFIRMMKDIR | FOF_MULTIDESTFILES | FOF_NOCONFIRMATION;
73 operFlags |= FOF_ALLOWUNDO;
75 vector<FileActionItem>::const_iterator iter = m_actions.begin();
76 while (iter != m_actions.end() && bContinue)
79 if ((*iter).atype == FileAction::ACT_COPY && !(*iter).dirflag)
81 if (!CMergeApp::CreateBackup(true, (*iter).dest))
83 String strErr = _("Error backing up file");
84 AfxMessageBox(strErr.c_str(), MB_OK | MB_ICONERROR);
89 if ((*iter).atype == FileAction::ACT_COPY &&
92 m_pCopyOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
93 m_bHasCopyOperations = true;
99 m_bHasCopyOperations = false;
100 m_pCopyOperations->Reset();
101 return SCRIPT_USERCANCEL;
104 if (m_bHasCopyOperations)
105 m_pCopyOperations->SetOperation(operation, operFlags, m_hParentWindow);
107 // Move operations next
109 operFlags = FOF_MULTIDESTFILES;
110 if (m_bUseRecycleBin)
111 operFlags |= FOF_ALLOWUNDO;
113 iter = m_actions.begin();
114 while (iter != m_actions.end())
116 if ((*iter).atype == FileAction::ACT_MOVE)
118 m_pMoveOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
119 m_bHasMoveOperations = true;
123 if (m_bHasMoveOperations)
124 m_pMoveOperations->SetOperation(operation, operFlags, m_hParentWindow);
126 // Rename operations nextbbbb
127 operation = FO_RENAME;
128 operFlags = FOF_MULTIDESTFILES;
129 if (m_bUseRecycleBin)
130 operFlags |= FOF_ALLOWUNDO;
132 iter = m_actions.begin();
133 while (iter != m_actions.end())
135 if ((*iter).atype == FileAction::ACT_RENAME)
137 m_pRenameOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
138 m_bHasRenameOperations = true;
142 if (m_bHasRenameOperations)
143 m_pRenameOperations->SetOperation(operation, operFlags, m_hParentWindow);
145 // Delete operations last
146 operation = FO_DELETE;
148 if (m_bUseRecycleBin)
149 operFlags |= FOF_ALLOWUNDO;
151 iter = m_actions.begin();
152 while (iter != m_actions.end())
154 if ((*iter).atype == FileAction::ACT_DEL)
156 m_pDelOperations->AddSource((*iter).src);
157 if (!(*iter).dest.empty())
158 m_pDelOperations->AddSource((*iter).dest);
159 m_bHasDelOperations = true;
163 if (m_bHasDelOperations)
164 m_pDelOperations->SetOperation(operation, operFlags, m_hParentWindow);
165 return SCRIPT_SUCCESS;
169 * @brief Run one operation set.
170 * @param [in] oplist List of operations to run.
171 * @param [out] userCancelled Did user cancel the operation?
172 * @return true if the operation succeeded and finished.
174 bool FileActionScript::RunOp(ShellFileOperations *oplist, bool & userCancelled)
176 bool fileOpSucceed = false;
179 fileOpSucceed = oplist->Run();
180 userCancelled = oplist->IsCanceled();
182 __except (EXCEPTION_EXECUTE_HANDLER)
184 fileOpSucceed = false;
186 return fileOpSucceed;
190 * @brief Execute fileoperations.
191 * @return `true` if all actions were done successfully, `false` otherwise.
193 bool FileActionScript::Run()
195 // Now process files/directories that got added to list
196 bool bFileOpSucceed = true;
197 bool bUserCancelled = false;
200 CreateOperationsScripts();
202 if (m_bHasCopyOperations)
204 vector<FileActionItem>::const_iterator iter = m_actions.begin();
205 while (iter != m_actions.end())
208 paths::CreateIfNeeded((*iter).dest);
211 bFileOpSucceed = RunOp(m_pCopyOperations.get(), bUserCancelled);
214 if (m_bHasMoveOperations)
216 if (bFileOpSucceed && !bUserCancelled)
218 bFileOpSucceed = RunOp(m_pMoveOperations.get(), bUserCancelled);
224 if (m_bHasRenameOperations)
226 if (bFileOpSucceed && !bUserCancelled)
228 bFileOpSucceed = RunOp(m_pRenameOperations.get(), bUserCancelled);
234 if (m_bHasDelOperations)
236 if (bFileOpSucceed && !bUserCancelled)
238 bFileOpSucceed = RunOp(m_pDelOperations.get(), bUserCancelled);
244 if (!bFileOpSucceed || bUserCancelled)
247 m_bCanceled = bUserCancelled;