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;
277 void CopyJobPrivate::slotStart()
285 m_reportTimer =
new QTimer(q);
287 q->connect(m_reportTimer,SIGNAL(
timeout()),q,SLOT(slotReport()));
299 void 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 );
340 if ( m_dest.isLocalFile() ) {
341 QString path(m_dest.toLocalFile());
342 QFileInfo fileInfo(path);
343 if (m_asMethod || !fileInfo.exists()) {
347 path = fileInfo.absolutePath();
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();
373 m_dest.setPath(sLocalPath);
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 );
392 void 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();
448 if (!sName.isEmpty())
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);
493 void 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());
584 void 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;
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);
649 destFileName = fileName;
652 destFileName = displayName.isEmpty() ? fileName : displayName;
658 if (destFileName.isEmpty()) {
670 dirsToRemove.append(info.
uSource);
678 void CopyJobPrivate::skipSrc(
bool isDir)
680 m_dest = m_globalDest;
681 destinationState = m_globalDestinationState;
682 skip(*m_currentStatSrc, isDir);
687 void CopyJobPrivate::statNextSrc()
693 m_dest = m_globalDest;
694 destinationState = m_globalDestinationState;
699 void 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) {
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);
755 if ( (m_currentSrcURL.protocol() == m_dest.protocol()) &&
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() );
827 void CopyJobPrivate::startRenameJob(
const KUrl& slave_url )
832 if (m_currentSrcURL.isLocalFile()) {
834 if (!m_parentDirs.contains(parentDir)) {
836 m_parentDirs.insert(parentDir);
842 if ( destinationState ==
DEST_IS_DIR && !m_asMethod )
843 dest.
addPath( m_currentSrcURL.fileName() );
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;
867 void CopyJobPrivate::startListing(
const KUrl & src )
878 q->addSubjob( newjob );
881 void CopyJobPrivate::skip(
const KUrl & sourceUrl,
bool isDir)
888 while (dirsToRemove.removeAll(dir) > 0) {
895 bool CopyJobPrivate::shouldOverwriteDir(
const QString& path )
const 897 if ( m_bOverwriteAllDirs )
899 return m_overwriteList.contains(path);
902 bool CopyJobPrivate::shouldOverwriteFile(
const QString& path )
const 904 if ( m_bOverwriteAllFiles )
906 return m_overwriteList.contains(path);
909 bool CopyJobPrivate::shouldSkip(
const QString& path )
const 911 Q_FOREACH(
const QString& skipPath, m_skipList) {
912 if ( path.startsWith(skipPath) )
918 void 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);
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() );
1039 void 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 );
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 );
1170 void 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);
1224 void 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);
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() );
1354 void 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 );
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() );
1479 KIO::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 ) )
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";
1555 void 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);
1663 SLOT(slotProcessedSize(
KJob*,qulonglong)) );
1665 SLOT(slotTotalSize(
KJob*,qulonglong)) );
1675 void 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();
1698 void 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 );
1716 #if 0 // ifdef Q_OS_UNIX 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();
1775 void 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);
1793 void CopyJobPrivate::slotTotalSize(
KJob*, qulonglong size )
1801 if ( m_bSingleFileCopy && size != m_totalSize)
1809 void CopyJobPrivate::slotResultDeletingDirs(
KJob * job )
1817 m_successSrcList.append(static_cast<KIO::SimpleJob*>(job)->url());
1819 q->removeSubjob( job );
1820 assert( !q->hasSubjobs() );
1824 void CopyJobPrivate::slotResultSettingDirAttributes(
KJob * job )
1833 q->removeSubjob( job );
1834 assert( !q->hasSubjobs() );
1835 setNextDirAttribute();
1839 void 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 )
1853 dest.
addPath( m_currentSrcURL.fileName() );
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() );
1867 const QString _dest( dest.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);
1927 m_dest.setPath(m_currentDestURL.path());
1928 m_dest.setFileName(newName);
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;
1952 if ( m_currentSrcURL.isLocalFile() &&
1953 KDE::stat(m_currentSrcURL.toLocalFile(), &stat_buf) == 0 ) {
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);
1959 if ( dest.isLocalFile() &&
1960 KDE::stat(dest.toLocalFile(), &stat_buf) == 0 ) {
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;
2015 m_dest.setPath( newPath );
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" An alternative URL (If different from the caption).
QString i18n(const char *text)
QString stringValue(uint field) const
When set, automatically overwrite the destination if it exists already.
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
qulonglong filesize_t
64-bit file size
static void emitFileRenamed(const QString &src, const QString &dst)
static KDirWatch * self()
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.
void writePathEntry(const QString &pKey, const QString &path, WriteConfigFlags pFlags=Normal)
bool kio_resolve_local_urls
void setAutoSkip(bool autoSkip)
Skip copying or moving any file when the destination already exists, instead of the default behavior ...
void setUiDelegate(KJobUiDelegate *delegate)
void setPrefix(const QString &prefix)
Universal Directory Service.
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...
A namespace for KIO globals.
A ListJob is allows you to get the get the content of a directory.
Hide progress information dialog, i.e.
CopyMode operationMode() const
Returns the mode of the operation (copy, move, or link), depending on whether KIO::copy(), KIO::move() or KIO::link() was called.
SimpleJob * mkdir(const KUrl &url, int permissions=-1)
Creates a single directory.
int stat(const QString &path, KDE_struct_stat *buf)
int rename(const QString &in, const QString &out)
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
StatJob * stat(const KUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
static quint32 f(DES_KEY *key, quint32 r, char *subkey)
void setSourceSize(KIO::filesize_t size)
If you know the size of the source file, call this method to inform this job.
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
A KIO job that retrieves information about a file or directory.
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 ...
FileCopyJob * file_move(const KUrl &src, const KUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Move a single file.
A local file path if the ioslave display files sitting on the local filesystem (but in another hierar...
QString errorString() const
Converts an error code and a non-i18n error message into an error message in the current language...
virtual bool removeSubjob(KJob *job)
Mark a sub job as being done.
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KUrl::List srcUrls() const
Returns the list of source URLs.
KIO::UDSEntry entry() const
Returns the UDS entry.
CopyJobState
States: STATE_STATING for the dest statCurrentSrc then does, for each src url: STATE_RENAMING if dire...
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
static bool canRenameToFile(const KUrl &url)
Returns whether the protocol can rename (i.e.
static void emitFilesAdded(const QString &directory)
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...
bool isNull() const
Return true if default-constructed.
void setUnrestricted(bool unrestricted)
Do not apply any KIOSK restrictions to this job.
KSharedConfigPtr config()
bool stopDirScan(const QString &path)
void setPath(const QString &path)
Show the progress info GUI, no Resume and no Overwrite.
CopyJob(CopyJobPrivate &dd)
KUrl mostLocalUrl(bool &local) const
Tries to give a local URL for this file item if possible.
void addPath(const QString &txt)
static void emitFilesRemoved(const QStringList &fileList)
static SimpleJob * newJobNoUi(const KUrl &url, int command, const QByteArray &packedArgs)
FileCopyJob * file_copy(const KUrl &src, const KUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Copy a single file.
void setModificationTime(const QDateTime &mtime)
Sets the modification time of the file.
void setWriteIntoExistingDirectories(bool overwriteAllDirs)
Reuse any directory that already exists, instead of the default behavior (interactive mode: showing a...
static bool supportsDeleting(const KUrl &url)
Returns whether the protocol can delete files/objects.
QString encodeFileName(const QString &str)
Encodes (from the text displayed to the real filename) This translates '/' into a "unicode fraction s...
long long numberValue(uint field, long long defaultValue=0) const
void totalSize(KJob *job, qulonglong size)
bool contains(uint field) const
check existence of a field
A UI delegate tuned to be used with KIO Jobs.
virtual void slotResult(KJob *job)
QString buildErrorString(int errorCode, const QString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
QString directory(const DirectoryOptions &options=IgnoreTrailingSlash) const
void setPass(const QString &pass)
KJobTrackerInterface * getJobTracker()
SimpleJob * rmdir(const KUrl &url)
Removes a single directory.
CopyJob * link(const KUrl &src, const KUrl &destDir, JobFlags flags=DefaultFlags)
Create a link.
RenameDialog_Mode
M_OVERWRITE: We have an existing dest, show details about it and offer to overwrite it...
virtual bool doSuspend()
Suspend this job.
void processedSize(KJob *job, qulonglong size)
void setDefaultPermissions(bool b)
By default the permissions of the copied files will be those of the source files. ...
The last time the file was modified.
CopyJob * move(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Moves a file or directory src to the given destination dest.
SimpleJob * symlink(const QString &target, const KUrl &dest, JobFlags flags=DefaultFlags)
Create or move a symlink.
const KUrl & url() const
Returns the SimpleJob's URL.
SimpleJob * setModificationTime(const KUrl &url, const QDateTime &mtime)
Changes the modification time on a file or directory.
int lstat(const QString &path, KDE_struct_stat *buf)
static ClipboardUpdater * create(Job *job, Mode mode)
Returns an instance of clipboard updater if QApplication::type() does not return a tty...
CopyJob * moveAs(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Moves a file or directory src to the given destination dest.
virtual void slotResult(KJob *job)
DeleteJob * del(const KUrl &src, JobFlags flags=DefaultFlags)
Delete a file or directory.
void setParentJob(Job *parentJob)
Set the parent Job.
CopyMode
Defines the mode of the operation.
CopyJob * linkAs(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Create a link.
QString dir(const QString &fileClass)
Returns the most recently used directory accociated with this file-class.
Access permissions (part of the mode returned by stat)
virtual QString errorString() const
The FileCopyJob copies data from one place to another.
ListJob * listRecursive(const KUrl &url, JobFlags flags=DefaultFlags, bool includeHidden=true)
The same as the previous method, but recurses subdirectories.
Filename - as displayed in directory listings etc.
Name of the file where the link points to Allows to check for a symlink (don't use S_ISLNK !) ...
virtual bool doSuspend()
Reimplemented for internal reasons.
RenameDialog_Result
The result of open_RenameDialog().
The base class for all jobs.
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...
The time the file was created.
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
If set, contains the label to display instead of the 'real name' in UDS_NAME.
void setAutoRename(bool autoRename)
Rename files automatically when the destination already exists, instead of the default behavior (inte...
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl destUrl() const
Returns the destination URL.
static bool supportsListing(const KUrl &url)
Returns whether the protocol can list files/objects.
virtual void registerJob(KJob *job)
QString errorText() const
KConfigGroup desktopGroup() const
static KProtocolInfo::FileNameUsedForCopying fileNameUsedForCopying(const KUrl &url)
This setting defines the strategy to use for generating a filename, when copying a file or directory ...
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
int utime(const QString &filename, struct utimbuf *buf)
static bool canRenameFromFile(const KUrl &url)
Returns whether the protocol can rename (i.e.
bool restartDirScan(const QString &path)
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
CopyJob * trash(const KUrl &src, JobFlags flags=DefaultFlags)
Trash a file or directory.
A KFileItem is a generic class to handle a file, local or remote.
CopyJob is used to move, copy or symlink files and directories.
QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.
static void emitFileMoved(const QString &src, const QString &dst)
A simple job (one url and one command).