~dpm/ubuntu-filemanager-app/run-ap-from-out-of-source-build

« back to all changes in this revision

Viewing changes to plugin/libnemofolderlistmodel/src/filesystemaction.cpp

  • Committer: nskaggs
  • Date: 2014-03-26 14:25:39 UTC
  • mto: This revision was merged to the branch mainline in revision 148.
  • Revision ID: nicholas.skaggs@canonical.com-20140326142539-tym4ip9b0z83ox2r
revert to r143 to merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************
2
 
 *
3
 
 * Copyright 2013 Canonical Ltd.
4
 
 * Copyright 2013 Carlos J Mazieri <carlos.mazieri@gmail.com>
5
 
 *
6
 
 * You may use this file under the terms of the BSD license as follows:
7
 
 *
8
 
 * "Redistribution and use in source and binary forms, with or without
9
 
 * modification, are permitted provided that the following conditions are
10
 
 * met:
11
 
 *   * Redistributions of source code must retain the above copyright
12
 
 *     notice, this list of conditions and the following disclaimer.
13
 
 *   * Redistributions in binary form must reproduce the above copyright
14
 
 *     notice, this list of conditions and the following disclaimer in
15
 
 *     the documentation and/or other materials provided with the
16
 
 *     distribution.
17
 
 *   * Neither the name of Nemo Mobile nor the names of its contributors
18
 
 *     may be used to endorse or promote products derived from this
19
 
 *     software without specific prior written permission.
20
 
 *
21
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
32
 
 *
33
 
 * File: filesystemaction.cpp
34
 
 * Date: 3/13/2013
35
 
 */
36
 
 
37
 
#include "filesystemaction.h"
38
 
#include "clipboard.h"
39
 
 
40
 
#if defined(Q_OS_UNIX)
41
 
#include <sys/statvfs.h>
42
 
#endif
43
 
 
44
 
#include <errno.h>
45
 
 
46
 
#include <QDirIterator>
47
 
#include <QDebug>
48
 
#include <QTimer>
49
 
#include <QFileInfo>
50
 
#include <QDir>
51
 
#include <QThread>
52
 
#include <QTemporaryFile>
53
 
 
54
 
/*!
55
 
 *   number of the files to work on a step, when this number is reached a signal is emitted
56
 
 */
57
 
#define  STEP_FILES               5
58
 
 
59
 
/*!
60
 
  * buffer size to to single read/write operation
61
 
 */
62
 
#define  COPY_BUFFER_SIZE         4096
63
 
 
64
 
/*!
65
 
 *  Auxiliar Actions do not emit progress() signal
66
 
 *  \sa moveDirToTempAndRemoveItLater()
67
 
 */
68
 
#define SHOULD_EMIT_PROGRESS_SIGNAL(action)       (!action->isAux)
69
 
 
70
 
#define   COMMON_SIZE_ITEM       120
71
 
 
72
 
 
73
 
 
74
 
 
75
 
void FileSystemAction::CopyFile::clear()
76
 
{
77
 
    bytesWritten = 0;
78
 
    if (source)   delete source;
79
 
    if (target)   delete target;
80
 
    source = 0;
81
 
    target = 0;
82
 
}
83
 
 
84
 
 
85
 
 
86
 
//===============================================================================================
87
 
/*!
88
 
 * \brief FileSystemAction::FileSystemAction
89
 
 * \param parent
90
 
 */
91
 
FileSystemAction::FileSystemAction(QObject *parent) :
92
 
    QObject(parent)
93
 
  , m_curAction(0)
94
 
  , m_cancelCurrentAction(false)
95
 
  , m_busy(false)  
96
 
  , m_clipboardChanged(false)
97
 
{
98
 
 
99
 
}
100
 
 
101
 
//===============================================================================================
102
 
/*!
103
 
 * \brief FileSystemAction::~FileSystemAction
104
 
 */
105
 
FileSystemAction::~FileSystemAction()
106
 
{   
107
 
 
108
 
}
109
 
 
110
 
//===============================================================================================
111
 
/*!
112
 
 * \brief FileSystemAction::remove
113
 
 * \param paths
114
 
 */
115
 
void FileSystemAction::remove(const QStringList &paths)
116
 
{
117
 
    createAndProcessAction(ActionRemove, paths);
118
 
}
119
 
 
120
 
//===============================================================================================
121
 
/*!
122
 
 * \brief FileSystemAction::createAction
123
 
 * \param type
124
 
 * \param origBase
125
 
 * \return
126
 
 */
127
 
FileSystemAction::Action* FileSystemAction::createAction(ActionType type, int  origBase)
128
 
{
129
 
    Action * action = new Action();
130
 
    action->type         = type;
131
 
    action->baseOrigSize = origBase;
132
 
    action->targetPath   = m_path;
133
 
    action->totalItems   = 0;
134
 
    action->currItem     = 0;
135
 
    action->currEntryIndex    = 0;
136
 
    action->totalBytes   = 0;
137
 
    action->bytesWritten = 0;
138
 
    action->done         = false;
139
 
    action->auxAction    = 0;
140
 
    action->isAux        = false;
141
 
    action->currEntry    = 0;
142
 
    action->steps        = 1;
143
 
 
144
 
    return action;
145
 
}
146
 
 
147
 
//===============================================================================================
148
 
/*!
149
 
 * \brief FileSystemAction::addEntry
150
 
 * \param action
151
 
 * \param pathname
152
 
 */
153
 
void  FileSystemAction::addEntry(Action* action, const QString& pathname)
154
 
{
155
 
#if DEBUG_MESSAGES
156
 
        qDebug() << Q_FUNC_INFO << pathname;
157
 
#endif
158
 
    DirItemInfo info(pathname);
159
 
    if (!info.isAbsolute())
160
 
    {
161
 
        info.setFile(action->targetPath, pathname);
162
 
    }
163
 
    if (!info.exists())
164
 
    {
165
 
        emit error(QObject::tr("File or Directory does not exist"),
166
 
                   pathname + QObject::tr(" does not exist")
167
 
                  );       
168
 
        return;
169
 
    }
170
 
    ActionEntry * entry = new ActionEntry();
171
 
    //this is the item being handled
172
 
    entry->reversedOrder.append(info);
173
 
    // verify if the destination item already exists
174
 
    if (action->type == ActionCopy ||
175
 
        action->type == ActionMove ||
176
 
        action->type == ActionHardMoveCopy)
177
 
    {
178
 
        DirItemInfo destination(targetFom(info.absoluteFilePath(), action));
179
 
        entry->alreadyExists = destination.exists();
180
 
    }
181
 
    //ActionMove will perform a rename, so no Directory expanding is necessary
182
 
    if (action->type != ActionMove && info.isDir() && !info.isSymLink())
183
 
    {
184
 
        QDirIterator it(info.absoluteFilePath(),
185
 
                        QDir::AllEntries | QDir::System |
186
 
                              QDir::NoDotAndDotDot | QDir::Hidden,
187
 
                        QDirIterator::Subdirectories);
188
 
        while (it.hasNext() &&  !it.next().isEmpty())
189
 
        {
190
 
            entry->reversedOrder.prepend(it.fileInfo());
191
 
        }
192
 
    }
193
 
    //set steps and total bytes considering all items in the Entry
194
 
    int counter = entry->reversedOrder.count();
195
 
    qint64 size = 0;
196
 
    int sizeSteps = 0;
197
 
    int bufferSize = (COPY_BUFFER_SIZE * STEP_FILES);
198
 
    while (counter--)
199
 
            {
200
 
        const DirItemInfo & item =  entry->reversedOrder.at(counter);
201
 
        size =  (item.isFile() && !item.isDir() && !item.isSymLink()) ?
202
 
                 item.size() :   COMMON_SIZE_ITEM;
203
 
        action->totalBytes +=  size;
204
 
        if (action->type == ActionCopy || action->type == ActionHardMoveCopy)
205
 
        {
206
 
            if ( (sizeSteps = size / bufferSize) )
207
 
            {
208
 
                if ( !(size % bufferSize) )
209
 
                {
210
 
                    --sizeSteps;
211
 
            }
212
 
                action->steps      += sizeSteps ;
213
 
        }
214
 
    }
215
 
    }
216
 
    //set final steps for the Entry based on Items number
217
 
    int entrySteps = entry->reversedOrder.count() / STEP_FILES;
218
 
    if ( entry->reversedOrder.count() % STEP_FILES) entrySteps++;
219
 
    action->steps      += entrySteps;
220
 
    action->totalItems += entry->reversedOrder.count();
221
 
#if DEBUG_MESSAGES
222
 
    qDebug() << "entrySteps" << entrySteps << "from entry counter" << entry->reversedOrder.count()
223
 
             << "total steps" << action->steps;
224
 
#endif
225
 
    //now put the Entry in the Action
226
 
    action->entries.append(entry);
227
 
}
228
 
 
229
 
//===============================================================================================
230
 
/*!
231
 
 * \brief FileSystemAction::processAction
232
 
 */
233
 
void FileSystemAction::processAction()
234
 
{
235
 
    if (m_curAction)
236
 
    {
237
 
        //it will be ActionHardMoveRemove only when switched from ActionHardMoveCopy
238
 
        //in this case the move is done in two steps COPY and REMOVE
239
 
        if (m_curAction->type != ActionHardMoveCopy)
240
 
        {
241
 
            delete m_curAction;
242
 
            m_curAction = 0;
243
 
        }
244
 
    }
245
 
    if (!m_curAction && m_queuedActions.count())
246
 
    {
247
 
        m_curAction = m_queuedActions.at(0);
248
 
        m_curAction->currEntry = static_cast<ActionEntry*>
249
 
                ( m_curAction->entries.at(0));
250
 
        m_queuedActions.remove(0,1);
251
 
    }
252
 
    if (m_curAction)
253
 
    {
254
 
#if DEBUG_MESSAGES
255
 
        qDebug() << Q_FUNC_INFO << "performing action type" << m_curAction->type;
256
 
#endif
257
 
        m_busy = true;
258
 
        m_cancelCurrentAction = false;
259
 
        m_errorMsg.clear();
260
 
        m_errorTitle.clear();
261
 
        scheduleSlot(SLOT(processActionEntry()));
262
 
        if (SHOULD_EMIT_PROGRESS_SIGNAL(m_curAction))
263
 
        {
264
 
            emit progress(0,m_curAction->totalItems, 0);
265
 
        }
266
 
    }
267
 
    else
268
 
    {
269
 
         m_busy = false;
270
 
    }
271
 
}
272
 
 
273
 
 
274
 
//===============================================================================================
275
 
/*!
276
 
 * \brief FileSystemAction::processActionEntry
277
 
 */
278
 
void FileSystemAction::processActionEntry()
279
 
{
280
 
#if DEBUG_MESSAGES
281
 
        qDebug() << Q_FUNC_INFO;
282
 
#endif
283
 
 
284
 
    ActionEntry * curEntry = m_curAction->currEntry;
285
 
 
286
 
#if defined(SIMULATE_LONG_ACTION)
287
 
    {
288
 
        unsigned int delay = SIMULATE_LONG_ACTION;
289
 
        if (delay == 1)
290
 
        {
291
 
            delay = 100;           //each (10 * STEP_FILES) files will waits a second
292
 
            QThread::currentThread()->wait(delay);
293
 
        }
294
 
    }
295
 
#endif
296
 
    if (!m_cancelCurrentAction)
297
 
    {
298
 
        switch(m_curAction->type)
299
 
        {
300
 
           case ActionRemove:
301
 
           case ActionHardMoveRemove:
302
 
                removeEntry(curEntry);
303
 
                endActionEntry();
304
 
                break;
305
 
           case ActionCopy:
306
 
           case ActionHardMoveCopy:
307
 
                processCopyEntry();          // specially: this is a slot
308
 
                break;
309
 
          case ActionMove:
310
 
                moveEntry(curEntry);
311
 
                endActionEntry();
312
 
                break;
313
 
        }
314
 
    }
315
 
}
316
 
 
317
 
//===============================================================================================
318
 
/*!
319
 
 * \brief FileSystemAction::endActionEntry
320
 
 */
321
 
void FileSystemAction::endActionEntry()
322
 
{
323
 
#if DEBUG_MESSAGES
324
 
        qDebug() << Q_FUNC_INFO;
325
 
#endif
326
 
     ActionEntry * curEntry = m_curAction->currEntry;
327
 
 
328
 
    // first of all check for any error or a cancel issued by the user
329
 
    if (m_cancelCurrentAction)
330
 
    {
331
 
        if (!m_errorTitle.isEmpty())
332
 
        {
333
 
            emit error(m_errorTitle, m_errorMsg);
334
 
        }
335
 
        //it may have other actions to do
336
 
        scheduleSlot(SLOT(processAction()));
337
 
        return;
338
 
    }
339
 
    // check if the current entry has finished
340
 
    // if so Views need to receive the notification about that
341
 
    if (curEntry->currItem == curEntry->reversedOrder.count())
342
 
    {
343
 
        const DirItemInfo & mainItem = curEntry->reversedOrder.at(curEntry->currItem -1);
344
 
        m_curAction->currEntryIndex++;
345
 
        switch(m_curAction->type)
346
 
        {
347
 
           case ActionRemove:           
348
 
                emit removed(mainItem);
349
 
                break;
350
 
           case ActionHardMoveRemove: // nothing to do
351
 
                break;
352
 
           case ActionHardMoveCopy:
353
 
                //check if is doing a hard move and the copy part has finished
354
 
                //if so switch the action to remove
355
 
                if (m_curAction->currEntryIndex == m_curAction->entries.count())
356
 
                {
357
 
                   m_curAction->type      = ActionHardMoveRemove;
358
 
                   m_curAction->currEntryIndex = 0;
359
 
                   int entryCounter = m_curAction->entries.count();
360
 
                   ActionEntry * entry;
361
 
                   while (entryCounter--)
362
 
                   {
363
 
                       entry = m_curAction->entries.at(entryCounter);
364
 
                       entry->currItem = 0;
365
 
                       entry->currStep = 0;
366
 
                   }
367
 
                }
368
 
           case ActionCopy: // ActionHardMoveCopy is also checked here
369
 
           case ActionMove:
370
 
                {
371
 
                    QString addedItem = targetFom(mainItem.absoluteFilePath(), m_curAction);
372
 
                    if (!curEntry->added && !curEntry->alreadyExists)
373
 
                    {
374
 
                        emit added(addedItem);
375
 
                        curEntry->added = true;
376
 
                    }
377
 
                    else
378
 
                    {
379
 
                        emit changed(DirItemInfo(addedItem));
380
 
                    }
381
 
                }
382
 
                break;
383
 
        }//switch
384
 
 
385
 
    }//end if (curEntry->currItem == curEntry->reversedOrder.count())
386
 
 
387
 
    if (curEntry->currStep == STEP_FILES)
388
 
    {
389
 
        curEntry->currStep = 0;
390
 
    }
391
 
 
392
 
    int percent = notifyProgress();
393
 
    //Check if the current action has finished or cancelled
394
 
    if (m_cancelCurrentAction ||
395
 
        m_curAction->currEntryIndex == m_curAction->entries.count())
396
 
    {
397
 
        if (!m_cancelCurrentAction)
398
 
        {
399
 
            endCurrentAction();
400
 
            if (percent < 100)
401
 
            {
402
 
                notifyProgress(100);
403
 
            }
404
 
        }
405
 
        //it may have other actions to do
406
 
        scheduleSlot(SLOT(processAction()));
407
 
    }
408
 
    else
409
 
    {
410
 
        m_curAction->currEntry = static_cast<ActionEntry*>
411
 
                ( m_curAction->entries.at(m_curAction->currEntryIndex) );
412
 
        //keep working on current Action maybe more entries
413
 
        scheduleSlot(SLOT(processActionEntry()));
414
 
    }
415
 
}
416
 
 
417
 
//===============================================================================================
418
 
/*!
419
 
 * \brief FileSystemAction::cancel
420
 
 */
421
 
void FileSystemAction::cancel()
422
 
{
423
 
    m_cancelCurrentAction = true;
424
 
}
425
 
 
426
 
//===============================================================================================
427
 
/*!
428
 
 * \brief FileSystemAction::removeEntry
429
 
 * \param entry
430
 
 */
431
 
void FileSystemAction::removeEntry(ActionEntry *entry)
432
 
{
433
 
    QDir dir;
434
 
    //do one step at least
435
 
    for(; !m_cancelCurrentAction                          &&
436
 
          entry->currStep       < STEP_FILES              &&
437
 
          m_curAction->currItem < m_curAction->totalItems &&
438
 
          entry->currItem       < entry->reversedOrder.count()
439
 
        ; entry->currStep++,    m_curAction->currItem++, entry->currItem++
440
 
        )
441
 
 
442
 
    {
443
 
        const DirItemInfo &fi = entry->reversedOrder.at(entry->currItem);
444
 
        if (fi.isDir() && !fi.isSymLink())
445
 
        {
446
 
            m_cancelCurrentAction = !dir.rmdir(fi.absoluteFilePath());
447
 
        }
448
 
        else
449
 
        {
450
 
            m_cancelCurrentAction = !QFile::remove(fi.absoluteFilePath());
451
 
        }
452
 
#if DEBUG_REMOVE
453
 
        qDebug() << Q_FUNC_INFO << "remove ret=" << !m_cancelCurrentAction << fi.absoluteFilePath();
454
 
#endif
455
 
        if (m_cancelCurrentAction)
456
 
        {
457
 
            m_errorTitle = QObject::tr("Could not remove the item ") +
458
 
                                       fi.absoluteFilePath();
459
 
            m_errorMsg   = ::strerror(errno);
460
 
        }
461
 
    }
462
 
}
463
 
 
464
 
 
465
 
//===============================================================================================
466
 
/*!
467
 
 * \brief FileSystemAction::copyEntry
468
 
 * \param entry
469
 
 */
470
 
void  FileSystemAction::processCopyEntry()
471
 
{
472
 
     ActionEntry * entry = m_curAction->currEntry;
473
 
 
474
 
#if DEBUG_MESSAGES
475
 
     qDebug() << Q_FUNC_INFO << "processing"
476
 
              << entry->reversedOrder.at(entry->reversedOrder.count() -1).absoluteFilePath();
477
 
#endif
478
 
    /*
479
 
     * This flag will be true when processCopySingleFile() has put any slot in the execution queue
480
 
     * it will work to stop the loop.
481
 
     * Later processCopyEntry() will be called again to continue working
482
 
     */
483
 
    bool scheduleAnySlot = false;
484
 
 
485
 
    //first item from an Entry,    
486
 
    if (entry->currItem == 0 && entry->alreadyExists && entry->newName == 0)
487
 
    {
488
 
        //making backup only if the targetpath == origPath, otherwise the item is overwritten
489
 
        if (m_curAction->targetPath == m_curAction->origPath)
490
 
        {
491
 
            //it will check again if the target exists
492
 
            //if so, sets the entry->newName
493
 
            //then targetFom() will use entry->newName for
494
 
            //  sub items in the Entry if the Entry is a directory
495
 
            if (!makeBackupNameForCurrentItem(m_curAction) )
496
 
            {
497
 
                m_cancelCurrentAction = true;
498
 
                m_errorTitle = QObject::tr("Could not find a suitable name to backup");
499
 
                m_errorMsg   = entry->reversedOrder.at(
500
 
                            entry->reversedOrder.count() -1
501
 
                            ).absoluteFilePath();
502
 
            }
503
 
        }
504
 
#if DEBUG_MESSAGES
505
 
        else
506
 
        {
507
 
            qDebug() <<  entry->reversedOrder.at(entry->reversedOrder.count() -1).absoluteFilePath()
508
 
                     << " already exists and will be overwritten";
509
 
        }
510
 
#endif
511
 
    }
512
 
 
513
 
    for(; !m_cancelCurrentAction  && !scheduleAnySlot     &&
514
 
          entry->currStep       < STEP_FILES              &&
515
 
          m_curAction->currItem < m_curAction->totalItems &&
516
 
          entry->currItem       < entry->reversedOrder.count()
517
 
        ; entry->currStep++,    entry->currItem++
518
 
        )
519
 
 
520
 
    {
521
 
        const DirItemInfo &fi = entry->reversedOrder.at(entry->currItem);
522
 
        QString orig    = fi.absoluteFilePath();
523
 
        QString target = targetFom(orig, m_curAction);
524
 
        QString path(target);
525
 
        // do this here to allow progress send right item number, copySingleFile will emit progress()
526
 
        m_curAction->currItem++;
527
 
        //--
528
 
        if (fi.isFile() || fi.isSymLink())
529
 
        {
530
 
            DirItemInfo  t(target);
531
 
            path = t.path();
532
 
        }
533
 
        //check if the main item in the entry is a directory
534
 
        //if so it needs to appear on any attached view
535
 
        if (   m_curAction->currItem == 1
536
 
            && entry->reversedOrder.last().isDir()
537
 
            && !entry->reversedOrder.last().isSymLink()
538
 
           )
539
 
        {
540
 
            QString entryDir = targetFom(entry->reversedOrder.last().absoluteFilePath(), m_curAction);
541
 
            QDir entryDirObj(entryDir);
542
 
            if (!entryDirObj.exists() && entryDirObj.mkpath(entryDir))
543
 
            {
544
 
                emit added(entryDir);
545
 
                entry->added = true;
546
 
            }
547
 
        }
548
 
        QDir d(path);
549
 
        if (!d.exists() && !d.mkpath(path))
550
 
        {
551
 
            m_cancelCurrentAction = true;
552
 
            m_errorTitle = QObject::tr("Could not create the directory");
553
 
            m_errorMsg   = path;
554
 
        }
555
 
        else
556
 
        if (fi.isSymLink())
557
 
        {
558
 
            m_cancelCurrentAction = ! copySymLink(target,fi.diskFileInfo());
559
 
            if (m_cancelCurrentAction)
560
 
            {
561
 
                m_errorTitle = QObject::tr("Could not create link to");
562
 
                m_errorMsg   = target;
563
 
            }
564
 
            m_curAction->bytesWritten += COMMON_SIZE_ITEM;
565
 
        }
566
 
        else
567
 
        if (fi.isDir())
568
 
        {
569
 
            m_cancelCurrentAction = !
570
 
                 QFile(target).setPermissions(fi.permissions());
571
 
            if (m_cancelCurrentAction)
572
 
            {
573
 
                m_errorTitle = QObject::tr("Could not set permissions to dir");
574
 
                m_errorMsg   = target;
575
 
            }
576
 
            m_curAction->bytesWritten += COMMON_SIZE_ITEM;
577
 
        }
578
 
        else
579
 
        if (fi.isFile())
580
 
        {
581
 
            qint64 needsSize = 0;
582
 
            m_curAction->copyFile.clear();
583
 
            m_curAction->copyFile.source = new QFile(orig);
584
 
            m_cancelCurrentAction = !m_curAction->copyFile.source->open(QFile::ReadOnly);
585
 
            if (m_cancelCurrentAction)
586
 
            {               
587
 
                m_errorTitle = QObject::tr("Could not open file");
588
 
                m_errorMsg   = orig;
589
 
            }
590
 
            else
591
 
            {
592
 
                needsSize = m_curAction->copyFile.source->size();
593
 
                //create destination
594
 
                m_curAction->copyFile.target = new QFile(target);             
595
 
                m_curAction->copyFile.targetName = target;
596
 
                //first open it read-only to get its size if exists
597
 
                if (m_curAction->copyFile.target->open(QFile::ReadOnly))
598
 
                {
599
 
                    needsSize -= m_curAction->copyFile.target->size();
600
 
                    m_curAction->copyFile.target->close();
601
 
                }
602
 
                //check if there is disk space to copy source to target
603
 
                if (needsSize > 0 && !isThereDiskSpace( needsSize ))
604
 
                {
605
 
                    m_cancelCurrentAction = true;
606
 
                    m_errorTitle = QObject::tr("There is no space on disk to copy");
607
 
                    m_errorMsg   =  m_curAction->copyFile.target->fileName();
608
 
                }
609
 
            }
610
 
            if (!m_cancelCurrentAction)
611
 
            {
612
 
                m_cancelCurrentAction =
613
 
                        !m_curAction->copyFile.target->open(QFile::WriteOnly | QFile::Truncate);
614
 
                if (m_cancelCurrentAction)
615
 
                {
616
 
                    m_errorTitle = QObject::tr("Could not create file");
617
 
                    m_errorMsg   =  m_curAction->copyFile.target->fileName();
618
 
                }
619
 
            }
620
 
            if (!m_cancelCurrentAction)
621
 
            {
622
 
                m_curAction->copyFile.isEntryItem = entry->currItem  == (entry->reversedOrder.count() -1);
623
 
                scheduleAnySlot =  processCopySingleFile();
624
 
                //main item from the entry. notify views new item inserted,
625
 
                //depending on the file size it may take longer, the view needs to be informed
626
 
                if (m_curAction->copyFile.isEntryItem && !m_cancelCurrentAction)
627
 
                {
628
 
                    if (!entry->alreadyExists)
629
 
                    {
630
 
                       emit added(target);
631
 
                       entry->added = true;
632
 
                    }
633
 
                    else
634
 
                    {
635
 
                        emit changed(DirItemInfo(target));
636
 
                    }
637
 
                }
638
 
            }
639
 
        }//end isFile
640
 
    }//for
641
 
 
642
 
    //no copy going on
643
 
    if (!scheduleAnySlot)
644
 
    {
645
 
        endActionEntry();
646
 
    }
647
 
}
648
 
 
649
 
 
650
 
//===============================================================================================
651
 
/*!
652
 
 * \brief FileSystemAction::moveEntry
653
 
 * \param entry
654
 
 */
655
 
void FileSystemAction::moveEntry(ActionEntry *entry)
656
 
{
657
 
    QFile file;
658
 
 
659
 
    for(; !m_cancelCurrentAction                          &&
660
 
          entry->currStep       < STEP_FILES              &&
661
 
          m_curAction->currItem < m_curAction->totalItems &&
662
 
          entry->currItem       < entry->reversedOrder.count()
663
 
        ; entry->currStep++,    m_curAction->currItem++, entry->currItem++
664
 
        )
665
 
 
666
 
    {
667
 
        const DirItemInfo &fi = entry->reversedOrder.at(entry->currItem);
668
 
        file.setFileName(fi.absoluteFilePath());
669
 
        QString target(targetFom(fi.absoluteFilePath(), m_curAction));
670
 
        DirItemInfo targetInfo(target);
671
 
        //rename will fail
672
 
        if (targetInfo.exists())
673
 
        {
674
 
            //will not emit removed() neither added()
675
 
            entry->added = true;
676
 
            if (targetInfo.isFile() || targetInfo.isSymLink())
677
 
            {
678
 
                if (!QFile::remove(target))
679
 
                {
680
 
                    m_cancelCurrentAction = true;
681
 
                    m_errorTitle = QObject::tr("Could remove the directory/file ") + target;
682
 
                    m_errorMsg   = ::strerror(errno);
683
 
                }
684
 
            }
685
 
            else
686
 
            if (targetInfo.isDir())
687
 
            {
688
 
               //move target to /tmp and remove it later by creating an Remove action
689
 
               //this will emit removed()
690
 
               moveDirToTempAndRemoveItLater(target);
691
 
            }
692
 
        }
693
 
        if (!m_cancelCurrentAction && !file.rename(target))
694
 
        {
695
 
            m_cancelCurrentAction = true;
696
 
            m_errorTitle = QObject::tr("Could not move the directory/file ") + target;
697
 
            m_errorMsg   = ::strerror(errno);
698
 
        }
699
 
    }//for
700
 
}
701
 
 
702
 
//===============================================================================================
703
 
/*!
704
 
 * \brief FileSystemAction::pathChanged
705
 
 * \param path
706
 
 */
707
 
void FileSystemAction::pathChanged(const QString &path)
708
 
{
709
 
    m_path = path;
710
 
}
711
 
 
712
 
 
713
 
 
714
 
void FileSystemAction::copyIntoCurrentPath(const QStringList& items)
715
 
{
716
 
#if DEBUG_MESSAGES
717
 
        qDebug() << Q_FUNC_INFO << items;
718
 
#endif
719
 
    m_clipboardChanged = false;
720
 
    if (items.count())
721
 
    {
722
 
        DirItemInfo destination(m_path);
723
 
        if (destination.isWritable())
724
 
        {
725
 
            createAndProcessAction(ActionCopy, items);
726
 
        }
727
 
        else
728
 
        {
729
 
            emit error(tr("Cannot copy items"),
730
 
                       tr("no write permission on folder ") + destination.absoluteFilePath() );
731
 
 
732
 
        }
733
 
    }
734
 
}
735
 
 
736
 
 
737
 
void FileSystemAction::moveIntoCurrentPath(const QStringList& items)
738
 
{
739
 
#if DEBUG_MESSAGES
740
 
        qDebug() << Q_FUNC_INFO << items;
741
 
#endif
742
 
    m_clipboardChanged = false;
743
 
    if (items.count())
744
 
    {
745
 
        DirItemInfo destination(m_path);
746
 
        DirItemInfo origin(DirItemInfo(items.at(0)).absolutePath());
747
 
        ActionType actionType  = ActionMove;
748
 
        static QString titleError     = tr("Cannot move items");
749
 
        static QString noWriteError   = tr("no write permission on folder ");
750
 
        //we allow Copy to backup items, but Cut must Fail
751
 
        if (destination.absoluteFilePath() == origin.absoluteFilePath())
752
 
        {
753
 
            emit error(titleError,
754
 
                       tr("origin and destination folders are the same"));
755
 
            return;
756
 
        }
757
 
        // cut needs write permission on origin
758
 
        if (!origin.isWritable())
759
 
        {
760
 
            emit error(titleError, noWriteError + origin.absoluteFilePath());
761
 
            return;
762
 
        }
763
 
        //check if it is possible to move items
764
 
        if ( !moveUsingSameFileSystem(items.at(0)) )
765
 
        {
766
 
            actionType = ActionHardMoveCopy; // first step
767
 
        }
768
 
        if (!destination.isWritable())
769
 
        {
770
 
            emit error(titleError, noWriteError + destination.absoluteFilePath());
771
 
            return;
772
 
        }
773
 
        createAndProcessAction(actionType, items);
774
 
    }
775
 
}
776
 
 
777
 
 
778
 
//===============================================================================================
779
 
/*!
780
 
 * \brief FileSystemAction::createAndProcessAction
781
 
 * \param actionType
782
 
 * \param paths
783
 
 * \param operation
784
 
 */
785
 
void  FileSystemAction::createAndProcessAction(ActionType actionType, const QStringList& paths)
786
 
{
787
 
#if DEBUG_MESSAGES
788
 
        qDebug() << Q_FUNC_INFO << paths;
789
 
#endif
790
 
    Action       *myAction       = 0;
791
 
    int           origPathLen    = 0;
792
 
    myAction                     = createAction(actionType, origPathLen);
793
 
    myAction->origPath           = DirItemInfo(paths.at(0)).absolutePath();
794
 
    myAction->baseOrigSize       = myAction->origPath.length();
795
 
    for (int counter=0; counter < paths.count(); counter++)
796
 
    {
797
 
        addEntry(myAction, paths.at(counter));
798
 
    }
799
 
    if (myAction->totalItems > 0)
800
 
    {
801
 
        if (actionType == ActionHardMoveCopy)
802
 
        {
803
 
            myAction->totalItems *= 2; //duplicate this
804
 
        }
805
 
        /*
806
 
        if (actionType == ActionHardMoveCopy || actionType == ActionCopy)
807
 
        {
808
 
            //if a file size is less than (COPY_BUFFER_SIZE * STEP_FILES) a single step does that
809
 
            //and it is already computed
810
 
            myAction->steps +=  myAction->totalBytes / (COPY_BUFFER_SIZE * STEP_FILES);
811
 
        }
812
 
        */        
813
 
        m_queuedActions.append(myAction);
814
 
        if (!m_busy)
815
 
        {
816
 
            processAction();
817
 
        }
818
 
    }
819
 
    else
820
 
    {   // no items were added into the Action, maybe items were removed
821
 
        //addEntry() emits error() signal when items do not exist
822
 
        delete myAction;
823
 
#if DEBUG_MESSAGES
824
 
        qDebug() << Q_FUNC_INFO << "Action is empty, no work to do";
825
 
#endif
826
 
    }
827
 
}
828
 
 
829
 
 
830
 
//===============================================================================================
831
 
/*!
832
 
 * \brief FileSystemAction::targetFom() makes a destination full pathname from \a origItem
833
 
 * \param origItem full pathname from a item intended to be copied or moved into current path
834
 
 * \return full pathname of target
835
 
 */
836
 
QString FileSystemAction::targetFom(const QString& origItem, const Action* const action)
837
 
{
838
 
    QString destinationUnderTarget(origItem.mid(action->baseOrigSize));
839
 
    if (action->currEntry  && action->currEntry->newName)
840
 
    {
841
 
        int len = destinationUnderTarget.indexOf(QDir::separator(), 1);
842
 
        if (len == -1) {
843
 
            len = destinationUnderTarget.size();
844
 
        }
845
 
        destinationUnderTarget.replace(1, len -1, *action->currEntry->newName);
846
 
    }
847
 
    QString target(action->targetPath + destinationUnderTarget);
848
 
 
849
 
#if DEBUG_MESSAGES
850
 
     qDebug() << Q_FUNC_INFO << "orig" << origItem
851
 
              << "target"    << target;
852
 
#endif
853
 
    return target;
854
 
}
855
 
 
856
 
 
857
 
//===============================================================================================
858
 
/*!
859
 
 * \brief FileSystemAction::moveUsingSameFileSystem() Checks if the item being moved to
860
 
 *   current m_path belongs to the same File System
861
 
 *
862
 
 *  It is used to set ActionHardMoveCopy or ActionMove for cut operations.
863
 
 *
864
 
 * \param itemToMovePathname  first item being moved from a paste operation
865
 
 *
866
 
 * \return true if the item being moved to the current m_path belongs to the same file system as m_path
867
 
 */
868
 
bool FileSystemAction::moveUsingSameFileSystem(const QString& itemToMovePathname)
869
 
{
870
 
    unsigned long targetFsId = 0xffff;
871
 
    unsigned long originFsId = 0xfffe;
872
 
#if defined(Q_OS_UNIX)
873
 
    struct statvfs  vfs;
874
 
    if ( ::statvfs( QFile::encodeName(m_path).constData(), &vfs) == 0 )
875
 
    {
876
 
        targetFsId = vfs.f_fsid;
877
 
    }
878
 
    if ( ::statvfs(QFile::encodeName(itemToMovePathname).constData(), &vfs) == 0)
879
 
    {
880
 
        originFsId = vfs.f_fsid;
881
 
    }   
882
 
#else
883
 
    Q_UNUSED(itemToMovePathname); 
884
 
#endif
885
 
    return targetFsId == originFsId;
886
 
}
887
 
 
888
 
 
889
 
//================================================================================
890
 
/*!
891
 
 * \brief FileSystemAction::endCurrentAction() finishes an Action
892
 
 *
893
 
 *  If a Paste was made from a Cut operation, items pasted become avaialable in the clipboard
894
 
 *   as from Copy source operation, so items can be now Pasted again, but with no source removal
895
 
 *
896
 
 * It checks for \a m_clipboardChanged that idenftifies if the clipboard was modified during the
897
 
 * operation maybe by another application.
898
 
 */
899
 
void FileSystemAction::endCurrentAction()
900
 
{
901
 
 
902
 
    if ( !m_clipboardChanged  &&
903
 
          m_curAction->origPath != m_curAction->targetPath &&
904
 
         (m_curAction->type == ActionMove  || m_curAction->type == ActionHardMoveRemove)
905
 
       )
906
 
    {
907
 
         QStringList items;
908
 
         const ActionEntry *entry;
909
 
         int   last;
910
 
         for(int e = 0; e < m_curAction->entries.count(); e++)
911
 
         {
912
 
             entry   = m_curAction->entries.at(e);
913
 
             last    = entry->reversedOrder.count() -1;
914
 
             QString item(targetFom(entry->reversedOrder.at(last).absoluteFilePath(), m_curAction));
915
 
             items.append(item);
916
 
         }
917
 
         if (items.count())
918
 
         {
919
 
             QString targetPath = m_curAction->targetPath;
920
 
             //it is not necessary to handle own clipboard here
921
 
             emit recopy(items, targetPath);
922
 
         }
923
 
    }
924
 
}
925
 
 
926
 
//================================================================================
927
 
/*!
928
 
 * \brief FileSystemAction::copySingleFile() do a single file copy
929
 
 *
930
 
 * Several write operations are required to copy big files, each operation writes (STEP_FILES * 4k) bytes.
931
 
 * After a write operation if more operations are required to copy the whole file,
932
 
 * a progress() signal is emitted and a new write operation is scheduled to happen in the next loop interaction.
933
 
 *
934
 
 * \return  true if scheduled to another slot either processCopyEntry() or itself; false if not.
935
 
 */
936
 
bool FileSystemAction::processCopySingleFile()
937
 
{
938
 
#if DEBUG_MESSAGES
939
 
        qDebug() << Q_FUNC_INFO;
940
 
#endif
941
 
    char block[COPY_BUFFER_SIZE];
942
 
    int  step = 0;
943
 
    bool copySingleFileDone = false;
944
 
    bool scheduleAnySlot    = true;
945
 
    int  startBytes         = m_curAction->copyFile.bytesWritten;
946
 
 
947
 
    while( m_curAction->copyFile.source           &&
948
 
           !m_curAction->copyFile.source->atEnd() &&
949
 
           !m_cancelCurrentAction                 &&
950
 
           m_curAction->copyFile.bytesWritten < m_curAction->copyFile.source->size() &&
951
 
           step++ < STEP_FILES
952
 
         )
953
 
    {
954
 
        qint64 in = m_curAction->copyFile.source->read(block, sizeof(block));
955
 
        if (in > 0)
956
 
        {
957
 
            if(in != m_curAction->copyFile.target->write(block, in))
958
 
            {
959
 
                  m_curAction->copyFile.source->close();
960
 
                  m_curAction->copyFile.target->close();
961
 
                  m_cancelCurrentAction = true;
962
 
                  m_errorTitle = QObject::tr("Write error in ")
963
 
                                  + m_curAction->copyFile.targetName,
964
 
                  m_errorMsg   = ::strerror(errno);
965
 
                  break;
966
 
            }
967
 
            m_curAction->bytesWritten          += in;
968
 
            m_curAction->copyFile.bytesWritten += in;
969
 
            if (m_curAction->copyFile.isEntryItem)
970
 
            {
971
 
                m_curAction->copyFile.amountSavedToRefresh -= in;
972
 
            }
973
 
        }
974
 
        else
975
 
        if (in < 0)
976
 
        {
977
 
           m_cancelCurrentAction = true;
978
 
           m_errorTitle = QObject::tr("Read error in ")
979
 
                           + m_curAction->copyFile.source->fileName();
980
 
           m_errorMsg   = ::strerror(errno);
981
 
           break;
982
 
        }
983
 
    }// end write loop
984
 
 
985
 
    // write loop finished, the copy might be finished
986
 
    if (!m_cancelCurrentAction
987
 
        && m_curAction->copyFile.source
988
 
        && m_curAction->copyFile.bytesWritten == m_curAction->copyFile.source->size()
989
 
        && m_curAction->copyFile.source->isOpen()
990
 
       )
991
 
    {
992
 
        copySingleFileDone = endCopySingleFile();
993
 
    }
994
 
 
995
 
    if (m_cancelCurrentAction)
996
 
    {
997
 
        if (m_curAction->copyFile.target)
998
 
        {
999
 
            if (m_curAction->copyFile.target->isOpen())
1000
 
            {
1001
 
                   m_curAction->copyFile.target->close();
1002
 
            }
1003
 
            if (m_curAction->copyFile.target->remove())
1004
 
            {               
1005
 
                emit removed(m_curAction->copyFile.targetName);
1006
 
            }
1007
 
        }
1008
 
        m_curAction->copyFile.clear();
1009
 
        endActionEntry();
1010
 
    }
1011
 
    else
1012
 
    {
1013
 
        if (copySingleFileDone)
1014
 
        {
1015
 
            m_curAction->copyFile.clear();
1016
 
            //whem the whole copy could be done just in one call
1017
 
            //do not schedule to call copyEntry()
1018
 
            if (startBytes > 0)
1019
 
            {
1020
 
                //the whole took more than one call to copySingleFile()
1021
 
                scheduleSlot(SLOT(processCopyEntry()));
1022
 
            }
1023
 
            else
1024
 
            {   //return normally to entry loop
1025
 
                scheduleAnySlot = false;
1026
 
            }
1027
 
        }
1028
 
        else
1029
 
        {
1030
 
            notifyProgress();
1031
 
            if (m_curAction->copyFile.isEntryItem && m_curAction->copyFile.amountSavedToRefresh <= 0)
1032
 
            {
1033
 
                m_curAction->copyFile.amountSavedToRefresh = AMOUNT_COPIED_TO_REFRESH_ITEM_INFO;
1034
 
                emit changed(DirItemInfo(m_curAction->copyFile.targetName));
1035
 
            }
1036
 
            scheduleSlot(SLOT(processCopySingleFile()));
1037
 
        }
1038
 
    }
1039
 
 
1040
 
    return scheduleAnySlot;
1041
 
}
1042
 
 
1043
 
 
1044
 
//================================================================================
1045
 
/*!
1046
 
 * \brief FileSystemAction::percentWorkDone() Compute the percent of work done
1047
 
 *
1048
 
 * Copy operations are based on bytes written while remove/move operations are based on items number
1049
 
 *
1050
 
 * \return the percent of work done
1051
 
 */
1052
 
int FileSystemAction::percentWorkDone()
1053
 
{
1054
 
    int percent = 0;
1055
 
 
1056
 
    //copying empty files will have totalBytes==0
1057
 
    if ( m_curAction->totalBytes > 0 &&
1058
 
         (m_curAction->type == ActionCopy || m_curAction->type == ActionHardMoveCopy)
1059
 
       )
1060
 
    {
1061
 
        percent = (m_curAction->bytesWritten * 100) / m_curAction->totalBytes ;
1062
 
    }
1063
 
    else
1064
 
    {   //percentage based on number of items performed
1065
 
        percent = (m_curAction->currItem * 100) / m_curAction->totalItems;
1066
 
    }
1067
 
 
1068
 
    if (percent > 100)
1069
 
    {
1070
 
        percent = 100;
1071
 
    }
1072
 
    return percent;
1073
 
}
1074
 
 
1075
 
 
1076
 
//================================================================================
1077
 
/*!
1078
 
 * \brief FileSystemAction::notifyProgress() Notify the progress signal
1079
 
 *
1080
 
 * \return the percent of work done
1081
 
 */
1082
 
int FileSystemAction::notifyProgress(int forcePercent)
1083
 
{
1084
 
    int percent = forcePercent > 0 ? forcePercent :  percentWorkDone();
1085
 
    if (percent == 0)
1086
 
    {
1087
 
        percent = 1;
1088
 
    }
1089
 
    if (SHOULD_EMIT_PROGRESS_SIGNAL(m_curAction) && !m_curAction->done)
1090
 
    {
1091
 
        if (m_curAction->type == ActionHardMoveCopy ||
1092
 
            m_curAction->type ==ActionHardMoveRemove)
1093
 
        {
1094
 
            emit progress(m_curAction->currItem/2,  m_curAction->totalItems/2, percent);
1095
 
        }
1096
 
        else
1097
 
        {
1098
 
            emit progress(m_curAction->currItem,  m_curAction->totalItems, percent);
1099
 
        }
1100
 
        if (percent == 100 && m_curAction->currItem == m_curAction->totalItems)
1101
 
        {
1102
 
            m_curAction->done = true;
1103
 
        }
1104
 
    }
1105
 
    return  percent;
1106
 
}
1107
 
 
1108
 
//================================================================================
1109
 
/*!
1110
 
 * \brief FileSystemAction::copySymLink() creates the \a target as a link according to \a orig
1111
 
 * \param target full pathname of the file to be created
1112
 
 * \param orig   original file, it carries the link that \a target will point to
1113
 
 * \return true if it could create, else if not
1114
 
 */
1115
 
bool FileSystemAction::copySymLink(const QString &target, const QFileInfo &orig)
1116
 
{
1117
 
    QString link(orig.symLinkTarget());
1118
 
    QFileInfo linkFile(link);
1119
 
    if (linkFile.isAbsolute() && linkFile.absolutePath() == orig.absolutePath())
1120
 
    {
1121
 
        link = linkFile.fileName();
1122
 
    }
1123
 
#if QT_VERSION <= 0x040704
1124
 
    QString current = QDir::currentPath();
1125
 
    QDir::setCurrent(linkFile.absolutePath());
1126
 
    bool ret = QFile::link(link, target);
1127
 
    QDir::setCurrent(current);
1128
 
#else
1129
 
    bool ret = QFile::link(link, target);
1130
 
#endif
1131
 
#if DEBUG_MESSAGES
1132
 
    qDebug() << Q_FUNC_INFO << ret << target << link;
1133
 
#endif
1134
 
    return ret;
1135
 
}
1136
 
 
1137
 
//================================================================================
1138
 
void FileSystemAction::scheduleSlot(const char *slot)
1139
 
{
1140
 
#if DEBUG_MESSAGES
1141
 
    qDebug() << Q_FUNC_INFO << slot;
1142
 
#endif
1143
 
    QTimer::singleShot(0, this, slot);
1144
 
}
1145
 
 
1146
 
 
1147
 
 
1148
 
//================================================================================
1149
 
/*!
1150
 
 * \brief FileSystemAction::moveDirToTempAndRemoveItLater() moves a directory to temp and shedules it for be removed later
1151
 
 *
1152
 
 * When pasting from cut actions, directories will be totally replaced, when they already exist, they need to be removed
1153
 
 * before moving the new content, so the solution is to move them to temp directory and create another action to remove
1154
 
 * them later, after that the content is moved to a target that does not exist any more.
1155
 
 *
1156
 
 * \param dir directory name which is the target for paste operation and needs get removed first
1157
 
 */
1158
 
void FileSystemAction::moveDirToTempAndRemoveItLater(const QString& dir)
1159
 
{
1160
 
    QString tempDir;
1161
 
    {
1162
 
        //create this temporary file just to get a unique name
1163
 
        QTemporaryFile d;
1164
 
        d.setAutoRemove(true);
1165
 
        d.open();
1166
 
        d.close();
1167
 
        tempDir = d.fileName();
1168
 
    }
1169
 
#if defined(DEBUG_MESSAGES) || defined(REGRESSION_TEST_FOLDERLISTMODEL)
1170
 
    qDebug() << Q_FUNC_INFO << dir <<  "being moved to" << tempDir;
1171
 
#endif
1172
 
    if (QFile::rename(dir, tempDir))
1173
 
    {
1174
 
        if (!m_curAction->auxAction)
1175
 
        {   // this new action as Remove will remove all dirs
1176
 
            m_curAction->auxAction            = createAction(ActionRemove);
1177
 
            m_curAction->auxAction->isAux     = true;
1178
 
            m_queuedActions.append(m_curAction->auxAction);
1179
 
        }
1180
 
        addEntry(m_curAction->auxAction, tempDir);
1181
 
    }
1182
 
}
1183
 
 
1184
 
//================================================================================
1185
 
/*!
1186
 
 * \brief FileSystemAction::isBusy() just inform if there is any Action going on
1187
 
 * \return  true when there is any Action going on
1188
 
 */
1189
 
bool FileSystemAction::isBusy() const
1190
 
{
1191
 
    return m_busy;
1192
 
}
1193
 
 
1194
 
//==================================================================
1195
 
/*!
1196
 
 * \brief FileSystemAction::makeBackupNameForCurrentItem() creates a new name suitable for backup an item
1197
 
 *
1198
 
 * The item can be a folder or a single file, but it is an Entry that means it is under the path were Copy happened
1199
 
 * The newName field from current entry will be set to a suitable name
1200
 
 * \param action
1201
 
 */
1202
 
bool FileSystemAction::makeBackupNameForCurrentItem(Action *action)
1203
 
{
1204
 
    bool ret = false;
1205
 
    if (action->currEntry->alreadyExists)
1206
 
    {
1207
 
        const DirItemInfo& fi =
1208
 
              action->currEntry->reversedOrder.at(action->currEntry->reversedOrder.count() -1);
1209
 
        DirItemInfo backuped;
1210
 
        int counter=0;
1211
 
        QString name;
1212
 
        do
1213
 
        {
1214
 
            QString copy(QObject::tr(" Copy"));
1215
 
            if(++counter > 0)
1216
 
            {
1217
 
                copy += QLatin1Char('(') +
1218
 
                        QString::number(counter) +
1219
 
                        QLatin1Char(')');
1220
 
            }
1221
 
            name = fi.fileName();
1222
 
            int  pos = name.size();
1223
 
            if (!fi.isDir())
1224
 
            {
1225
 
                int dot = name.lastIndexOf(QChar('.'));
1226
 
                if (dot != -1)
1227
 
                {
1228
 
                    pos = dot;
1229
 
                }
1230
 
            }
1231
 
            name.insert(pos,copy);
1232
 
            backuped.setFile(fi.absolutePath(), name);
1233
 
        } while (backuped.exists() && counter < 100);
1234
 
        if (counter < 100)
1235
 
        {
1236
 
            action->currEntry->newName = new QString(backuped.fileName());
1237
 
            ret = true;
1238
 
        }
1239
 
    }
1240
 
    return ret;
1241
 
}
1242
 
 
1243
 
//==================================================================
1244
 
/*!
1245
 
 * \brief FileSystemAction::getProgressCounter
1246
 
 * \return number of progress notification from current Action
1247
 
 */
1248
 
int FileSystemAction::getProgressCounter() const
1249
 
{
1250
 
    int steps = 0;
1251
 
    if (m_curAction)
1252
 
    {
1253
 
        steps = m_curAction->steps;
1254
 
    }
1255
 
    return steps;
1256
 
}
1257
 
 
1258
 
 
1259
 
//==================================================================
1260
 
bool FileSystemAction::endCopySingleFile()
1261
 
{
1262
 
    bool ret = true;
1263
 
    m_curAction->copyFile.source->close();
1264
 
    m_curAction->copyFile.target->close();
1265
 
    m_cancelCurrentAction = !m_curAction->copyFile.target->setPermissions(
1266
 
                                 m_curAction->copyFile.source->permissions());
1267
 
    if (m_cancelCurrentAction)
1268
 
    {
1269
 
        m_errorTitle = QObject::tr("Set permissions error in ")
1270
 
                        + m_curAction->copyFile.targetName,
1271
 
        m_errorMsg   = ::strerror(errno);
1272
 
        ret          = false;
1273
 
    }
1274
 
    return ret;
1275
 
}
1276
 
 
1277
 
//==================================================================
1278
 
bool FileSystemAction::isThereDiskSpace(qint64 requiredSize)
1279
 
{
1280
 
    bool ret = true;
1281
 
#if defined(Q_OS_UNIX)
1282
 
    struct statvfs  vfs;
1283
 
    if ( ::statvfs( QFile::encodeName(m_path).constData(), &vfs) == 0 )
1284
 
    {
1285
 
        qint64 free =  vfs.f_bsize * vfs.f_bfree;
1286
 
        ret = free > requiredSize;
1287
 
    }
1288
 
#endif
1289
 
   return ret;
1290
 
}
1291
 
 
1292
 
 
1293
 
//==================================================================
1294
 
/*!
1295
 
 * \brief FileSystemAction::onClipboardChanged()
1296
 
 *
1297
 
 *  sets \ref m_clipboardChanged indicating the fhe Clipboard was changed.
1298
 
 */
1299
 
void FileSystemAction::onClipboardChanged()
1300
 
{
1301
 
    m_clipboardChanged = true;
1302
 
}