Logo Search packages:      
Sourcecode: ultracopier version File versions  Download package

CopyThread.cpp

/***************************************************************************
                        CopyThread.cpp
                        -------------------
 
     Begin  : Fri Dec 21 2007 22:48 alpha_one_x86
     Project      : Ultracopier
     Email  : ultracopier@first-world.info
     Note    : See README for copyright and developer
     Target  : Define the class of the copy threads
 
****************************************************************************/

#include "env.h"
#include "CopyThread.h"

/*! \todo checksun while copy
  \todo check block size is really 1MB and not 1KB and is correctly loaded from default options
  \todo Dir source and destination need be as QDir as param of methode
  \todo list the variable used in concurrent access and check mutex on it
  */

/*! \brief Initialise the copy thread
*/
00024 copyThread::copyThread(Main_window * parent) :
      QThread((QObject*)parent)
{
      RightCopy         = false;
      maxSpeed          = 0;
      stopped                 = true;
      movingMode        = false;
      blockSizeCurrent  = 1024*1024;
      preallocation           = false;
      keepDate          = false;
      theCurrentStat          = Stopped;
      totalCopiedSize         = 0;
      previousSizeReturned    = 0;
      numberOfItemRemoved     = 0;
      actionAfterUnlock = -1;
      firstScanTot            = 0;
      firstScanCur            = 0;
      NumberOfFileTot         = 0;
      NumberOfFileCopied      = 0;
      currentFileSize         = 0;
      currentFileTotPos = 0;
      syntetizedStringCurrentFile= "";
      syntetizedStringOverall = "";
      syntetizedStringTo      = "";
      syntetizedStringFrom    = "";
      copyHadBegin            = false;
      useWriteThread          = false;
      timeCopyElapsed         = 0;
      writeThreadSem          = new QSemaphore(MAXWRITETHREAD);
      #if (DEBUG_ULTRACOPIER>0)
      theCurrentWait          = NoWait;
      #endif

      intervalCopySpeed.start();

      this->parent            = parent;

      connect(&clockForTheCopySpeed,      SIGNAL(timeout()),            this, SLOT(timeOfTheBlockCopyFinished()));
      connect(this,                 SIGNAL(started()),            this, SLOT(pre_operation()));
      connect(this,                 SIGNAL(finished()),           this, SLOT(post_operation()));
      connect(this,                 SIGNAL(queryNewWriteThread()),      this, SLOT(createNewWriteThread()));
      connect(this,                 SIGNAL(queryStartThread(int)),      this, SLOT(startWriteThread(int)));

      //load the translation
      translationOfCopyOf           = tr("Copy of") + " ";
      translationErrorResize        = tr("The file cannot be resized") + ": ";
      translationErrorWriting       = tr("Error in writing destination") + ": ";
      translationErrorDate          = tr("Date cannot be modified!");
      translationErrorRemove        = tr("Unable to remove the source file in moving mode") + ": ";
      translationErrorSourceReadWrite     = tr("Unable to open source file in read/write mode") + ": ";
      translationErrorSourceRead    = tr("Unable to open source file in read mode") + ": ";
      translationErrorDestinationWrite= tr("Unable to open destination file in write mode") + ": ";
      translationErrorPermissions   = tr("The permissions cannot be modified") + ": ";
      translationErrorReadSource    = tr("Error while reading source file") + ": ";
      translationDay                = " " + tr("day");
      translationDays               = " " + tr("days");
      translationHour               = " " + tr("hour");
      translationHours        = " " + tr("hours");
      translationMinute       = " " + tr("minute");
      translationMinutes            = " " + tr("minutes");
      translationSecond       = " " + tr("second");
      translationSeconds            = " " + tr("seconds");
}

/** \brief The destructor
\see copyThread()
*/
00091 copyThread::~copyThread()
{
      DEBUGCONSOLE(90,"copyThread::~copyThread","start");
      stopTheCopy();
      DEBUGCONSOLE(90,"copyThread::~copyThread","delete the write thread");
      {
            QMutexLocker lock_mutex(&MultiThread_ThreadList);
            while(theWriteThreadList.size()>0) {
                  theWriteThreadList.first()->stop();
                  theWriteThreadList.first()->disconnect();
                  delete theWriteThreadList.first();
                  theWriteThreadList.removeFirst();
            }
      }
      DEBUGCONSOLE(90,"copyThread::~copyThread","check the current thread");
      if(isRunning())
      {
            DEBUGCONSOLE(90,"copyThread::~copyThread","seam be running, wait");
            wait(5000);
      }
      delete writeThreadSem;
      DEBUGCONSOLE(90,"copyThread::~copyThread","stop");
}

/// \brief return text overall
00116 QString copyThread::getSyntetizedStringTo()
{
      QString temp=syntetizedStringTo;
      syntetizedStringTo="";
      return temp;
}

/// \brief return string to
00124 QString copyThread::getSyntetizedStringFrom()
{
      QString temp=syntetizedStringFrom;
      syntetizedStringFrom="";
      return temp;
}

/// \brief check if need wait write thread
00132 void copyThread::checkIfNeedWaitWriteThread()
{
      for (int i = 0; i < theWriteThreadList.size(); ++i) {
            checkIfNeedWaitOneWriteThread(theWriteThreadList.at(i));
      }
}

/// \brief check if need wait one write thread
00140 void copyThread::checkIfNeedWaitOneWriteThread(WriteThread* theWriteThreadToCheck)
{
      if(theWriteThreadToCheck->getTheCurrentStat()==WriteThread::PausedInError)
      {
            actionAfterUnlock=-1;
            writeThreadError temp=theWriteThreadToCheck->getTheCurrentError();
            DEBUGCONSOLE(70,"copyThread::checkIfNeedWaitWriteThread","In write thread "+QString::number(theWriteThreadList.indexOf(theWriteThreadToCheck))+" error: "+temp.error_file+": "+temp.error_string);
            emit errorOnFile(temp.error_code,temp.error_file,temp.error_string,temp.error_itemId);
            waitNeedAction();
            if(actionAfterUnlock==FILEEXIST_ACTION_CANCEL)
                  stopTheCopy();
            else if(theWriteThreadToCheck==theCurrentThread && actionAfterUnlock==ERRORACTION_SKIP)
                  skipCurrentFile();
            else if(actionAfterUnlock==ERRORACTION_ENDOF)
            {
                  if(theWriteThreadToCheck==theCurrentThread)
                        putFirstFileAtEnd();
                  else
                  {
                        copyItemInternal tempItem;
                        tempItem=theWriteThreadToCheck->getCopyItemInternal();
                        putAtEnd<<tempItem;
                        firstScanTot+=tempItem.size;
                        NumberOfFileTot++;
                        syntetizedStringOverall="File "+QString::number(NumberOfFileCopied)+"/"+QString::number(NumberOfFileTot)+", Total: "+intToQtringSize(firstScanTot);
                        QMutexLocker lock_mutex(&MultiThreadCopyList);
                        theCopyList<<tempItem;
                  }
            }
            theWriteThreadToCheck->errorAction(actionAfterUnlock);
      }
}

/// \brief wait because need action
00174 void copyThread::waitNeedAction()
{
      DEBUGCONSOLE(90,"copyThread::waitNeedAction","start");
      timeCopyElapsed+=tempTimeElapsed.elapsed();
      theCurrentStat=copyThread::Paused;
      if(waitInPause)
            emit isInPauseOrNot();
      waitAction.acquire();
      theCurrentStat=copyThread::Running;
      tempTimeElapsed.restart();
}

/// \brief create new write thread
00187 void copyThread::createNewWriteThread()
{
      DEBUGCONSOLE(90,"copyThread::createNewWriteThread","start");
      theCurrentThread=new WriteThread(this);
      #if (DEBUG_ULTRACOPIER>0)
      {
            QMutexLocker lock_mutex(&MultiThread_ThreadList);
            theCurrentThread->setId(theWriteThreadList.size());
      }
      #endif
      theCurrentThread->setMovingMode(movingMode);
      theCurrentThread->start(this->priority());
      {
            QMutexLocker lock_mutex(&MultiThread_ThreadList);
            theWriteThreadList.append(theCurrentThread);
      }
      connect(theCurrentThread,     SIGNAL(finished()),                 this, SLOT(newWriteThreadFinish()));
      connect(theCurrentThread,     SIGNAL(haveFinishFileOperation()),  this, SLOT(writeThreadOperationFinish()));
      waitNewWriteThread.release();
      DEBUGCONSOLE(90,"copyThread::createNewWriteThread","stop");
}

00209 void copyThread::startWriteThread(int id)
{
      theWriteThreadList.at(id)->start(this->priority());
      waitNewWriteThread.release();
}

00215 void copyThread::writeThreadOperationFinish()
{
      DEBUGCONSOLE(90,"copyThread::writeThreadOperationFinish","start");
      #if (DEBUG_ULTRACOPIER>0)
      if(writeThreadSem->available()>MAXWRITETHREAD)
            DEBUGCONSOLE(10,"copyThread::writeThreadOperationFinish","The autorised max thread is not limited! Internal bug.");
      #endif
      writeThreadSem->release();
      DEBUGCONSOLE(90,"copyThread::writeThreadOperationFinish","stop");
}

/// \brief set action on file exist
00227 void copyThread::fileExistsAction(int action)
{
      DEBUGCONSOLE(50,"copyThread::fileExistsAction","action: "+QString::number(action));
      actionAfterUnlock=action;
      if(action==FILEEXIST_ACTION_CANCEL)
            stopTheCopy();
      waitAction.release();
}

/// \brief number of item removed
00237 int copyThread::getNumberOfItemRemoved()
{
      int numberOfItemRemoved=this->numberOfItemRemoved;
      this->numberOfItemRemoved=0;
      return numberOfItemRemoved;
}

/// \brief return the statut
00245 copyThread::currentStat copyThread::getCurrentStat()
{
      return theCurrentStat;
}

//insert at end without count
void copyThread::insterAtEndWithoutCount(copyItemInternal theItem)
{
      QMutexLocker lock_mutex(&MultiThreadCopyList);
      NumberOfFileCopied--;
      firstScanCur-=theItem.size;
      theCopyList.append(theItem);
}

/// \brief get current file copied as String as Name and size
00260 QString copyThread::getCurrentFileCopied()
{
      QString syntetizedStringCurrentFile=this->syntetizedStringCurrentFile;
      this->syntetizedStringCurrentFile="";
      return syntetizedStringCurrentFile;
}

/// \brief return text overall
00268 QString copyThread::getTextOverall()
{
      QString syntetizedStringOverall=this->syntetizedStringOverall;
      this->syntetizedStringOverall="";
      return syntetizedStringOverall;
}

/// \brief return the right string precision
00276 QString copyThread::adaptStr(float nb)
{
    if(nb>=100)
      return QString::number(nb,'f',0);
    else
      return QString::number(nb,'g',3);
}

/// \brief Return string for the size
00285 QString copyThread::intToQtringSize(double nb)
{
      if(nb<1024)
            return QString::number(nb)+tr("B");
      if((nb=nb/1024)<1024)
            return adaptStr(nb)+"K"+tr("B");
      if((nb=nb/1024)<1024)
            return adaptStr(nb)+"M"+tr("B");
      if((nb=nb/1024)<1024)
            return adaptStr(nb)+"G"+tr("B");
      if((nb=nb/1024)<1024)
            return adaptStr(nb)+"T"+tr("B");
      if((nb=nb/1024)<1024)
            return adaptStr(nb)+"P"+tr("B");
      return tr( "Too big" );
}

//set thread write
void copyThread::setThreadWrite(int useWriteThread)
{
      this->useWriteThread=useWriteThread;
}

/// \brief set action on error
00309 void copyThread::errorAction(int action)
{
      DEBUGCONSOLE(50,"copyThread::fileExistsAction","action: "+QString::number(action));
      actionAfterUnlock=action;
      if(action==ERRORACTION_CLOSE)
            stopTheCopy();
      waitAction.release();
}

//pause the copy
void copyThread::pauseCopy()
{
      DEBUGCONSOLE(90,"copyThread::pauseCopy","start");
      if(theCurrentStat==copyThread::Running)
            waitInPause=true;
      else
      {
            //alpha_one_x86: possibility to be where, I don't know why
            DEBUGCONSOLE(10,"copyThread::pauseCopy","Copy thread not running");
      }
}

//resume the copy
void copyThread::resumeCopy()
{
      DEBUGCONSOLE(90,"copyThread::resumeCopy","waitInPause=false");
      waitInPause=false;
      if(theCurrentStat==copyThread::Paused)
      {
            //this line is uncommented because, the resume not work, repported by user
            //should stay uncomment, if bug fix it by other ways
            waitAction.release();
      }
      else
      {
            if(theCurrentStat==copyThread::Stopped)
            {
                  DEBUGCONSOLE(10,"copyThread::resumeCopy","Copy thread stopped, cannot be resume");
            }
            else
            {
                  DEBUGCONSOLE(70,"copyThread::resumeCopy","Copy thread not in pause, is running?");
            }
      }
}

//skip the current file
00356 void copyThread::skipCurrentFile()
{
      DEBUGCONSOLE(90,"copyThread::skipCurrentFile","start");
      /// \todo skip the current file here
      if(theCurrentStat==copyThread::Stopped)
      {
            QList<int> ids;
            {
                  QMutexLocker lock_mutex(&MultiThreadCopyList);
                  if(theCopyList.size())
                        ids<<theCopyList.first().id;
            }
            if(ids.size())
                  removeItems(ids);
      }
      else
      {
            stopIt=true;
            skipThecurrentFile=true;
      }
}

//remove one entry
//warning the first entry is accessible will copy
void copyThread::removeItems(QList<int> ids)
{
      DEBUGCONSOLE(70,"copyThread::removeItems","start");
      if(ids.size()==0)
            return;
      //do list operation
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            int first=0;
            if(theCurrentStat!=Stopped)
                  first=1;
            for (int i=first; i < theCopyList.size(); ++i) {
                  if(ids.indexOf(theCopyList.at(i).id)!=-1)
                  {
                        DEBUGCONSOLE(90,"copyThread::removeItems",QString("remove: ")+theCopyList.at(i).source.absoluteFilePath()+" ("+intToQtringSize(theCopyList.at(i).size)+") and "+theCopyList.at(i).destination.absoluteFilePath());
                        firstScanCur+=theCopyList.at(i).size;
                        theCopyList.removeAt(i);
                        //bug, this variable is do for remove the top level item
                        //numberOfItemRemoved++;
                        NumberOfFileCopied++;
                        i--;
                  }
            }
      }
      DEBUGCONSOLE(90,"copyThread::removeItems","stop");
      syntetizedStringOverall="File "+QString::number(NumberOfFileCopied)+"/"+QString::number(NumberOfFileTot)+", Total: "+intToQtringSize(firstScanTot);
}

//put on top
returnIdsTransaction copyThread::putOnTop(QList<int> ids)
{
      DEBUGCONSOLE(70,"copyThread::putOnTop","start");
      returnIdsTransaction returnVar;
      //do list operation
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            if(ids.size()==0 || theCopyList.size()<=1)
                  return returnVar;
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::putOnTop"," before argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
            int first=0;
            if(theCurrentStat!=Stopped)
                  first=1;
            int indexToMove=first;
            for (int i=first; i<theCopyList.size(); ++i) {
                  if(ids.indexOf(theCopyList.at(i).id)!=-1)
                  {
                        returnVar.idsAction.append(theCopyList.at(i).id);
                        ids.removeOne(theCopyList.at(i).id);
                        DEBUGCONSOLE(90,"copyThread::putOnTop",QString("move item ")+QString::number(i)+" to "+QString::number(indexToMove));
                        theCopyList.move(i,indexToMove);
                        indexToMove++;
                  }
            }
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::putOnTop"," after argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
      }
      DEBUGCONSOLE(70,"copyThread::putOnTop","stop");
      returnVar.idsRemove=ids;
      return returnVar;
}

//move up
returnIdsTransaction copyThread::moveUp(QList<int> ids)
{
      DEBUGCONSOLE(70,"copyThread::moveUp","start");
      returnIdsTransaction returnVar;
      //do list operation
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            if(ids.size()==0 || theCopyList.size()<=1)
                  return returnVar;
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::moveUp"," before argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
            int first=1;
            if(theCurrentStat!=Stopped)
                  first=2;
            bool entryIsMovable=(ids.indexOf(theCopyList.at(first-1).id)==-1);
            for (int i=first; i<theCopyList.size(); ++i) {
                  if(ids.indexOf(theCopyList.at(i).id)!=-1)
                  {
                        if(entryIsMovable)
                        {
                              returnVar.idsAction.append(theCopyList.at(i).id);
                              DEBUGCONSOLE(90,"copyThread::moveUp",QString("move item ")+QString::number(i)+" to "+QString::number(i-1));
                              theCopyList.swap(i,i-1);
                        }
                        else
                        {
                              DEBUGCONSOLE(10,"copyThread::moveUp",QString("Try move up false, item ")+QString::number(i));
                        }
                        ids.removeOne(theCopyList.at(i).id);
                  }
                  else
                  {
                        entryIsMovable=true;
                  }
            }
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::moveUp"," after argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
      }
      DEBUGCONSOLE(70,"copyThread::moveUp","stop");
      returnVar.idsRemove=ids;
      return returnVar;
}

//move down
returnIdsTransaction copyThread::moveDown(QList<int> ids)
{
      DEBUGCONSOLE(70,"copyThread::moveDown","start");
      returnIdsTransaction returnVar;
      //do list operation
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            if(ids.size()==0 || theCopyList.size()<=1)
                  return returnVar;
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::moveDown"," before argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
            int first=theCopyList.size()-1;
            if(theCurrentStat!=Stopped)
                  first++;
            bool entryIsMovable=(ids.indexOf(theCopyList.at(theCopyList.size()-1).id)==-1);
            for (int i=first; i>=0; --i) {
                  if(ids.indexOf(theCopyList.at(i).id)!=-1)
                  {
                        if(entryIsMovable)
                        {
                              DEBUGCONSOLE(90,"copyThread::moveDown",QString("move item ")+QString::number(i)+" to "+QString::number(i+1));
                              returnVar.idsAction.append(theCopyList.at(i).id);
                              theCopyList.swap(i,i+1);
                        }
                        else
                        {
                              DEBUGCONSOLE(10,"copyThread::moveDown",QString("Try move up false, item ")+QString::number(i));
                        }
                        ids.removeOne(theCopyList.at(i).id);
                  }
                  else
                        entryIsMovable=true;
            }
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::moveDown"," after argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
      }
      DEBUGCONSOLE(70,"copyThread::moveDown","stop");
      returnVar.idsRemove=ids;
      return returnVar;
}

//put on bottom
returnIdsTransaction copyThread::putOnBottom(QList<int> ids)
{
      DEBUGCONSOLE(70,"copyThread::putOnBottom","start");
      returnIdsTransaction returnVar;
      //do list operation
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            if(ids.size()==0 || theCopyList.size()<=1)
                  return returnVar;
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::putOnBottom"," before argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
            int onTop=0;
            if(theCurrentStat!=Stopped)
                  onTop=1;
            int indexToMove=theCopyList.size()-1;
            for (int i=theCopyList.size()-1; i>=onTop; --i) {
                  DEBUGCONSOLE(90,"copyThread::putOnBottom",QString("Check action on item ")+QString::number(i));
                  if(ids.indexOf(theCopyList.at(i).id)!=-1)
                  {
                        DEBUGCONSOLE(90,"copyThread::putOnBottom",QString("move item ")+QString::number(i)+" to "+QString::number(indexToMove));
                        returnVar.idsAction.append(theCopyList.at(i).id);
                        ids.removeOne(theCopyList.at(i).id);
                        theCopyList.move(i,indexToMove);
                        indexToMove--;
                  }
            }
            #if (DEBUG_ULTRACOPIER>0)
            for(int i=0; i<theCopyList.size(); ++i) { DEBUGCONSOLE(90,"copyThread::putOnBottom"," after argument["+QString::number(i)+"]: "+QString::number(theCopyList.at(i).id)); }
            #endif
      }
      DEBUGCONSOLE(70,"copyThread::putOnBottom","stop");
      returnVar.idsRemove=ids;
      return returnVar;
}

/** \brief set block size
\param block the new block size
\return Return true if succes */
00574 bool copyThread::setBlockSize(const int block)
{
      DEBUGCONSOLE(50,"copyThread::setBlockSize","Set new block size: "+QString::number(block));
      if(block<1 || block>16384)
      {
            blockSizeCurrent=block*1024;
            //set the new max speed because the timer have changed
            setMaxSpeed(maxSpeed);
            return true;
      }
      else
            return false;
}

/** \brief set keep date
\param value The value setted */
00590 void copyThread::setKeepDate(const int value)
{
      keepDate=value;
}

/** \brief Add item to list
\param id The id of the copy
\param source The source
\param size The file of the current index
\param destination The folder or file destination
*/
00601 void copyThread::addToList(quint64 id,const QFileInfo& source,qint64 size,const QFileInfo& destination)
{
      copyItemInternal theAddItem;
      theAddItem.id=id;
      theAddItem.source=source;
      theAddItem.size=size;
      theAddItem.destination=destination;

      firstScanTot+=size;
      NumberOfFileTot++;
      syntetizedStringOverall="File "+QString::number(NumberOfFileCopied)+"/"+QString::number(NumberOfFileTot)+", Total: "+intToQtringSize(firstScanTot);
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            theCopyList.append(theAddItem);
      }
}

00618 int copyThread::lenghtOfCopyList()
{
      int size=-1;
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            size=theCopyList.size();
      }
      return size;
}

/** \brief return the progression percent
\param max the return value it should be beteen 0 and max value
\return the file progression
*/
00632 int copyThread::getProgressionPercent(const int max)
{
      qint64 sourcePos=totalCopiedSize-currentFileTotPos;
      if(currentFileSize<=0 || sourcePos>currentFileSize)
            return 0;
      return (int)((sourcePos*max)/currentFileSize);
}

//return the progression percent
int copyThread::getProgressionPercentTotal(const int max)
{
      if(firstScanTot==0)
            return -1;
      qint64 tempNum=firstScanCur;
      qint64 sourcePos=totalCopiedSize-currentFileTotPos;
      if(sourcePos>currentFileSize)
            sourcePos=currentFileSize;
      tempNum+=sourcePos;
      if(tempNum>firstScanTot)
      {
            DEBUGCONSOLE(10,"copyThread::getProgressionPercentTotal",QString("tempNum>firstScanTot: ")+QString::number(tempNum)+">"+QString::number(firstScanTot));
            tempNum=firstScanTot;
      }
      tempNum*=max;
      tempNum/=firstScanTot;
      return tempNum;
}

/** \brief get copy speed in byte per second
\return Return the speed in byte per second */
00662 QString copyThread::getCopySpeed()
{
      //for have fixed value (not change durring copy)
      qint64 totalCopiedSize=this->totalCopiedSize;
      //for calcul copied size
      qint64 returnedValue=totalCopiedSize-previousSizeReturned;
      if(returnedValue==0)
            return "0B/s";
      //get elapsed time
      int timeFromNextRestart=intervalCopySpeed.elapsed();
      if(timeFromNextRestart<=0)
            return "";
      else
      {
            returnedValue=(returnedValue*1000/timeFromNextRestart);
            intervalCopySpeed.restart();
      }
      previousSizeReturned=totalCopiedSize;
      return intToQtringSize(returnedValue)+"/s";
}

/** \brief set prealoc file size
\param prealloc True if should be prealloc */
00685 void copyThread::setPreallocateFileSize(const bool prealloc)
{
      preallocation=prealloc;
}

/*! \brief Set if in copy or move mode
\param setMove If true is in moving mode
*/
00693 void copyThread::setMovingMode(const bool setMove)
{
      DEBUGCONSOLE(30,"copyThread::setMovingMode","Set copy thread as moving mode");
      movingMode=setMove;
}

/*! \brief Set the copy info and options before runing
\param doRightCopy If true copy the right of the file
*/
00702 void copyThread::setRightCopy(const int doRightCopy)
{
      #if (DEBUG_ULTRACOPIER>0)
      if(doRightCopy)
            DEBUGCONSOLE(70,"copyThread::setRightCopy","doRightCopy: true");
      else
            DEBUGCONSOLE(70,"copyThread::setRightCopy","doRightCopy: false");
      #endif
      RightCopy=doRightCopy;
}

/// \brief For give timer envery X ms
00714 void copyThread::timeOfTheBlockCopyFinished()
{
      if(waitNewClockForSpeed.available()<NUMSEMSPEEDMANAGEMENT)
            waitNewClockForSpeed.release();
}

/*! \brief Add one entry to dir list
\param theDir Is set for define the source folder, it need be requested in moving mode
\see movingMode and AddFolderThread::putToDirList()
*/
00724 void copyThread::addEntryToDirList(const QDir& theDir)
{
      if(movingMode)
      {
            DEBUGCONSOLE(90,"copyThread::addEntryToDirList","dir: \""+theDir.absolutePath()+"\"");
            sourceDirList<<theDir;
      }
      else
      {
            DEBUGCONSOLE(10,"copyThread::addEntryToDirList","copy mode, can't have an folder here");
      }
}

/** \brief add one entry to empty dir destination list
\param theDir Which empty destination folder should be created  */
00739 void copyThread::addEntryToEmptyDestinationDirList(const QDir& theDir)
{
      emptyDestDir<<theDir;
}

/** \brief Remove all the source empty folder
\return Return true if success */
00746 void copyThread::removeAllFolderEmpty(const QDir& TheDir)
{
      DEBUGCONSOLE(90,"copyThread::removeAllFolderEmpty","The dir: "+TheDir.absolutePath());
      QFileInfoList list = TheDir.entryInfoList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::Hidden|QDir::System,QDir::DirsFirst);
      if(list.isEmpty())
      {
            DEBUGCONSOLE(90,"copyThread::removeAllFolderEmpty","The folder is empty");
      }
      else
      {
            DEBUGCONSOLE(90,"copyThread::removeAllFolderEmpty","Listing");
            for (int i = 0; i < list.size(); ++i)
            {
                  QFileInfo fileInfo(list.at(i));
                  if(!fileInfo.isDir())
                  {
                        DEBUGCONSOLE(90,"copyThread::removeAllFolderEmpty","found a file: "+fileInfo.fileName());
                  }
                  else
                  {
                        //return the fonction for scan the new folder
                        removeAllFolderEmpty(TheDir.absolutePath()+fileInfo.fileName()+'/');
                        TheDir.rmdir(TheDir.absolutePath()+fileInfo.fileName()+'/');
                  }
            }
      }
}

/// \brief Flush the last thread
00775 void copyThread::flush()
{
      DEBUGCONSOLE(90,"copyThread::flush","start");
      QDir *dest_dir_folder=new QDir("");
      //create here the empty destination folder
      while(!emptyDestDir.isEmpty())
      {
            DEBUGCONSOLE(90,"copyThread::flush","emptyDestDir.isEmpty() is not empty");
            dest_dir_folder->setPath(emptyDestDir.first().absolutePath());
            retryMkpathEmptyDestinationFolder:
            if(!dest_dir_folder->exists())
            {
                  if(!dest_dir_folder->mkpath(emptyDestDir.first().absolutePath()))
                  {
                        DEBUGCONSOLE(10,"copyThread::flush","Unable to create the folder: "+emptyDestDir.first().absolutePath());
                        switch(errorOnFileAndWait(ERROR_DEF_NOENDOF,emptyDestDir.first().absolutePath(),tr("Error while create destination folder"),0))
                        {
                              case ERRORACTION_RETRY:
                                    goto retryMkpathEmptyDestinationFolder;
                              case ERRORACTION_SKIP:
                                    goto SkipMkpathEmptyDestinationFolder;
                              case ERRORACTION_CLOSE:
                                    stopTheCopy();
                                    return;
                              default:
                                    DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                    stopTheCopy();
                                    return;
                        }
                  }
                  else
                  {
                        DEBUGCONSOLE(90,"copyThread::flush","Folder created: "+emptyDestDir.first().absolutePath());
                  }
            }
            else
            {
                  DEBUGCONSOLE(90,"copyThread::flush","dest_dir_folder->exists() not exists");
            }
            SkipMkpathEmptyDestinationFolder:
            emptyDestDir.removeFirst();
      }
      
      //remove here the empty source folder when is in moving mode
      if(movingMode)
      {
            // remove recusively here the sourceDirList list
            QDir thedir;
            while(!sourceDirList.isEmpty())
            {
                  DEBUGCONSOLE(90,"copyThread::flush","Clean this folder for removing: "+sourceDirList.first().absolutePath());
                  removeAllFolderEmpty(sourceDirList.first());
                  if(sourceDirList.first().absolutePath()!=getMountPoint(sourceDirList.first().absolutePath()))
                  {

                        retryRemoveSourceFolder:
                        if(!thedir.rmpath(sourceDirList.first().absolutePath()))
                        {
                              DEBUGCONSOLE(10,"copyThread::flush","Unable to create the folder: "+sourceDirList.first().absolutePath());
                              switch(errorOnFileAndWait(ERROR_DEF_NOENDOF,sourceDirList.first().absolutePath(),tr("Error while create destination folder"),0))
                              {
                                    case ERRORACTION_RETRY:
                                          goto retryRemoveSourceFolder;
                                    case ERRORACTION_SKIP:
                                          goto SkipRemoveSourceFolder;
                                    case ERRORACTION_CLOSE:
                                          stopTheCopy();
                                          return;
                                    default:
                                          DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                          stopTheCopy();
                                          return;
                              }
                        }
                  }
                  else
                  {
                        DEBUGCONSOLE(10,"copyThread::flush","Folder is the mount point: "+sourceDirList.first().absolutePath());
                  }
                  SkipRemoveSourceFolder:
                  sourceDirList.removeFirst();
            }
      }
}

/** \brief try open file in special mode
\param theFile Pointer on the file
\param theModeShouldBeUsed Wich mode should be used
*/
00864 bool copyThread::tryOpenFileInSpecialMode(QFile *theFile,QIODevice::OpenMode theModeShouldBeUsed)
{
      //if file is already open
      if(theFile->isOpen())
      {
            DEBUGCONSOLE(50,"copyThread::tryOpenFileInSpecialMode","already open");
            //check the open mode
            if(theFile->openMode()!=theModeShouldBeUsed)
            {
                  theFile->close();
                  return theFile->open(theModeShouldBeUsed);
            }
            else
                  return true;
      }
      else
      {
            #if (DEBUG_ULTRACOPIER>0)
            if(theModeShouldBeUsed==QIODevice::WriteOnly)
                  DEBUGCONSOLE(90,"copyThread::tryOpenFileInSpecialMode","file: "+theFile->fileName()+", QIODevice::WriteOnly");
            else
                  DEBUGCONSOLE(90,"copyThread::tryOpenFileInSpecialMode","file: "+theFile->fileName()+", not QIODevice::WriteOnly");
            #endif
            return theFile->open(theModeShouldBeUsed);
      }
}

/*! \brief Set the max speed
\param tempMaxSpeed Set the max speed in KB/s, 0 for no limit */
00893 void copyThread::setMaxSpeed(const int tempMaxSpeed)
{
      if(tempMaxSpeed>=0)
      {
            if(maxSpeed==0 && tempMaxSpeed==0 && waitNewClockForSpeed.available()>0)
                  waitNewClockForSpeed.tryAcquire(waitNewClockForSpeed.available());
            maxSpeed=tempMaxSpeed;
            DEBUGCONSOLE(50,"copyThread::setMaxSpeed",QString("tempMaxSpeed=")+QString::number(tempMaxSpeed));
            if(maxSpeed>0)
            {
                  int NewInterval,newMultForBigSpeed=0;
                  do
                  {
                        newMultForBigSpeed++;
                        NewInterval=(blockSizeCurrent*newMultForBigSpeed)/(maxSpeed);
                  }
                  while (NewInterval<MINTIMERINTERVAL);
                  if(NewInterval>MAXTIMERINTERVAL)
                  {
                        NewInterval=MAXTIMERINTERVAL;
                        newMultForBigSpeed=1;
                        blockSizeCurrent=maxSpeed*NewInterval;
                  }
                  MultForBigSpeed=newMultForBigSpeed;
                        clockForTheCopySpeed.setInterval(NewInterval);
                  DEBUGCONSOLE(90,"copyThread::setMaxSpeed","setInterval at: "+QString::number(NewInterval)+"ms for "+QString::number(MultForBigSpeed)+" block(s) of "+QString::number(blockSizeCurrent)+"B.");
                  DEBUGCONSOLE(90,"copyThread::setMaxSpeed","for speed of: "+QString::number(((blockSizeCurrent*MultForBigSpeed)/NewInterval))+"KB/s");
                  if(!clockForTheCopySpeed.isActive() && theCurrentStat!=Stopped)
                        clockForTheCopySpeed.start();
            }
            else
            {
                  if(clockForTheCopySpeed.isActive())
                        clockForTheCopySpeed.stop();
                  waitNewClockForSpeed.release();
            }
      }
}

/*! \brief Query for stop the current thread

  For stop in urgence the copy thread, use only with cancel!
\see stopIt, run() and stop()
*/
00937 void copyThread::stopTheCopy()
{
      /// \note never do the unlock() of mutex here, cause crash because it need by close by the opener thread
      DEBUGCONSOLE(50,"copyThread::stopTheCopy","stopTheCopy");
      stopIt=true;

      if(theCurrentStat!=copyThread::Stopped)
      {
            QMutexLocker lock_mutex(&MultiThread_ThreadList);
            for (int i = 0; i < theWriteThreadList.size(); ++i) {
                  theWriteThreadList.at(i)->stop();
            }
      }
      DEBUGCONSOLE(90,"copyThread::stopTheCopy","this->isRunning(): true");
      while(waitAction.available()<=0)
            waitAction.release();
      waitAction.acquire();
      while(waitNewClockForSpeed.available()<=0)
            waitNewClockForSpeed.release();
      waitNewClockForSpeed.acquire();
      DEBUGCONSOLE(90,"copyThread::stopTheCopy","stop done");
}

/*! \brief Run the copy
\warning The pointer sould be given and thread initilised
\see QObjectOfMwindow(), stopTheCopy() and stop()

each action is checked by:
retryAction:
if(Action()==ERROR)
{
      actionAfterUnlock=-1;
      emit someSignalNeedAction();
      timeCopyElapsed+=tempTimeElapsed.elapsed();
      theCurrentStat=copyThread::Paused;
      if(actionAfterUnlock==-1)
            controlMutex.wait(&mutexWaitControl);
      if(stopIt || actionAfterUnlock==ERRORACTION_CLOSE)
            goto SkipFile;
      theCurrentStat=copyThread::Running;
      tempTimeElapsed.restart();
      if(actionAfterUnlock==ERRORACTION_RETRY)
            goto retryMkpath;
      else if(actionAfterUnlock==ERRORACTION_SKIP)
            goto SkipFile;
      else
      {
            DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
            goto SkipFile;
      }
}

normal run with write thread:
void copyThread::run()
{
    while(!CopyList->isEmpty())
    {
      sourceFile.open(QIODevice::ReadOnly);
      theCurrentThread->openDestination();
      //set permissions
      if(RightCopy)
          destinationFile.setPermissions(sourceFile.permissions()):
      //pre-allocation
      if(!preallocation)
          destinationFile.resize(0);
      else
          destinationFile.resize(sourceFile.size());
      sourceFile.seek(0);
      theCurrentThread->setFiles(sourceFile,destinationFile,tempItem);
      do
      {
          //read one block
          retryReadThisBlock:
          positionInSource=sourceFile.pos();
          blockArray=sourceFile.read(blockSizeCurrent);
          //write one block
          if(!blockArray.isEmpty())
          {
            bytesWriten=blockArray.size();
            theCurrentThread->addNewBlock(blockArray);
            totalCopiedSize+=bytesWriten;
          }
      }
      while(!blockArray.isEmpty() && bytesWriten==blockArray.size());
      theCurrentThread->endOfSourceDetected();
      if(sourceFile.isOpen())
          sourceFile.close();
    }
}

normal run without write thread:
void copyThread::run()
{
      while(!theCopyList())
      {
            sourceFile.open(QIODevice::ReadOnly);
            destinationFile.open(QIODevice::WriteOnly);
            //set permissions
            if(RightCopy)
                  destinationFile.setPermissions(sourceFile.permissions());
            //pre-allocation
            if(!preallocation)
                  destinationFile.resize(0);
            else
                  destinationFile.resize(sourceFile.size());
            sourceFile.seek(0);
            destinationFile.seek(0);
            do
            {
                  //read one block
                  blockArray=sourceFile.read(blockSizeCurrent);
                  //write one block
                  if(!blockArray.isEmpty())
                        destinationFile.write(blockArray);
            }
            while(!blockArray.isEmpty() && bytesWriten==blockArray.size());
            if(sourceFile.isOpen())
                  sourceFile.close();
            if(destinationFile.isOpen())
                  destinationFile.close();
            //set the time if no write thread used
            if(keepDate)
                  changeFileDateTime(destinationFile.fileName(),sourceFile.fileName());
            //remove source in moving mode
            if(movingMode)
                  sourceFile.remove();
      }
}
*/
01066 void copyThread::run()
{
      // initialise the variable for copy
      QByteArray        blockArray;       ///< For store the block array
      QDir              destinationFolder;      ///< Just for do operation on folder, static method is missing
      QFileInfo         destintationFileInfo;   ///< Just for do operation on folder, static method is missing
      QString                 destinationFolderPath;
      bool              resultOpen;
      bool              destinationIsOpenNow;
      int               id;

      timeCopyElapsed         = 0;
      qint64 bytesWriten      = 0;              ///< Number of bytes writen
      quint64 CurentCopiedSize= 0;
      theCurrentStat          = copyThread::Running;
      stopIt                  = false;
      errorMessageInCopy      = "";
      stopped                 = false;
      waitInPause       = false;
      theCurrentThread  = NULL;
      currentFileSize         = 0;
      currentFileTotPos = totalCopiedSize;

      emit isInPauseOrNot();
      tempTimeElapsed.start();
      int copyListSize;
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            copyListSize=theCopyList.size();
      }
      #if (DEBUG_ULTRACOPIER>0)
      {
            QMutexLocker lock_mutex(&MultiThreadCopyList);
            if(!copyListSize)
            {
                  DEBUGCONSOLE(70,"copyThread::run","theCopyList.size()==0");//possible if listing of folder is empty
                  if(sourceDirList.isEmpty())
                        DEBUGCONSOLE(10,"copyThread::run","sourceDirList.isEmpty() and copy list is empty! bug?");
                  if(emptyDestDir.isEmpty())
                        DEBUGCONSOLE(10,"copyThread::run","emptyDestDir.isEmpty() and copy list is empty! bug?");
            }
      }
      #endif

      DEBUGCONSOLE(90,"copyThread::run","start the copy loop");
      while(copyListSize && !stopIt)
      {
            //initialise the variable for current file
            actionAfterUnlock = -1;
            copyHadBegin            = false;
            skipThecurrentFile      = false;
            destinationIsOpenNow    = false;
            theCurrentThread  = NULL;
            needRemoveFileToList    = true;

            /**************************
                  extra check
            **************************/
            DEBUGCONSOLE(90,"copyThread::run","start extra check");
            #if (DEBUG_ULTRACOPIER>0)
            if(sourceFile.isOpen())
                  DEBUGCONSOLE(10,"copyThread::run","source: \""+sourceFile.fileName()+"\" is already open");
            if(destinationFile.isOpen())
                  DEBUGCONSOLE(10,"copyThread::run","destination: \""+destinationFile.fileName()+"\" is already open");
            {
                  QMutexLocker lock_mutex(&MultiThreadCopyList);
                  if(theCopyList.first().source.absoluteFilePath().isEmpty())
                  {
                        DEBUGCONSOLE(10,"copyThread::run","The source file path is empty");
                        goto SkipFile;
                  }
                  if(theCopyList.first().destination.absoluteFilePath().isEmpty())
                  {
                        DEBUGCONSOLE(10,"copyThread::run","The destination file path is empty");
                        goto SkipFile;
                  }
                  if(theCopyList.first().destination.absolutePath().isEmpty())
                  {
                        DEBUGCONSOLE(10,"copyThread::run","The destination folder name is empty");
                        goto SkipFile;
                  }
                  for (int i=0;i<theWriteThreadList.size();++i) {
                        if(theWriteThreadList.at(i)->getTheCurrentStat()==WriteThread::Stopped)
                        {
                              if(theWriteThreadList.at(i)->isFinished())
                                    DEBUGCONSOLE(50,"copyThread::run","The thread id "+QString::number(i)+" is finised but present in the list!");
                        }
                  }
            }
            #endif

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            checkIfNeedWaitWriteThread();

            //set file name
            DEBUGCONSOLE(90,"copyThread::run","load file name");
            {
                  QMutexLocker lock_mutex(&MultiThreadCopyList);
                  //determine if the path source should be resolved or if use protocol
                  if(getMountType(theCopyList.first().source.filePath())!="protocol")
                        sourceFile.setFileName(theCopyList.first().source.absoluteFilePath());
                  else
                        sourceFile.setFileName(theCopyList.first().source.filePath());
                  //determine if the path destination should be resolved or if use protocol
                  QString destinationAbsoluteFilePath;
                  if(getMountType(theCopyList.first().destination.filePath())!="protocol")
                        destinationAbsoluteFilePath=theCopyList.first().destination.absoluteFilePath();
                  else
                        destinationAbsoluteFilePath=theCopyList.first().destination.filePath();
                  //add QDir::separator (/ under unix or \ under windows) to destination and file name of the source if needed
                  if(!destinationAbsoluteFilePath.endsWith('\\') && !destinationAbsoluteFilePath.endsWith('/'))
                  {
                        if(theCopyList.first().destination.isDir())
                              destinationFile.setFileName(destinationAbsoluteFilePath+QDir::separator()+theCopyList.first().source.fileName());
                        else
                              destinationFile.setFileName(destinationAbsoluteFilePath+theCopyList.first().source.fileName());
                  }
                  else
                        destinationFile.setFileName(destinationAbsoluteFilePath+theCopyList.first().source.fileName());
                  //load the current id copied
                  id=theCopyList.first().id;
            }
            //load the object for get informations to the destination
            destintationFileInfo.setFile(destinationFile.fileName());

            //check if write thread in error need be wait
            checkIfNeedWaitWriteThread();

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            //wait in pause stat if needed
            if(waitInPause)
            {
                  waitNeedAction();
                  emit isInPauseOrNot();
                  if(stopIt)
                        goto SkipFile;
            }

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            /****************************
                  start FS check
            *****************************/

            //check if both file are not the same
            DEBUGCONSOLE(90,"copyThread::run","check sourceFile.fileName()==destinationFile.fileName()");
            if(sourceFile.fileName()==destinationFile.fileName())
            {
                  actionAfterUnlock=-1;
                  DEBUGCONSOLE(90,"copyThread::run","source and destination are the same!");
                  emit fileIsSame(destinationFile.fileName());
                  waitNeedAction();
                  if(stopIt || actionAfterUnlock==FILEEXIST_ACTION_CANCEL)
                        goto SkipFile;
                  else if(actionAfterUnlock==FILEEXIST_ACTION_RENAME)
                        destinationFile.setFileName(QFileInfo(destinationFile.fileName()).absolutePath()+QDir::separator()+translationOfCopyOf+QFileInfo(destinationFile.fileName()).fileName());
                  else if(actionAfterUnlock==FILEEXIST_ACTION_SKIP)
                        goto SkipFile;
                  else
                  {
                        DEBUGCONSOLE(10,"copyThread::run","Unknow File Exists action when is same! ("+QString::number(actionAfterUnlock)+")");
                        goto SkipFile;
                  }
            }
            DEBUGCONSOLE(50,"copyThread::run","source: \""+sourceFile.fileName()+"\" dest: \""+destinationFile.fileName()+"\"");

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            DEBUGCONSOLE(90,"copyThread::run","opening the destination...: "+destinationFile.fileName());

            //check if destination exists
            CheckIfExists:
            DEBUGCONSOLE(90,"copyThread::run","check destinationFile.exists()");
            if(destinationFile.exists())
            {
                  actionAfterUnlock=-1;
                  DEBUGCONSOLE(90,"copyThread::run","The destination exists: true");
                  emit fileIsExists(sourceFile.fileName(),destinationFile.fileName());
                  waitNeedAction();
                  switch(actionAfterUnlock)
                  {
                        default:
                        case FILEEXIST_ACTION_CANCEL:
                        case FILEEXIST_ACTION_SKIP:
                              goto SkipFile;
                        case FILEEXIST_ACTION_OVERWRITE_IFNEWER:
                              //check if same then skip the file
                              if(QFileInfo(sourceFile).lastModified()<QFileInfo(destinationFile).lastModified())
                                    goto SkipFile;
                              break;
                        case FILEEXIST_ACTION_OVERWRITE_IFNOTSAME:
                              //check if same then skip the file
                              if(sourceFile.size()==destinationFile.size() && QFileInfo(sourceFile).lastModified()==QFileInfo(destinationFile).lastModified())
                                    goto SkipFile;
                              break;
                        case FILEEXIST_ACTION_RENAME:
                        {
                              QString path=QFileInfo(destinationFile.fileName()).absolutePath();
                              if(!path.endsWith('/') && !path.endsWith('\\'))
                                    path+=QDir::separator();
                              destinationFile.setFileName(path+translationOfCopyOf+QFileInfo(destinationFile.fileName()).fileName());
                              goto CheckIfExists;
                        }
                        case FILEEXIST_ACTION_OVERWRITE:
                              break;
                  }
            }

            DEBUGCONSOLE(90,"copyThread::run","opening the destination...: "+destinationFile.fileName());

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            //check if destination folder exists, and create it
            destinationFolderPath=destintationFileInfo.absolutePath();
            DEBUGCONSOLE(90,"copyThread::run","destinationFolder: "+destinationFolderPath);
            if(!destinationFolder.exists(destinationFolderPath))
            {
                  retryMkpath:
                  DEBUGCONSOLE(90,"copyThread::run","destintationFileInfo.absolutePath(): "+destintationFileInfo.absolutePath());
                  if(!destinationFolder.mkpath(destinationFolderPath))
                  {
                        DEBUGCONSOLE(70,"copyThread::run","Error while create destination folder");
                        DEBUGCONSOLE(70,"copyThread::run","Note: bug if file exists with same name as the folder");
                        switch(errorOnFileAndWait(ERROR_DEF_ALL,destintationFileInfo.absolutePath(),tr("Error while create destination folder"),0))
                        {
                              case ERRORACTION_RETRY:
                                    goto retryMkpath;
                              case ERRORACTION_SKIP:
                                    skipCurrentFile();
                              case ERRORACTION_CLOSE:
                                    goto SkipFile;
                              case ERRORACTION_ENDOF:
                                    putFirstFileAtEnd();
                                    goto SkipFile;
                              default:
                                    DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                    goto SkipFile;
                        }
                  }
                  #if (DEBUG_ULTRACOPIER>0)
                  else
                        DEBUGCONSOLE(90,"copyThread::run","Destination folder created!");
                  #endif
            }
            #if (DEBUG_ULTRACOPIER>0)
            else
                  DEBUGCONSOLE(90,"copyThread::run","Destination folder exists!");
            #endif

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            //move if on same mount point
            #ifdef ULTRACOPIER_MODE_WINDOWS
            if(movingMode && getMountPoint(destinationFile.fileName())==getMountPoint(sourceFile.fileName()))
            {
                  DEBUGCONSOLE(90,"copyThread::run","getMountPoint(destinationFile.fileName())==getMountPoint(sourceFile.fileName()) in moving mode");
                  retryMoveReal:
                  bool errorFound=false;
                  actionAfterUnlock=-1;
                  if(destinationFile.exists())
                        if(!destinationFile.remove())
                        {
                              errorFound=true;
                              DEBUGCONSOLE(90,"copyThread::run","Unable to move the file on the same partition and remove dest: "+destinationFile.errorString());
                              if(copyListSize>1)
                                    emit errorOnFile(ERROR_DEF_ALL,destinationFile.fileName(),tr("Unable to remove the destination file: ")+destinationFile.errorString(),id);
                              else
                                    emit errorOnFile(ERROR_DEF_NOENDOF,destinationFile.fileName(),tr("Unable to remove the destination file: ")+destinationFile.errorString(),id);
                        }
                  if(!errorFound)
                        if(!sourceFile.rename(destinationFile.fileName()))
                        {
                              errorFound=true;
                              DEBUGCONSOLE(90,"copyThread::run","Unable to move the file on the same partition: "+sourceFile.errorString());
                              if(copyListSize>1)
                                    emit errorOnFile(ERROR_DEF_ALL,destinationFile.fileName(),tr("Unable to remove the destination file: ")+destinationFile.errorString(),id);
                              else
                                    emit errorOnFile(ERROR_DEF_NOENDOF,destinationFile.fileName(),tr("Unable to remove the destination file: ")+destinationFile.errorString(),id);
                        }
                  if(errorFound)
                  {
                        waitNeedAction();
                        switch(actionAfterUnlock)
                        {
                              case ERRORACTION_ENDOF:
                                    putFirstFileAtEnd();
                                    goto SkipFile;
                              case ERRORACTION_RETRY:
                                    goto retryMoveReal;
                              case ERRORACTION_SKIP:
                                    skipCurrentFile();
                              case ERRORACTION_CLOSE:
                                    goto SkipFile;
                              default:
                                    DEBUGCONSOLE(10,"copyThread::run","Unknow action at moving windows ("+QString::number(actionAfterUnlock)+")");
                                    goto SkipFile;
                        }
                  }
                  //file moved skip to the next file
                  goto SkipFile;
            }
            #endif

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            #ifdef Q_OS_UNIX
            //if symbolic link should be not read the destination file content but just copy the link
            if(QFileInfo(sourceFile).isSymLink())
            {
                  if(destinationFile.exists())
                  {
                        retrySymLinkDestRemove:
                        if(!destinationFile.remove())
                        {
                              DEBUGCONSOLE(70,"copyThread::run","error at the removing the symLink removig: "+destinationFile.errorString());
                              switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),destinationFile.errorString(),0))
                              {
                                    case ERRORACTION_RETRY:
                                          goto retrySymLinkDestRemove;
                                    case ERRORACTION_SKIP:
                                          skipCurrentFile();
                                    case ERRORACTION_CLOSE:
                                          goto SkipFile;
                                    case ERRORACTION_ENDOF:
                                          putFirstFileAtEnd();
                                          goto SkipFile;
                                    default:
                                          DEBUGCONSOLE(10,"copyThread::run","Unknow action at SymLink ("+QString::number(actionAfterUnlock)+")");
                                          goto SkipFile;
                              }
                        }
                  }
                  retrySymLink:
                  DEBUGCONSOLE(70,"copyThread::run","QFileInfo(\""+QFileInfo(sourceFile).absoluteFilePath()+"\").symLinkTarget(): "+QFileInfo(sourceFile).symLinkTarget());
                  DEBUGCONSOLE(70,"copyThread::run","destinationFile: "+destinationFile.fileName());
                  if(!QFile::link(QFileInfo(sourceFile).symLinkTarget(),destinationFile.fileName()))
                  {
                        //QFileInfo(sourceFile).symLinkTarget()
                        DEBUGCONSOLE(70,"copyThread::run","error at the symLinkTarget: "+destinationFile.errorString());
                        switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),destinationFile.errorString(),0))
                        {
                              case ERRORACTION_RETRY:
                                    goto retrySymLink;
                              case ERRORACTION_SKIP:
                                    skipCurrentFile();
                              case ERRORACTION_CLOSE:
                                    goto SkipFile;
                              case ERRORACTION_ENDOF:
                                    putFirstFileAtEnd();
                                    goto SkipFile;
                              default:
                                    DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                    goto SkipFile;
                        }
                  }
            }
            else
            {
            #endif
                  //try open source is read only for copy and read/write for move
                  retryOpenSource:
                  DEBUGCONSOLE(90,"copyThread::run","opening the source...");
                  if(movingMode)
                               resultOpen=tryOpenFileInSpecialMode(&sourceFile,QIODevice::ReadWrite);
                  else
                               resultOpen=tryOpenFileInSpecialMode(&sourceFile,QIODevice::ReadOnly);
                  if(!resultOpen)
                  {
                        actionAfterUnlock=-1;
                        DEBUGCONSOLE(70,"copyThread::run","try: sourceFile.open(): "+sourceFile.errorString());
                        int buttonToActivate=ERROR_DEF_ALL;
                        //desactivate skip of if only one item
                        if(theCopyList.size()<=1)
                              buttonToActivate=ERROR_DEF_NOENDOF;
                        DEBUGCONSOLE(90,"copyThread::run","Unable to remove the destination file, buttonToActivate: "+QString::number(buttonToActivate));
                        if(movingMode)
                              emit errorOnFile(buttonToActivate,QFileInfo(sourceFile).absoluteFilePath(),translationErrorSourceReadWrite+sourceFile.errorString(),id);
                        else
                              emit errorOnFile(buttonToActivate,QFileInfo(sourceFile).absoluteFilePath(),translationErrorSourceRead+sourceFile.errorString(),id);
                        DEBUGCONSOLE(90,"copyThread::run","Error at open source, stop the thread");
                        waitNeedAction();
                        DEBUGCONSOLE(90,"copyThread::run","Error at open source, resume the thread");
                        switch(actionAfterUnlock)
                        {
                              case ERRORACTION_ENDOF:
                                    putFirstFileAtEnd();
                                    goto SkipFile;
                              case ERRORACTION_RETRY:
                                    goto retryOpenSource;
                              case ERRORACTION_SKIP:
                                    skipCurrentFile();
                              case ERRORACTION_CLOSE:
                                    goto SkipFile;
                              default:
                                    DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                    goto SkipFile;
                        }
                  }
                  currentFileSize=sourceFile.size();
                  currentFileTotPos=totalCopiedSize;
                  DEBUGCONSOLE(90,"copyThread::run","Source opened and sized to: "+QString::number(sourceFile.size()));

                  DEBUGCONSOLE(90,"copyThread::run","check if need be in pause");
                  //if write thread should be used load it here
                  if(useWriteThread)
                  {
                        DEBUGCONSOLE(90,"copyThread::run","writeThreadSem->available():"+QString::number(writeThreadSem->available()));
                        //block here with semaphore if too many thread is open
                        writeThreadSem->acquire();
                        {
                              //search write thread free
                              QMutexLocker lock_mutex(&MultiThread_ThreadList);
                              for (int i=0;i<theWriteThreadList.size();++i) {
                                    if(theWriteThreadList.at(i)->getTheCurrentStat()==WriteThread::Stopped)
                                    {
                                          //if have been closed by previous copy list finish restart it
                                          if(theWriteThreadList.at(i)->isFinished())
                                          {
                                                DEBUGCONSOLE(50,"copyThread::run","The thread id "+QString::number(i)+" is finised but present in the list! Start it!");
                                                //use signal/slot and mutex for create it in main thread
                                                emit queryStartThread(i);
                                                waitNewWriteThread.acquire();
                                                DEBUGCONSOLE(50,"copyThread::run","The thread id "+QString::number(i)+" is finised but present in the list! Started!");
                                          }
                                          //set the pointer on it for use it
                                          theCurrentThread=theWriteThreadList.at(i);
                                          break;
                                    }
                              }
                        }
                        //check if no other thread is in error
                        checkIfNeedWaitWriteThread();
                        //if no existing thread is loaded, create it
                        if(theCurrentThread==NULL)
                        {
                              DEBUGCONSOLE(50,"copyThread::run","Create new Write thread existing");
                              //use signal/slot and mutex for create it in main thread
                              emit queryNewWriteThread();
                              waitNewWriteThread.acquire();
                              DEBUGCONSOLE(90,"copyThread::run","create write thread done");
                        }
                        #if (DEBUG_ULTRACOPIER>0)
                        {
                              //return number of the current thread and the number of total thread for debug
                              QMutexLocker lock_mutex(&MultiThread_ThreadList);
                              DEBUGCONSOLE(90,"copyThread::run","Use Write thread existing, the number "+QString::number(theWriteThreadList.indexOf(theCurrentThread))+" on "+QString::number(theWriteThreadList.size()));
                        }
                        #endif
                        if(theCurrentThread->isFinished())
                        {
                              stopIt=true;
                              DEBUGCONSOLE(10,"copyThread::run","Write thread existing is not running!");
                        }
                        //for the current thread selected, set the actual options
                        theCurrentThread->setKeepDate(keepDate);
                        theCurrentThread->setPreallocation(preallocation);
                  }

                  //open destination here
                  retryOpenDestination:
                  /** \note if the pointer for the current thread is not null
                    then write thread should be used, then it's to write
                    thread to open and do operation on destination file
                    **/
                  if(theCurrentThread!=NULL)
                  {
                        DEBUGCONSOLE(90,"copyThread::run","theCurrentThread is not NULL");
                        copyItemInternal tempItem;
                        {
                              QMutexLocker lock_mutex(&MultiThreadCopyList);
                              tempItem=theCopyList.first();
                        }
                        DEBUGCONSOLE(50,"copyThread::run","theCurrentThread->setFiles()");
                        theCurrentThread->setFiles(sourceFile.fileName(),destinationFile.fileName(),tempItem);
                        destinationIsOpenNow=theCurrentThread->openDestination();
                  }
                  else
                        destinationIsOpenNow=tryOpenFileInSpecialMode(&destinationFile,QIODevice::WriteOnly);
                  //error management
                  if(!destinationIsOpenNow)
                  {
                        QString error;
                        if(theCurrentThread==NULL)
                              error=destinationFile.errorString();
                        else
                              error=theCurrentThread->errorString();
                        DEBUGCONSOLE(70,"copyThread::run","try: destination->open(): "+error);
                        switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),translationErrorDestinationWrite+error,id))
                        {
                              case ERRORACTION_ENDOF:
                                    putFirstFileAtEnd();
                                    if(theCurrentThread!=NULL)
                                          writeThreadOperationFinish();
                                    goto SkipFile;
                              case ERRORACTION_RETRY:
                                    goto retryOpenDestination;
                              case ERRORACTION_SKIP:
                                    if(theCurrentThread!=NULL)
                                          writeThreadOperationFinish();
                                    skipCurrentFile();
                              case ERRORACTION_CLOSE:
                                    goto SkipFile;
                              default:
                                    DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                    if(theCurrentThread!=NULL)
                                          writeThreadOperationFinish();
                                    goto SkipFile;
                        }
                  }
                  DEBUGCONSOLE(90,"copyThread::run","Destination open");

                  //set permision, only for real file, because Qt not support for the symLink
                  if(RightCopy)
                  {
                        retrySetPermissions:
                        DEBUGCONSOLE(90,"copyThread::run","set permissions...");
                        if(!destinationFile.setPermissions(sourceFile.permissions()))
                        {
                              DEBUGCONSOLE(90,"copyThread::run",destinationFile.fileName()+", the permissions cannot be modified: "+destinationFile.errorString());
                              switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),translationErrorPermissions+destinationFile.errorString(),id))
                              {
                                    case ERRORACTION_ENDOF:
                                          putFirstFileAtEnd();
                                          goto SkipFile;
                                    case ERRORACTION_RETRY:
                                          goto retrySetPermissions;
                                    case ERRORACTION_SKIP:
                                          skipCurrentFile();
                                    case ERRORACTION_CLOSE:
                                          goto SkipFile;
                                    default:
                                          DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                          goto SkipFile;
                              }
                        }
                        DEBUGCONSOLE(90,"copyThread::run","set permissions done");
                  }
            #ifdef Q_OS_UNIX
            }
            #endif

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            #ifdef Q_OS_UNIX
            if(!QFileInfo(sourceFile).isSymLink())
            {
            #endif
                  if(theCurrentThread==NULL && preallocation)
                  {
                        DEBUGCONSOLE(90,"copyThread::run","resize destination to "+QString::number(sourceFile.size())+"...");
                        retryResizeFirst:
                        if(!destinationFile.resize(sourceFile.size()))
                        {
                                        DEBUGCONSOLE(90,"copyThread::run",destinationFile.fileName()+", cannot be resized: "+destinationFile.errorString()+" at: "+QString::number(sourceFile.size()));
                              switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),translationErrorResize+destinationFile.errorString(),id))
                              {
                                    case ERRORACTION_ENDOF:
                                          putFirstFileAtEnd();
                                          goto SkipFile;
                                    case ERRORACTION_RETRY:
                                          goto retryResizeFirst;
                                    case ERRORACTION_SKIP:
                                          skipCurrentFile();
                                    case ERRORACTION_CLOSE:
                                          goto SkipFile;
                                    default:
                                          DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                          goto SkipFile;
                              }
                        }
                        DEBUGCONSOLE(90,"copyThread::run","resize done");
                  }

                  //if query to stop, directly go to SkipFile
                  if(stopIt)
                        goto SkipFile;

                  DEBUGCONSOLE(90,"copyThread::run","seek...");
                  sourceFile.seek(0);
                  if(theCurrentThread==NULL)
                        destinationFile.seek(0);
                  DEBUGCONSOLE(90,"copyThread::run","seek done");

                  //if query to stop, directly go to SkipFile
                  if(stopIt)
                        goto SkipFile;

                  //source file is ready for the copy
                  numberOfBlockCopied=0;

                  #if (DEBUG_ULTRACOPIER>0)
                  if(maxSpeed>0)
                  {
                        DEBUGCONSOLE(90,"copyThread::run","maxSpeed>0: "+QString::number(maxSpeed));
                        DEBUGCONSOLE(90,"copyThread::run","setInterval at: "+QString::number(clockForTheCopySpeed.interval())+"ms for "+QString::number(MultForBigSpeed)+" block(s).");
                        if(clockForTheCopySpeed.interval()>0)
                              DEBUGCONSOLE(90,"copyThread::run","for speed of: "+QString::number(((blockSizeCurrent*MultForBigSpeed)/clockForTheCopySpeed.interval())/1024)+"MB/s");
                  }
                  #endif

                  //if query to stop, directly go to SkipFile
                  if(stopIt)
                        goto SkipFile;

                  DEBUGCONSOLE(90,"copyThread::run","load current file string for gui update the current file string");
                  syntetizedStringCurrentFile=destintationFileInfo.fileName()+" "+intToQtringSize(sourceFile.size());
                  syntetizedStringTo=destintationFileInfo.absoluteFilePath();
                  syntetizedStringFrom=sourceFile.fileName();

                  qint64 positionInSource;
                  qint64 positionInDestination;
                  copyHadBegin=true;
                  CurentCopiedSize=0;
                  DEBUGCONSOLE(90,"copyThread::run","star copy");
                  do
                  {
                        //wait in pause stat if needed
                        if(!stopIt && waitInPause)
                        {
                              waitNeedAction();
                              if(stopIt)
                                    goto SkipFile;
                        }

                        //read one block
                        retryReadThisBlock:
                        #if (DEBUG_ULTRACOPIER>0)
                        theCurrentWait          = WaitInRead;
                        #endif
                        positionInSource=sourceFile.pos();
                        blockArray=sourceFile.read(blockSizeCurrent);
                        #if (DEBUG_ULTRACOPIER>0)
                        theCurrentWait          = WaitInThread;
                        #endif
                        if(!stopIt && sourceFile.error()!=QFile::NoError)
                        {
                              retrySeekSource:
                              DEBUGCONSOLE(90,"copyThread::run","Error while reading source file: "+sourceFile.errorString());
                              switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(sourceFile).absoluteFilePath(),translationErrorReadSource+sourceFile.errorString(),id))
                              {
                                    case ERRORACTION_ENDOF:
                                          putFirstFileAtEnd();
                                          goto SkipFile;
                                    case ERRORACTION_RETRY:
                                          if(!sourceFile.seek(positionInSource))
                                                goto retrySeekSource;
                                          goto retryReadThisBlock;
                                    case ERRORACTION_SKIP:
                                          skipCurrentFile();
                                    case ERRORACTION_CLOSE:
                                          goto SkipFile;
                                    default:
                                          DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                          goto SkipFile;
                              }
                        }
                        CurentCopiedSize+=blockArray.size();

                        //write one block
                        if(!stopIt && !blockArray.isEmpty())
                        {
                              #if (DEBUG_ULTRACOPIER>0)
                              theCurrentWait          = WaitInWrite;
                              #endif
                              if(theCurrentThread==NULL)
                              {
                                    positionInDestination=destinationFile.pos();
                                    retryWriteThisBlock:
                                    bytesWriten=destinationFile.write(blockArray);
                                    if(destinationFile.error()!=QFile::NoError || bytesWriten!=blockArray.size())
                                    {
                                          retrySeekDestination:
                                          DEBUGCONSOLE(90,"copyThread::run","Error in writing: "+destinationFile.errorString());
                                          switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),translationErrorWriting+destinationFile.errorString(),id))
                                          {
                                                case ERRORACTION_ENDOF:
                                                      putFirstFileAtEnd();
                                                      goto SkipFile;
                                                case ERRORACTION_RETRY:
                                                      if(!destinationFile.seek(positionInDestination))
                                                            goto retrySeekDestination;
                                                      goto retryWriteThisBlock;
                                                case ERRORACTION_SKIP:
                                                      skipCurrentFile();
                                                case ERRORACTION_CLOSE:
                                                      goto SkipFile;
                                                default:
                                                      DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                                      goto SkipFile;
                                          }
                                    }
                              }
                              else
                              {
                                    bytesWriten=blockArray.size();
                                    theCurrentThread->addNewBlock(blockArray);
                                    checkIfNeedWaitOneWriteThread(theCurrentThread);
                              }
                              #if (DEBUG_ULTRACOPIER>0)
                              theCurrentWait          = WaitInThread;
                              #endif
                              totalCopiedSize+=bytesWriten;
                        }

                        //wait for limitation speed if stop not query
                        if(!stopIt && maxSpeed>0)
                        {
                              numberOfBlockCopied++;
                              if(numberOfBlockCopied>=MultForBigSpeed)
                              {
                                    numberOfBlockCopied=0;
                                    waitNewClockForSpeed.acquire();
                              }
                        }
                  }
                  while(!blockArray.isEmpty() && bytesWriten==blockArray.size() && !stopIt);
                  DEBUGCONSOLE(90,"copyThread::run","blockArray.isEmpty(): "+QString::number(blockArray.isEmpty()));
                  DEBUGCONSOLE(90,"copyThread::run","bytesWriten: "+QString::number(bytesWriten));
                  DEBUGCONSOLE(90,"copyThread::run","blockArray.size(): "+QString::number(blockArray.size()));
                  DEBUGCONSOLE(90,"copyThread::run","stopIt: "+QString::number(stopIt));
                  DEBUGCONSOLE(90,"copyThread::run","blockSizeCurrent: "+QString::number(blockSizeCurrent));
                  currentFileSize         = 0;
                  currentFileTotPos = totalCopiedSize;

                  if(theCurrentThread==NULL && !stopIt)
                  {
                        DEBUGCONSOLE(90,"copyThread::run","resize destination to "+QString::number(sourceFile.size())+"...");
                        retryResizeLast:
                        if(!destinationFile.resize(CurentCopiedSize))
                        {
                                        DEBUGCONSOLE(90,"copyThread::run",destinationFile.fileName()+", cannot be resized: "+destinationFile.errorString()+" at: "+QString::number(CurentCopiedSize));
                              switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),translationErrorResize+destinationFile.errorString(),id))
                              {
                                    case ERRORACTION_ENDOF:
                                          putFirstFileAtEnd();
                                          goto SkipFile;
                                    case ERRORACTION_RETRY:
                                          goto retryResizeLast;
                                    case ERRORACTION_SKIP:
                                          skipCurrentFile();
                                    case ERRORACTION_CLOSE:
                                          goto SkipFile;
                                    default:
                                          DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                          goto SkipFile;
                              }
                        }
                        DEBUGCONSOLE(90,"copyThread::run","resizing done");
                  }

                  if(theCurrentThread!=NULL)
                  {
                        if(stopIt)
                              theCurrentThread->stop();
                        else
                        {
                              DEBUGCONSOLE(70,"copyThread::run","call theCurrentThread->endOfSourceDetected()");
                              theCurrentThread->endOfSourceDetected();
                        }
                  }
            #ifdef Q_OS_UNIX
            }
            #endif

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            //close file
            DEBUGCONSOLE(90,"copyThread::run","closing source and destination...");
            if(sourceFile.isOpen())
                  sourceFile.close();
            DEBUGCONSOLE(90,"copyThread::run","closing source done");
            if(theCurrentThread==NULL)
            {
                  if(destinationFile.isOpen())
                  {
                        destinationFile.close();
                        DEBUGCONSOLE(90,"copyThread::run","closing destination done");
                  }
            }

            //set the time if no write thread used
            if(keepDate && theCurrentThread==NULL
            #ifdef Q_OS_UNIX
            && !QFileInfo(sourceFile).isSymLink()
            #endif
            )
            {
                  retrySetDate:
                  DEBUGCONSOLE(90,"copyThread::run","set date...");
                  if(!changeFileDateTime(destinationFile.fileName(),sourceFile.fileName()))
                  {
                        DEBUGCONSOLE(90,"copyThread::run","Date cannot be modified!");
                        switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(sourceFile).absoluteFilePath(),translationErrorDate,id))
                        {
                              case ERRORACTION_ENDOF:
                                    putFirstFileAtEnd();
                                    goto SkipFile;
                              case ERRORACTION_RETRY:
                                    goto retrySetDate;
                              case ERRORACTION_SKIP:
                                    skipCurrentFile();
                              case ERRORACTION_CLOSE:
                                    goto SkipFile;
                              default:
                                    DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                    goto SkipFile;
                        }
                  }
                  DEBUGCONSOLE(90,"copyThread::run","set date done");
            }

            //if query to stop, directly go to SkipFile
            if(stopIt)
                  goto SkipFile;

            //remove source in moving mode
            if(movingMode && theCurrentThread==NULL)
            {
                  retrySourceFile:
                  DEBUGCONSOLE(90,"copyThread::run","try remove sourceFile...");
                  if(destinationFile.exists())
                  {
                        if(!sourceFile.remove())
                        {
                              DEBUGCONSOLE(70,"copyThread::run","sourceFile.errorString():\""+sourceFile.errorString()+"\" while removing the source");
                              switch(errorOnFileAndWait(ERROR_DEF_ALL,QFileInfo(destinationFile).absoluteFilePath(),translationErrorRemove+sourceFile.errorString(),id))
                              {
                                    case ERRORACTION_ENDOF:
                                          putFirstFileAtEnd();
                                          goto SkipFile;
                                    case ERRORACTION_RETRY:
                                          goto retrySourceFile;
                                    case ERRORACTION_SKIP:
                                          skipCurrentFile();
                                    case ERRORACTION_CLOSE:
                                          goto SkipFile;
                                    default:
                                          DEBUGCONSOLE(10,"copyThread::run","Unknow action at mkpath ("+QString::number(actionAfterUnlock)+")");
                                          goto SkipFile;
                              }
                        }
                  }
                  else
                  {
                        DEBUGCONSOLE(10,"copyThread::run","try remove source but destination not exists!");
                  }
                  DEBUGCONSOLE(90,"copyThread::run","try remove sourceFile done");
            }

            DEBUGCONSOLE(90,"copyThread::run","now is in SkipFile point!");

/////////////////////////////////
SkipFile:
/////////////////////////////////

            //close file
            DEBUGCONSOLE(90,"copyThread::run","closing source and destination...");
            if(sourceFile.isOpen())
                  sourceFile.close();
            DEBUGCONSOLE(90,"copyThread::run","closing source done");
            if(copyHadBegin)
            {
                  if(theCurrentThread==NULL)
                  {
                        if(destinationFile.isOpen())
                        {
                              DEBUGCONSOLE(90,"copyThread::run","closing destination done");
                              destinationFile.close();
                        }
                  }
            }

            DEBUGCONSOLE(90,"copyThread::run","At the end of copy, actionAfterUnlock: "+QString::number(actionAfterUnlock));
            DEBUGCONSOLE(90,"copyThread::run","At the end of copy, stopIt: "+QString::number(stopIt));
            if(theCurrentThread==NULL)
            {
                  DEBUGCONSOLE(90,"copyThread::run","destinationFile.exists(): "+QString::number(destinationFile.exists()));
                  DEBUGCONSOLE(90,"copyThread::run","copyHadBegin: "+QString::number(copyHadBegin));
                  if((actionAfterUnlock==ERRORACTION_SKIP || actionAfterUnlock==ERRORACTION_CLOSE || actionAfterUnlock==ERRORACTION_ENDOF || stopIt) && destinationFile.exists()    && sourceFile.exists() && copyHadBegin)
                  {
                        DEBUGCONSOLE(50,"copyThread::run","try remove destination: "+destinationFile.fileName());
                        destinationFile.remove();
                  }
            }
            else
            {
                  if(skipThecurrentFile)
                        theCurrentThread->skipTheCurrentFile();
            }

            if(skipThecurrentFile)
            {
                  stopIt=false;
                  skipThecurrentFile=false;
            }
            if(stopIt && theCurrentThread!=NULL)
                  theCurrentThread->stop();
            //do list operation
            if(needRemoveFileToList)
            {
                  QMutexLocker lock_mutex(&MultiThreadCopyList);
                  copyListSize=theCopyList.size();
                  if(copyListSize)
                  {
                        firstScanCur+=theCopyList.first().size;
                        theCopyList.removeFirst();
                        numberOfItemRemoved++;
                        NumberOfFileCopied++;
                        copyListSize--;
                  }
                  else
                  {
                        DEBUGCONSOLE(70,"copyThread::run","copy list is empty");
                  }
            }
            syntetizedStringOverall="File "+QString::number(NumberOfFileCopied)+"/"+QString::number(NumberOfFileTot)+", Total: "+intToQtringSize(firstScanTot);
                DEBUGCONSOLE(90,"copyThread::run","copyListSize: "+QString::number(copyListSize));
      }
      /// \brief Flush the last thread
      if(!stopIt)
      {
            DEBUGCONSOLE(90,"copyThread::run","flush()");
            for (int i = 0; i < theWriteThreadList.size(); ++i) {
                  theWriteThreadList.at(i)->stopWhenIsFinish(true);
            }
            flush();
      }

      timeCopyElapsed         +=tempTimeElapsed.elapsed();
}

/*! \brief Stop the copy thread
\see stopIt, stopTheCopy() and run()
*/
02020 void copyThread::stop()
{
      DEBUGCONSOLE(90,"copyThread::stop","start");
      stopTheCopy();
      DEBUGCONSOLE(90,"copyThread::stop","stop");
}

02027 void copyThread::pre_operation()
{
      DEBUGCONSOLE(90,"copyThread::pre_operation","start");
      if(maxSpeed>0 && !clockForTheCopySpeed.isActive())
            clockForTheCopySpeed.start();
      currentFileSize         = 0;
      currentFileTotPos = totalCopiedSize;
      #if (DEBUG_ULTRACOPIER>0)
      theCurrentWait          = WaitInThread;
      #endif
      DEBUGCONSOLE(90,"copyThread::pre_operation","stop");
}

02040 void copyThread::post_operation()
{
      DEBUGCONSOLE(90,"copyThread::post_operation","start");
      if(clockForTheCopySpeed.isActive())
            clockForTheCopySpeed.stop();
      if(allThreadIsFinish())
            emit allThreadIsFinishNow();
      emit isInPauseOrNot();

      while(waitAction.available()<=0)
            waitAction.release();
      waitAction.acquire();
      while(waitNewClockForSpeed.available()<=0)
            waitNewClockForSpeed.release();
      waitNewClockForSpeed.acquire();
      currentFileSize         = 0;
      currentFileTotPos = totalCopiedSize;
      theCurrentStat          = copyThread::Stopped;
      stopped                 = true;
      #if (DEBUG_ULTRACOPIER>0)
      theCurrentWait          = NoWait;
      #endif
      DEBUGCONSOLE(90,"copyThread::post_operation","stop");
}

//remaining time
QString copyThread::remainingTime()
{
      if(firstScanCur==firstScanTot)
            return "0 second";
      if(theCurrentStat!=copyThread::Running || timeCopyElapsed==0)
            return "";
      qint64 sourcePos=totalCopiedSize-currentFileTotPos;
      if(sourcePos>currentFileSize)
            sourcePos=currentFileSize;
      double precent=(double)(firstScanCur+sourcePos)/firstScanTot;
      if(precent==0)
            return "";
      int timeRemaining=(int)((double)timeCopyElapsed/precent*(1-precent));
      int d=timeRemaining/(3600*24);
      timeRemaining-=d*3600*24;
      int h=timeRemaining/3600;
      timeRemaining-=h*3600;
      int m=timeRemaining/60;
      timeRemaining-=m*60;
      int s=timeRemaining;
      QString tempString;
      if(d)
      {
            tempString+=QString::number(d);
            if(d==1)
                  tempString+=translationDay;
            else
                  tempString+=translationDays;
            return tempString;
      }
      if(h)
      {
            tempString+=QString::number(h);
            if(h==1)
                  tempString+=translationHour;
            else
                  tempString+=translationHours;
      }
      if(h || m)
      {
            if(tempString!="")
                  tempString+=' ';
            tempString+=QString::number(m);
            if(m<=1)
                  tempString+=translationMinute;
            else
                  tempString+=translationMinutes;
            if(h)
                  return tempString;
      }
      if(tempString!="")
            tempString+=' ';
      tempString+=QString::number(s);
      if(s<=1)
            tempString+=translationSecond;
      else
            tempString+=translationSeconds;
      return tempString;
}

#if (DEBUG_ULTRACOPIER>0)
QStringList copyThread::DebugReturnCopyThreadStat()
{
      int numberIlde=0,numberRunning=0,numberError=0,numberInPause=0;
      {
            QMutexLocker lock_mutex(&MultiThread_ThreadList);
            for (int j=0; j<theWriteThreadList.size(); ++j) {
                  if(theWriteThreadList.at(j)->isFinished() && theWriteThreadList.at(j)->getTheCurrentStat()==WriteThread::Running)
                        numberError++;
                  if(theWriteThreadList.at(j)->getTheCurrentStat()==WriteThread::PausedInError)
                        numberInPause++;
                  else if(theWriteThreadList.at(j)->getTheCurrentStat()==WriteThread::Running)
                        numberRunning++;
                  else
                        numberIlde++;
            }
      }
      QString string;
      if(numberError>0)
            string="ilde: "+QString::number(numberIlde)+", run: "+QString::number(numberRunning)+", pause: "+QString::number(numberInPause)+", error: "+QString::number(numberError);
      else
            string="ilde: "+QString::number(numberIlde)+", run: "+QString::number(numberRunning)+", pause: "+QString::number(numberInPause);
      QStringList temp;
      temp.append(string);
      QString color;
      if(numberError>0)
            color="background-color: rgb(255, 0, 0);";
      else if(numberIlde==0 && numberRunning>0)
            color="background-color: rgb(255, 170, 0);";
      else if((numberIlde>0 && numberRunning>0) || numberInPause>0)
            color="background-color: rgb(255, 255, 0);";
      else
            color="background-color: rgb(0, 170, 0);";
      temp.append(color);
      return temp;
}
#endif

bool copyThread::allThreadIsFinish()
{
      DEBUGCONSOLE(90,"copyThread::allThreadIsFinish","start");
      bool allThreadIsFinishVar=true;
      if(this->getCurrentStat()!=copyThread::Stopped)
      {
            DEBUGCONSOLE(90,"copyThread::allThreadIsFinish","!this->isFinished()");
            allThreadIsFinishVar=false;
      }
      else
      {
            for (int i = 0; i < theWriteThreadList.size(); ++i) {
                  if(!theWriteThreadList.at(i)->isFinished() || theWriteThreadList.at(i)->isRunning())
                  {
                        #if (DEBUG_ULTRACOPIER>0)
                        if(!theWriteThreadList.at(i)->isFinished())
                              DEBUGCONSOLE(90,"copyThread::allThreadIsFinish","!theWriteThreadList.at("+QString::number(i)+")->isFinished()");
                        if(theWriteThreadList.at(i)->isRunning())
                              DEBUGCONSOLE(90,"copyThread::allThreadIsFinish","theWriteThreadList.at("+QString::number(i)+")->isRunning()");
                        #endif
                        allThreadIsFinishVar=false;
                        break;
                  }
            }
      }
      return allThreadIsFinishVar;
}

02192 void copyThread::newWriteThreadFinish()
{
      DEBUGCONSOLE(90,"copyThread::newWriteThreadFinish","start");
      checkIfNeedWaitWriteThread();
      if(allThreadIsFinish())
            emit allThreadIsFinishNow();
      DEBUGCONSOLE(90,"copyThread::newWriteThreadFinish","stop");
}

02201 void copyThread::putFirstFileAtEnd()
{
      needRemoveFileToList=false;
      QMutexLocker lock_mutex(&MultiThreadCopyList);
      putAtEnd<<theCopyList.first();
      if(theCopyList.size()>1)
            theCopyList.move(0,theCopyList.size()-1);
}

/// \brief error on file or folder, bouton enable, file path, error message, and wait
02211 int copyThread::errorOnFileAndWait(int errorCode,QString file,QString error,quint64 id)
{
      actionAfterUnlock=-1;
      emit errorOnFile(errorCode,file,error,id);
      waitNeedAction();
      #if (DEBUG_ULTRACOPIER>0)
      if(actionAfterUnlock==-1)
            DEBUGCONSOLE(10,"copyThread::errorOnFileAndWait","Action is unknow: "+QString::number(actionAfterUnlock));
      if((errorCode==ERROR_DEF_NOENDOF || errorCode==ERROR_DEF_NOSKIPNOENDOF) && actionAfterUnlock==ERRORACTION_ENDOF)
            DEBUGCONSOLE(10,"copyThread::errorOnFileAndWait","Action is not possible: "+QString::number(actionAfterUnlock));
      if(errorCode==ERROR_DEF_NOSKIPNOENDOF && actionAfterUnlock==ERRORACTION_SKIP)
            DEBUGCONSOLE(10,"copyThread::errorOnFileAndWait","Action is not possible: "+QString::number(actionAfterUnlock));
      #endif
      return actionAfterUnlock;
}

//put at end after error occured
QList<copyItemInternal> copyThread::putAtEndAfterError()
{
      QList<copyItemInternal> temp=putAtEnd;
      putAtEnd.clear();
      return temp;
}

#if (DEBUG_ULTRACOPIER>0)
QString copyThread::WaitInWhat()
{
      switch(theCurrentWait)
      {
            case NoWait:
                  return "No wait";
            case WaitInRead:
                  return "Wait in read";
            case WaitInWrite:
                  return "Wait in write";
            case WaitInThread:
                  return "Wait in thread";
      }
      return "Internal error";
}
#endif

Generated by  Doxygen 1.6.0   Back to index