Merge lp:~carlos-mazieri/ubuntu-filemanager-app/trash-operations-2 into lp:ubuntu-filemanager-app
- trash-operations-2
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Arto Jalkanen |
Approved revision: | 187 |
Merged at revision: | 190 |
Proposed branch: | lp:~carlos-mazieri/ubuntu-filemanager-app/trash-operations-2 |
Merge into: | lp:ubuntu-filemanager-app |
Prerequisite: | lp:~carlos-mazieri/ubuntu-filemanager-app/trash-operations-1 |
Diff against target: |
965 lines (+320/-214) 5 files modified
src/plugin/folderlistmodel/filesystemaction.cpp (+283/-180) src/plugin/folderlistmodel/filesystemaction.h (+28/-30) src/plugin/folderlistmodel/locationsfactory.cpp (+5/-1) src/plugin/folderlistmodel/locationsfactory.h (+2/-2) src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp (+2/-1) |
To merge this branch: | bzr merge lp:~carlos-mazieri/ubuntu-filemanager-app/trash-operations-2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Arto Jalkanen | Approve | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Review via email: mp+219940@code.launchpad.net |
Commit message
ActionPaths now is used in Actions
Description of the change
ActionPaths now is used in Actions.
FileSystemActio
Each entry (item being handled) has its own FileSystemActio
so they are independent from the whole Action itself.
When restoring items from Trash for example they need to be independent;
the check for different file systems is also made for every item (when moving items),
it used to be done just once for the whole Action.
There will be a "ActionRestoreF
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Arto Jalkanen (ajalkane) wrote : | # |
1)
39 + delete auxAction;
40 + auxAction = 0;
On line incorrect indentation.
2)
FileSystemActio
why not delete auxAction like in reset() ? Looks like it could leak memory.
3)
Not part of the diff, but noticed during review:
void FileSystemActio
{
if (m_curAction)
{
delete m_curAction;
}
if (!m_curAction && m_queuedActions
if (!m_curAction) is unnecessary since it can never happen as it's been deleted just above.
4)
446 + m_errorTitle = QObject::tr("Could remove the directory/file ") +
447 + targetInfo.
Should be "Could not remove ..."
5)
500 + Action *myAction = 0;
501 + myAction = createAction(
For clarity, replace with:
Action *myAction = createAction(
6)
Weird function name:
542 +QString FileSystemActio
This probably is meant to be targetFrom?
- 187. By Carlos Jose Mazieri
-
renamed FileSystemActio
n::targetFom( ) para FileSystemActio n::targetFrom( )
fixed memory leak in FileSystemAction::addEntry( )
fixed memory leak in FileSystemAction::~FileSystemA ction()
fixed memory leak in LocationsFactory::~LocationsFa ctory()
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:187
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Carlos Jose Mazieri (carlos-mazieri) wrote : | # |
revision 187 solves all requirements.
The auxAction commented in item 2) does not need be deleted in FileSystemActio
Arto Jalkanen (ajalkane) wrote : | # |
Thanks for the fixes and the explanation.
Preview Diff
1 | === modified file 'src/plugin/folderlistmodel/filesystemaction.cpp' |
2 | --- src/plugin/folderlistmodel/filesystemaction.cpp 2014-02-05 15:31:44 +0000 |
3 | +++ src/plugin/folderlistmodel/filesystemaction.cpp 2014-05-24 01:40:38 +0000 |
4 | @@ -70,7 +70,97 @@ |
5 | #define COMMON_SIZE_ITEM 120 |
6 | |
7 | |
8 | - |
9 | +//=============================================================================================== |
10 | +FileSystemAction::CopyFile::CopyFile(): |
11 | + bytesWritten(0), |
12 | + source(0), |
13 | + target(0), |
14 | + isEntryItem(false) , |
15 | + amountSavedToRefresh(AMOUNT_COPIED_TO_REFRESH_ITEM_INFO) |
16 | +{ |
17 | + |
18 | +} |
19 | + |
20 | + |
21 | +FileSystemAction::CopyFile::~CopyFile() |
22 | +{ |
23 | + clear(); |
24 | +} |
25 | + |
26 | + |
27 | + |
28 | +//=============================================================================================== |
29 | +FileSystemAction::Action::Action() |
30 | + : auxAction(0), isAux(false) |
31 | +{ |
32 | + reset(); |
33 | +} |
34 | + |
35 | +FileSystemAction::Action::~Action() |
36 | +{ |
37 | + ::qDeleteAll(entries); |
38 | + entries.clear(); |
39 | + copyFile.clear(); |
40 | + //it is not necessary to delete auxAction, because it should be |
41 | + //inside FileSystemAction::m_queuedActions |
42 | +} |
43 | + |
44 | +/*! |
45 | + * \brief FileSystemAction::Action::reset() Used for Undo operations |
46 | + */ |
47 | +void FileSystemAction::Action::reset() |
48 | +{ |
49 | + totalItems = 0; |
50 | + currItem = 0; |
51 | + currEntryIndex = 0; |
52 | + totalBytes = 0; |
53 | + bytesWritten = 0; |
54 | + done = false; |
55 | + isAux = false; |
56 | + currEntry = 0; |
57 | + steps = 1; |
58 | + //auxAction should be in FileSystemAction::m_queuedActions |
59 | + //it is not necessary to delete |
60 | + auxAction = 0; |
61 | + copyFile.clear(); |
62 | + |
63 | +} |
64 | + |
65 | + |
66 | + |
67 | +//=============================================================================================== |
68 | +FileSystemAction::ActionEntry::ActionEntry(): newName(0) |
69 | +{ |
70 | + init(); |
71 | +} |
72 | + |
73 | +FileSystemAction::ActionEntry::~ActionEntry() |
74 | +{ |
75 | + reversedOrder.clear(); |
76 | + if (newName) { delete newName; } |
77 | +} |
78 | + |
79 | +void FileSystemAction::ActionEntry::init() |
80 | +{ |
81 | + currItem = 0 ; |
82 | + currStep = 0; |
83 | + added = false; |
84 | + alreadyExists = false; |
85 | + if (newName) |
86 | + { |
87 | + delete newName; |
88 | + newName = 0; |
89 | + } |
90 | +} |
91 | + |
92 | +/*! |
93 | + * \brief FileSystemAction::Action::reset() Used for Undo operations |
94 | + */ |
95 | +void FileSystemAction::ActionEntry::reset() |
96 | +{ |
97 | + init(); |
98 | + reversedOrder.clear(); |
99 | +} |
100 | |
101 | void FileSystemAction::CopyFile::clear() |
102 | { |
103 | @@ -94,6 +184,9 @@ |
104 | , m_cancelCurrentAction(false) |
105 | , m_busy(false) |
106 | , m_clipboardChanged(false) |
107 | +#if defined(REGRESSION_TEST_FOLDERLISTMODEL) //used in Unit/Regression tests |
108 | + , m_forceUsingOtherFS(false) |
109 | +#endif |
110 | { |
111 | |
112 | } |
113 | @@ -104,7 +197,12 @@ |
114 | */ |
115 | FileSystemAction::~FileSystemAction() |
116 | { |
117 | - |
118 | + if (m_curAction) |
119 | + { |
120 | + delete m_curAction; |
121 | + } |
122 | + ::qDeleteAll(m_queuedActions); |
123 | + m_queuedActions.clear(); |
124 | } |
125 | |
126 | //=============================================================================================== |
127 | @@ -124,23 +222,10 @@ |
128 | * \param origBase |
129 | * \return |
130 | */ |
131 | -FileSystemAction::Action* FileSystemAction::createAction(ActionType type, int origBase) |
132 | +FileSystemAction::Action* FileSystemAction::createAction(ActionType type) |
133 | { |
134 | Action * action = new Action(); |
135 | - action->type = type; |
136 | - action->baseOrigSize = origBase; |
137 | - action->targetPath = m_path; |
138 | - action->totalItems = 0; |
139 | - action->currItem = 0; |
140 | - action->currEntryIndex = 0; |
141 | - action->totalBytes = 0; |
142 | - action->bytesWritten = 0; |
143 | - action->done = false; |
144 | - action->auxAction = 0; |
145 | - action->isAux = false; |
146 | - action->currEntry = 0; |
147 | - action->steps = 1; |
148 | - |
149 | + action->type = type; |
150 | return action; |
151 | } |
152 | |
153 | @@ -150,36 +235,54 @@ |
154 | * \param action |
155 | * \param pathname |
156 | */ |
157 | -void FileSystemAction::addEntry(Action* action, const QString& pathname) |
158 | +void FileSystemAction::addEntry(Action* action, const ActionPaths& pairPaths) |
159 | { |
160 | #if DEBUG_MESSAGES |
161 | - qDebug() << Q_FUNC_INFO << pathname; |
162 | + qDebug() << Q_FUNC_INFO << pairPaths.source(); |
163 | #endif |
164 | - DirItemInfo info(pathname); |
165 | - if (!info.isAbsolute()) |
166 | - { |
167 | - info.setFile(action->targetPath, pathname); |
168 | - } |
169 | + |
170 | + ActionEntry * entry = new ActionEntry(); |
171 | + entry->itemPaths = pairPaths; |
172 | + if (populateEntry(action, entry)) |
173 | + { |
174 | + //now put the Entry in the Action |
175 | + action->entries.append(entry); |
176 | + } |
177 | + else |
178 | + { |
179 | + delete entry; |
180 | + } |
181 | +} |
182 | + |
183 | +bool FileSystemAction::populateEntry(Action* action, ActionEntry* entry) |
184 | +{ |
185 | + DirItemInfo info(entry->itemPaths.source()); |
186 | if (!info.exists()) |
187 | { |
188 | emit error(QObject::tr("File or Directory does not exist"), |
189 | - pathname + QObject::tr(" does not exist") |
190 | - ); |
191 | - return; |
192 | + info.absoluteFilePath() + QObject::tr(" does not exist") |
193 | + ); |
194 | + return false; |
195 | } |
196 | - ActionEntry * entry = new ActionEntry(); |
197 | + //action->type is top level for all items, entry->type drives item behaviour |
198 | + entry->type = action->type; //normal behaviour |
199 | //this is the item being handled |
200 | entry->reversedOrder.append(info); |
201 | - // verify if the destination item already exists |
202 | - if (action->type == ActionCopy || |
203 | - action->type == ActionMove || |
204 | - action->type == ActionHardMoveCopy) |
205 | + // verify if the destination item already exists and it the destination path is in other file system |
206 | + if (entry->type == ActionCopy || |
207 | + entry->type == ActionMove |
208 | + ) |
209 | { |
210 | - DirItemInfo destination(targetFom(info.absoluteFilePath(), action)); |
211 | + DirItemInfo destination(entry->itemPaths.target()); |
212 | entry->alreadyExists = destination.exists(); |
213 | + //check if it is possible to move items |
214 | + if (entry->type == ActionMove && !moveUsingSameFileSystem(entry->itemPaths) ) |
215 | + { |
216 | + entry->type = ActionHardMoveCopy; // first step |
217 | + } |
218 | } |
219 | //ActionMove will perform a rename, so no Directory expanding is necessary |
220 | - if (action->type != ActionMove && info.isDir() && !info.isSymLink()) |
221 | + if (entry->type != ActionMove && info.isDir() && !info.isSymLink()) |
222 | { |
223 | QDirIterator it(info.absoluteFilePath(), |
224 | QDir::AllEntries | QDir::System | |
225 | @@ -196,23 +299,23 @@ |
226 | int sizeSteps = 0; |
227 | int bufferSize = (COPY_BUFFER_SIZE * STEP_FILES); |
228 | while (counter--) |
229 | - { |
230 | + { |
231 | const DirItemInfo & item = entry->reversedOrder.at(counter); |
232 | size = (item.isFile() && !item.isDir() && !item.isSymLink()) ? |
233 | item.size() : COMMON_SIZE_ITEM; |
234 | action->totalBytes += size; |
235 | - if (action->type == ActionCopy || action->type == ActionHardMoveCopy) |
236 | + if (entry->type == ActionCopy || entry->type == ActionHardMoveCopy) |
237 | { |
238 | if ( (sizeSteps = size / bufferSize) ) |
239 | { |
240 | if ( !(size % bufferSize) ) |
241 | { |
242 | --sizeSteps; |
243 | + } |
244 | } |
245 | - action->steps += sizeSteps ; |
246 | + action->steps += sizeSteps ; |
247 | } |
248 | } |
249 | - } |
250 | //set final steps for the Entry based on Items number |
251 | int entrySteps = entry->reversedOrder.count() / STEP_FILES; |
252 | if ( entry->reversedOrder.count() % STEP_FILES) entrySteps++; |
253 | @@ -222,8 +325,8 @@ |
254 | qDebug() << "entrySteps" << entrySteps << "from entry counter" << entry->reversedOrder.count() |
255 | << "total steps" << action->steps; |
256 | #endif |
257 | - //now put the Entry in the Action |
258 | - action->entries.append(entry); |
259 | + |
260 | + return true; |
261 | } |
262 | |
263 | //=============================================================================================== |
264 | @@ -233,16 +336,11 @@ |
265 | void FileSystemAction::processAction() |
266 | { |
267 | if (m_curAction) |
268 | - { |
269 | - //it will be ActionHardMoveRemove only when switched from ActionHardMoveCopy |
270 | - //in this case the move is done in two steps COPY and REMOVE |
271 | - if (m_curAction->type != ActionHardMoveCopy) |
272 | - { |
273 | + { |
274 | delete m_curAction; |
275 | m_curAction = 0; |
276 | - } |
277 | } |
278 | - if (!m_curAction && m_queuedActions.count()) |
279 | + if (m_queuedActions.count()) |
280 | { |
281 | m_curAction = m_queuedActions.at(0); |
282 | m_curAction->currEntry = static_cast<ActionEntry*> |
283 | @@ -277,12 +375,12 @@ |
284 | */ |
285 | void FileSystemAction::processActionEntry() |
286 | { |
287 | -#if DEBUG_MESSAGES |
288 | - qDebug() << Q_FUNC_INFO; |
289 | -#endif |
290 | - |
291 | ActionEntry * curEntry = m_curAction->currEntry; |
292 | |
293 | +#if DEBUG_MESSAGES |
294 | + qDebug() << Q_FUNC_INFO << "entry:" << curEntry << "type:" << curEntry->type; |
295 | +#endif |
296 | + |
297 | #if defined(SIMULATE_LONG_ACTION) |
298 | { |
299 | unsigned int delay = SIMULATE_LONG_ACTION; |
300 | @@ -295,7 +393,7 @@ |
301 | #endif |
302 | if (!m_cancelCurrentAction) |
303 | { |
304 | - switch(m_curAction->type) |
305 | + switch(curEntry->type) |
306 | { |
307 | case ActionRemove: |
308 | case ActionHardMoveRemove: |
309 | @@ -310,6 +408,8 @@ |
310 | moveEntry(curEntry); |
311 | endActionEntry(); |
312 | break; |
313 | + default: |
314 | + break; |
315 | } |
316 | } |
317 | } |
318 | @@ -320,11 +420,12 @@ |
319 | */ |
320 | void FileSystemAction::endActionEntry() |
321 | { |
322 | -#if DEBUG_MESSAGES |
323 | - qDebug() << Q_FUNC_INFO; |
324 | -#endif |
325 | ActionEntry * curEntry = m_curAction->currEntry; |
326 | |
327 | +#if DEBUG_MESSAGES |
328 | + qDebug() << Q_FUNC_INFO << "entry:" << curEntry << "type:" << curEntry->type; |
329 | +#endif |
330 | + |
331 | // first of all check for any error or a cancel issued by the user |
332 | if (m_cancelCurrentAction) |
333 | { |
334 | @@ -336,60 +437,54 @@ |
335 | scheduleSlot(SLOT(processAction())); |
336 | return; |
337 | } |
338 | + |
339 | + int percent = notifyProgress(); |
340 | + |
341 | // check if the current entry has finished |
342 | // if so Views need to receive the notification about that |
343 | if (curEntry->currItem == curEntry->reversedOrder.count()) |
344 | { |
345 | const DirItemInfo & mainItem = curEntry->reversedOrder.at(curEntry->currItem -1); |
346 | m_curAction->currEntryIndex++; |
347 | - switch(m_curAction->type) |
348 | - { |
349 | - case ActionRemove: |
350 | + |
351 | + switch(curEntry->type) |
352 | + { |
353 | + case ActionRemove: |
354 | emit removed(mainItem); |
355 | break; |
356 | - case ActionHardMoveRemove: // nothing to do |
357 | - break; |
358 | - case ActionHardMoveCopy: |
359 | - //check if is doing a hard move and the copy part has finished |
360 | - //if so switch the action to remove |
361 | - if (m_curAction->currEntryIndex == m_curAction->entries.count()) |
362 | - { |
363 | - m_curAction->type = ActionHardMoveRemove; |
364 | - m_curAction->currEntryIndex = 0; |
365 | - int entryCounter = m_curAction->entries.count(); |
366 | - ActionEntry * entry; |
367 | - while (entryCounter--) |
368 | - { |
369 | - entry = m_curAction->entries.at(entryCounter); |
370 | - entry->currItem = 0; |
371 | - entry->currStep = 0; |
372 | - } |
373 | - } |
374 | - case ActionCopy: // ActionHardMoveCopy is also checked here |
375 | - case ActionMove: |
376 | - { |
377 | - QString addedItem = targetFom(mainItem.absoluteFilePath(), m_curAction); |
378 | - if (!curEntry->added && !curEntry->alreadyExists) |
379 | - { |
380 | - emit added(addedItem); |
381 | - curEntry->added = true; |
382 | - } |
383 | - else |
384 | - { |
385 | - emit changed(DirItemInfo(addedItem)); |
386 | - } |
387 | - } |
388 | - break; |
389 | - }//switch |
390 | - |
391 | + case ActionHardMoveRemove: // nothing to do |
392 | + break; |
393 | + case ActionHardMoveCopy: |
394 | + case ActionCopy: // ActionHardMoveCopy is lso checked here |
395 | + case ActionMove: |
396 | + if (!curEntry->added && !curEntry->alreadyExists) |
397 | + { |
398 | + emit added(curEntry->itemPaths.target()); |
399 | + curEntry->added = true; |
400 | + } |
401 | + else |
402 | + { |
403 | + emit changed(DirItemInfo(curEntry->itemPaths.target())); |
404 | + } |
405 | + if (curEntry->type == ActionHardMoveCopy) |
406 | + { |
407 | + //process same Entry again, |
408 | + m_curAction->currEntryIndex--; |
409 | + curEntry->type = ActionHardMoveRemove; |
410 | + m_curAction->currItem -= curEntry->reversedOrder.count(); |
411 | + curEntry->init(); |
412 | + } |
413 | + break; |
414 | + default: |
415 | + break; |
416 | + }//switch |
417 | }//end if (curEntry->currItem == curEntry->reversedOrder.count()) |
418 | |
419 | if (curEntry->currStep == STEP_FILES) |
420 | { |
421 | curEntry->currStep = 0; |
422 | - } |
423 | + } |
424 | |
425 | - int percent = notifyProgress(); |
426 | //Check if the current action has finished or cancelled |
427 | if (m_cancelCurrentAction || |
428 | m_curAction->currEntryIndex == m_curAction->entries.count()) |
429 | @@ -485,14 +580,14 @@ |
430 | //first item from an Entry, |
431 | if (entry->currItem == 0 && entry->alreadyExists && entry->newName == 0) |
432 | { |
433 | - //making backup only if the targetpath == origPath, otherwise the item is overwritten |
434 | - if (m_curAction->targetPath == m_curAction->origPath) |
435 | + //making backup only if the targetpath == origPath, otherwise the item is overwritten |
436 | + if (entry->itemPaths.areEquals()) |
437 | { |
438 | //it will check again if the target exists |
439 | //if so, sets the entry->newName |
440 | //then targetFom() will use entry->newName for |
441 | // sub items in the Entry if the Entry is a directory |
442 | - if (!makeBackupNameForCurrentItem(m_curAction) ) |
443 | + if (!makeBackupNameForCurrentItem(entry) ) |
444 | { |
445 | m_cancelCurrentAction = true; |
446 | m_errorTitle = QObject::tr("Could not find a suitable name to backup"); |
447 | @@ -520,7 +615,7 @@ |
448 | { |
449 | const DirItemInfo &fi = entry->reversedOrder.at(entry->currItem); |
450 | QString orig = fi.absoluteFilePath(); |
451 | - QString target = targetFom(orig, m_curAction); |
452 | + QString target = targetFrom(orig, entry); |
453 | QString path(target); |
454 | // do this here to allow progress send right item number, copySingleFile will emit progress() |
455 | m_curAction->currItem++; |
456 | @@ -537,7 +632,7 @@ |
457 | && !entry->reversedOrder.last().isSymLink() |
458 | ) |
459 | { |
460 | - QString entryDir = targetFom(entry->reversedOrder.last().absoluteFilePath(), m_curAction); |
461 | + QString entryDir = targetFrom(entry->reversedOrder.last().absoluteFilePath(), entry); |
462 | QDir entryDirObj(entryDir); |
463 | if (!entryDirObj.exists() && entryDirObj.mkpath(entryDir)) |
464 | { |
465 | @@ -600,7 +695,7 @@ |
466 | m_curAction->copyFile.target->close(); |
467 | } |
468 | //check if there is disk space to copy source to target |
469 | - if (needsSize > 0 && !isThereDiskSpace( needsSize )) |
470 | + if (needsSize > 0 && !isThereDiskSpace(entry, needsSize )) |
471 | { |
472 | m_cancelCurrentAction = true; |
473 | m_errorTitle = QObject::tr("There is no space on disk to copy"); |
474 | @@ -666,8 +761,7 @@ |
475 | { |
476 | const DirItemInfo &fi = entry->reversedOrder.at(entry->currItem); |
477 | file.setFileName(fi.absoluteFilePath()); |
478 | - QString target(targetFom(fi.absoluteFilePath(), m_curAction)); |
479 | - DirItemInfo targetInfo(target); |
480 | + DirItemInfo targetInfo(entry->itemPaths.target()); |
481 | //rename will fail |
482 | if (targetInfo.exists()) |
483 | { |
484 | @@ -675,10 +769,11 @@ |
485 | entry->added = true; |
486 | if (targetInfo.isFile() || targetInfo.isSymLink()) |
487 | { |
488 | - if (!QFile::remove(target)) |
489 | + if (!QFile::remove(targetInfo.absoluteFilePath())) |
490 | { |
491 | m_cancelCurrentAction = true; |
492 | - m_errorTitle = QObject::tr("Could remove the directory/file ") + target; |
493 | + m_errorTitle = QObject::tr("Could not remove the directory/file ") + |
494 | + targetInfo.absoluteFilePath(); |
495 | m_errorMsg = ::strerror(errno); |
496 | } |
497 | } |
498 | @@ -687,13 +782,14 @@ |
499 | { |
500 | //move target to /tmp and remove it later by creating an Remove action |
501 | //this will emit removed() |
502 | - moveDirToTempAndRemoveItLater(target); |
503 | + moveDirToTempAndRemoveItLater(targetInfo.absoluteFilePath()); |
504 | } |
505 | } |
506 | - if (!m_cancelCurrentAction && !file.rename(target)) |
507 | + if (!m_cancelCurrentAction && !file.rename(entry->itemPaths.target())) |
508 | { |
509 | m_cancelCurrentAction = true; |
510 | - m_errorTitle = QObject::tr("Could not move the directory/file ") + target; |
511 | + m_errorTitle = QObject::tr("Could not move the directory/file ") + |
512 | + targetInfo.absoluteFilePath(); |
513 | m_errorMsg = ::strerror(errno); |
514 | } |
515 | }//for |
516 | @@ -759,12 +855,7 @@ |
517 | { |
518 | emit error(titleError, noWriteError + origin.absoluteFilePath()); |
519 | return; |
520 | - } |
521 | - //check if it is possible to move items |
522 | - if ( !moveUsingSameFileSystem(items.at(0)) ) |
523 | - { |
524 | - actionType = ActionHardMoveCopy; // first step |
525 | - } |
526 | + } |
527 | if (!destination.isWritable()) |
528 | { |
529 | emit error(titleError, noWriteError + destination.absoluteFilePath()); |
530 | @@ -780,28 +871,33 @@ |
531 | * \brief FileSystemAction::createAndProcessAction |
532 | * \param actionType |
533 | * \param paths |
534 | - * \param operation |
535 | + * |
536 | */ |
537 | void FileSystemAction::createAndProcessAction(ActionType actionType, const QStringList& paths) |
538 | { |
539 | #if DEBUG_MESSAGES |
540 | qDebug() << Q_FUNC_INFO << paths; |
541 | #endif |
542 | - Action *myAction = 0; |
543 | - int origPathLen = 0; |
544 | - myAction = createAction(actionType, origPathLen); |
545 | - myAction->origPath = DirItemInfo(paths.at(0)).absolutePath(); |
546 | - myAction->baseOrigSize = myAction->origPath.length(); |
547 | + Action *myAction = createAction(actionType); |
548 | for (int counter=0; counter < paths.count(); counter++) |
549 | { |
550 | - addEntry(myAction, paths.at(counter)); |
551 | + DirItemInfo info(paths.at(counter)); |
552 | + if (!info.isAbsolute()) |
553 | + { |
554 | + info.setFile(m_path, paths.at(counter)); |
555 | + } |
556 | + ActionPaths pairPaths(info.absoluteFilePath()); |
557 | + pairPaths.setTargetPathOnly(m_path); |
558 | + addEntry(myAction, pairPaths); |
559 | } |
560 | + queueAction(myAction); |
561 | +} |
562 | + |
563 | + |
564 | +void FileSystemAction::queueAction(Action *myAction) |
565 | +{ |
566 | if (myAction->totalItems > 0) |
567 | - { |
568 | - if (actionType == ActionHardMoveCopy) |
569 | - { |
570 | - myAction->totalItems *= 2; //duplicate this |
571 | - } |
572 | + { |
573 | /* |
574 | if (actionType == ActionHardMoveCopy || actionType == ActionCopy) |
575 | { |
576 | @@ -830,21 +926,24 @@ |
577 | //=============================================================================================== |
578 | /*! |
579 | * \brief FileSystemAction::targetFom() makes a destination full pathname from \a origItem |
580 | - * \param origItem full pathname from a item intended to be copied or moved into current path |
581 | + * \param origItem full pathname from a item intended to be copied or moved under entry->itemPaths.target |
582 | + * \param entry which the item belongs to (item may be a sub item if the entry is a Directory) |
583 | * \return full pathname of target |
584 | + * |
585 | + * \sa makeBackupNameForCurrentItem() |
586 | */ |
587 | -QString FileSystemAction::targetFom(const QString& origItem, const Action* const action) |
588 | +QString FileSystemAction::targetFrom(const QString& origItem, ActionEntry *entry) |
589 | { |
590 | - QString destinationUnderTarget(origItem.mid(action->baseOrigSize)); |
591 | - if (action->currEntry && action->currEntry->newName) |
592 | + QString destinationUnderTarget(origItem.mid(entry->itemPaths.baseOrigSize())); |
593 | + if (entry->newName) |
594 | { |
595 | int len = destinationUnderTarget.indexOf(QDir::separator(), 1); |
596 | if (len == -1) { |
597 | len = destinationUnderTarget.size(); |
598 | } |
599 | - destinationUnderTarget.replace(1, len -1, *action->currEntry->newName); |
600 | + destinationUnderTarget.replace(1, len -1, *entry->newName); |
601 | } |
602 | - QString target(action->targetPath + destinationUnderTarget); |
603 | + QString target(entry->itemPaths.targetPath() + destinationUnderTarget); |
604 | |
605 | #if DEBUG_MESSAGES |
606 | qDebug() << Q_FUNC_INFO << "orig" << origItem |
607 | @@ -856,31 +955,39 @@ |
608 | |
609 | //=============================================================================================== |
610 | /*! |
611 | - * \brief FileSystemAction::moveUsingSameFileSystem() Checks if the item being moved to |
612 | - * current m_path belongs to the same File System |
613 | + * \brief FileSystemAction::moveUsingSameFileSystem() Checks if the item being moved to another path |
614 | + * belongs to the same File System as the target path |
615 | * |
616 | * It is used to set ActionHardMoveCopy or ActionMove for cut operations. |
617 | * |
618 | - * \param itemToMovePathname first item being moved from a paste operation |
619 | + * \param paths |
620 | * |
621 | - * \return true if the item being moved to the current m_path belongs to the same file system as m_path |
622 | + * \return true if the operation is going to performed in the same file system |
623 | */ |
624 | -bool FileSystemAction::moveUsingSameFileSystem(const QString& itemToMovePathname) |
625 | +bool FileSystemAction::moveUsingSameFileSystem(const ActionPaths& movedItem) |
626 | { |
627 | unsigned long targetFsId = 0xffff; |
628 | unsigned long originFsId = 0xfffe; |
629 | + |
630 | +#if defined(REGRESSION_TEST_FOLDERLISTMODEL) |
631 | + if (m_forceUsingOtherFS) |
632 | + { |
633 | + return false; |
634 | + } |
635 | +#endif |
636 | + |
637 | #if defined(Q_OS_UNIX) |
638 | struct statvfs vfs; |
639 | - if ( ::statvfs( QFile::encodeName(m_path).constData(), &vfs) == 0 ) |
640 | + if ( ::statvfs( QFile::encodeName(movedItem.source()).constData(), &vfs) == 0 ) |
641 | { |
642 | targetFsId = vfs.f_fsid; |
643 | } |
644 | - if ( ::statvfs(QFile::encodeName(itemToMovePathname).constData(), &vfs) == 0) |
645 | + if ( ::statvfs(QFile::encodeName(movedItem.targetPath()).constData(), &vfs) == 0) |
646 | { |
647 | originFsId = vfs.f_fsid; |
648 | } |
649 | #else |
650 | - Q_UNUSED(itemToMovePathname); |
651 | + Q_UNUSED(movedItem); |
652 | #endif |
653 | return targetFsId == originFsId; |
654 | } |
655 | @@ -899,26 +1006,23 @@ |
656 | void FileSystemAction::endCurrentAction() |
657 | { |
658 | |
659 | - if ( !m_clipboardChanged && |
660 | - m_curAction->origPath != m_curAction->targetPath && |
661 | - (m_curAction->type == ActionMove || m_curAction->type == ActionHardMoveRemove) |
662 | - ) |
663 | - { |
664 | - QStringList items; |
665 | - const ActionEntry *entry; |
666 | - int last; |
667 | - for(int e = 0; e < m_curAction->entries.count(); e++) |
668 | - { |
669 | - entry = m_curAction->entries.at(e); |
670 | - last = entry->reversedOrder.count() -1; |
671 | - QString item(targetFom(entry->reversedOrder.at(last).absoluteFilePath(), m_curAction)); |
672 | - items.append(item); |
673 | - } |
674 | - if (items.count()) |
675 | - { |
676 | - QString targetPath = m_curAction->targetPath; |
677 | - //it is not necessary to handle own clipboard here |
678 | - emit recopy(items, targetPath); |
679 | + if ( !m_clipboardChanged && m_curAction->type == ActionMove ) |
680 | + { |
681 | + const ActionEntry *entry = m_curAction->entries.at(0); |
682 | + if (!entry->itemPaths.arePathsEquals()) |
683 | + { |
684 | + QString destinationPath = entry->itemPaths.targetPath(); |
685 | + QStringList items; |
686 | + for(int e = 0; e < m_curAction->entries.count(); e++) |
687 | + { |
688 | + entry = m_curAction->entries.at(e); |
689 | + items.append(entry->itemPaths.target()); |
690 | + } |
691 | + if (items.count()) |
692 | + { |
693 | + //it is not necessary to handle own clipboard here |
694 | + emit recopy(items, destinationPath); |
695 | + } |
696 | } |
697 | } |
698 | } |
699 | @@ -1055,7 +1159,9 @@ |
700 | |
701 | //copying empty files will have totalBytes==0 |
702 | if ( m_curAction->totalBytes > 0 && |
703 | - (m_curAction->type == ActionCopy || m_curAction->type == ActionHardMoveCopy) |
704 | + (m_curAction->currEntry->type == ActionCopy || |
705 | + m_curAction->currEntry->type == ActionHardMoveCopy |
706 | + ) |
707 | ) |
708 | { |
709 | percent = (m_curAction->bytesWritten * 100) / m_curAction->totalBytes ; |
710 | @@ -1086,17 +1192,12 @@ |
711 | { |
712 | percent = 1; |
713 | } |
714 | - if (SHOULD_EMIT_PROGRESS_SIGNAL(m_curAction) && !m_curAction->done) |
715 | - { |
716 | - if (m_curAction->type == ActionHardMoveCopy || |
717 | - m_curAction->type ==ActionHardMoveRemove) |
718 | - { |
719 | - emit progress(m_curAction->currItem/2, m_curAction->totalItems/2, percent); |
720 | - } |
721 | - else |
722 | - { |
723 | - emit progress(m_curAction->currItem, m_curAction->totalItems, percent); |
724 | - } |
725 | + if ( SHOULD_EMIT_PROGRESS_SIGNAL(m_curAction) && |
726 | + !m_curAction->done && |
727 | + m_curAction->currEntry->type != ActionHardMoveRemove |
728 | + ) |
729 | + { |
730 | + emit progress(m_curAction->currItem, m_curAction->totalItems, percent); |
731 | if (percent == 100 && m_curAction->currItem == m_curAction->totalItems) |
732 | { |
733 | m_curAction->done = true; |
734 | @@ -1171,13 +1272,14 @@ |
735 | #endif |
736 | if (QFile::rename(dir, tempDir)) |
737 | { |
738 | - if (!m_curAction->auxAction) |
739 | + if (m_curAction->auxAction == 0) |
740 | { // this new action as Remove will remove all dirs |
741 | m_curAction->auxAction = createAction(ActionRemove); |
742 | m_curAction->auxAction->isAux = true; |
743 | m_queuedActions.append(m_curAction->auxAction); |
744 | } |
745 | - addEntry(m_curAction->auxAction, tempDir); |
746 | + ActionPaths pathToRemove(tempDir); |
747 | + addEntry(m_curAction->auxAction, pathToRemove); |
748 | } |
749 | } |
750 | |
751 | @@ -1199,13 +1301,13 @@ |
752 | * The newName field from current entry will be set to a suitable name |
753 | * \param action |
754 | */ |
755 | -bool FileSystemAction::makeBackupNameForCurrentItem(Action *action) |
756 | +bool FileSystemAction::makeBackupNameForCurrentItem(ActionEntry *entry) |
757 | { |
758 | bool ret = false; |
759 | - if (action->currEntry->alreadyExists) |
760 | + if (entry->alreadyExists) |
761 | { |
762 | const DirItemInfo& fi = |
763 | - action->currEntry->reversedOrder.at(action->currEntry->reversedOrder.count() -1); |
764 | + entry->reversedOrder.at(entry->reversedOrder.count() -1); |
765 | DirItemInfo backuped; |
766 | int counter=0; |
767 | QString name; |
768 | @@ -1233,7 +1335,8 @@ |
769 | } while (backuped.exists() && counter < 100); |
770 | if (counter < 100) |
771 | { |
772 | - action->currEntry->newName = new QString(backuped.fileName()); |
773 | + entry->newName = new QString(backuped.fileName()); |
774 | + entry->itemPaths.setTargetFullName( backuped.absoluteFilePath() ); |
775 | ret = true; |
776 | } |
777 | } |
778 | @@ -1275,12 +1378,12 @@ |
779 | } |
780 | |
781 | //================================================================== |
782 | -bool FileSystemAction::isThereDiskSpace(qint64 requiredSize) |
783 | +bool FileSystemAction::isThereDiskSpace(const ActionEntry *entry, qint64 requiredSize) |
784 | { |
785 | bool ret = true; |
786 | #if defined(Q_OS_UNIX) |
787 | struct statvfs vfs; |
788 | - if ( ::statvfs( QFile::encodeName(m_path).constData(), &vfs) == 0 ) |
789 | + if ( ::statvfs( QFile::encodeName(entry->itemPaths.targetPath()).constData(), &vfs) == 0 ) |
790 | { |
791 | qint64 free = vfs.f_bsize * vfs.f_bfree; |
792 | ret = free > requiredSize; |
793 | |
794 | === modified file 'src/plugin/folderlistmodel/filesystemaction.h' |
795 | --- src/plugin/folderlistmodel/filesystemaction.h 2014-02-05 15:31:44 +0000 |
796 | +++ src/plugin/folderlistmodel/filesystemaction.h 2014-05-24 01:40:38 +0000 |
797 | @@ -142,12 +142,9 @@ |
798 | struct CopyFile |
799 | { |
800 | public: |
801 | - CopyFile() : bytesWritten(0), source(0), target(0), |
802 | - isEntryItem(false) , amountSavedToRefresh(AMOUNT_COPIED_TO_REFRESH_ITEM_INFO) |
803 | - {} |
804 | - ~CopyFile() { clear(); } |
805 | + CopyFile(); |
806 | + ~CopyFile(); |
807 | void clear(); |
808 | - |
809 | qint64 bytesWritten; // set 0 when reach bytesToNotify, notify progress |
810 | QFile * source; |
811 | QFile * target; |
812 | @@ -164,42 +161,40 @@ |
813 | struct ActionEntry |
814 | { |
815 | public: |
816 | - ActionEntry(): currStep(0),currItem(0),alreadyExists(false), newName(0), added(false) {} |
817 | - ~ActionEntry() |
818 | - { |
819 | - reversedOrder.clear(); |
820 | - if (newName) { delete newName; } |
821 | - } |
822 | - QList<DirItemInfo> reversedOrder; //!< last item must be the item from the list |
823 | + ActionEntry(); |
824 | + ~ActionEntry(); |
825 | + void init(); |
826 | + void reset(); |
827 | + ActionPaths itemPaths; //!< identifies the item being handled source and destination |
828 | + ActionType type; |
829 | + QList<DirItemInfo> reversedOrder; //!< last item must be the item from the list |
830 | int currStep; |
831 | - int currItem; |
832 | - bool alreadyExists; |
833 | + int currItem; |
834 | QString * newName; //TODO: allow to rename an existent file when it already exists. |
835 | // So far it is possible to backup items when copy/paste in the |
836 | // same place, in this case it is renamed to "<name> Copy (%d).termination" |
837 | - |
838 | - bool added; //!< signal added() already emitted for the current ActionEntry |
839 | + bool added :1; //!< signal added() already emitted for the current ActionEntry |
840 | + bool alreadyExists :1; |
841 | }; |
842 | |
843 | struct Action |
844 | { |
845 | public: |
846 | - ~Action() {qDeleteAll(entries); entries.clear(); copyFile.clear();} |
847 | + Action(); |
848 | + ~Action(); |
849 | + void reset(); |
850 | ActionType type; |
851 | QList<ActionEntry*> entries; |
852 | int totalItems; |
853 | - int currItem; |
854 | - int baseOrigSize; |
855 | - QString origPath; |
856 | - QString targetPath; |
857 | + int currItem; |
858 | quint64 totalBytes; |
859 | quint64 bytesWritten; |
860 | int currEntryIndex; |
861 | ActionEntry * currEntry; |
862 | - CopyFile copyFile; |
863 | - bool done; |
864 | + CopyFile copyFile; |
865 | Action * auxAction; |
866 | - bool isAux; |
867 | + bool isAux :1; |
868 | + bool done :1; |
869 | int steps; |
870 | }; |
871 | |
872 | @@ -215,12 +210,13 @@ |
873 | |
874 | |
875 | private: |
876 | - Action * createAction(ActionType, int origBase = 0); |
877 | - void addEntry(Action* action, const QString &pathname); |
878 | + Action * createAction(ActionType); |
879 | + void addEntry(Action* action, const ActionPaths& pairPaths); |
880 | + bool populateEntry(Action* action, ActionEntry* entry); |
881 | void removeEntry(ActionEntry *); |
882 | void moveEntry(ActionEntry *entry); |
883 | - bool moveUsingSameFileSystem(const QString& itemToMovePathname); |
884 | - QString targetFom(const QString& origItem, const Action * const action); |
885 | + bool moveUsingSameFileSystem(const ActionPaths &movedItem); |
886 | + QString targetFrom(const QString& origItem, ActionEntry * entry); |
887 | void endCurrentAction(); |
888 | int percentWorkDone(); |
889 | int notifyProgress(int forcePercent = 0); |
890 | @@ -228,11 +224,13 @@ |
891 | bool copySymLink(const QString& target, const QFileInfo& orig); |
892 | void scheduleSlot(const char *slot); |
893 | void moveDirToTempAndRemoveItLater(const QString& dir); |
894 | - bool makeBackupNameForCurrentItem(Action *action); |
895 | + bool makeBackupNameForCurrentItem(ActionEntry *entry); |
896 | bool endCopySingleFile(); |
897 | - bool isThereDiskSpace(qint64 requiredSize); |
898 | + bool isThereDiskSpace(const ActionEntry *entry, qint64 requiredSize); |
899 | + void queueAction(Action *myAction); |
900 | |
901 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) //used in Unit/Regression tests |
902 | + bool m_forceUsingOtherFS; |
903 | friend class TestDirModel; |
904 | #endif |
905 | }; |
906 | |
907 | === modified file 'src/plugin/folderlistmodel/locationsfactory.cpp' |
908 | --- src/plugin/folderlistmodel/locationsfactory.cpp 2014-05-17 12:57:46 +0000 |
909 | +++ src/plugin/folderlistmodel/locationsfactory.cpp 2014-05-24 01:40:38 +0000 |
910 | @@ -46,6 +46,10 @@ |
911 | { |
912 | ::qDeleteAll(m_locations); |
913 | m_locations.clear(); |
914 | + if (m_lastValidFileInfo) |
915 | + { |
916 | + delete m_lastValidFileInfo; |
917 | + } |
918 | } |
919 | |
920 | |
921 | @@ -173,7 +177,7 @@ |
922 | } |
923 | |
924 | |
925 | -void LocationsFactory::storeValidFileInfo(const DirItemInfo *item) |
926 | +void LocationsFactory::storeValidFileInfo(DirItemInfo *item) |
927 | { |
928 | if (m_lastValidFileInfo) |
929 | { |
930 | |
931 | === modified file 'src/plugin/folderlistmodel/locationsfactory.h' |
932 | --- src/plugin/folderlistmodel/locationsfactory.h 2014-05-14 22:51:47 +0000 |
933 | +++ src/plugin/folderlistmodel/locationsfactory.h 2014-05-24 01:40:38 +0000 |
934 | @@ -113,7 +113,7 @@ |
935 | */ |
936 | const DirItemInfo* lastValidFileInfo() const { return m_lastValidFileInfo; } |
937 | |
938 | - void storeValidFileInfo(const DirItemInfo *item); |
939 | + void storeValidFileInfo(DirItemInfo *item); |
940 | |
941 | signals: |
942 | void locationChanged(const Location *old, const Location *current); |
943 | @@ -125,7 +125,7 @@ |
944 | Location * m_curLoc; |
945 | QList<Location*> m_locations; |
946 | QString m_tmpPath; |
947 | - const DirItemInfo * m_lastValidFileInfo; |
948 | + DirItemInfo * m_lastValidFileInfo; |
949 | |
950 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) |
951 | friend class TestDirModel; |
952 | |
953 | === modified file 'src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp' |
954 | --- src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp 2014-05-02 12:22:11 +0000 |
955 | +++ src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp 2014-05-24 01:40:38 +0000 |
956 | @@ -914,7 +914,8 @@ |
957 | QStringList allFiles(m_deepDir_01->firstLevel()); |
958 | allFiles.append(tempFiles.createdList()); |
959 | |
960 | - m_dirModel_02->m_fsAction->createAndProcessAction(FileSystemAction::ActionHardMoveCopy, |
961 | + m_dirModel_02->m_fsAction->m_forceUsingOtherFS = true; |
962 | + m_dirModel_02->m_fsAction->createAndProcessAction(FileSystemAction::ActionMove, |
963 | allFiles); |
964 | |
965 | QTest::qWait(TIME_TO_PROCESS); |
PASSED: Continuous integration, rev:186 91.189. 93.70:8080/ job/ubuntu- filemanager- app-ci/ 235/ 91.189. 93.70:8080/ job/generic- mediumtests- trusty/ 2680 91.189. 93.70:8080/ job/generic- mediumtests- trusty/ 2680/artifact/ work/output/ *zip*/output. zip 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 217 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 217/artifact/ work/output/ *zip*/output. zip 91.189. 93.70:8080/ job/ubuntu- filemanager- app-trusty- amd64-ci/ 185 91.189. 93.70:8080/ job/ubuntu- filemanager- app-utopic- amd64-ci/ 33
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- filemanager- app-ci/ 235/rebuild
http://