~carlos-mazieri/ubuntu-filemanager-app/model

« back to all changes in this revision

Viewing changes to folderlistmodel/filesystemaction.cpp

  • Committer: carlos.mazieri at gmail
  • Date: 2013-12-31 16:57:19 UTC
  • Revision ID: carlos.mazieri@gmail.com-20131231165719-8jrz2gfz1h3l33d5
Copy files no longer is saved into temporary file first then renamed to final item
Disk space verified before Copy
Added notification to refresh file information every 50 MB bytes copied

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
 */
36
36
 
37
37
#include "filesystemaction.h"
 
38
 
 
39
#if defined(Q_OS_UNIX)
38
40
#include <sys/statvfs.h>
 
41
#endif
 
42
 
39
43
#include <errno.h>
40
44
 
41
45
#include <QDirIterator>
720
724
    if (curEntry->currItem == curEntry->reversedOrder.count())
721
725
    {
722
726
        const QFileInfo & mainItem = curEntry->reversedOrder.at(curEntry->currItem -1);
723
 
        if (m_curAction->type == ActionRemove || m_curAction->type == ActionMove ||
724
 
                m_curAction->type == ActionHardMoveRemove)
725
 
        {
726
 
            emit removed(mainItem);
727
 
        }
728
 
        if (m_curAction->type == ActionCopy || m_curAction->type == ActionMove ||
729
 
            m_curAction->type == ActionHardMoveCopy)
730
 
        {
731
 
            bool toAdd = true;
732
 
            QString addedItem = targetFom(mainItem.absoluteFilePath(), m_curAction);
733
 
            if (curEntry->alreadyExists && curEntry->newName == 0)
734
 
            {
735
 
                //if an item already exists there are two possibilities:
736
 
                //   1. emit removed(), then emit added()
737
 
                //   2. emit removedThenAdded() which should be attached to a kind of change slot
738
 
                if (m_curAction->type == ActionHardMoveCopy)
739
 
                {
740
 
                    emit removed(addedItem);
741
 
                }
742
 
                else
743
 
                {   //ActionCopy ActionMove
744
 
                    emit removedThenAdded(QFileInfo(addedItem));
745
 
                    toAdd = false;
746
 
                }
747
 
            }
748
 
            if(toAdd)
749
 
            {
750
 
                emit added(addedItem);
751
 
            }
752
 
        }
753
727
        m_curAction->currEntryIndex++;
754
 
        //check if is doing a hard move and the copy part has finished
755
 
        //if so switch the action to remove
756
 
        if (m_curAction->type == ActionHardMoveCopy &&
757
 
                m_curAction->currEntryIndex == m_curAction->entries.count() )
 
728
        switch(m_curAction->type)
758
729
        {
759
 
            m_curAction->type      = ActionHardMoveRemove;
760
 
            m_curAction->currEntryIndex = 0;
761
 
            int entryCounter = m_curAction->entries.count();
762
 
            ActionEntry * entry;
763
 
            while (entryCounter--)
764
 
            {
765
 
                entry = m_curAction->entries.at(entryCounter);
766
 
                entry->currItem = 0;
767
 
                entry->currStep = 0;
768
 
            }
769
 
        }
770
 
    }
 
730
           case ActionRemove:           
 
731
                emit removed(mainItem);
 
732
                break;
 
733
           case ActionHardMoveRemove: // nothing to do
 
734
                break;
 
735
           case ActionHardMoveCopy:
 
736
                //check if is doing a hard move and the copy part has finished
 
737
                //if so switch the action to remove
 
738
                if (m_curAction->currEntryIndex == m_curAction->entries.count())
 
739
                {
 
740
                   m_curAction->type      = ActionHardMoveRemove;
 
741
                   m_curAction->currEntryIndex = 0;
 
742
                   int entryCounter = m_curAction->entries.count();
 
743
                   ActionEntry * entry;
 
744
                   while (entryCounter--)
 
745
                   {
 
746
                       entry = m_curAction->entries.at(entryCounter);
 
747
                       entry->currItem = 0;
 
748
                       entry->currStep = 0;
 
749
                   }
 
750
                }
 
751
           case ActionCopy: // ActionHardMoveCopy is also checked here
 
752
           case ActionMove:
 
753
                {
 
754
                    QString addedItem = targetFom(mainItem.absoluteFilePath(), m_curAction);
 
755
                    if (!curEntry->added && !curEntry->alreadyExists)
 
756
                    {
 
757
                        emit added(addedItem);
 
758
                        curEntry->added = true;
 
759
                    }
 
760
                    else
 
761
                    {
 
762
                        emit changed(QFileInfo(addedItem));
 
763
                    }
 
764
                }
 
765
                break;
 
766
        }//switch
 
767
 
 
768
    }//end if (curEntry->currItem == curEntry->reversedOrder.count())
 
769
 
771
770
    if (curEntry->currStep == STEP_FILES)
772
771
    {
773
772
        curEntry->currStep = 0;
908
907
        QString path(target);
909
908
        // do this here to allow progress send right item number, copySingleFile will emit progress()
910
909
        m_curAction->currItem++;
911
 
 
 
910
        //--
912
911
        if (fi.isFile() || fi.isSymLink())
913
912
        {
914
913
            QFileInfo  t(target);
915
914
            path = t.path();
916
915
        }
 
916
        //check if the main item in the entry is a directory
 
917
        //if so it needs to appear on any attached view
 
918
        if (   m_curAction->currItem == 1
 
919
            && entry->reversedOrder.last().isDir()
 
920
            && !entry->reversedOrder.last().isSymLink()
 
921
           )
 
922
        {
 
923
            QString entryDir = targetFom(entry->reversedOrder.last().absoluteFilePath(), m_curAction);
 
924
            QDir entryDirObj(entryDir);
 
925
            if (!entryDirObj.exists() && entryDirObj.mkpath(entryDir))
 
926
            {
 
927
                emit added(entryDir);
 
928
                entry->added = true;
 
929
            }
 
930
        }
917
931
        QDir d(path);
918
932
        if (!d.exists() && !d.mkpath(path))
919
933
        {
947
961
        else
948
962
        if (fi.isFile())
949
963
        {
 
964
            qint64 needsSize = 0;
950
965
            m_curAction->copyFile.clear();
951
966
            m_curAction->copyFile.source = new QFile(orig);
952
 
            if (!m_curAction->copyFile.source->open(QFile::ReadOnly))
953
 
            {
954
 
                m_cancelCurrentAction = true;
 
967
            m_cancelCurrentAction = !m_curAction->copyFile.source->open(QFile::ReadOnly);
 
968
            if (m_cancelCurrentAction)
 
969
            {               
955
970
                m_errorTitle = QObject::tr("Could not open file");
956
971
                m_errorMsg   = orig;
957
972
            }
958
 
            m_curAction->copyFile.target = new QTemporaryFile();
959
 
            if (! m_curAction->copyFile.target->open())
960
 
            {
961
 
                m_cancelCurrentAction = true;
962
 
                m_errorTitle = QObject::tr("Could not create temporary file");
963
 
                m_errorMsg   =  m_curAction->copyFile.target->fileName();
964
 
            }
965
 
            m_curAction->copyFile.targetName = target;
966
 
            scheduleAnySlot =  processCopySingleFile();
967
 
        }
 
973
            else
 
974
            {
 
975
                needsSize = m_curAction->copyFile.source->size();
 
976
                //create destination
 
977
                m_curAction->copyFile.target = new QFile(target);             
 
978
                m_curAction->copyFile.targetName = target;
 
979
                //first open it read-only to get its size if exists
 
980
                if (m_curAction->copyFile.target->open(QFile::ReadOnly))
 
981
                {
 
982
                    needsSize -= m_curAction->copyFile.target->size();
 
983
                    m_curAction->copyFile.target->close();
 
984
                }
 
985
                //check if there is disk space to copy source to target
 
986
                if (needsSize > 0 && !isThereDiskSpace( needsSize ))
 
987
                {
 
988
                    m_cancelCurrentAction = true;
 
989
                    m_errorTitle = QObject::tr("There is no space on disk to copy");
 
990
                    m_errorMsg   =  m_curAction->copyFile.target->fileName();
 
991
                }
 
992
            }
 
993
            if (!m_cancelCurrentAction)
 
994
            {
 
995
                m_cancelCurrentAction =
 
996
                        !m_curAction->copyFile.target->open(QFile::WriteOnly | QFile::Truncate);
 
997
                if (m_cancelCurrentAction)
 
998
                {
 
999
                    m_errorTitle = QObject::tr("Could not create file");
 
1000
                    m_errorMsg   =  m_curAction->copyFile.target->fileName();
 
1001
                }
 
1002
            }
 
1003
            if (!m_cancelCurrentAction)
 
1004
            {
 
1005
                m_curAction->copyFile.isEntryItem = entry->currItem  == (entry->reversedOrder.count() -1);
 
1006
                scheduleAnySlot =  processCopySingleFile();
 
1007
                //main item from the entry. notify views new item inserted,
 
1008
                //depending on the file size it may take longer, the view needs to be informed
 
1009
                if (m_curAction->copyFile.isEntryItem && !m_cancelCurrentAction)
 
1010
                {
 
1011
                    if (!entry->alreadyExists)
 
1012
                    {
 
1013
                       emit added(target);
 
1014
                       entry->added = true;
 
1015
                    }
 
1016
                    else
 
1017
                    {
 
1018
                        emit changed(QFileInfo(target));
 
1019
                    }
 
1020
                }
 
1021
            }
 
1022
        }//end isFile
968
1023
    }//for
969
1024
 
970
1025
    //no copy going on
999
1054
        //rename will fail
1000
1055
        if (targetInfo.exists())
1001
1056
        {
 
1057
            //will not emit removed() neither added()
 
1058
            entry->added = true;
1002
1059
            if (targetInfo.isFile() || targetInfo.isSymLink())
1003
1060
            {
1004
1061
                if (!QFile::remove(target))
1012
1069
            if (targetInfo.isDir())
1013
1070
            {
1014
1071
               //move target to /tmp and remove it later by creating an Remove action
 
1072
               //this will emit removed()
1015
1073
               moveDirToTempAndRemoveItLater(target);
1016
1074
            }
1017
1075
        }
1206
1264
    unsigned long originFsId = 0xfffe;
1207
1265
#if defined(Q_OS_UNIX)
1208
1266
    struct statvfs  vfs;
1209
 
    if ( ::statvfs(m_path.toLatin1().constData(), &vfs) == 0 )
 
1267
    if ( ::statvfs( QFile::encodeName(m_path).constData(), &vfs) == 0 )
1210
1268
    {
1211
1269
        targetFsId = vfs.f_fsid;
1212
1270
    }
1213
 
    if ( ::statvfs(itemToMovePathname.toLatin1().constData(), &vfs) == 0)
 
1271
    if ( ::statvfs(QFile::encodeName(itemToMovePathname).constData(), &vfs) == 0)
1214
1272
    {
1215
1273
        originFsId = vfs.f_fsid;
1216
1274
    }   
1309
1367
            }
1310
1368
            m_curAction->bytesWritten          += in;
1311
1369
            m_curAction->copyFile.bytesWritten += in;
 
1370
            if (m_curAction->copyFile.isEntryItem)
 
1371
            {
 
1372
                m_curAction->copyFile.amountSavedToRefresh -= in;
 
1373
            }
1312
1374
        }
1313
1375
        else
1314
1376
        if (in < 0)
1328
1390
        && m_curAction->copyFile.source->isOpen()
1329
1391
       )
1330
1392
    {
1331
 
        m_curAction->copyFile.source->close();
1332
 
        m_curAction->copyFile.target->close();
1333
 
        m_curAction->copyFile.target->setAutoRemove(false);
1334
 
        m_cancelCurrentAction = !m_curAction->copyFile.target->setPermissions(
1335
 
                                     m_curAction->copyFile.source->permissions());
1336
 
        if (m_cancelCurrentAction)
1337
 
        {
1338
 
            m_errorTitle = QObject::tr("Set permissions error in ")
1339
 
                            + m_curAction->copyFile.targetName,
1340
 
            m_errorMsg   = ::strerror(errno);
1341
 
        }
1342
 
        else
1343
 
        {
1344
 
            QFile testExistTarget(m_curAction->copyFile.targetName);
1345
 
            if (testExistTarget.exists())
1346
 
            {
1347
 
                if ((m_cancelCurrentAction = ! testExistTarget.remove()))
1348
 
                {
1349
 
                    m_errorTitle = QObject::tr("Could not remove original file ")
1350
 
                                    + m_curAction->copyFile.targetName,
1351
 
                    m_errorMsg   = ::strerror(errno);
1352
 
                }
1353
 
            }
1354
 
            if (!m_cancelCurrentAction)
1355
 
            {
1356
 
                m_cancelCurrentAction = ! m_curAction->copyFile.target->
1357
 
                        rename(m_curAction->copyFile.targetName);
1358
 
                if (m_cancelCurrentAction)
1359
 
                {
1360
 
                    m_errorTitle = QObject::tr("Rename error: renaming to ")
1361
 
                            + m_curAction->copyFile.targetName,
1362
 
                            m_errorMsg   = ::strerror(errno);
1363
 
                }
1364
 
                else
1365
 
                {
1366
 
                    copySingleFileDone = true;
1367
 
                }
1368
 
            }
1369
 
        }
 
1393
        copySingleFileDone = endCopySingleFile();
1370
1394
    }
1371
1395
 
1372
1396
    if (m_cancelCurrentAction)
1373
1397
    {
1374
1398
        if (m_curAction->copyFile.target)
1375
1399
        {
1376
 
            m_curAction->copyFile.target->setAutoRemove(true);
 
1400
            if (m_curAction->copyFile.target->isOpen())
 
1401
            {
 
1402
                   m_curAction->copyFile.target->close();
 
1403
            }
 
1404
            if (m_curAction->copyFile.target->remove())
 
1405
            {               
 
1406
                emit removed(m_curAction->copyFile.targetName);
 
1407
            }
1377
1408
        }
1378
1409
        m_curAction->copyFile.clear();
1379
1410
        endActionEntry();
1398
1429
        else
1399
1430
        {
1400
1431
            notifyProgress();
 
1432
            if (m_curAction->copyFile.isEntryItem && m_curAction->copyFile.amountSavedToRefresh <= 0)
 
1433
            {
 
1434
                m_curAction->copyFile.amountSavedToRefresh = AMOUNT_COPIED_TO_REFRESH_ITEM_INFO;
 
1435
                emit changed(QFileInfo(m_curAction->copyFile.targetName));
 
1436
            }
1401
1437
            scheduleSlot(SLOT(processCopySingleFile()));
1402
1438
        }
1403
1439
    }
1652
1688
         emit clipboardChanged();
1653
1689
     }
1654
1690
}
 
1691
 
 
1692
 
 
1693
//==================================================================
 
1694
bool FileSystemAction::endCopySingleFile()
 
1695
{
 
1696
    bool ret = true;
 
1697
    m_curAction->copyFile.source->close();
 
1698
    m_curAction->copyFile.target->close();
 
1699
    m_cancelCurrentAction = !m_curAction->copyFile.target->setPermissions(
 
1700
                                 m_curAction->copyFile.source->permissions());
 
1701
    if (m_cancelCurrentAction)
 
1702
    {
 
1703
        m_errorTitle = QObject::tr("Set permissions error in ")
 
1704
                        + m_curAction->copyFile.targetName,
 
1705
        m_errorMsg   = ::strerror(errno);
 
1706
        ret          = false;
 
1707
    }
 
1708
    return ret;
 
1709
}
 
1710
 
 
1711
//==================================================================
 
1712
bool FileSystemAction::isThereDiskSpace(qint64 requiredSize)
 
1713
{
 
1714
    bool ret = true;
 
1715
#if defined(Q_OS_UNIX)
 
1716
    struct statvfs  vfs;
 
1717
    if ( ::statvfs( QFile::encodeName(m_path).constData(), &vfs) == 0 )
 
1718
    {
 
1719
        qint64 free =  vfs.f_bsize * vfs.f_bfree;
 
1720
        ret = free > requiredSize;
 
1721
    }
 
1722
#endif
 
1723
   return ret;
 
1724
}