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()
46 * @brief Remove last action item from the list.
47 * @return Item removed from the list.
49 FileActionItem FileActionScript::RemoveTailActionItem()
51 FileActionItem item = m_actions.back();
57 * @brief Create ShellFileOperations operation lists from our scripts.
59 * We use ShellFileOperations internally to do actual file operations.
60 * ShellFileOperations can do only one type of operation (copy, move, delete)
61 * with one instance at a time, so we use own instance for every
63 * @return One of CreateScriptReturn values.
65 int FileActionScript::CreateOperationsScripts()
68 FILEOP_FLAGS operFlags = 0;
69 bool bContinue = true;
71 // Copy operations first
73 operFlags |= FOF_NOCONFIRMMKDIR | FOF_MULTIDESTFILES | FOF_NOCONFIRMATION;
75 operFlags |= FOF_ALLOWUNDO;
77 vector<FileActionItem>::const_iterator iter = m_actions.begin();
78 while (iter != m_actions.end() && bContinue)
81 if ((*iter).atype == FileAction::ACT_COPY && !(*iter).dirflag)
85 if (!theApp.CreateBackup(true, (*iter).dest))
87 String strErr = _("Error backing up file");
88 AfxMessageBox(strErr.c_str(), MB_OK | MB_ICONERROR);
94 if ((*iter).atype == FileAction::ACT_COPY &&
97 m_pCopyOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
98 m_bHasCopyOperations = true;
104 m_bHasCopyOperations = false;
105 m_pCopyOperations->Reset();
106 return SCRIPT_USERCANCEL;
109 if (m_bHasCopyOperations)
110 m_pCopyOperations->SetOperation(operation, operFlags, m_hParentWindow);
112 // Move operations next
114 operFlags = FOF_MULTIDESTFILES;
115 if (m_bUseRecycleBin)
116 operFlags |= FOF_ALLOWUNDO;
118 iter = m_actions.begin();
119 while (iter != m_actions.end())
121 if ((*iter).atype == FileAction::ACT_MOVE)
123 m_pMoveOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
124 m_bHasMoveOperations = true;
128 if (m_bHasMoveOperations)
129 m_pMoveOperations->SetOperation(operation, operFlags, m_hParentWindow);
131 // Rename operations nextbbbb
132 operation = FO_RENAME;
133 operFlags = FOF_MULTIDESTFILES;
134 if (m_bUseRecycleBin)
135 operFlags |= FOF_ALLOWUNDO;
137 iter = m_actions.begin();
138 while (iter != m_actions.end())
140 if ((*iter).atype == FileAction::ACT_RENAME)
142 m_pRenameOperations->AddSourceAndDestination((*iter).src, (*iter).dest);
143 m_bHasRenameOperations = true;
147 if (m_bHasRenameOperations)
148 m_pRenameOperations->SetOperation(operation, operFlags, m_hParentWindow);
150 // Delete operations last
151 operation = FO_DELETE;
153 if (m_bUseRecycleBin)
154 operFlags |= FOF_ALLOWUNDO;
156 iter = m_actions.begin();
157 while (iter != m_actions.end())
159 if ((*iter).atype == FileAction::ACT_DEL)
161 m_pDelOperations->AddSource((*iter).src);
162 if (!(*iter).dest.empty())
163 m_pDelOperations->AddSource((*iter).dest);
164 m_bHasDelOperations = true;
168 if (m_bHasDelOperations)
169 m_pDelOperations->SetOperation(operation, operFlags, m_hParentWindow);
170 return SCRIPT_SUCCESS;
174 * @brief Run one operation set.
175 * @param [in] oplist List of operations to run.
176 * @param [out] userCancelled Did user cancel the operation?
177 * @return true if the operation succeeded and finished.
179 bool FileActionScript::RunOp(ShellFileOperations *oplist, bool & userCancelled)
181 bool fileOpSucceed = false;
184 fileOpSucceed = oplist->Run();
185 userCancelled = oplist->IsCanceled();
187 __except (EXCEPTION_EXECUTE_HANDLER)
189 fileOpSucceed = false;
191 return fileOpSucceed;
195 * @brief Execute fileoperations.
196 * @return `true` if all actions were done successfully, `false` otherwise.
198 bool FileActionScript::Run()
200 // Now process files/directories that got added to list
201 bool bFileOpSucceed = true;
202 bool bUserCancelled = false;
205 CreateOperationsScripts();
207 if (m_bHasCopyOperations)
209 vector<FileActionItem>::const_iterator iter = m_actions.begin();
210 while (iter != m_actions.end())
213 paths::CreateIfNeeded((*iter).dest);
216 bFileOpSucceed = RunOp(m_pCopyOperations.get(), bUserCancelled);
219 if (m_bHasMoveOperations)
221 if (bFileOpSucceed && !bUserCancelled)
223 bFileOpSucceed = RunOp(m_pMoveOperations.get(), bUserCancelled);
229 if (m_bHasRenameOperations)
231 if (bFileOpSucceed && !bUserCancelled)
233 bFileOpSucceed = RunOp(m_pRenameOperations.get(), bUserCancelled);
239 if (m_bHasDelOperations)
241 if (bFileOpSucceed && !bUserCancelled)
243 bFileOpSucceed = RunOp(m_pDelOperations.get(), bUserCancelled);
249 if (!bFileOpSucceed || bUserCancelled)
252 m_bCanceled = bUserCancelled;