Merge lp:~carlos-mazieri/ubuntu-filemanager-app/model into lp:ubuntu-filemanager-app/plugin

Proposed by Carlos Jose Mazieri
Status: Superseded
Proposed branch: lp:~carlos-mazieri/ubuntu-filemanager-app/model
Merge into: lp:ubuntu-filemanager-app/plugin
Diff against target: 946 lines (+358/-193)
4 files modified
folderlistmodel/diriteminfo.h (+78/-0)
folderlistmodel/filesystemaction.cpp (+250/-167)
folderlistmodel/filesystemaction.h (+28/-25)
test_folderlistmodel/regression/tst_folderlistmodel.cpp (+2/-1)
To merge this branch: bzr merge lp:~carlos-mazieri/ubuntu-filemanager-app/model
Reviewer Review Type Date Requested Status
David Planella Needs Fixing
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+215783@code.launchpad.net

Commit message

preparation for Trash move/restore operations

Description of the change

Actions which represent user copy/cut operations used to copy/move items into a unique target directory. Restore from Trash requires that items can be moved into different directories in a unique Action.So, some information were moved from Action data structure to ActionEntry data structure which represents single items bening handled inside an Action.

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
David Planella (dpm) wrote :

Thanks Carlos. Now that the branch that includes the plugin code in the source tree has landed in trunk, would you mind resubmitting this MP against trunk? I think you can simply edit the merge proposal and change the target branch. If not, submitting a new MP would also work.

review: Needs Fixing
Revision history for this message
Carlos Jose Mazieri (carlos-mazieri) wrote :

OK, I will do.

If I just change the target branch do I need to specify where it goes
into (like the sub-folder) ?

On 4/15/14, David Planella <email address hidden> wrote:
> Review: Needs Fixing
>
> Thanks Carlos. Now that the branch that includes the plugin code in the
> source tree has landed in trunk, would you mind resubmitting this MP against
> trunk? I think you can simply edit the merge proposal and change the target
> branch. If not, submitting a new MP would also work.
> --
> https://code.launchpad.net/~carlos-mazieri/ubuntu-filemanager-app/model/+merge/215783
> You are the owner of lp:~carlos-mazieri/ubuntu-filemanager-app/model.
>

Revision history for this message
David Planella (dpm) wrote :

On Tue, Apr 15, 2014 at 6:51 PM, Carlos Jose Mazieri <
<email address hidden>> wrote:

> OK, I will do.
>
> If I just change the target branch do I need to specify where it goes
> into (like the sub-folder) ?
>
>
Thanks Carlos! You'll just need to specify this as the target branch:

~ubuntu-filemanager-dev/ubuntu-filemanager-app/trunk

Cheers,
David.

65. By Carlos Jose Mazieri

added moveToTrash, removeFromTrash, restoreFromTrash and emptyTrash facilities.
Test View remade to use selection.

66. By Carlos Jose Mazieri

remade C++ UI

Unmerged revisions

66. By Carlos Jose Mazieri

remade C++ UI

65. By Carlos Jose Mazieri

added moveToTrash, removeFromTrash, restoreFromTrash and emptyTrash facilities.
Test View remade to use selection.

64. By Carlos Jose Mazieri

Preparation for Move/Restore to/from Trash and Undo Actions:
 * Some information from Action data structure were moved into ActionEntry data structure.
 * Actions used to have "targetPath" saying all items (ActionEntry items) were copied/moved into a unique path.
   Now having ActionEntry more indenpendent allows to move/copy items to different paths inside an Action.
   This is required for Restore items from Trash.

Preview Diff

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

Subscribers

People subscribed via source and target branches