49#include <QtCore/QTimer>
50#include <QtCore/QFile>
60#define REPORT_TIMEOUT 200
105 , m_defaultPermissions(
false)
108 , m_asMethod(asMethod)
114 , m_fileProcessedSize(0)
115 , m_processedFiles(0)
118 , m_currentStatSrc(m_srcList.constBegin())
119 , m_bCurrentOperationIsLink(
false)
120 , m_bSingleFileCopy(
false)
123 , m_bAutoRenameFiles(
false)
124 , m_bAutoRenameDirs(
false)
125 , m_bAutoSkipFiles(
false )
126 , m_bAutoSkipDirs(
false )
127 , m_bOverwriteAllFiles(
false )
128 , m_bOverwriteAllDirs(
false )
142 bool m_defaultPermissions;
147 QLinkedList<CopyInfo> m_directoriesCopied;
148 QLinkedList<CopyInfo>::const_iterator m_directoriesCopiedIterator;
160 int m_processedFiles;
167 KUrl::List::const_iterator m_currentStatSrc;
168 bool m_bCurrentSrcIsDir;
169 bool m_bCurrentOperationIsLink;
170 bool m_bSingleFileCopy;
175 QStringList m_skipList;
177 bool m_bAutoRenameFiles;
178 bool m_bAutoRenameDirs;
179 bool m_bAutoSkipFiles;
180 bool m_bAutoSkipDirs;
181 bool m_bOverwriteAllFiles;
182 bool m_bOverwriteAllDirs;
185 QTimer *m_reportTimer;
189 KUrl m_currentSrcURL;
190 KUrl m_currentDestURL;
194 void statCurrentSrc();
198 void slotResultStating(
KJob * job );
199 void startListing(
const KUrl & src );
200 void slotResultCreatingDirs(
KJob * job );
201 void slotResultConflictCreatingDirs(
KJob * job );
202 void createNextDir();
203 void slotResultCopyingFiles(
KJob * job );
204 void slotResultConflictCopyingFiles(
KJob * job );
206 KIO::Job* linkNextFile(
const KUrl& uSource,
const KUrl& uDest, JobFlags flags );
208 void slotResultDeletingDirs(
KJob * job );
209 void deleteNextDir();
210 void sourceStated(
const UDSEntry& entry,
const KUrl& sourceUrl);
211 void skip(
const KUrl & sourceURL,
bool isDir);
212 void slotResultRenaming(
KJob * job );
213 void slotResultSettingDirAttributes(
KJob * job );
214 void setNextDirAttribute();
216 void startRenameJob(
const KUrl &slave_url);
217 bool shouldOverwriteDir(
const QString& path )
const;
218 bool shouldOverwriteFile(
const QString& path )
const;
219 bool shouldSkip(
const QString& path )
const;
220 void skipSrc(
bool isDir);
225 void addCopyInfoFromUDSEntry(
const UDSEntry& entry,
const KUrl& srcUrl,
bool srcIsDir,
const KUrl& currentDest);
229 void slotProcessedSize(
KJob*, qulonglong data_size );
234 void slotTotalSize(
KJob*, qulonglong size );
243 CopyJob *job =
new CopyJob(*
new CopyJobPrivate(src,dest,mode,asMethod));
248 job->d_func()->m_bOverwriteAllDirs =
true;
249 job->d_func()->m_bOverwriteAllFiles =
true;
258 setProperty(
"destUrl", d_func()->m_dest.
url());
259 QTimer::singleShot(0,
this, SLOT(slotStart()));
260 qRegisterMetaType<KIO::UDSEntry>(
"KIO::UDSEntry");
269 return d_func()->m_srcList;
274 return d_func()->m_dest;
277void CopyJobPrivate::slotStart()
285 m_reportTimer =
new QTimer(q);
287 q->connect(m_reportTimer,SIGNAL(
timeout()),q,SLOT(slotReport()));
299void CopyJobPrivate::slotResultStating(
KJob *job )
312 kDebug(7007) <<
"Error while stating source. Activating hack";
313 q->removeSubjob( job );
314 assert ( !q->hasSubjobs() );
317 info.
mtime = (time_t) -1;
318 info.
ctime = (time_t) -1;
323 if ( destinationState ==
DEST_IS_DIR && !m_asMethod )
326 files.append( info );
332 q->Job::slotResult( job );
342 QFileInfo fileInfo(path);
343 if (m_asMethod || !fileInfo.exists()) {
347 path = fileInfo.absolutePath();
349 KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(path);
350 if (freeSpaceInfo.isValid()) {
351 m_freeSpace = freeSpaceInfo.available();
353 kDebug(7007) <<
"Couldn't determine free space information for" << path;
359 const bool isGlobalDest = m_dest == m_globalDest;
360 const bool isDir = entry.
isDir();
375 m_globalDest = m_dest;
379 m_globalDestinationState = destinationState;
381 q->removeSubjob( job );
382 assert ( !q->hasSubjobs() );
387 sourceStated(entry,
static_cast<SimpleJob*
>(job)->url());
388 q->removeSubjob( job );
392void CopyJobPrivate::sourceStated(
const UDSEntry& entry,
const KUrl& sourceUrl)
395 const bool isDir = entry.
isDir();
414 kDebug() <<
"Using sLocalPath. destinationState=" << destinationState;
421 addCopyInfoFromUDSEntry(entry, srcurl,
false, m_dest);
423 m_currentDest = m_dest;
424 m_bCurrentSrcIsDir =
false;
435 m_parentDirs.insert(parentDir);
438 m_bCurrentSrcIsDir =
true;
444 QString directory = srcurl.
fileName();
447 if (fnu == KProtocolInfo::Name) {
448 if (!sName.isEmpty())
450 }
else if (fnu == KProtocolInfo::DisplayName) {
452 if (!dispName.isEmpty())
453 directory = dispName;
454 else if (!sName.isEmpty())
457 m_currentDest.
addPath( directory );
467 if ( m_dest == m_globalDest )
468 m_globalDestinationState = destinationState;
471 startListing( srcurl );
479 m_parentDirs.insert(parentDir);
493void CopyJobPrivate::slotReport()
496 if ( q->isSuspended() )
504 q->setProcessedAmount(
KJob::Files, m_processedFiles );
511 emitMoving(q, m_currentSrcURL, m_currentDestURL);
512 emit q->moving( q, m_currentSrcURL, m_currentDestURL);
516 emitCopying( q, m_currentSrcURL, m_currentDestURL );
517 emit q->linking( q, m_currentSrcURL.
path(), m_currentDestURL );
521 emitCopying( q, m_currentSrcURL, m_currentDestURL );
522 emit q->copying( q, m_currentSrcURL, m_currentDestURL );
532 emit q->creatingDir( q, m_currentDestURL );
533 emitCreatingDir( q, m_currentDestURL );
544 emitMoving( q, m_currentSrcURL, m_currentDestURL );
548 emitCopying( q, m_currentSrcURL, m_currentDestURL );
564 UDSEntryList::ConstIterator it =
list.constBegin();
565 UDSEntryList::ConstIterator
end =
list.constEnd();
566 for (; it !=
end; ++it) {
568 addCopyInfoFromUDSEntry(entry,
static_cast<SimpleJob *
>(job)->url(), m_bCurrentSrcIsDir, m_currentDest);
574 const KUrl url = subJob->
url();
579 emit q->warning(job, subJob->
errorString(), QString());
584void CopyJobPrivate::addCopyInfoFromUDSEntry(
const UDSEntry& entry,
const KUrl& srcUrl,
bool srcIsDir,
const KUrl& currentDest)
592 m_totalSize += info.size;
598 if (!urlStr.isEmpty())
601 const bool isDir = entry.
isDir();
604 if (fileName != QLatin1String(
"..") && fileName != QLatin1String(
".")) {
605 const bool hasCustomURL = !url.isEmpty() || !localPath.isEmpty();
616 url =
KUrl(localPath);
620 info.uDest = currentDest;
628 QString destFileName;
631 fnu == KProtocolInfo::FromUrl) {
634 int numberOfSlashes = fileName.count(
'/');
635 QString path = url.
path();
637 for (
int n = 0; n < numberOfSlashes + 1; ++n) {
638 pos = path.lastIndexOf(
'/', pos - 1);
640 kWarning(7007) <<
"kioslave bug: not enough slashes in UDS_URL" << path <<
"- looking for" << numberOfSlashes <<
"slashes";
645 destFileName = path.mid(pos + 1);
648 }
else if ( fnu == KProtocolInfo::Name ) {
649 destFileName = fileName;
652 destFileName = displayName.isEmpty() ? fileName : displayName;
658 if (destFileName.isEmpty()) {
663 info.uDest.addPath(destFileName);
667 if (info.linkDest.isEmpty() && isDir && m_mode !=
CopyJob::Link) {
670 dirsToRemove.append(info.uSource);
678void CopyJobPrivate::skipSrc(
bool isDir)
680 m_dest = m_globalDest;
681 destinationState = m_globalDestinationState;
682 skip(*m_currentStatSrc, isDir);
687void CopyJobPrivate::statNextSrc()
693 m_dest = m_globalDest;
694 destinationState = m_globalDestinationState;
699void CopyJobPrivate::statCurrentSrc()
702 if (m_currentStatSrc != m_srcList.constEnd()) {
703 m_currentSrcURL = (*m_currentStatSrc);
707 m_currentDest = m_dest;
710 info.mtime = (time_t) -1;
711 info.ctime = (time_t) -1;
713 info.uSource = m_currentSrcURL;
714 info.uDest = m_currentDest;
716 if (destinationState ==
DEST_IS_DIR && !m_asMethod) {
718 (m_currentSrcURL.
protocol() == info.uDest.protocol()) &&
719 (m_currentSrcURL.host() == info.uDest.host()) &&
720 (m_currentSrcURL.port() == info.uDest.port()) &&
721 (m_currentSrcURL.
user() == info.uDest.user()) &&
722 (m_currentSrcURL.
pass() == info.uDest.pass()) ) {
732 files.append( info );
740 if (!cachedItem.
isNull()) {
741 entry = cachedItem.
entry();
744 m_currentSrcURL = cachedItem.
mostLocalUrl(dummyIsLocal);
756 (m_currentSrcURL.host() == m_dest.host()) &&
757 (m_currentSrcURL.port() == m_dest.port()) &&
758 (m_currentSrcURL.
user() == m_dest.
user()) &&
759 (m_currentSrcURL.
pass() == m_dest.
pass()) )
761 startRenameJob( m_currentSrcURL );
766 startRenameJob( m_dest );
771 startRenameJob( m_currentSrcURL );
778 QPointer<CopyJob> that = q;
785 m_bOnlyRenames =
false;
790 kDebug(7007) <<
"fast path! found info about" << m_currentSrcURL <<
"in KDirLister";
792 QMetaObject::invokeMethod(q,
"sourceStated", Qt::QueuedConnection, Q_ARG(
KIO::UDSEntry, entry), Q_ARG(
KUrl, m_currentSrcURL));
801 m_currentDestURL = m_dest;
812 kDebug(7007)<<
"Stating finished. To copy:"<<m_totalSize<<
", available:"<<m_freeSpace;
816 emit q->aboutToCreate( q, dirs );
817 if (!files.isEmpty())
818 emit q->aboutToCreate( q, files );
820 m_bSingleFileCopy = ( files.count() == 1 &&
dirs.isEmpty() );
827void CopyJobPrivate::startRenameJob(
const KUrl& slave_url )
834 if (!m_parentDirs.contains(parentDir)) {
836 m_parentDirs.insert(parentDir);
842 if ( destinationState ==
DEST_IS_DIR && !m_asMethod )
844 m_currentDestURL = dest;
845 kDebug(7007) << m_currentSrcURL <<
"->" << dest <<
"trying direct rename first";
850 info.mtime = (time_t) -1;
851 info.ctime = (time_t) -1;
853 info.uSource = m_currentSrcURL;
857 emit q->aboutToCreate( q, files );
859 KIO_ARGS << m_currentSrcURL << dest << (qint8)
false ;
862 q->addSubjob( newJob );
863 if ( m_currentSrcURL.
directory() != dest.directory() )
864 m_bOnlyRenames =
false;
867void CopyJobPrivate::startListing(
const KUrl & src )
878 q->addSubjob( newjob );
881void CopyJobPrivate::skip(
const KUrl & sourceUrl,
bool isDir)
886 dir.setPath(
dir.directory());
888 while (dirsToRemove.removeAll(dir) > 0) {
891 dir.setPath(
dir.directory());
895bool CopyJobPrivate::shouldOverwriteDir(
const QString& path )
const
897 if ( m_bOverwriteAllDirs )
899 return m_overwriteList.contains(path);
902bool CopyJobPrivate::shouldOverwriteFile(
const QString& path )
const
904 if ( m_bOverwriteAllFiles )
906 return m_overwriteList.contains(path);
909bool CopyJobPrivate::shouldSkip(
const QString& path )
const
911 Q_FOREACH(
const QString& skipPath, m_skipList) {
912 if ( path.startsWith(skipPath) )
918void CopyJobPrivate::slotResultCreatingDirs(
KJob * job )
926 m_conflictError = job->
error();
932 if ( m_bAutoSkipDirs ) {
939 const QString destDir = (*it).uDest.path();
940 if ( shouldOverwriteDir( destDir ) ) {
941 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true ,
false );
944 if (m_bAutoRenameDirs) {
947 KUrl destDirectory((*it).uDest);
948 destDirectory.setPath(destDirectory.directory());
951 KUrl newUrl((*it).uDest);
952 newUrl.setFileName(newName);
954 emit q->renamed(q, (*it).uDest, newUrl);
963 for(; renamedirit !=
dirs.end() ; ++renamedirit) {
964 QString path = (*renamedirit).uDest.path();
965 if (path.startsWith(oldPath)) {
967 n.replace(0, oldPath.length(), newPath);
968 kDebug(7007) <<
"dirs list:" << (*renamedirit).uSource.path()
969 <<
"was going to be" << path
970 <<
", changed into" << n;
971 (*renamedirit).uDest.setPath(n);
976 for(; renamefileit != files.end() ; ++renamefileit) {
977 QString path = (*renamefileit).uDest.path();
978 if (path.startsWith(oldPath)) {
980 n.replace(0, oldPath.length(), newPath);
981 kDebug(7007) <<
"files list:" << (*renamefileit).uSource.path()
982 <<
"was going to be" << path
983 <<
", changed into" << n;
984 (*renamefileit).uDest.setPath(n);
987 if (!
dirs.isEmpty()) {
988 emit q->aboutToCreate(q, dirs);
990 if (!files.isEmpty()) {
991 emit q->aboutToCreate(q, files);
996 if (!q->isInteractive()) {
997 q->Job::slotResult(job);
1001 assert(((
SimpleJob*)job)->url().url() == (*it).uDest.
url());
1002 q->removeSubjob(job);
1003 assert (!q->hasSubjobs());
1006 KUrl existingDest((*it).uDest);
1009 kDebug(7007) <<
"KIO::stat for resolving conflict on " << existingDest;
1011 q->addSubjob(newJob);
1020 q->Job::slotResult( job );
1027 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true,
false );
1028 m_directoriesCopied.append( *it );
1034 q->removeSubjob( job );
1035 assert( !q->hasSubjobs() );
1039void CopyJobPrivate::slotResultConflictCreatingDirs(
KJob * job )
1056 q->removeSubjob( job );
1057 assert ( !q->hasSubjobs() );
1064 if( (*it).uSource == (*it).uDest ||
1065 ((*it).uSource.protocol() == (*it).uDest.protocol() &&
1072 QString existingDest = (*it).uDest.path();
1075 m_reportTimer->stop();
1077 (*it).uSource.url(),
1080 (*it).size, destsize,
1081 (*it).ctime, destctime,
1082 (*it).mtime, destmtime );
1091 m_bAutoRenameDirs =
true;
1096 KUrl newUrl( (*it).uDest );
1097 newUrl.setPath( newPath );
1098 emit q->renamed( q, (*it).uDest, newUrl );
1106 for( ; renamedirit !=
dirs.end() ; ++renamedirit )
1108 QString path = (*renamedirit).uDest.path();
1109 if ( path.startsWith( oldPath ) ) {
1111 n.replace( 0, oldPath.length(), newPath );
1112 kDebug(7007) <<
"dirs list:" << (*renamedirit).uSource.path()
1113 <<
"was going to be" << path
1114 <<
", changed into" << n;
1115 (*renamedirit).uDest.setPath( n );
1120 for( ; renamefileit != files.end() ; ++renamefileit )
1122 QString path = (*renamefileit).uDest.path();
1123 if ( path.startsWith( oldPath ) ) {
1125 n.replace( 0, oldPath.length(), newPath );
1126 kDebug(7007) <<
"files list:" << (*renamefileit).uSource.path()
1127 <<
"was going to be" << path
1128 <<
", changed into" << n;
1129 (*renamefileit).uDest.setPath( n );
1132 if (!
dirs.isEmpty())
1133 emit q->aboutToCreate( q, dirs );
1134 if (!files.isEmpty())
1135 emit q->aboutToCreate( q, files );
1139 m_bAutoSkipDirs =
true;
1142 m_skipList.append( existingDest );
1143 skip((*it).uSource,
true);
1149 m_overwriteList.insert( existingDest );
1150 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true ,
false );
1156 m_bOverwriteAllDirs =
true;
1157 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
true ,
false );
1170void CopyJobPrivate::createNextDir()
1174 if ( !
dirs.isEmpty() )
1179 while( it !=
dirs.end() && udir.isEmpty() )
1181 const QString
dir = (*it).uDest.path();
1182 if ( shouldSkip( dir ) ) {
1189 if ( !udir.isEmpty() )
1195 if (shouldOverwriteFile(udir.
path())) {
1199 m_currentDestURL = udir;
1202 q->addSubjob(newjob);
1224void CopyJobPrivate::slotResultCopyingFiles(
KJob * job )
1232 if ( m_bAutoSkipFiles )
1234 skip((*it).uSource,
false);
1235 m_fileProcessedSize = (*it).size;
1240 m_conflictError = job->
error();
1246 if (m_bAutoRenameFiles) {
1247 KUrl destDirectory((*it).uDest);
1248 destDirectory.setPath(destDirectory.directory());
1251 KUrl newUrl((*it).uDest);
1252 newUrl.setFileName(newName);
1254 emit q->renamed(q, (*it).uDest, newUrl);
1255 (*it).uDest = newUrl;
1259 emit q->aboutToCreate(q, files);
1262 if ( !q->isInteractive() ) {
1263 q->Job::slotResult( job );
1267 q->removeSubjob(job);
1268 assert (!q->hasSubjobs());
1270 KUrl existingFile((*it).uDest);
1273 kDebug(7007) <<
"KIO::stat for resolving conflict on " << existingFile;
1275 q->addSubjob(newJob);
1281 if ( m_bCurrentOperationIsLink && qobject_cast<KIO::DeleteJob*>( job ) )
1285 m_fileProcessedSize = (*it).size;
1288 if ( !q->isInteractive() ) {
1289 q->Job::slotResult( job );
1294 slotResultConflictCopyingFiles( job );
1303 && !qobject_cast<KIO::DeleteJob *>( job )
1306 q->removeSubjob( job );
1307 assert ( !q->hasSubjobs() );
1311 q->addSubjob( newjob );
1315 if ( m_bCurrentOperationIsLink )
1317 QString target = ( m_mode ==
CopyJob::Link ? (*it).uSource.path() : (*it).linkDest );
1319 emit q->copyingLinkDone( q, (*it).uSource, target, (*it).uDest );
1323 emit q->copyingDone( q, (*it).uSource, (*it).uDest, (*it).mtime,
false,
false );
1328 m_successSrcList.append((*it).uSource);
1330 m_freeSpace -= (*it).size;
1340 m_processedSize += m_fileProcessedSize;
1341 m_fileProcessedSize = 0;
1348 m_incomingMetaData += kiojob->
metaData();
1349 q->removeSubjob( job );
1350 assert( !q->hasSubjobs() );
1354void CopyJobPrivate::slotResultConflictCopyingFiles(
KJob * job )
1365 m_reportTimer->stop();
1388 if ( (*it).uSource == (*it).uDest ||
1389 ((*it).uSource.protocol() == (*it).uDest.protocol() &&
1397 if ( !m_bSingleFileCopy )
1400 res = q->ui()->askFileRename( q, !isDir ?
1401 i18n(
"File Already Exists") :
i18n(
"Already Exists as Folder"),
1402 (*it).uSource.url(),
1405 (*it).size, destsize,
1406 (*it).ctime, destctime,
1407 (*it).mtime, destmtime );
1414 else if ( !q->isInteractive() ) {
1415 q->Job::slotResult( job );
1433 q->removeSubjob( job );
1434 assert ( !q->hasSubjobs() );
1441 m_bAutoRenameFiles =
true;
1445 KUrl newUrl( (*it).uDest );
1446 newUrl.setPath( newPath );
1447 emit q->renamed( q, (*it).uDest, newUrl );
1448 (*it).uDest = newUrl;
1452 emit q->aboutToCreate( q, files );
1456 m_bAutoSkipFiles =
true;
1460 skip((*it).uSource,
false);
1461 m_processedSize += (*it).size;
1466 m_bOverwriteAllFiles =
true;
1470 m_overwriteList.insert( (*it).uDest.path() );
1479KIO::Job* CopyJobPrivate::linkNextFile(
const KUrl& uSource,
const KUrl& uDest, JobFlags flags )
1484 (uSource.host() == uDest.host()) &&
1485 (uSource.port() == uDest.port()) &&
1486 (uSource.
user() == uDest.
user()) &&
1494 m_bCurrentOperationIsLink =
true;
1495 m_currentSrcURL=uSource;
1496 m_currentDestURL=uDest;
1509 if (
f.open( QIODevice::ReadWrite ) )
1516 config.writePathEntry(
"URL", url.
url() );
1518 config.writeEntry(
"Type", QString::fromLatin1(
"Link") );
1519 QString protocol = uSource.
protocol();
1520 if ( protocol == QLatin1String(
"ftp") )
1521 config.writeEntry(
"Icon", QString::fromLatin1(
"folder-remote") );
1522 else if ( protocol == QLatin1String(
"http") )
1523 config.writeEntry(
"Icon", QString::fromLatin1(
"text-html") );
1524 else if ( protocol == QLatin1String(
"info") )
1525 config.writeEntry(
"Icon", QString::fromLatin1(
"text-x-texinfo") );
1526 else if ( protocol == QLatin1String(
"mailto") )
1527 config.writeEntry(
"Icon", QString::fromLatin1(
"internet-mail") );
1529 config.writeEntry(
"Icon", QString::fromLatin1(
"unknown") );
1531 files.erase( files.begin() );
1539 kDebug(7007) <<
"ERR_CANNOT_OPEN_FOR_WRITING";
1555void CopyJobPrivate::copyNextFile()
1558 bool bCopyFile =
false;
1563 while (it != files.end() && !bCopyFile)
1565 const QString destFile = (*it).uDest.path();
1566 bCopyFile = !shouldSkip( destFile );
1577 if (m_freeSpace < (*it).size) {
1585 const KUrl& uSource = (*it).uSource;
1586 const KUrl& uDest = (*it).uDest;
1589 const QString destFile = uDest.
path();
1591 if ( uDest == uSource )
1594 bOverwrite = shouldOverwriteFile( destFile );
1596 m_bCurrentOperationIsLink =
false;
1601 newjob = linkNextFile(uSource, uDest, flags);
1604 }
else if ( !(*it).linkDest.isEmpty() &&
1606 (uSource.host() == uDest.host()) &&
1607 (uSource.port() == uDest.port()) &&
1608 (uSource.
user() == uDest.
user()) &&
1617 m_currentSrcURL =
KUrl( (*it).linkDest );
1618 m_currentDestURL = uDest;
1622 m_bCurrentOperationIsLink =
true;
1629 if ((*it).mtime != -1) {
1635 m_currentSrcURL=uSource;
1636 m_currentDestURL=uDest;
1645 int permissions = (*it).permissions;
1646 if ( m_defaultPermissions || ( remoteSource && uDest.
isLocalFile() ) )
1652 if ((*it).mtime != -1) {
1657 m_currentSrcURL=uSource;
1658 m_currentDestURL=uDest;
1661 q->addSubjob(newjob);
1662 q->connect( newjob, SIGNAL(processedSize(
KJob*,qulonglong)),
1663 SLOT(slotProcessedSize(
KJob*,qulonglong)) );
1664 q->connect( newjob, SIGNAL(totalSize(
KJob*,qulonglong)),
1665 SLOT(slotTotalSize(
KJob*,qulonglong)) );
1675void CopyJobPrivate::deleteNextDir()
1683 KUrl::List::Iterator it = --dirsToRemove.end();
1686 dirsToRemove.erase(it);
1687 q->addSubjob( job );
1693 m_directoriesCopiedIterator = m_directoriesCopied.constBegin();
1694 setNextDirAttribute();
1698void CopyJobPrivate::setNextDirAttribute()
1701 while (m_directoriesCopiedIterator != m_directoriesCopied.constEnd() &&
1702 (*m_directoriesCopiedIterator).mtime == -1) {
1703 ++m_directoriesCopiedIterator;
1705 if ( m_directoriesCopiedIterator != m_directoriesCopied.constEnd() ) {
1706 const KUrl url = (*m_directoriesCopiedIterator).uDest;
1707 const time_t mtime = (*m_directoriesCopiedIterator).mtime;
1708 const QDateTime dt = QDateTime::fromTime_t(mtime);
1709 ++m_directoriesCopiedIterator;
1713 q->addSubjob( job );
1720 QLinkedList<CopyInfo>::const_iterator it = m_directoriesCopied.constBegin();
1721 for ( ; it != m_directoriesCopied.constEnd() ; ++it ) {
1722 const KUrl& url = (*it).uDest;
1723 if ( url.
isLocalFile() && (*it).mtime != (time_t)-1 ) {
1724 KDE_struct_stat statbuf;
1726 struct utimbuf utbuf;
1727 utbuf.actime = statbuf.st_atime;
1728 utbuf.modtime = (*it).mtime;
1729 utime( path, &utbuf );
1734 m_directoriesCopied.clear();
1739 m_reportTimer->stop();
1753 if (!d->m_bOnlyRenames) {
1755 KUrl url(d->m_globalDest);
1756 if (d->m_globalDestinationState !=
DEST_IS_DIR || d->m_asMethod)
1761 if (d->m_mode ==
CopyJob::Move && !d->m_successSrcList.isEmpty()) {
1762 kDebug(7007) <<
"KDirNotify'ing FilesRemoved" << d->m_successSrcList.toStringList();
1775void CopyJobPrivate::slotProcessedSize(
KJob*, qulonglong data_size )
1779 m_fileProcessedSize = data_size;
1780 q->setProcessedAmount(
KJob::Bytes, m_processedSize + m_fileProcessedSize);
1782 if ( m_processedSize + m_fileProcessedSize > m_totalSize )
1785 m_totalSize = m_processedSize + m_fileProcessedSize;
1790 q->setProcessedAmount(
KJob::Bytes, m_processedSize + m_fileProcessedSize);
1793void CopyJobPrivate::slotTotalSize(
KJob*, qulonglong size )
1801 if ( m_bSingleFileCopy && size != m_totalSize)
1809void CopyJobPrivate::slotResultDeletingDirs(
KJob * job )
1817 m_successSrcList.append(
static_cast<KIO::SimpleJob*
>(job)->url());
1819 q->removeSubjob( job );
1820 assert( !q->hasSubjobs() );
1824void CopyJobPrivate::slotResultSettingDirAttributes(
KJob * job )
1833 q->removeSubjob( job );
1834 assert( !q->hasSubjobs() );
1835 setNextDirAttribute();
1839void CopyJobPrivate::slotResultRenaming(
KJob* job )
1842 int err = job->
error();
1843 const QString errText = job->
errorText();
1847 m_incomingMetaData += kiojob->
metaData();
1848 q->removeSubjob( job );
1849 assert ( !q->hasSubjobs() );
1852 if ( destinationState ==
DEST_IS_DIR && !m_asMethod )
1865 kDebug(7007) <<
"Couldn't rename directly, dest already exists. Detected special case of lower/uppercase renaming in same dir, try with 2 rename calls";
1866 const QString _src( m_currentSrcURL.
toLocalFile() );
1871 const bool openOk = tmpFile.open();
1873 kWarning(7007) <<
"Couldn't open temp file in" << _tmpPrefix;
1875 const QString _tmp( tmpFile.fileName() );
1878 kDebug(7007) <<
"KTemporaryFile using" << _tmp <<
"as intermediary";
1881 if (!QFile::exists( _dest ) &&
KDE::rename(_tmp, _dest) == 0) {
1885 kDebug(7007) <<
"Didn't manage to rename" << _tmp <<
"to" << _dest <<
", reverting";
1888 kError(7007) <<
"Couldn't rename" << _tmp <<
"back to" << _src <<
'!';
1890 q->Job::slotResult(job);
1895 kDebug(7007) <<
"mv" << _src << _tmp <<
"failed:" << strerror(errno);
1916 if ((isDir && m_bAutoSkipDirs) || (!isDir && m_bAutoSkipFiles)) {
1920 }
else if ((isDir && m_bOverwriteAllDirs) || (!isDir && m_bOverwriteAllFiles)) {
1922 }
else if ((isDir && m_bAutoRenameDirs) || (!isDir && m_bAutoRenameFiles)) {
1923 KUrl destDirectory(m_currentDestURL);
1924 destDirectory.setPath(destDirectory.directory());
1934 }
else if ( q->isInteractive() ) {
1941 time_t ctimeSrc = (time_t) -1;
1942 time_t ctimeDest = (time_t) -1;
1943 time_t mtimeSrc = (time_t) -1;
1944 time_t mtimeDest = (time_t) -1;
1951 KDE_struct_stat stat_buf;
1954 sizeSrc = stat_buf.st_size;
1955 ctimeSrc = stat_buf.st_ctime;
1956 mtimeSrc = stat_buf.st_mtime;
1957 isDir = S_ISDIR(stat_buf.st_mode);
1961 sizeDest = stat_buf.st_size;
1962 ctimeDest = stat_buf.st_ctime;
1963 mtimeDest = stat_buf.st_mtime;
1964 destIsDir = S_ISDIR(stat_buf.st_mode);
1969 if (!isDir && destIsDir) {
1974 if ( m_srcList.count() > 1 )
1980 m_reportTimer->stop();
1985 m_currentSrcURL.
url(),
1989 ctimeSrc, ctimeDest,
1990 mtimeSrc, mtimeDest );
2005 m_bAutoRenameDirs =
true;
2008 m_bAutoRenameFiles =
true;
2024 m_bAutoSkipDirs =
true;
2026 m_bAutoSkipFiles =
true;
2034 m_bOverwriteAllDirs =
true;
2036 m_bOverwriteAllFiles =
true;
2044 kDebug(7007) <<
"adding to overwrite list: " << dest.
path();
2045 m_overwriteList.insert( dest.
path() );
2054 q->setErrorText( errText );
2059 kDebug(7007) <<
"Couldn't rename" << m_currentSrcURL <<
"to" << dest <<
", aborting";
2061 q->setErrorText( errText );
2065 kDebug(7007) <<
"Couldn't rename" << m_currentSrcURL <<
"to" << dest <<
", reverting to normal way, starting with stat";
2070 m_bOnlyRenames =
false;
2074 kDebug(7007) <<
"Renaming succeeded, move on";
2076 emit q->copyingDone( q, *m_currentStatSrc, dest, -1 ,
true,
true );
2077 m_successSrcList.append(*m_currentStatSrc);
2091 switch ( d->state ) {
2093 d->slotResultStating( job );
2097 d->slotResultRenaming( job );
2115 d->slotResultCreatingDirs( job );
2118 d->slotResultConflictCreatingDirs( job );
2121 d->slotResultCopyingFiles( job );
2124 d->slotResultConflictCopyingFiles( job );
2127 d->slotResultDeletingDirs( job );
2130 d->slotResultSettingDirAttributes( job );
2139 d_func()->m_defaultPermissions = b;
2144 return d_func()->m_mode;
2149 d_func()->m_bAutoSkipFiles = autoSkip;
2150 d_func()->m_bAutoSkipDirs = autoSkip;
2155 d_func()->m_bAutoRenameFiles = autoRename;
2156 d_func()->m_bAutoRenameDirs = autoRename;
2161 d_func()->m_bOverwriteAllDirs = overwriteAll;
2168 srcList.append( src );
2169 return CopyJobPrivate::newJob(srcList, dest,
CopyJob::Copy,
false, flags);
2176 srcList.append( src );
2177 return CopyJobPrivate::newJob(srcList, dest,
CopyJob::Copy,
true, flags);
2183 return CopyJobPrivate::newJob(src, dest,
CopyJob::Copy,
false, flags);
2190 srcList.append( src );
2200 srcList.append( src );
2217 srcList.append( src );
2218 return CopyJobPrivate::newJob(srcList, destDir,
CopyJob::Link,
false, flags);
2223 return CopyJobPrivate::newJob(srcList, destDir,
CopyJob::Link,
false, flags);
2229 srcList.append( src );
2230 return CopyJobPrivate::newJob(srcList, destDir,
CopyJob::Link,
false, flags);
2236 srcList.append( src );
2237 return CopyJobPrivate::newJob(srcList,
KUrl(
"trash:/" ),
CopyJob::Move,
false, flags);
2242 return CopyJobPrivate::newJob(srcList,
KUrl(
"trash:/" ),
CopyJob::Move,
false, flags);
2245#include "copyjob.moc"
virtual void slotResult(KJob *job)
static KFileItem cachedItemForUrl(const KUrl &url)
Return the KFileItem for the given URL, if we listed it recently and it's still in the cache - which ...
bool stopDirScan(const QString &path)
static KDirWatch * self()
bool restartDirScan(const QString &path)
A KFileItem is a generic class to handle a file, local or remote.
KUrl mostLocalUrl(bool &local) const
Tries to give a local URL for this file item if possible.
bool isNull() const
Return true if default-constructed.
KIO::UDSEntry entry() const
Returns the UDS entry.
static ClipboardUpdater * create(Job *job, Mode mode)
Returns an instance of clipboard updater if QApplication::type() does not return a tty.
CopyJob is used to move, copy or symlink files and directories.
KUrl::List srcUrls() const
Returns the list of source URLs.
CopyMode
Defines the mode of the operation.
virtual bool doSuspend()
Reimplemented for internal reasons.
void setDefaultPermissions(bool b)
By default the permissions of the copied files will be those of the source files.
void setWriteIntoExistingDirectories(bool overwriteAllDirs)
Reuse any directory that already exists, instead of the default behavior (interactive mode: showing a...
CopyMode operationMode() const
Returns the mode of the operation (copy, move, or link), depending on whether KIO::copy(),...
CopyJob(CopyJobPrivate &dd)
void setAutoRename(bool autoRename)
Rename files automatically when the destination already exists, instead of the default behavior (inte...
virtual void slotResult(KJob *job)
void setAutoSkip(bool autoSkip)
Skip copying or moving any file when the destination already exists, instead of the default behavior ...
KUrl destUrl() const
Returns the destination URL.
The FileCopyJob copies data from one place to another.
void setModificationTime(const QDateTime &mtime)
Sets the modification time of the file.
void setSourceSize(KIO::filesize_t size)
If you know the size of the source file, call this method to inform this job.
A UI delegate tuned to be used with KIO Jobs.
The base class for all jobs.
void setParentJob(Job *parentJob)
Set the parent Job.
QString errorString() const
Converts an error code and a non-i18n error message into an error message in the current language.
virtual bool doSuspend()
Suspend this job.
virtual bool removeSubjob(KJob *job)
Mark a sub job as being done.
MetaData metaData() const
Get meta data received from the slave.
void addMetaData(const QString &key, const QString &value)
Add key/value pair to the meta data that is sent to the slave.
A ListJob is allows you to get the get the content of a directory.
void setUnrestricted(bool unrestricted)
Do not apply any KIOSK restrictions to this job.
static void setJobPriority(SimpleJob *job, int priority)
Changes the priority of job; jobs of the same priority run in the order in which they were created.
static SimpleJob * newJobNoUi(const KUrl &url, int command, const QByteArray &packedArgs)
A simple job (one url and one command).
const KUrl & url() const
Returns the SimpleJob's URL.
A KIO job that retrieves information about a file or directory.
Universal Directory Service.
QString stringValue(uint field) const
long long numberValue(uint field, long long defaultValue=0) const
@ UDS_CREATION_TIME
The time the file was created.
@ UDS_URL
An alternative URL (If different from the caption).
@ UDS_LINK_DEST
Name of the file where the link points to Allows to check for a symlink (don't use S_ISLNK !...
@ UDS_LOCAL_PATH
A local file path if the ioslave display files sitting on the local filesystem (but in another hierar...
@ UDS_MODIFICATION_TIME
The last time the file was modified.
@ UDS_SIZE
Size of the file.
@ UDS_DISPLAY_NAME
If set, contains the label to display instead of the 'real name' in UDS_NAME.
@ UDS_NAME
Filename - as displayed in directory listings etc.
@ UDS_ACCESS
Access permissions (part of the mode returned by stat)
bool contains(uint field) const
check existence of a field
virtual void registerJob(KJob *job)
virtual QString errorString() const
QString errorText() const
void setUiDelegate(KJobUiDelegate *delegate)
static bool supportsDeleting(const KUrl &url)
Returns whether the protocol can delete files/objects.
static KProtocolInfo::FileNameUsedForCopying fileNameUsedForCopying(const KUrl &url)
This setting defines the strategy to use for generating a filename, when copying a file or directory ...
static bool canRenameToFile(const KUrl &url)
Returns whether the protocol can rename (i.e.
static bool supportsListing(const KUrl &url)
Returns whether the protocol can list files/objects.
static bool canRenameFromFile(const KUrl &url)
Returns whether the protocol can rename (i.e.
void setPrefix(const QString &prefix)
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
void setFileName(const QString &_txt)
QString directory(const DirectoryOptions &options=IgnoreTrailingSlash) const
void setPath(const QString &path)
void setPass(const QString &pass)
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
void addPath(const QString &txt)
static void emitFileRenamed(const QString &src, const QString &dst)
static void emitFilesAdded(const QString &directory)
static void emitFilesRemoved(const QStringList &fileList)
static void emitFileMoved(const QString &src, const QString &dst)
bool kio_resolve_local_urls
CopyJobState
States: STATE_STATING for the dest statCurrentSrc then does, for each src url: STATE_RENAMING if dire...
@ STATE_SETTING_DIR_ATTRIBUTES
@ STATE_CONFLICT_CREATING_DIRS
@ STATE_CONFLICT_COPYING_FILES
static quint32 f(DES_KEY *key, quint32 r, char *subkey)
QString i18n(const char *text)
int lstat(const QString &path, KDE_struct_stat *buf)
int utime(const QString &filename, struct utimbuf *buf)
int stat(const QString &path, KDE_struct_stat *buf)
int rename(const QString &in, const QString &out)
KSharedConfigPtr config()
A namespace for KIO globals.
DeleteJob * del(const KUrl &src, JobFlags flags=DefaultFlags)
Delete a file or directory.
CopyJob * move(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Moves a file or directory src to the given destination dest.
CopyJob * trash(const KUrl &src, JobFlags flags=DefaultFlags)
Trash a file or directory.
SimpleJob * setModificationTime(const KUrl &url, const QDateTime &mtime)
Changes the modification time on a file or directory.
CopyJob * link(const KUrl &src, const KUrl &destDir, JobFlags flags=DefaultFlags)
Create a link.
CopyJob * moveAs(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Moves a file or directory src to the given destination dest.
SimpleJob * rmdir(const KUrl &url)
Removes a single directory.
ListJob * listRecursive(const KUrl &url, JobFlags flags=DefaultFlags, bool includeHidden=true)
The same as the previous method, but recurses subdirectories.
QString buildErrorString(int errorCode, const QString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
CopyJob * linkAs(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Create a link.
StatJob * stat(const KUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
QString encodeFileName(const QString &str)
Encodes (from the text displayed to the real filename) This translates '/' into a "unicode fraction s...
FileCopyJob * file_copy(const KUrl &src, const KUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Copy a single file.
CopyJob * copy(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Copy a file or directory src into the destination dest, which can be a file (including the final file...
FileCopyJob * file_move(const KUrl &src, const KUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Move a single file.
SimpleJob * mkdir(const KUrl &url, int permissions=-1)
Creates a single directory.
RenameDialog_Result
The result of open_RenameDialog().
RenameDialog_Mode
M_OVERWRITE: We have an existing dest, show details about it and offer to overwrite it.
@ DefaultFlags
Show the progress info GUI, no Resume and no Overwrite.
@ HideProgressInfo
Hide progress information dialog, i.e.
@ Overwrite
When set, automatically overwrite the destination if it exists already.
qulonglong filesize_t
64-bit file size
CopyJob * copyAs(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Copy a file or directory src into the destination dest, which is the destination name in any case,...
@ ERR_CANNOT_OPEN_FOR_WRITING
KJobTrackerInterface * getJobTracker()
SimpleJob * symlink(const QString &target, const KUrl &dest, JobFlags flags=DefaultFlags)
Create or move a symlink.
QString dir(const QString &fileClass)
Returns the most recently used directory accociated with this file-class.
QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.