diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | e9ae80694875f869892f13f4fcaf1170a00dea41 (patch) | |
tree | aa2f8d8a217e2d376224c8d46b7397b68d35de2d /lib/qextfileinfo.cpp | |
download | tdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.tar.gz tdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/qextfileinfo.cpp')
-rw-r--r-- | lib/qextfileinfo.cpp | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/lib/qextfileinfo.cpp b/lib/qextfileinfo.cpp new file mode 100644 index 00000000..b7c7e741 --- /dev/null +++ b/lib/qextfileinfo.cpp @@ -0,0 +1,619 @@ +/* + From WebMaker - KDE HTML Editor + Copyright (C) 1998, 1999 Alexei Dets <dets@services.ru> + + Rewritten for Quanta Plus: (C) 2002 Andras Mantia <amantia@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + + +//qt includes +#include <qdir.h> +#include <qapplication.h> +#include <qptrlist.h> +#include <qstringlist.h> +#include <qregexp.h> +#include <qtimer.h> + +//kde includes +#include <kurl.h> +#include <kio/job.h> +#include <kio/netaccess.h> +#include <kio/scheduler.h> +#include <kdirlister.h> +#include <kfileitem.h> +#include <kglobal.h> +#include <kdebug.h> + +//app includes +#include "qextfileinfo.h" + +QString QExtFileInfo::lastErrorMsg = ""; + +QString QExtFileInfo::canonicalPath(const QString& path) +{ + if (!path.startsWith("/") || path == "/") + return path; + bool endsWithSlash = path.endsWith("/"); + QDir dir(path); + if (dir.exists() || QFileInfo(path).exists()) + { + QString s = dir.canonicalPath(); + if (endsWithSlash) + s.append("/"); + return s; + } else + { + KURL u = KURL::fromPathOrURL(path).upURL(); + QString s = u.path(-1) + "/"; + if (s == "//") s = "/"; + QString s2 = path.mid(s.length()); + s2 = QExtFileInfo::canonicalPath(s) + s2; + return s2; + } +} + +QString QExtFileInfo::homeDirPath() +{ + return QDir(QDir::homeDirPath()).canonicalPath(); +} + +/** create a relative short url based in baseURL*/ +KURL QExtFileInfo::toRelative(const KURL& _urlToConvert,const KURL& _baseURL, bool resolveSymlinks) +{ + KURL urlToConvert = _urlToConvert; + KURL baseURL = _baseURL; + KURL resultURL = urlToConvert; + if (urlToConvert.protocol() == baseURL.protocol()) + { + if (urlToConvert.isLocalFile()) + { + QString path; + if (resolveSymlinks) + path = QExtFileInfo::canonicalPath(urlToConvert.path()); + else + path = urlToConvert.path(); + if (!path.isEmpty()) + urlToConvert.setPath(path); + if (resolveSymlinks) + path = QExtFileInfo::canonicalPath(baseURL.path()); + else + path = baseURL.path(); + if (!path.isEmpty()) + baseURL.setPath(path); + } + QString path = urlToConvert.path(); + QString basePath = baseURL.path(1); + if (path.startsWith("/")) + { + path.remove(0, 1); + basePath.remove(0, 1); + if ( basePath.right(1) != "/" ) basePath.append("/"); + + int pos=0; + int pos1=0; + for (;;) + { + pos=path.find("/"); + pos1=basePath.find("/"); + if ( pos<0 || pos1<0 ) break; + if ( path.left(pos+1 ) == basePath.left(pos1+1) ) + { + path.remove(0, pos+1); + basePath.remove(0, pos1+1); + } + else + break; + }; + + if ( basePath == "/" ) basePath=""; + int level = basePath.contains("/"); + for (int i=0; i<level; i++) + { + path="../"+path; + }; + } + + resultURL.setPath(QDir::cleanDirPath(path)); + } + + if (urlToConvert.path().endsWith("/") && !resultURL.path().isEmpty()) + resultURL.adjustPath(1); + return resultURL; +} +/** convert relative filename to absolute */ +KURL QExtFileInfo::toAbsolute(const KURL& _urlToConvert,const KURL& _baseURL) +{ + KURL urlToConvert = _urlToConvert; + KURL baseURL = _baseURL; + KURL resultURL = urlToConvert; + + if (urlToConvert.protocol() == baseURL.protocol() && !urlToConvert.path().startsWith("/")) + { + if (urlToConvert.isLocalFile()) + { + QString path = QExtFileInfo::canonicalPath(baseURL.path()); + if (!path.isEmpty()) + baseURL.setPath(path); + } + int pos; + QString cutname = urlToConvert.path(); + QString cutdir = baseURL.path(1); + while ( (pos = cutname.find("../")) >=0 ) + { + cutname.remove( 0, pos+3 ); + cutdir.remove( cutdir.length()-1, 1 ); + cutdir.remove( cutdir.findRev('/')+1 , 1000); + } + resultURL.setPath(QDir::cleanDirPath(cutdir+cutname)); + } + + if (urlToConvert.path().endsWith("/")) resultURL.adjustPath(1); + return resultURL; +} + +/** All files in a dir. + The return will also contain the name of the subdirectories. + This is needed for empty directory adding/handling. (Andras) + Currently works only for local directories +*/ +KURL::List QExtFileInfo::allFiles( const KURL& path, const QString& mask, QWidget *window) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.allFilesInternal(path, mask, window); +} + +KURL::List QExtFileInfo::allFilesRelative( const KURL& path, const QString& mask, QWidget *window, bool resolveSymlinks) +{ + QExtFileInfo internalFileInfo; + KURL::List r = internalFileInfo.allFilesInternal(path, mask, window); + + KURL::List::Iterator it; + for ( it = r.begin(); it != r.end(); ++it ) + { + *it = QExtFileInfo::toRelative( *it, path, resolveSymlinks ); + } + + return r; +} + +QDict<KFileItem> QExtFileInfo::allFilesDetailed(const KURL& path, const QString& mask, QWidget *window) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.allFilesDetailedInternal(path, mask, window); +} + + +bool QExtFileInfo::createDir(const KURL& path, QWidget *window) +{ + int i = 0; + bool result; + KURL dir3; + KURL dir2; + KURL dir1 = path; + dir1.setPath("/"); + if (!exists(dir1, false, window) && path.protocol() != "webdav" ) + { + return false; //the root is not accessible, possible wrong username/password supplied + } + while (!exists(path, false, window) && dir2.path() != path.path()) + { + dir1 = path; + dir2 = path; + + dir1=cdUp(dir1); + while (!exists(dir1, false, window) && dir1.path() != "/") + { + dir1 = cdUp(dir1); + dir2 = cdUp(dir2); + // debug(d1); + } + dir3 = dir2; + dir3.adjustPath(-1); //some servers refuse to create directories ending with a slash + result = KIO::NetAccess::mkdir(dir3, window); + if (dir2.path() == "/" || !result) + break; + i++; + } + result = exists(path, false, window); + return result; +} + +KURL QExtFileInfo::cdUp(const KURL &url) +{ + KURL u = url; + QString dir = u.path(-1); + while ( !dir.isEmpty() && dir.right(1) != "/" ) + { + dir.remove( dir.length()-1,1); + } + u.setPath(dir); + return u; +} + +QString QExtFileInfo::shortName(const QString &fname) +{ + return fname.section("/", -1); +} + +KURL QExtFileInfo::path( const KURL &url ) +{ + KURL result = url; + result.setPath(result.directory(false,false)); + return result; +} + +KURL QExtFileInfo::home() +{ + KURL url; + url.setPath(QDir::currentDirPath()+"/"); + return url; +} + + +bool QExtFileInfo::exists(const KURL& a_url, bool readingOnly, QWidget *window) +{ +// Andras: Don't use it now, as it brings up an extra dialog and need manual +// intervention when usign fish +// return KIO::NetAccess::exists(a_url, false); + +// No dialog when stating. + if (a_url.isLocalFile()) + { + return QFile::exists(a_url.path()); + } else + { + QExtFileInfo internalFileInfo; + return internalFileInfo.internalExists(a_url, readingOnly, window); + } +} + +/* Synchronous copy, like NetAccess::file_copy in KDE 3.2 */ +bool QExtFileInfo::copy( const KURL& src, const KURL& target, int permissions, + bool overwrite, bool resume, QWidget* window ) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.internalCopy( src, target, permissions, overwrite, resume, window ); +} + +/** No descriptions */ +KURL::List QExtFileInfo::allFilesInternal(const KURL& startURL, const QString& mask, QWidget *window) +{ + if (startURL.isLocalFile()) + return allLocalFiles(startURL.path(-1), mask); + + dirListItems.clear(); + if (internalExists(startURL, true, window)) + { + lstFilters.setAutoDelete(true); + lstFilters.clear(); + // Split on white space + QStringList list = QStringList::split( ' ', mask ); + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + lstFilters.append( new QRegExp(*it, false, true ) ); + + bJobOK = true; + KIO::ListJob *job = KIO::listRecursive(startURL, false, true); + job->setWindow(window); + m_listJobCount = 1; + connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList&)), + this, SLOT(slotNewEntries(KIO::Job *, const KIO::UDSEntryList&))); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotListResult (KIO::Job *) ) ); + m_listStartURL = startURL.url(); + + //kdDebug(24000) << "Now listing: " << startURL.url() << endl; + enter_loop(); + //kdDebug(24000) << "Listing done: " << startURL.url() << endl; + lstFilters.clear(); + if (!bJobOK) + { + // kdDebug(24000) << "Error while listing "<< startURL.url() << endl; + dirListItems.clear(); + } + } + return dirListItems; +} + +/** No descriptions */ +QDict<KFileItem> QExtFileInfo::allFilesDetailedInternal(const KURL& startURL, const QString& mask, QWidget *window) +{ + detailedDirListItems.setAutoDelete(true); + detailedDirListItems.clear(); + detailedDirListItems.setAutoDelete(false); + if (internalExists(startURL, true, window)) + { + lstFilters.setAutoDelete(true); + lstFilters.clear(); + // Split on white space + QStringList list = QStringList::split( ' ', mask ); + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + lstFilters.append( new QRegExp(*it, false, true ) ); + + bJobOK = true; + KIO::ListJob *job = KIO::listRecursive(startURL, false, true); + job->setWindow(window); + m_listJobCount = 1; + connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList&)), + this, SLOT(slotNewDetailedEntries(KIO::Job *, const KIO::UDSEntryList&))); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotListResult (KIO::Job *) ) ); + m_listStartURL = startURL.url(); + //kdDebug(24000) << "Now listing: " << startURL.url() << endl; + enter_loop(); + //kdDebug(24000) << "Listing done: " << startURL.url() << endl; + lstFilters.clear(); + if (!bJobOK) + { + // kdDebug(24000) << "Error while listing "<< startURL.url() << endl; + detailedDirListItems.clear(); + } + } + return detailedDirListItems; +} + +KURL::List QExtFileInfo::allLocalFiles(const QString& startPath, const QString& mask) +{ + KURL::List list; + QDir d(startPath, mask); + QStringList l = d.entryList(); + QStringList::ConstIterator end = l.constEnd(); + QString path; + for (QStringList::ConstIterator it = l.constBegin(); it != end; ++it) + { + path = *it; + if (path != "." && path != "..") + { + path = startPath + "/" + path; + if (QFileInfo(path).isDir()) + path.append("/"); + list.append(KURL::fromPathOrURL(path)); + } + } + l = d.entryList("*", QDir::Dirs); + end = l.constEnd(); + for (QStringList::ConstIterator it = l.constBegin(); it != end; ++it) + { + if ((*it) != "." && (*it) != "..") + list += allLocalFiles(startPath + "/" + (*it), mask); + } + return list; +} + + +//Some hackery from KIO::NetAccess as they do not do exactly what we want +/* return true if the url exists*/ +bool QExtFileInfo::internalExists(const KURL& url, bool readingOnly, QWidget *window) +{ + bJobOK = true; + KURL url2 = url; + url2.adjustPath(-1); + // kdDebug(24000)<<"QExtFileInfo::internalExists"<<endl; + KIO::StatJob * job = KIO::stat(url2, false); + job->setWindow(window); + job->setDetails(0); + job->setSide(readingOnly); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotResult (KIO::Job *) ) ); + + //To avoid lock-ups, start a timer. + QTimer::singleShot(60*1000, this,SLOT(slotTimeout())); + //kdDebug(24000)<<"QExtFileInfo::internalExists:before enter_loop"<<endl; + enter_loop(); + //kdDebug(24000)<<"QExtFileInfo::internalExists:after enter_loop"<<endl; + return bJobOK; +} + +bool QExtFileInfo::internalCopy(const KURL& src, const KURL& target, int permissions, + bool overwrite, bool resume, QWidget* window) +{ + bJobOK = true; // success unless further error occurs + + KIO::Scheduler::checkSlaveOnHold(true); + KIO::Job * job = KIO::file_copy( src, target, permissions, overwrite, resume, false ); +// KIO::Job * job2 = KIO::del(target, false ); + //job2->setWindow (window); + //connect( job2, SIGNAL( result (KIO::Job *) ), +// this, SLOT( slotResult (KIO::Job *) ) ); + + //enter_loop(); + //if (bJobOK) + { +// kdDebug(24000) << "Copying " << src << " to " << target << endl; + // KIO::Job *job = KIO::copy( src, target, false ); + job->setWindow (window); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotResult (KIO::Job *) ) ); + enter_loop(); + } + return bJobOK; +} + + +void qt_enter_modal( QWidget *widget ); +void qt_leave_modal( QWidget *widget ); + +void QExtFileInfo::enter_loop() +{ + QWidget dummy(0,0,WType_Dialog | WShowModal); + dummy.setFocusPolicy( QWidget::NoFocus ); + qt_enter_modal(&dummy); + //kdDebug(24000)<<"QExtFileInfo::enter_loop:before qApp->enter_loop()"<< endl; + qApp->enter_loop(); +// kdDebug(24000)<<"QExtFileInfo::enter_loop:after qApp->enter_loop()"<<endl; + qt_leave_modal(&dummy); +} + +void QExtFileInfo::slotListResult(KIO::Job *job) +{ + m_listJobCount--; + if (m_listJobCount == 0) + slotResult(job); +} + +void QExtFileInfo::slotResult(KIO::Job *job) +{ + //kdDebug(24000)<<"QExtFileInfo::slotResult"<<endl; + bJobOK = !job->error(); + if ( !bJobOK ) + { + if ( !lastErrorMsg ) + lastErrorMsg = job->errorString(); + } + if ( job->isA("KIO::StatJob") ) + m_entry = static_cast<KIO::StatJob *>(job)->statResult(); + qApp->exit_loop(); +} + +void QExtFileInfo::slotNewEntries(KIO::Job *job, const KIO::UDSEntryList& udsList) +{ + KURL url = static_cast<KIO::ListJob *>(job)->url(); + url.adjustPath(-1); + // avoid creating these QStrings again and again + static const QString& dot = KGlobal::staticQString("."); + static const QString& dotdot = KGlobal::staticQString(".."); + + KIO::UDSEntryListConstIterator it = udsList.begin(); + KIO::UDSEntryListConstIterator end = udsList.end(); + KURL itemURL; + QPtrList<KFileItem> linkItems; + linkItems.setAutoDelete(true); + for ( ; it != end; ++it ) + { + QString name; + + // find out about the name + KIO::UDSEntry::ConstIterator entit = (*it).begin(); + for( ; entit != (*it).end(); ++entit ) + if ((*entit).m_uds == KIO::UDS_NAME) + { + name = (*entit).m_str; + break; + } + + if (!name.isEmpty() && name != dot && name != dotdot) + { + KFileItem* item = new KFileItem( *it, url, false, true ); + if (item->isDir() && item->isLink()) + { + KURL u = item->url(); + QString linkDest = item->linkDest(); + kdDebug(24000) << "Got link: " << name << " Points to:" << linkDest << endl; + if (linkDest.startsWith("./") || linkDest.startsWith("../") ) + { + u.setPath(u.directory(false, true) + linkDest); + u.cleanPath(); + } + else + u.setPath(linkDest); + u.adjustPath(+1); + if (!dirListItems.contains(u) && u.url() != m_listStartURL && !u.isParentOf(item->url())) + { + linkItems.append(new KFileItem(*item)); + } else + { + kdDebug(24000) << "Recursive link " << u.url() << endl; + continue; + } + } + itemURL = item->url(); + if (item->isDir()) + itemURL.adjustPath(1); + for (QPtrListIterator<QRegExp> filterIt(lstFilters); filterIt.current(); ++filterIt ) + { + if (filterIt.current()->exactMatch(item->text())) + dirListItems.append(itemURL); + } + delete item; + } + } + for (QPtrList<KFileItem>::ConstIterator it = linkItems.constBegin(); it != linkItems.constEnd(); ++it) + { + KIO::ListJob *ljob = KIO::listRecursive((*it)->url(), false, true); + m_listJobCount++; + //kdDebug(24000) << "Now listing: " << (*it)->url() << endl; + connect( ljob, SIGNAL(entries(KIO::Job *,const KIO::UDSEntryList &)), + this,SLOT (slotNewEntries(KIO::Job *,const KIO::UDSEntryList &))); + connect( ljob, SIGNAL(result(KIO::Job *)), + this,SLOT (slotListResult(KIO::Job *))); + } +} + +void QExtFileInfo::slotNewDetailedEntries(KIO::Job *job, const KIO::UDSEntryList& udsList) +{ + KURL url = static_cast<KIO::ListJob *>(job)->url(); + url.adjustPath(-1); + // avoid creating these QStrings again and again + static const QString& dot = KGlobal::staticQString("."); + static const QString& dotdot = KGlobal::staticQString(".."); + + KIO::UDSEntryListConstIterator it = udsList.begin(); + KIO::UDSEntryListConstIterator end = udsList.end(); + KURL itemURL; + QPtrList<KFileItem> linkItems; + linkItems.setAutoDelete(true); + for ( ; it != end; ++it ) + { + QString name; + + // find out about the name + KIO::UDSEntry::ConstIterator entit = (*it).begin(); + for( ; entit != (*it).end(); ++entit ) + if ((*entit).m_uds == KIO::UDS_NAME) + { + name = (*entit).m_str; + break; + } + + if (!name.isEmpty() && name != dot && name != dotdot) + { + KFileItem *item= new KFileItem(*it, url, false, true ); + if (item->isDir() && item->isLink()) + { + KURL u = item->url(); + u.setPath(item->linkDest()); + QString urlStr = u.url(); + if (detailedDirListItems.find(urlStr) == 0L && + (urlStr != m_listStartURL)) + { + linkItems.append(new KFileItem(*item)); + } else + { + kdDebug(24000) << "Recursive link" << item->url() << endl; + continue; + } + } + bool added = false; + for (QPtrListIterator<QRegExp> filterIt( lstFilters ); filterIt.current(); ++filterIt) + if (filterIt.current()->exactMatch(item->text())) + { + detailedDirListItems.insert(item->url().url(), item); + added = true; + } + if (!added) + delete item; + } + } + for (QPtrList<KFileItem>::ConstIterator it = linkItems.constBegin(); it != linkItems.constEnd(); ++it) + { + KIO::ListJob *ljob = KIO::listRecursive((*it)->url(), false, true); + m_listJobCount++; + // kdDebug(24000) << "Now listing: " << (*it)->url() << endl; + connect( ljob, SIGNAL(entries(KIO::Job *,const KIO::UDSEntryList &)), + this,SLOT (slotNewDetailedEntries(KIO::Job *,const KIO::UDSEntryList &))); + connect( ljob, SIGNAL(result(KIO::Job *)), + this,SLOT (slotListResult(KIO::Job *))); + } +} + +/** Timeout occurred while waiting for some network function to return. */ +void QExtFileInfo::slotTimeout() +{ + bJobOK = false; + qApp->exit_loop(); +} +#include "qextfileinfo.moc" |