]> git.lyx.org Git - lyx.git/blobdiff - src/support/FileName.cpp
Revert qprocess code. Revisions reverted: 22026, 22030, 22044, 22048,
[lyx.git] / src / support / FileName.cpp
index 8203da462b7dc80d91cf5fd66623040e530dd1a4..40e717516c971614267e9dab8f06f3678b205061 100644 (file)
 #include <config.h>
 
 #include "support/FileName.h"
+#include "support/FileNameList.h"
+
+#include "support/debug.h"
 #include "support/filetools.h"
 #include "support/lstrings.h"
+#include "support/lyxlib.h"
 #include "support/os.h"
 #include "support/qstring_helpers.h"
 
-#include "debug.h"
-#include "lyxlib.h"
-
 #include <QDateTime>
 #include <QDir>
 #include <QFile>
 #include <QFileInfo>
 #include <QList>
+#include <QTime>
 
 #include <boost/assert.hpp>
 
 #include <cerrno>
 #include <fcntl.h>
 
-
-using std::map;
-using std::string;
-using std::ifstream;
-using std::ostringstream;
-using std::endl;
+using namespace std;
 
 namespace lyx {
 namespace support {
@@ -79,13 +76,16 @@ FileName::FileName() : d(new Private)
 {
 }
 
+
 FileName::FileName(string const & abs_filename)
        : d(abs_filename.empty() ? new Private : new Private(abs_filename))
 {
-       BOOST_ASSERT(empty() || d->fi.isAbsolute());
-#if defined(_WIN32)
-       BOOST_ASSERT(!contains(abs_filename, '\\'));
-#endif
+}
+
+
+FileName::~FileName()
+{
+       delete d;
 }
 
 
@@ -118,9 +118,6 @@ void FileName::set(string const & name)
 {
        d->fi.setFile(toqstr(name));
        BOOST_ASSERT(d->fi.isAbsolute());
-#if defined(_WIN32)
-       BOOST_ASSERT(!contains(name, '\\'));
-#endif
 }
 
 
@@ -130,9 +127,15 @@ void FileName::erase()
 }
 
 
-bool FileName::copyTo(FileName const & name) const
+bool FileName::copyTo(FileName const & name, bool overwrite) const
 {
-       return QFile::copy(d->fi.absoluteFilePath(), name.d->fi.absoluteFilePath());
+       if (overwrite)
+               QFile::remove(name.d->fi.absoluteFilePath());
+       bool success = QFile::copy(d->fi.absoluteFilePath(), name.d->fi.absoluteFilePath());
+       if (!success)
+               lyxerr << "FileName::copyTo(): Could not copy file "
+                       << *this << " to " << name << endl;
+       return success;
 }
 
 
@@ -219,11 +222,44 @@ bool FileName::isDirWritable() const
        if (tmpfl.empty())
                return false;
 
-       unlink(tmpfl);
+       tmpfl.removeFile();
        return true;
 }
 
 
+FileNameList FileName::dirList(std::string const & ext) const
+{
+       FileNameList dirlist;
+       if (!isDirectory()) {
+               LYXERR0("Directory '" << *this << "' does not exist!");
+               return dirlist;
+       }
+
+       QDir dir = d->fi.absoluteDir();
+
+       if (!ext.empty()) {
+               QString filter;
+               switch (ext[0]) {
+               case '.': filter = "*" + toqstr(ext); break;
+               case '*': filter = toqstr(ext); break;
+               default: filter = "*." + toqstr(ext);
+               }
+               dir.setNameFilters(QStringList(filter));
+               LYXERR(Debug::FILES, "filtering on extension "
+                       << fromqstr(filter) << " is requested.");
+       }
+
+       QFileInfoList list = dir.entryInfoList();
+       for (int i = 0; i != list.size(); ++i) {
+               FileName fi(fromqstr(list.at(i).absoluteFilePath()));
+               dirlist.push_back(fi);
+               LYXERR(Debug::FILES, "found file " << fi);
+       }
+
+       return dirlist;
+}
+
+
 FileName FileName::tempName(FileName const & dir, std::string const & mask)
 {
        return support::tempName(dir, mask);
@@ -236,36 +272,76 @@ std::time_t FileName::lastModified() const
 }
 
 
+bool FileName::chdir() const
+{
+       return QDir::setCurrent(d->fi.absoluteFilePath());
+}
+
+
+extern unsigned long sum(char const * file);
+
+unsigned long FileName::checksum() const
+{
+       if (!exists()) {
+               LYXERR0("File \"" << absFilename() << "\" does not exist!");
+               return 0;
+       }
+       // a directory may be passed here so we need to test it. (bug 3622)
+       if (isDirectory()) {
+               LYXERR0('"' << absFilename() << "\" is a directory!");
+               return 0;
+       }
+       if (!lyxerr.debugging(Debug::FILES))
+               return sum(absFilename().c_str());
+
+       QTime t;
+       t.start();
+       unsigned long r = sum(absFilename().c_str());
+       lyxerr << "Checksumming \"" << absFilename() << "\" lasted "
+               << t.elapsed() << " ms." << endl;
+       return r;
+}
+
+
+bool FileName::removeFile() const
+{
+       bool const success = QFile::remove(d->fi.absoluteFilePath());
+       if (!success && exists())
+               LYXERR0("Could not delete file " << *this);
+       return success;
+}
+
+
 static bool rmdir(QFileInfo const & fi)
 {
        QDir dir(fi.absoluteFilePath());
        QFileInfoList list = dir.entryInfoList();
-       bool global_success = true;
-       for (int i = 0; i < list.size(); ++i) {
+       bool success = true;
+       for (int i = 0; i != list.size(); ++i) {
                if (list.at(i).fileName() == ".")
                        continue;
                if (list.at(i).fileName() == "..")
                        continue;
-               bool success;
+               bool removed;
                if (list.at(i).isDir()) {
-                       LYXERR(Debug::FILES, "Erasing dir " 
+                       LYXERR(Debug::FILES, "Removing dir " 
                                << fromqstr(list.at(i).absoluteFilePath()));
-                       success = rmdir(list.at(i));
+                       removed = rmdir(list.at(i));
                }
                else {
-                       LYXERR(Debug::FILES, "Erasing file " 
+                       LYXERR(Debug::FILES, "Removing file " 
                                << fromqstr(list.at(i).absoluteFilePath()));
-                       success = dir.remove(list.at(i).fileName());
+                       removed = dir.remove(list.at(i).fileName());
                }
-               if (!success) {
-                       global_success = false;
-                       lyxerr << "Could not delete "
-                               << fromqstr(list.at(i).absoluteFilePath()) << "." << endl;
+               if (!removed) {
+                       success = false;
+                       LYXERR0("Could not delete "
+                               << fromqstr(list.at(i).absoluteFilePath()));
                }
        } 
        QDir parent = fi.absolutePath();
-       global_success |= parent.rmdir(fi.fileName());
-       return global_success;
+       success &= parent.rmdir(fi.fileName());
+       return success;
 }
 
 
@@ -273,7 +349,7 @@ bool FileName::destroyDirectory() const
 {
        bool const success = rmdir(d->fi);
        if (!success)
-               lyxerr << "Could not delete " << *this << "." << endl;
+               LYXERR0("Could not delete " << *this);
 
        return success;
 }
@@ -286,62 +362,71 @@ bool FileName::createDirectory(int permission) const
 }
 
 
-std::vector<FileName> FileName::dirList(std::string const & ext)
+docstring const FileName::absoluteFilePath() const
 {
-       std::vector<FileName> dirlist;
-       if (!exists() || !isDirectory()) {
-               lyxerr << "FileName::dirList(): Directory \"" << absFilename()
-                       << "\" does not exist!" << endl;
-               return dirlist;
-       }
+       return qstring_to_ucs4(d->fi.absoluteFilePath());
+}
 
-       QDir dir(d->fi.absoluteFilePath());
 
-       if (!ext.empty()) {
-               QString filter;
-               switch (ext[0]) {
-               case '.': filter = "*" + toqstr(ext); break;
-               case '*': filter = toqstr(ext); break;
-               default: filter = "*." + toqstr(ext);
-               }
-               dir.setNameFilters(QStringList(filter));
-               LYXERR(Debug::FILES, "FileName::dirList(): filtering on extension "
-                       << fromqstr(filter) << " is requested." << endl);
+docstring FileName::displayName(int threshold) const
+{
+       return makeDisplayPath(absFilename(), threshold);
+}
+
+
+docstring FileName::fileContents(string const & encoding) const
+{
+       if (!isReadableFile()) {
+               LYXERR0("File '" << *this << "' is not redable!");
+               return docstring();
        }
 
-       QFileInfoList list = dir.entryInfoList();
-       for (int i = 0; i < list.size(); ++i) {
-               FileName fi;
-               fi.d->fi = list.at(i);
-               dirlist.push_back(fi);
-               LYXERR(Debug::FILES, "FileName::dirList(): found file "
-                       << fi.absFilename() << endl);
+       QFile file(d->fi.absoluteFilePath());
+       if (!file.open(QIODevice::ReadOnly)) {
+               LYXERR0("File '" << *this
+                       << "' could not be opened in read only mode!");
+               return docstring();
        }
+       QByteArray contents = file.readAll();
+       file.close();
 
-       return dirlist;
-}
+       if (contents.isEmpty()) {
+               LYXERR(Debug::FILES, "File '" << *this
+                       << "' is either empty or some error happened while reading it.");
+               return docstring();
+       }
 
+       QString s;
+       if (encoding.empty() || encoding == "UTF-8")
+               s = QString::fromUtf8(contents.data());
+       else if (encoding == "ascii")
+               s = QString::fromAscii(contents.data());
+       else if (encoding == "local8bit")
+               s = QString::fromLocal8Bit(contents.data());
+       else if (encoding == "latin1")
+               s = QString::fromLatin1(contents.data());
 
-docstring FileName::displayName(int threshold) const
-{
-       return makeDisplayPath(absFilename(), threshold);
+       return qstring_to_ucs4(s);
 }
 
 
-string FileName::fileContents() const
+void FileName::changeExtension(std::string const & extension)
 {
-       if (exists()) {
-               string const encodedname = toFilesystemEncoding();
-               ifstream ifs(encodedname.c_str());
-               ostringstream ofs;
-               if (ifs && ofs) {
-                       ofs << ifs.rdbuf();
-                       ifs.close();
-                       return ofs.str();
-               }
-       }
-       lyxerr << "LyX was not able to read file '" << *this << '\'' << std::endl;
-       return string();
+       // FIXME: use Qt native methods...
+       string const oldname = absFilename();
+       string::size_type const last_slash = oldname.rfind('/');
+       string::size_type last_dot = oldname.rfind('.');
+       if (last_dot < last_slash && last_slash != string::npos)
+               last_dot = string::npos;
+
+       string ext;
+       // Make sure the extension starts with a dot
+       if (!extension.empty() && extension[0] != '.')
+               ext= '.' + extension;
+       else
+               ext = extension;
+
+       set(oldname.substr(0, last_dot) + ext);
 }
 
 
@@ -373,8 +458,8 @@ string FileName::guessFormatFromContents() const
        // GZIP \037\213        http://www.ietf.org/rfc/rfc1952.txt
        // ZIP  PK...                   http://www.halyava.ru/document/ind_arch.htm
        // Z    \037\235                UNIX compress
-       // paranoia check
 
+       // paranoia check
        if (empty() || !isReadableFile())
                return string();
 
@@ -527,6 +612,13 @@ bool FileName::isZippedFile() const
 }
 
 
+docstring const FileName::relPath(string const & path) const
+{
+       // FIXME UNICODE
+       return makeRelPath(absoluteFilePath(), from_utf8(path));
+}
+
+
 bool operator==(FileName const & lhs, FileName const & rhs)
 {
        return lhs.absFilename() == rhs.absFilename();
@@ -594,20 +686,20 @@ void DocFileName::erase()
 }
 
 
-string const DocFileName::relFilename(string const & path) const
+string DocFileName::relFilename(string const & path) const
 {
        // FIXME UNICODE
-       return to_utf8(makeRelPath(qstring_to_ucs4(d->fi.absoluteFilePath()), from_utf8(path)));
+       return to_utf8(relPath(path));
 }
 
 
-string const DocFileName::outputFilename(string const & path) const
+string DocFileName::outputFilename(string const & path) const
 {
        return save_abs_path_ ? absFilename() : relFilename(path);
 }
 
 
-string const DocFileName::mangledFilename(std::string const & dir) const
+string DocFileName::mangledFilename(std::string const & dir) const
 {
        // We need to make sure that every DocFileName instance for a given
        // filename returns the same mangled name.
@@ -621,7 +713,7 @@ string const DocFileName::mangledFilename(std::string const & dir) const
        // Now the real work
        string mname = os::internal_path(name);
        // Remove the extension.
-       mname = changeExtension(name, string());
+       mname = support::changeExtension(name, string());
        // The mangled name must be a valid LaTeX name.
        // The list of characters to keep is probably over-restrictive,
        // but it is not really a problem.
@@ -636,7 +728,7 @@ string const DocFileName::mangledFilename(std::string const & dir) const
        while ((pos = mname.find_first_not_of(keep, pos)) != string::npos)
                mname[pos++] = '_';
        // Add the extension back on
-       mname = changeExtension(mname, getExtension(name));
+       mname = support::changeExtension(mname, getExtension(name));
 
        // Prepend a counter to the filename. This is necessary to make
        // the mangled name unique.
@@ -679,7 +771,7 @@ bool DocFileName::isZipped() const
 }
 
 
-string const DocFileName::unzippedFilename() const
+string DocFileName::unzippedFilename() const
 {
        return unzippedFileName(absFilename());
 }