Thu, 09 Mar 2017 12:50:14 +0200
Laid groundwork for library collection support.
--- a/CMakeLists.txt Thu Mar 09 00:54:45 2017 +0200 +++ b/CMakeLists.txt Thu Mar 09 12:50:14 2017 +0200 @@ -44,6 +44,7 @@ src/hierarchyelement.cpp src/lddocument.cpp src/ldpaths.cpp + src/librarycollection.cpp src/main.cpp src/mainwindow.cpp src/mathfunctions.cpp @@ -111,6 +112,7 @@ src/lddocument.h src/ldobjectiterator.h src/ldpaths.h + src/librarycollection.h src/macros.h src/main.h src/mainwindow.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/librarycollection.cpp Thu Mar 09 12:50:14 2017 +0200 @@ -0,0 +1,94 @@ +#include "librarycollection.h" + +const QStringList LibraryCollection::directoryNames = {"parts", "p"}; + +/* + * Searches the libraries for a file by relative path. + */ +QString LibraryCollection::find(QString relativePath) const +{ + // LDraw uses backslashes for directory separators. We need to convert them to forward + // slashes so that Qt understands them on all platforms. + relativePath.replace('\\', '/'); + + for (const Library& library : m_libraries) + { + for (const QString& directoryName : directoryNames) + { + QDir dir = library.path; + + if (dir.exists() and dir.cd(directoryName) and dir.exists(relativePath)) + return QDir::cleanPath(dir.absoluteFilePath(relativePath)); + } + } + + return ""; +} + +/* + * Searches the libraries for a file. This overload takes the parameters of a FileSpec and + * calls another overload with a ready spec. + */ +QString LibraryCollection::find(const QString &name, FileType type) const +{ + return find(FileSpec {name, type}); +} + +/* + * Searches the libraries for a file by the given file specification. The type attribute + * specifies what kind of file we are looking for. + */ +QString LibraryCollection::find(const FileSpec& spec) const +{ + for (const Library& library : m_libraries) + { + try + { + QDir subdirectory = library.subdirectory(spec.type); + if (subdirectory.exists(spec.name)) + return QDir::cleanPath(subdirectory.absoluteFilePath(spec.name)); + } + catch (SubdirectoryNotFoundError&) {} + } + + return ""; +} + +/* + * Returns the appropriate subdirectory for the given file type. + */ +QDir LibraryCollection::Library::subdirectory(FileType type) const +{ + QString subdirectory = subdirectoryName(type); + + if (path.exists(subdirectory)) + return path.absolutePath() + "/" + subdirectory; + else + throw SubdirectoryNotFoundError {}; +} + +/* + * Returns the appropriate subdirectory name for the given file type. + */ +QString LibraryCollection::Library::subdirectoryName(FileType type) +{ + switch (type) + { + case Part: + return "/parts/"; + + case Subpart: + return "/parts/s/"; + + case Primitive: + return "/p/"; + + case HighResolutionPrimitive: + return "/p/48/"; + + case LowResolutionPrimitive: + return "/p/8/"; + } + + return ""; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/librarycollection.h Thu Mar 09 12:50:14 2017 +0200 @@ -0,0 +1,46 @@ +#pragma once +#include <QDir> +#include "main.h" + +/* + * Models a collection of libraries. A library is a folder containing directories named "p" and + * "parts" that contains part and subpart files. + */ +class LibraryCollection +{ +public: + enum FileType + { + Part, + Subpart, + Primitive, + HighResolutionPrimitive, + LowResolutionPrimitive, + }; + + struct FileSpec + { + QString name; + FileType type; + }; + + QString find(QString relativePath) const; + QString find(const QString& name, FileType type) const; + QString find(const FileSpec& spec) const; + + static const QStringList directoryNames; + +private: + class SubdirectoryNotFoundError : public std::exception {}; + + struct Library + { + QDir path; + QString name; + + QDir subdirectory(FileType type) const; + static QString subdirectoryName(FileType type); + }; + + QVector<Library> m_libraries; +};