📄 synchronizer.cpp
字号:
/*************************************************************************** synchronizer.cpp - description ------------------- copyright : (C) 2003 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include "synchronizer.h"#include "synchronizerdirlist.h"#include "../krusader.h"#include "../krservices.h"#include "../VFS/vfs.h"#include "../VFS/krquery.h"#include "config.h"#include <kurl.h>#include <kmessagebox.h>#include <klocale.h>#include <qapplication.h>#include <qregexp.h>#include <qdir.h>#include <qtimer.h>#include <kio/job.h>#include <kdialogbase.h>#include <kio/observer.h>#include <kio/renamedlg.h>#include <kio/skipdlg.h>#include <unistd.h>#include <qeventloop.h>#include <qpushbutton.h>#include <qdatetime.h>#include <kprocess.h>#include <kdialogbase.h>#include <kprogress.h>#include <qlayout.h>#include <kurlcompletion.h>#include <sys/types.h>#include <sys/time.h>#include <utime.h>#include <pwd.h>#include <grp.h>#include <qlabel.h>#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )#include <sys/acl.h>#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS#include <acl/libacl.h>#endif#endif#define DISPLAY_UPDATE_PERIOD 2Synchronizer::Synchronizer() : displayUpdateCount( 0 ), markEquals( true ), markDiffers ( true ), markCopyToLeft( true ), markCopyToRight( true ), markDeletable( true ), stack(), jobMap(), receivedMap(), parentWidget( 0 ){ resultList.setAutoDelete( true ); stack.setAutoDelete( true );}void Synchronizer::reset(){ displayUpdateCount = 0; markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = true; stopped = false; recurseSubDirs = followSymLinks = ignoreDate = asymmetric = cmpByContent = ignoreCase = autoScroll = false; markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = markDuplicates = markSingles = false; leftCopyEnabled = rightCopyEnabled = deleteEnabled = overWrite = autoSkip = paused = false; leftCopyNr = rightCopyNr = deleteNr = 0; leftCopySize = rightCopySize = deleteSize = 0; comparedDirs = fileCount = 0; leftBaseDir = rightBaseDir = QString::null; resultList.clear(); temporaryList.clear(); stack.clear();}int Synchronizer::compare( QString leftURL, QString rightURL, KRQuery *query, bool subDirs, bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase, bool autoSc, QStringList &selFiles, int equThres, int timeOffs, int parThreads, bool hiddenFiles ){ resultList.clear(); temporaryList.clear(); recurseSubDirs = subDirs; followSymLinks = symLinks; ignoreDate = igDate; asymmetric = asymm; cmpByContent = cmpByCnt; autoScroll = autoSc; ignoreCase = igCase; selectedFiles = selFiles; equalsThreshold= equThres; timeOffset = timeOffs; parallelThreads= parThreads; ignoreHidden = hiddenFiles; stopped = false; this->query = query; leftURL = KURLCompletion::replacedPath( leftURL, true, true ); rightURL = KURLCompletion::replacedPath( rightURL, true, true ); if( !leftURL.endsWith("/" )) leftURL+="/"; if( !rightURL.endsWith("/" )) rightURL+="/"; excludedPaths = query->dontSearchInDirs().toStringList(); for( unsigned i = 0; i != excludedPaths.count(); i++ ) if( excludedPaths[ i ].endsWith( "/" ) ) excludedPaths[ i ].truncate( excludedPaths[ i ].length() - 1 ); comparedDirs = fileCount = 0; stack.append( new CompareTask( 0, leftBaseDir = leftURL, rightBaseDir = rightURL, "", "", ignoreHidden ) ); compareLoop(); SynchronizerFileItem *item = temporaryList.first(); while( item ) { if( item->isTemporary() ) delete item; item = temporaryList.next(); } temporaryList.clear(); if( !autoScroll ) refresh( true ); emit statusInfo( i18n( "Number of files: %1" ).arg( fileCount ) ); return fileCount;}void Synchronizer::compareLoop() { while( !stopped && !stack.isEmpty() ) { for( int thread=0; thread < (int)stack.count() && thread < parallelThreads; thread++ ) { SynchronizerTask * entry = stack.at( thread ); if( entry->state() == ST_STATE_NEW ) entry->start( parentWidget ); if( entry->inherits("CompareTask") ) { if( entry->state() == ST_STATE_READY ) { CompareTask *ctentry = (CompareTask *) entry; if( ctentry->isDuplicate() ) compareDirectory( ctentry->parent(), ctentry->leftDirList(), ctentry->rightDirList(), ctentry->leftDir(), ctentry->rightDir() ); else addSingleDirectory( ctentry->parent(), ctentry->dirList(), ctentry->dir(), ctentry->isLeft() ); } if( entry->state() == ST_STATE_READY || entry->state() == ST_STATE_ERROR ) comparedDirs++; } switch( entry->state() ) { case ST_STATE_STATUS: emit statusInfo( entry->status() ); break; case ST_STATE_READY: case ST_STATE_ERROR: emit statusInfo( i18n( "Number of compared directories: %1" ).arg( comparedDirs ) ); stack.removeRef( entry ); continue; default: break; } } if( !stack.isEmpty() ) qApp->processEvents(); } stack.clear();}void Synchronizer::compareDirectory( SynchronizerFileItem *parent, SynchronizerDirList * left_directory, SynchronizerDirList * right_directory, const QString &leftDir, const QString &rightDir ){ const QString &leftURL = left_directory->url(); const QString &rightURL = right_directory->url(); vfile * left_file; vfile * right_file; QString file_name; bool checkIfSelected = false; if( leftDir.isEmpty() && rightDir.isEmpty() && selectedFiles.count() ) checkIfSelected = true; /* walking through in the left directory */ for( left_file=left_directory->first(); left_file != 0 && !stopped ; left_file=left_directory->next() ) { if ( isDir( left_file ) ) continue; file_name = left_file->vfile_getName(); if( checkIfSelected && !selectedFiles.contains( file_name ) ) continue; if( !query->match( left_file ) ) continue; if( (right_file = right_directory->search( file_name, ignoreCase )) == 0 ) addLeftOnlyItem( parent, file_name, leftDir, left_file->vfile_getSize(), left_file->vfile_getTime_t(), readLink( left_file ), left_file->vfile_getOwner(), left_file->vfile_getGroup(), left_file->vfile_getMode(), left_file->vfile_getACL() ); else { if( isDir( right_file ) ) continue; addDuplicateItem( parent, file_name, right_file->vfile_getName(), leftDir, rightDir, left_file->vfile_getSize(), right_file->vfile_getSize(), left_file->vfile_getTime_t(), right_file->vfile_getTime_t(), readLink( left_file ), readLink( right_file ), left_file->vfile_getOwner(), right_file->vfile_getOwner(), left_file->vfile_getGroup(), right_file->vfile_getGroup(), left_file->vfile_getMode(), right_file->vfile_getMode(), left_file->vfile_getACL(), right_file->vfile_getACL() ); } } /* walking through in the right directory */ for( right_file=right_directory->first(); right_file != 0 && !stopped ; right_file=right_directory->next() ) { if( isDir( right_file ) ) continue; file_name = right_file->vfile_getName(); if( checkIfSelected && !selectedFiles.contains( file_name ) ) continue; if( !query->match( right_file ) ) continue; if( left_directory->search( file_name, ignoreCase ) == 0 ) addRightOnlyItem( parent, file_name, rightDir, right_file->vfile_getSize(), right_file->vfile_getTime_t(), readLink( right_file ), right_file->vfile_getOwner(), right_file->vfile_getGroup(), right_file->vfile_getMode(), right_file->vfile_getACL() ); } /* walking through the subdirectories */ if( recurseSubDirs ) { for( left_file=left_directory->first(); left_file != 0 && !stopped ; left_file=left_directory->next() ) { if ( left_file->vfile_isDir() && ( followSymLinks || !left_file->vfile_isSymLink()) ) { QString left_file_name = left_file->vfile_getName(); if( checkIfSelected && !selectedFiles.contains( left_file_name ) ) continue; if( excludedPaths.contains( leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name ) ) continue; if( !query->matchDirName( left_file_name ) ) continue; if( (right_file = right_directory->search( left_file_name, ignoreCase )) == 0 ) { SynchronizerFileItem *me = addLeftOnlyItem( parent, left_file_name, leftDir, 0, left_file->vfile_getTime_t(), readLink( left_file ), left_file->vfile_getOwner(), left_file->vfile_getGroup(), left_file->vfile_getMode(), left_file->vfile_getACL(), true, !query->match( left_file ) ); stack.append( new CompareTask( me, leftURL+left_file_name+"/", leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name, true, ignoreHidden ) ); } else { QString right_file_name = right_file->vfile_getName(); SynchronizerFileItem *me = addDuplicateItem( parent, left_file_name, right_file_name, leftDir, rightDir, 0, 0, left_file->vfile_getTime_t(), right_file->vfile_getTime_t(), readLink( left_file ), readLink( right_file ), left_file->vfile_getOwner(), right_file->vfile_getOwner(), left_file->vfile_getGroup(), right_file->vfile_getGroup(), left_file->vfile_getMode(), right_file->vfile_getMode(), left_file->vfile_getACL(), right_file->vfile_getACL(), true, !query->match( left_file ) ); stack.append( new CompareTask( me, leftURL+left_file_name+"/", rightURL+right_file_name+"/", leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name, rightDir.isEmpty() ? right_file_name : rightDir+"/"+right_file_name, ignoreHidden ) ); } } } /* walking through the the right side subdirectories */ for( right_file=right_directory->first(); right_file != 0 && !stopped ; right_file=right_directory->next() ) { if ( right_file->vfile_isDir() && (followSymLinks || !right_file->vfile_isSymLink()) ) { file_name = right_file->vfile_getName(); if( checkIfSelected && !selectedFiles.contains( file_name ) ) continue; if( excludedPaths.contains( rightDir.isEmpty() ? file_name : rightDir+"/"+file_name ) ) continue; if( !query->matchDirName( file_name ) ) continue; if( left_directory->search( file_name, ignoreCase ) == 0 ) { SynchronizerFileItem *me = addRightOnlyItem( parent, file_name, rightDir, 0, right_file->vfile_getTime_t(), readLink( right_file ), right_file->vfile_getOwner(), right_file->vfile_getGroup(), right_file->vfile_getMode(), right_file->vfile_getACL(), true, !query->match( right_file ) ); stack.append( new CompareTask( me, rightURL+file_name+"/", rightDir.isEmpty() ? file_name : rightDir+"/"+file_name, false, ignoreHidden ) ); } } } }}QString Synchronizer::getTaskTypeName( TaskType taskType ){ static QString names[] = {"=","!=","<-","->","DEL","?","?","?","?","?"}; return names[taskType];}SynchronizerFileItem * Synchronizer::addItem( SynchronizerFileItem *parent, const QString &leftFile, const QString &rightFile, const QString &leftDir, const QString &rightDir, bool existsLeft, bool existsRight, KIO::filesize_t leftSize, KIO::filesize_t rightSize, time_t leftDate, time_t rightDate, const QString &leftLink, const QString &rightLink, const QString &leftOwner, const QString &rightOwner, const QString &leftGroup, const QString &rightGroup, mode_t leftMode, mode_t rightMode, const QString &leftACL, const QString &rightACL, TaskType tsk, bool isDir, bool isTemp ){ bool marked = autoScroll ? !isTemp && isMarked( tsk, existsLeft && existsRight ) : false; SynchronizerFileItem *item = new SynchronizerFileItem( leftFile, rightFile, leftDir, rightDir, marked, existsLeft, existsRight, leftSize, rightSize, leftDate, rightDate, leftLink, rightLink, leftOwner, rightOwner, leftGroup, rightGroup, leftMode, rightMode, leftACL, rightACL, tsk, isDir, isTemp, parent ); if( !isTemp ) { while( parent && parent->isTemporary() )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -