49 #include <QtCore/QTimer>
50 #include <QtCore/QFile>
61 #define REPORT_TIMEOUT 200
106 , m_defaultPermissions(
false)
109 , m_asMethod(asMethod)
115 , m_fileProcessedSize(0)
116 , m_processedFiles(0)
119 , m_currentStatSrc(m_srcList.constBegin())
120 , m_bCurrentOperationIsLink(
false)
121 , m_bSingleFileCopy(
false)
124 , m_bAutoRenameFiles(
false)
125 , m_bAutoRenameDirs(
false)
126 , m_bAutoSkipFiles(
false )
127 , m_bAutoSkipDirs(
false )
128 , m_bOverwriteAllFiles(
false )
129 , m_bOverwriteAllDirs(
false )
143 bool m_defaultPermissions;
148 QLinkedList<CopyInfo> m_directoriesCopied;
149 QLinkedList<CopyInfo>::const_iterator m_directoriesCopiedIterator;
161 int m_processedFiles;
168 KUrl::List::const_iterator m_currentStatSrc;
169 bool m_bCurrentSrcIsDir;
170 bool m_bCurrentOperationIsLink;
171 bool m_bSingleFileCopy;
178 bool m_bAutoRenameFiles;
179 bool m_bAutoRenameDirs;
180 bool m_bAutoSkipFiles;
181 bool m_bAutoSkipDirs;
182 bool m_bOverwriteAllFiles;
183 bool m_bOverwriteAllDirs;
186 QTimer *m_reportTimer;
190 KUrl m_currentSrcURL;
191 KUrl m_currentDestURL;
195 void statCurrentSrc();
199 void slotResultStating(
KJob * job );
200 void startListing(
const KUrl & src );
201 void slotResultCreatingDirs(
KJob * job );
202 void slotResultConflictCreatingDirs(
KJob * job );
203 void createNextDir();
204 void slotResultCopyingFiles(
KJob * job );
205 void slotResultConflictCopyingFiles(
KJob * job );
207 KIO::Job* linkNextFile(
const KUrl& uSource,
const KUrl& uDest, JobFlags flags );
209 void slotResultDeletingDirs(
KJob * job );
210 void deleteNextDir();
211 void sourceStated(
const UDSEntry& entry,
const KUrl& sourceUrl);
212 void skip(
const KUrl & sourceURL,
bool isDir);
213 void slotResultRenaming(
KJob * job );
214 void slotResultSettingDirAttributes(
KJob * job );
215 void setNextDirAttribute();
217 void startRenameJob(
const KUrl &slave_url);
218 bool shouldOverwriteDir(
const QString& path )
const;
219 bool shouldOverwriteFile(
const QString& path )
const;
220 bool shouldSkip(
const QString& path )
const;
221 void skipSrc(
bool isDir);
226 void addCopyInfoFromUDSEntry(
const UDSEntry& entry,
const KUrl& srcUrl,
bool srcIsDir,
const KUrl& currentDest);
230 void slotProcessedSize(
KJob*, qulonglong data_size );
235 void slotTotalSize(
KJob*, qulonglong size );
242 CopyJob::CopyMode mode,
bool asMethod, JobFlags flags)
244 CopyJob *job =
new CopyJob(*
new CopyJobPrivate(src,dest,mode,asMethod));
249 job->d_func()->m_bOverwriteAllDirs =
true;
250 job->d_func()->m_bOverwriteAllFiles =
true;
259 setProperty(
"destUrl", d_func()->m_dest.url());
260 QTimer::singleShot(0,
this, SLOT(slotStart()));
261 qRegisterMetaType<KIO::UDSEntry>(
"KIO::UDSEntry");
270 return d_func()->m_srcList;
275 return d_func()->m_dest;
278 void CopyJobPrivate::slotStart()
286 m_reportTimer =
new QTimer(q);
288 q->connect(m_reportTimer,SIGNAL(
timeout()),q,SLOT(slotReport()));
300 void CopyJobPrivate::slotResultStating(
KJob *job )
313 kDebug(7007) <<
"Error while stating source. Activating hack";
314 q->removeSubjob( job );
315 assert ( !q->hasSubjobs() );
318 info.
mtime = (time_t) -1;
319 info.
ctime = (time_t) -1;
324 if ( destinationState ==
DEST_IS_DIR && !m_asMethod )
327 files.append( info );
333 q->Job::slotResult( job );
341 if ( m_dest.isLocalFile() ) {
342 QString path = m_dest.toLocalFile();
347 path = QFileInfo(path).absolutePath();
349 KFileSystemType::Type fsType = KFileSystemType::fileSystemType( path );
350 if ( fsType != KFileSystemType::Nfs && fsType != KFileSystemType::Smb && fsType != KFileSystemType::Ramfs ) {
351 m_freeSpace = KDiskFreeSpaceInfo::freeSpaceInfo( path ).available();
357 const bool isGlobalDest = m_dest == m_globalDest;
358 const bool isDir = entry.
isDir();
371 m_dest.setPath(sLocalPath);
373 m_globalDest = m_dest;
377 m_globalDestinationState = destinationState;
379 q->removeSubjob( job );
380 assert ( !q->hasSubjobs() );
385 sourceStated(entry, static_cast<SimpleJob*>(job)->url());
386 q->removeSubjob( job );
390 void CopyJobPrivate::sourceStated(
const UDSEntry& entry,
const KUrl& sourceUrl)
393 const bool isDir = entry.
isDir();
412 kDebug() <<
"Using sLocalPath. destinationState=" << destinationState;
419 addCopyInfoFromUDSEntry(entry, srcurl,
false, m_dest);
421 m_currentDest = m_dest;
422 m_bCurrentSrcIsDir =
false;
433 m_parentDirs.insert(parentDir);
436 m_bCurrentSrcIsDir =
true;
446 if (!sName.isEmpty())
450 if (!dispName.isEmpty())
451 directory = dispName;
452 else if (!sName.isEmpty())
455 m_currentDest.addPath( directory );
465 if ( m_dest == m_globalDest )
466 m_globalDestinationState = destinationState;
469 startListing( srcurl );
477 m_parentDirs.insert(parentDir);
491 void CopyJobPrivate::slotReport()
494 if ( q->isSuspended() )
499 q->setTotalAmount(KJob::Files, m_srcList.count());
502 q->setProcessedAmount( KJob::Files, m_processedFiles );
509 emitMoving(q, m_currentSrcURL, m_currentDestURL);
510 emit q->moving( q, m_currentSrcURL, m_currentDestURL);
514 emitCopying( q, m_currentSrcURL, m_currentDestURL );
515 emit q->linking( q, m_currentSrcURL.path(), m_currentDestURL );
519 emitCopying( q, m_currentSrcURL, m_currentDestURL );
520 emit q->copying( q, m_currentSrcURL, m_currentDestURL );
526 q->setProcessedAmount( KJob::Directories, m_processedDirs );
530 emit q->creatingDir( q, m_currentDestURL );
531 emitCreatingDir( q, m_currentDestURL );
542 emitMoving( q, m_currentSrcURL, m_currentDestURL );
546 emitCopying( q, m_currentSrcURL, m_currentDestURL );
549 q->setTotalAmount(KJob::Bytes, m_totalSize);
550 q->setTotalAmount(KJob::Files, files.count());
551 q->setTotalAmount(KJob::Directories,
dirs.count());
562 UDSEntryList::ConstIterator it = list.constBegin();
563 UDSEntryList::ConstIterator
end = list.constEnd();
564 for (; it != end; ++it) {
566 addCopyInfoFromUDSEntry(entry, static_cast<SimpleJob *>(job)->url(), m_bCurrentSrcIsDir, m_currentDest);
572 const KUrl url = subJob->
url();
582 void CopyJobPrivate::addCopyInfoFromUDSEntry(
const UDSEntry& entry,
const KUrl& srcUrl,
bool srcIsDir,
const KUrl& currentDest)
590 m_totalSize += info.size;
596 if (!urlStr.isEmpty())
599 const bool isDir = entry.
isDir();
602 if (fileName != QLatin1String(
"..") && fileName != QLatin1String(
".")) {
603 const bool hasCustomURL = !url.isEmpty() || !localPath.isEmpty();
614 url =
KUrl(localPath);
618 info.uDest = currentDest;
632 int numberOfSlashes = fileName.count(
'/');
635 for (
int n = 0; n < numberOfSlashes + 1; ++n) {
636 pos = path.lastIndexOf(
'/', pos - 1);
638 kWarning(7007) <<
"kioslave bug: not enough slashes in UDS_URL" << path <<
"- looking for" << numberOfSlashes <<
"slashes";
643 destFileName = path.mid(pos + 1);
647 destFileName = fileName;
650 destFileName = displayName.isEmpty() ? fileName : displayName;
656 if (destFileName.isEmpty()) {
661 info.uDest.addPath(destFileName);
665 if (info.linkDest.isEmpty() && isDir && m_mode !=
CopyJob::Link) {
668 dirsToRemove.append(info.uSource);
676 void CopyJobPrivate::skipSrc(
bool isDir)
678 m_dest = m_globalDest;
679 destinationState = m_globalDestinationState;
680 skip(*m_currentStatSrc, isDir);
685 void CopyJobPrivate::statNextSrc()
691 m_dest = m_globalDest;
692 destinationState = m_globalDestinationState;
697 void CopyJobPrivate::statCurrentSrc()
700 if (m_currentStatSrc != m_srcList.constEnd()) {
701 m_currentSrcURL = (*m_currentStatSrc);
705 m_currentDest = m_dest;
708 info.mtime = (time_t) -1;
709 info.ctime = (time_t) -1;
711 info.uSource = m_currentSrcURL;
712 info.uDest = m_currentDest;
714 if (destinationState ==
DEST_IS_DIR && !m_asMethod) {
716 (m_currentSrcURL.protocol() == info.uDest.protocol()) &&
717 (m_currentSrcURL.host() == info.uDest.host()) &&
718 (m_currentSrcURL.port() == info.uDest.port()) &&
719 (m_currentSrcURL.user() == info.uDest.user()) &&
720 (m_currentSrcURL.pass() == info.uDest.pass()) ) {
722 info.uDest.addPath( m_currentSrcURL.fileName() );
730 files.append( info );
738 if (!cachedItem.
isNull()) {
739 entry = cachedItem.
entry();
742 m_currentSrcURL = cachedItem.
mostLocalUrl(dummyIsLocal);
753 if ( (m_currentSrcURL.protocol() == m_dest.protocol()) &&
754 (m_currentSrcURL.host() == m_dest.host()) &&
755 (m_currentSrcURL.port() == m_dest.port()) &&
756 (m_currentSrcURL.user() == m_dest.user()) &&
757 (m_currentSrcURL.pass() == m_dest.pass()) )
759 startRenameJob( m_currentSrcURL );
764 startRenameJob( m_dest );
769 startRenameJob( m_currentSrcURL );
776 QPointer<CopyJob> that = q;
783 m_bOnlyRenames =
false;
788 kDebug(7007) <<
"fast path! found info about" << m_currentSrcURL <<
"in KDirLister";
790 QMetaObject::invokeMethod(q,
"sourceStated", Qt::QueuedConnection, Q_ARG(
KIO::UDSEntry, entry), Q_ARG(
KUrl, m_currentSrcURL));
799 m_currentDestURL = m_dest;
810 kDebug(7007)<<
"Stating finished. To copy:"<<m_totalSize<<
", available:"<<m_freeSpace;
814 emit q->aboutToCreate( q, dirs );
815 if (!files.isEmpty())
816 emit q->aboutToCreate( q, files );
818 m_bSingleFileCopy = ( files.count() == 1 &&
dirs.isEmpty() );
825 void CopyJobPrivate::startRenameJob(
const KUrl& slave_url )
830 if (m_currentSrcURL.isLocalFile()) {
832 if (!m_parentDirs.contains(parentDir)) {
834 m_parentDirs.insert(parentDir);
840 if ( destinationState ==
DEST_IS_DIR && !m_asMethod )
841 dest.
addPath( m_currentSrcURL.fileName() );
842 m_currentDestURL = dest;
843 kDebug(7007) << m_currentSrcURL <<
"->" << dest <<
"trying direct rename first";
848 info.mtime = (time_t) -1;
849 info.ctime = (time_t) -1;
851 info.uSource = m_currentSrcURL;
855 emit q->aboutToCreate( q, files );
857 KIO_ARGS << m_currentSrcURL << dest << (qint8)
false ;
860 q->addSubjob( newJob );
861 if ( m_currentSrcURL.directory() != dest.directory() )
862 m_bOnlyRenames =
false;
865 void CopyJobPrivate::startListing(
const KUrl & src )
876 q->addSubjob( newjob );
879 void CopyJobPrivate::skip(
const KUrl & sourceUrl,
bool isDir)
886 while (dirsToRemove.removeAll(dir) > 0) {
893 bool CopyJobPrivate::shouldOverwriteDir(
const QString& path )
const
895 if ( m_bOverwriteAllDirs )
897 return m_overwriteList.contains(path);
900 bool CopyJobPrivate::shouldOverwriteFile(
const QString& path )
const
902 if ( m_bOverwriteAllFiles )
904 return m_overwriteList.contains(path);
907 bool CopyJobPrivate::shouldSkip(
const QString& path )
const
909 Q_FOREACH(
const QString& skipPath, m_skipList) {
910 if ( path.startsWith(skipPath) )
916 void CopyJobPrivate::slotResultCreatingDirs(
KJob * job )
924 m_conflictError = job->error();
930 if ( m_bAutoSkipDirs ) {
937 const QString destDir = (*it).uDest.path();
938 if ( shouldOverwriteDir( destDir ) ) {
939 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true ,
false );
942 if (m_bAutoRenameDirs) {
945 KUrl destDirectory((*it).uDest);
946 destDirectory.setPath(destDirectory.directory());
949 KUrl newUrl((*it).uDest);
950 newUrl.setFileName(newName);
952 emit q->renamed(q, (*it).uDest, newUrl);
961 for(; renamedirit !=
dirs.end() ; ++renamedirit) {
962 QString path = (*renamedirit).uDest.path();
963 if (path.startsWith(oldPath)) {
965 n.replace(0, oldPath.length(), newPath);
966 kDebug(7007) <<
"dirs list:" << (*renamedirit).uSource.path()
967 <<
"was going to be" << path
968 <<
", changed into" << n;
969 (*renamedirit).uDest.setPath(n);
974 for(; renamefileit != files.end() ; ++renamefileit) {
975 QString path = (*renamefileit).uDest.path();
976 if (path.startsWith(oldPath)) {
978 n.replace(0, oldPath.length(), newPath);
979 kDebug(7007) <<
"files list:" << (*renamefileit).uSource.path()
980 <<
"was going to be" << path
981 <<
", changed into" << n;
982 (*renamefileit).uDest.setPath(n);
985 if (!
dirs.isEmpty()) {
986 emit q->aboutToCreate(q, dirs);
988 if (!files.isEmpty()) {
989 emit q->aboutToCreate(q, files);
994 if (!q->isInteractive()) {
995 q->Job::slotResult(job);
999 assert(((
SimpleJob*)job)->url().url() == (*it).uDest.
url());
1000 q->removeSubjob(job);
1001 assert (!q->hasSubjobs());
1004 KUrl existingDest((*it).uDest);
1007 kDebug(7007) <<
"KIO::stat for resolving conflict on " << existingDest;
1009 q->addSubjob(newJob);
1018 q->Job::slotResult( job );
1025 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true,
false );
1026 m_directoriesCopied.append( *it );
1032 q->removeSubjob( job );
1033 assert( !q->hasSubjobs() );
1037 void CopyJobPrivate::slotResultConflictCreatingDirs(
KJob * job )
1054 q->removeSubjob( job );
1055 assert ( !q->hasSubjobs() );
1062 if( (*it).uSource == (*it).uDest ||
1063 ((*it).uSource.protocol() == (*it).uDest.protocol() &&
1070 QString existingDest = (*it).uDest.path();
1073 m_reportTimer->stop();
1075 (*it).uSource.url(),
1078 (*it).size, destsize,
1079 (*it).ctime, destctime,
1080 (*it).mtime, destmtime );
1089 m_bAutoRenameDirs =
true;
1094 KUrl newUrl( (*it).uDest );
1095 newUrl.setPath( newPath );
1096 emit q->renamed( q, (*it).uDest, newUrl );
1104 for( ; renamedirit !=
dirs.end() ; ++renamedirit )
1106 QString path = (*renamedirit).uDest.path();
1107 if ( path.startsWith( oldPath ) ) {
1109 n.replace( 0, oldPath.length(), newPath );
1110 kDebug(7007) <<
"dirs list:" << (*renamedirit).uSource.path()
1111 <<
"was going to be" << path
1112 <<
", changed into" << n;
1113 (*renamedirit).uDest.setPath( n );
1118 for( ; renamefileit != files.end() ; ++renamefileit )
1120 QString path = (*renamefileit).uDest.path();
1121 if ( path.startsWith( oldPath ) ) {
1123 n.replace( 0, oldPath.length(), newPath );
1124 kDebug(7007) <<
"files list:" << (*renamefileit).uSource.path()
1125 <<
"was going to be" << path
1126 <<
", changed into" << n;
1127 (*renamefileit).uDest.setPath( n );
1130 if (!
dirs.isEmpty())
1131 emit q->aboutToCreate( q, dirs );
1132 if (!files.isEmpty())
1133 emit q->aboutToCreate( q, files );
1137 m_bAutoSkipDirs =
true;
1140 m_skipList.append( existingDest );
1141 skip((*it).uSource,
true);
1147 m_overwriteList.insert( existingDest );
1148 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true ,
false );
1154 m_bOverwriteAllDirs =
true;
1155 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true ,
false );
1168 void CopyJobPrivate::createNextDir()
1172 if ( !
dirs.isEmpty() )
1177 while( it !=
dirs.end() && udir.isEmpty() )
1180 if ( shouldSkip( dir ) ) {
1187 if ( !udir.isEmpty() )
1193 if (shouldOverwriteFile(udir.
path())) {
1197 m_currentDestURL = udir;
1200 q->addSubjob(newjob);
1205 q->setProcessedAmount( KJob::Directories, m_processedDirs );
1222 void CopyJobPrivate::slotResultCopyingFiles(
KJob * job )
1230 if ( m_bAutoSkipFiles )
1232 skip((*it).uSource,
false);
1233 m_fileProcessedSize = (*it).size;
1238 m_conflictError = job->error();
1244 if (m_bAutoRenameFiles) {
1245 KUrl destDirectory((*it).uDest);
1246 destDirectory.setPath(destDirectory.directory());
1249 KUrl newUrl((*it).uDest);
1250 newUrl.setFileName(newName);
1252 emit q->renamed(q, (*it).uDest, newUrl);
1253 (*it).uDest = newUrl;
1257 emit q->aboutToCreate(q, files);
1260 if ( !q->isInteractive() ) {
1261 q->Job::slotResult( job );
1265 q->removeSubjob(job);
1266 assert (!q->hasSubjobs());
1268 KUrl existingFile((*it).uDest);
1271 kDebug(7007) <<
"KIO::stat for resolving conflict on " << existingFile;
1273 q->addSubjob(newJob);
1279 if ( m_bCurrentOperationIsLink && qobject_cast<KIO::DeleteJob*>( job ) )
1283 m_fileProcessedSize = (*it).size;
1286 if ( !q->isInteractive() ) {
1287 q->Job::slotResult( job );
1292 slotResultConflictCopyingFiles( job );
1301 && !qobject_cast<KIO::DeleteJob *>( job )
1304 q->removeSubjob( job );
1305 assert ( !q->hasSubjobs() );
1309 q->addSubjob( newjob );
1313 if ( m_bCurrentOperationIsLink )
1317 emit q->copyingLinkDone( q, (*it).uSource, target, (*it).uDest );
1321 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
false,
false );
1326 m_successSrcList.append((*it).uSource);
1328 m_freeSpace -= (*it).size;
1338 m_processedSize += m_fileProcessedSize;
1339 m_fileProcessedSize = 0;
1346 m_incomingMetaData += kiojob->
metaData();
1347 q->removeSubjob( job );
1348 assert( !q->hasSubjobs() );
1352 void CopyJobPrivate::slotResultConflictCopyingFiles(
KJob * job )
1363 m_reportTimer->stop();
1386 if ( (*it).uSource == (*it).uDest ||
1387 ((*it).uSource.protocol() == (*it).uDest.protocol() &&
1395 if ( !m_bSingleFileCopy )
1398 res = q->ui()->askFileRename( q, !isDir ?
1399 i18n(
"File Already Exists") :
i18n(
"Already Exists as Folder"),
1400 (*it).uSource.url(),
1403 (*it).size, destsize,
1404 (*it).ctime, destctime,
1405 (*it).mtime, destmtime );
1412 else if ( !q->isInteractive() ) {
1413 q->Job::slotResult( job );
1419 job->errorString() );
1431 q->removeSubjob( job );
1432 assert ( !q->hasSubjobs() );
1439 m_bAutoRenameFiles =
true;
1443 KUrl newUrl( (*it).uDest );
1444 newUrl.setPath( newPath );
1445 emit q->renamed( q, (*it).uDest, newUrl );
1446 (*it).uDest = newUrl;
1450 emit q->aboutToCreate( q, files );
1454 m_bAutoSkipFiles =
true;
1458 skip((*it).uSource,
false);
1459 m_processedSize += (*it).size;
1464 m_bOverwriteAllFiles =
true;
1468 m_overwriteList.insert( (*it).uDest.path() );
1477 KIO::Job* CopyJobPrivate::linkNextFile(
const KUrl& uSource,
const KUrl& uDest, JobFlags flags )
1482 (uSource.host() == uDest.host()) &&
1483 (uSource.port() == uDest.port()) &&
1484 (uSource.
user() == uDest.
user()) &&
1492 m_bCurrentOperationIsLink =
true;
1493 m_currentSrcURL=uSource;
1494 m_currentDestURL=uDest;
1507 if (
f.open( QIODevice::ReadWrite ) )
1516 config.
writeEntry(
"Type", QString::fromLatin1(
"Link") );
1518 if ( protocol == QLatin1String(
"ftp") )
1519 config.
writeEntry(
"Icon", QString::fromLatin1(
"folder-remote") );
1520 else if ( protocol == QLatin1String(
"http") )
1521 config.
writeEntry(
"Icon", QString::fromLatin1(
"text-html") );
1522 else if ( protocol == QLatin1String(
"info") )
1523 config.
writeEntry(
"Icon", QString::fromLatin1(
"text-x-texinfo") );
1524 else if ( protocol == QLatin1String(
"mailto") )
1525 config.
writeEntry(
"Icon", QString::fromLatin1(
"internet-mail") );
1527 config.
writeEntry(
"Icon", QString::fromLatin1(
"unknown") );
1529 files.erase( files.begin() );
1537 kDebug(7007) <<
"ERR_CANNOT_OPEN_FOR_WRITING";
1553 void CopyJobPrivate::copyNextFile()
1556 bool bCopyFile =
false;
1561 while (it != files.end() && !bCopyFile)
1563 const QString destFile = (*it).uDest.path();
1564 bCopyFile = !shouldSkip( destFile );
1575 if (m_freeSpace < (*it).size) {
1583 const KUrl& uSource = (*it).uSource;
1584 const KUrl& uDest = (*it).uDest;
1589 if ( uDest == uSource )
1592 bOverwrite = shouldOverwriteFile( destFile );
1594 m_bCurrentOperationIsLink =
false;
1599 newjob = linkNextFile(uSource, uDest, flags);
1602 }
else if ( !(*it).linkDest.isEmpty() &&
1604 (uSource.host() == uDest.host()) &&
1605 (uSource.port() == uDest.port()) &&
1606 (uSource.
user() == uDest.
user()) &&
1615 m_currentSrcURL =
KUrl( (*it).linkDest );
1616 m_currentDestURL = uDest;
1620 m_bCurrentOperationIsLink =
true;
1627 if ((*it).mtime != -1) {
1633 m_currentSrcURL=uSource;
1634 m_currentDestURL=uDest;
1643 int permissions = (*it).permissions;
1644 if ( m_defaultPermissions || ( remoteSource && uDest.
isLocalFile() ) )
1650 if ((*it).mtime != -1) {
1655 m_currentSrcURL=uSource;
1656 m_currentDestURL=uDest;
1659 q->addSubjob(newjob);
1660 q->connect( newjob, SIGNAL(processedSize(
KJob*,qulonglong)),
1661 SLOT(slotProcessedSize(
KJob*,qulonglong)) );
1662 q->connect( newjob, SIGNAL(totalSize(
KJob*,qulonglong)),
1663 SLOT(slotTotalSize(
KJob*,qulonglong)) );
1673 void CopyJobPrivate::deleteNextDir()
1681 KUrl::List::Iterator it = --dirsToRemove.end();
1684 dirsToRemove.erase(it);
1685 q->addSubjob( job );
1691 m_directoriesCopiedIterator = m_directoriesCopied.constBegin();
1692 setNextDirAttribute();
1696 void CopyJobPrivate::setNextDirAttribute()
1699 while (m_directoriesCopiedIterator != m_directoriesCopied.constEnd() &&
1700 (*m_directoriesCopiedIterator).mtime == -1) {
1701 ++m_directoriesCopiedIterator;
1703 if ( m_directoriesCopiedIterator != m_directoriesCopied.constEnd() ) {
1704 const KUrl url = (*m_directoriesCopiedIterator).uDest;
1705 const time_t mtime = (*m_directoriesCopiedIterator).mtime;
1706 const QDateTime dt = QDateTime::fromTime_t(mtime);
1707 ++m_directoriesCopiedIterator;
1711 q->addSubjob( job );
1714 #if 0 // ifdef Q_OS_UNIX
1718 QLinkedList<CopyInfo>::const_iterator it = m_directoriesCopied.constBegin();
1719 for ( ; it != m_directoriesCopied.constEnd() ; ++it ) {
1720 const KUrl& url = (*it).uDest;
1721 if ( url.
isLocalFile() && (*it).mtime != (time_t)-1 ) {
1722 KDE_struct_stat statbuf;
1723 if (KDE::lstat(url.
path(), &statbuf) == 0) {
1724 struct utimbuf utbuf;
1725 utbuf.actime = statbuf.st_atime;
1726 utbuf.modtime = (*it).mtime;
1727 utime( path, &utbuf );
1732 m_directoriesCopied.clear();
1737 m_reportTimer->stop();
1751 if (!d->m_bOnlyRenames) {
1753 KUrl url(d->m_globalDest);
1754 if (d->m_globalDestinationState !=
DEST_IS_DIR || d->m_asMethod)
1759 if (d->m_mode ==
CopyJob::Move && !d->m_successSrcList.isEmpty()) {
1760 kDebug(7007) <<
"KDirNotify'ing FilesRemoved" << d->m_successSrcList.toStringList();
1773 void CopyJobPrivate::slotProcessedSize(
KJob*, qulonglong data_size )
1777 m_fileProcessedSize = data_size;
1778 q->setProcessedAmount(KJob::Bytes, m_processedSize + m_fileProcessedSize);
1780 if ( m_processedSize + m_fileProcessedSize > m_totalSize )
1783 m_totalSize = m_processedSize + m_fileProcessedSize;
1785 q->setTotalAmount(KJob::Bytes, m_totalSize);
1788 q->setProcessedAmount(KJob::Bytes, m_processedSize + m_fileProcessedSize);
1791 void CopyJobPrivate::slotTotalSize(
KJob*, qulonglong size )
1799 if ( m_bSingleFileCopy && size != m_totalSize)
1803 q->setTotalAmount(KJob::Bytes, size);
1807 void CopyJobPrivate::slotResultDeletingDirs(
KJob * job )
1815 m_successSrcList.append(static_cast<KIO::SimpleJob*>(job)->url());
1817 q->removeSubjob( job );
1818 assert( !q->hasSubjobs() );
1822 void CopyJobPrivate::slotResultSettingDirAttributes(
KJob * job )
1831 q->removeSubjob( job );
1832 assert( !q->hasSubjobs() );
1833 setNextDirAttribute();
1837 void CopyJobPrivate::slotResultRenaming(
KJob* job )
1840 int err = job->error();
1841 const QString errText = job->errorText();
1845 m_incomingMetaData += kiojob->
metaData();
1846 q->removeSubjob( job );
1847 assert ( !q->hasSubjobs() );
1850 if ( destinationState ==
DEST_IS_DIR && !m_asMethod )
1851 dest.
addPath( m_currentSrcURL.fileName() );
1863 kDebug(7007) <<
"Couldn't rename directly, dest already exists. Detected special case of lower/uppercase renaming in same dir, try with 2 rename calls";
1864 const QString _src( m_currentSrcURL.toLocalFile() );
1865 const QString _dest( dest.toLocalFile() );
1869 const bool openOk = tmpFile.open();
1871 kWarning(7007) <<
"Couldn't open temp file in" << _tmpPrefix;
1873 const QString _tmp( tmpFile.fileName() );
1876 kDebug(7007) <<
"KTemporaryFile using" << _tmp <<
"as intermediary";
1877 if (KDE::rename( _src, _tmp ) == 0) {
1879 if (!QFile::exists( _dest ) && KDE::rename(_tmp, _dest) == 0) {
1883 kDebug(7007) <<
"Didn't manage to rename" << _tmp <<
"to" << _dest <<
", reverting";
1885 if (KDE::rename( _tmp, _src ) != 0) {
1886 kError(7007) <<
"Couldn't rename" << _tmp <<
"back to" << _src <<
'!';
1888 q->Job::slotResult(job);
1893 kDebug(7007) <<
"mv" << _src << _tmp <<
"failed:" << strerror(errno);
1914 if ((isDir && m_bAutoSkipDirs) || (!isDir && m_bAutoSkipFiles)) {
1918 }
else if ((isDir && m_bOverwriteAllDirs) || (!isDir && m_bOverwriteAllFiles)) {
1920 }
else if ((isDir && m_bAutoRenameDirs) || (!isDir && m_bAutoRenameFiles)) {
1921 KUrl destDirectory(m_currentDestURL);
1922 destDirectory.setPath(destDirectory.directory());
1925 m_dest.setPath(m_currentDestURL.path());
1926 m_dest.setFileName(newName);
1932 }
else if ( q->isInteractive() ) {
1939 time_t ctimeSrc = (time_t) -1;
1940 time_t ctimeDest = (time_t) -1;
1941 time_t mtimeSrc = (time_t) -1;
1942 time_t mtimeDest = (time_t) -1;
1949 KDE_struct_stat stat_buf;
1950 if ( m_currentSrcURL.isLocalFile() &&
1951 KDE::stat(m_currentSrcURL.toLocalFile(), &stat_buf) == 0 ) {
1952 sizeSrc = stat_buf.st_size;
1953 ctimeSrc = stat_buf.st_ctime;
1954 mtimeSrc = stat_buf.st_mtime;
1955 isDir = S_ISDIR(stat_buf.st_mode);
1957 if ( dest.isLocalFile() &&
1958 KDE::stat(dest.toLocalFile(), &stat_buf) == 0 ) {
1959 sizeDest = stat_buf.st_size;
1960 ctimeDest = stat_buf.st_ctime;
1961 mtimeDest = stat_buf.st_mtime;
1962 destIsDir = S_ISDIR(stat_buf.st_mode);
1967 if (!isDir && destIsDir) {
1972 if ( m_srcList.count() > 1 )
1978 m_reportTimer->stop();
1983 m_currentSrcURL.url(),
1987 ctimeSrc, ctimeDest,
1988 mtimeSrc, mtimeDest );
2003 m_bAutoRenameDirs =
true;
2006 m_bAutoRenameFiles =
true;
2013 m_dest.setPath( newPath );
2022 m_bAutoSkipDirs =
true;
2024 m_bAutoSkipFiles =
true;
2032 m_bOverwriteAllDirs =
true;
2034 m_bOverwriteAllFiles =
true;
2042 kDebug(7007) <<
"adding to overwrite list: " << dest.path();
2043 m_overwriteList.insert( dest.path() );
2052 q->setErrorText( errText );
2057 kDebug(7007) <<
"Couldn't rename" << m_currentSrcURL <<
"to" << dest <<
", aborting";
2059 q->setErrorText( errText );
2063 kDebug(7007) <<
"Couldn't rename" << m_currentSrcURL <<
"to" << dest <<
", reverting to normal way, starting with stat";
2068 m_bOnlyRenames =
false;
2072 kDebug(7007) <<
"Renaming succeeded, move on";
2074 emit q->copyingDone( q, *m_currentStatSrc, dest, -1 ,
true,
true );
2075 m_successSrcList.append(*m_currentStatSrc);
2089 switch ( d->state ) {
2091 d->slotResultStating( job );
2095 d->slotResultRenaming( job );
2113 d->slotResultCreatingDirs( job );
2116 d->slotResultConflictCreatingDirs( job );
2119 d->slotResultCopyingFiles( job );
2122 d->slotResultConflictCopyingFiles( job );
2125 d->slotResultDeletingDirs( job );
2128 d->slotResultSettingDirAttributes( job );
2137 d_func()->m_defaultPermissions = b;
2142 return d_func()->m_mode;
2147 d_func()->m_bAutoSkipFiles = autoSkip;
2148 d_func()->m_bAutoSkipDirs = autoSkip;
2153 d_func()->m_bAutoRenameFiles = autoRename;
2154 d_func()->m_bAutoRenameDirs = autoRename;
2159 d_func()->m_bOverwriteAllDirs = overwriteAll;
2166 srcList.append( src );
2167 return CopyJobPrivate::newJob(srcList, dest,
CopyJob::Copy,
false, flags);
2174 srcList.append( src );
2175 return CopyJobPrivate::newJob(srcList, dest,
CopyJob::Copy,
true, flags);
2181 return CopyJobPrivate::newJob(src, dest,
CopyJob::Copy,
false, flags);
2188 srcList.append( src );
2198 srcList.append( src );
2215 srcList.append( src );
2216 return CopyJobPrivate::newJob(srcList, destDir,
CopyJob::Link,
false, flags);
2221 return CopyJobPrivate::newJob(srcList, destDir,
CopyJob::Link,
false, flags);
2227 srcList.append( src );
2228 return CopyJobPrivate::newJob(srcList, destDir,
CopyJob::Link,
false, flags);
2234 srcList.append( src );
2235 return CopyJobPrivate::newJob(srcList,
KUrl(
"trash:/" ),
CopyJob::Move,
false, flags);
2240 return CopyJobPrivate::newJob(srcList,
KUrl(
"trash:/" ),
CopyJob::Move,
false, flags);
2243 #include "copyjob.moc"