#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 {
{
}
+
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;
}
{
d->fi.setFile(toqstr(name));
BOOST_ASSERT(d->fi.isAbsolute());
-#if defined(_WIN32)
- BOOST_ASSERT(!contains(name, '\\'));
-#endif
}
}
-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;
}
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);
}
+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;
}
{
bool const success = rmdir(d->fi);
if (!success)
- lyxerr << "Could not delete " << *this << "." << endl;
+ LYXERR0("Could not delete " << *this);
return success;
}
}
-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);
}
// 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();
}
+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();
}
-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.
// 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.
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.
}
-string const DocFileName::unzippedFilename() const
+string DocFileName::unzippedFilename() const
{
return unzippedFileName(absFilename());
}