diff --git a/aegisub/libaegisub/Makefile b/aegisub/libaegisub/Makefile index a2619c7df..daf685903 100644 --- a/aegisub/libaegisub/Makefile +++ b/aegisub/libaegisub/Makefile @@ -17,6 +17,7 @@ LDFLAGS += -L../universalchardet -luniversalchardet endif common/charset_conv.o: CXXFLAGS += $(CFLAGS_ICONV) +unix/path.o: CXXFLAGS += -DDIR_DATA=\"$(P_DATA)\" -DDIR_DOC=\"$(P_DOC)\" SRC = \ common/charset.cpp \ @@ -27,6 +28,7 @@ SRC = \ common/mru.cpp \ common/option.cpp \ common/option_visit.cpp \ + common/path.cpp \ common/progress.cpp \ common/keyframe.cpp \ common/log.cpp \ @@ -35,7 +37,8 @@ SRC = \ unix/util.cpp \ unix/io.cpp \ unix/access.cpp \ - unix/log.cpp + unix/log.cpp \ + unix/path.cpp ifeq (yes, $(BUILD_DARWIN)) SRC += \ diff --git a/aegisub/libaegisub/common/path.cpp b/aegisub/libaegisub/common/path.cpp index 3e7b19cd7..097e3d728 100644 --- a/aegisub/libaegisub/common/path.cpp +++ b/aegisub/libaegisub/common/path.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2010, Amar Takhar +// Copyright (c) 2010-2011, Amar Takhar // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -18,18 +18,130 @@ /// @brief Common paths. /// @ingroup libaegisub +#ifndef LAGI_PRE +#include +#endif -#include +#include "libaegisub/access.h" +#include "libaegisub/log.h" +#include "libaegisub/path.h" namespace agi { -Path::Path(const std::string &file, const std::string& default_path): path_file(file), path_default(default_path) { +Path::Path(const std::string &file, const std::string& default_path) +: path_file(file), +path_default(default_path) { opt = new agi::Options(file, default_path); opt->ConfigUser(); + LOG_D("agi/path") << "New Path object"; } Path::~Path() { opt->Flush(); } + +const std::string Path::Get(const char *name) { + std::string path; + try { + path = std::string(opt->Get(name)->GetString()); + } catch (OptionErrorNotFound& e) { + throw PathErrorNotFound("Invalid path key"); + } + + Decode(path); + return path; +} + + +void Path::Set(const char *name, const std::string &path) { + std::string set(path); + + if (path[0] == 94) { + std::string tmp(path); + // Check that the used cookie exists. + Decode(tmp); + agi::acs::CheckDirWrite(path); + } + + try { + opt->Get(name)->SetString(set); + } catch (OptionErrorNotFound& e) { + throw PathErrorNotFound("Invalid path key"); + } + +} + + +void Path::ListGet(const char *name, std::vector &out) { + opt->Get(name)->GetListString(out); +} + + +void Path::ListSet(const char *name, std::vector list) { + opt->Get(name)->SetListString(list); +} + + +const void Path::Decode(std::string &path) { + if (path[0] != 94) // "^" + return; + try { + if (path.find("^CONFIG") == 0) { + path.replace(0, 7, Config()); + return; + } + + if (path.find("^USER") == 0) { + path.replace(0, 5, User()); + return; + } + + if (path.find("^DATA") == 0) { + path.replace(0, 5, Data()); + return; + } + + if (path.find("^DOC") == 0) { + path.replace(0, 4, Doc()); + return; + } + + if (path.find("^TEMP") == 0) { + path.replace(0, 5, Temp()); + return; + } + + if (path.find("^AUDIO") == 0) { + std::string path_str(opt->Get("Last/Audio")->GetString()); + Decode(path_str); + path.replace(0, 6, path_str); + return; + } + + if (path.find("^VIDEO") == 0) { + std::string path_str(opt->Get("Last/Video")->GetString()); + Decode(path_str); + path.replace(0, 6, path_str); + return; + } + + if (path.find("^SUBTITLE") == 0) { + std::string path_str(opt->Get("Last/Subtitle")->GetString()); + Decode(path_str); + path.replace(0, 5, path_str); + return; + } + + throw PathErrorInvalid("Invalid cookie used"); + + } catch (OptionErrorNotFound& e) { + throw PathErrorInternal("Failed to find key in Decode"); + } +} + +void Path::Encode(std::string &path) { +} + + } // namespace agi diff --git a/aegisub/libaegisub/include/libaegisub/path.h b/aegisub/libaegisub/include/libaegisub/path.h index a22a4d981..c484b76b0 100644 --- a/aegisub/libaegisub/include/libaegisub/path.h +++ b/aegisub/libaegisub/include/libaegisub/path.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010, Amar Takhar +// Copyright (c) 2010-2011, Amar Takhar // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -21,14 +21,22 @@ #ifndef AGI_PRE #endif +#include #include namespace agi { +DEFINE_BASE_EXCEPTION_NOINNER(PathError, Exception) +DEFINE_SIMPLE_EXCEPTION_NOINNER(PathErrorNotFound, PathError, "path/not_found") +DEFINE_SIMPLE_EXCEPTION_NOINNER(PathErrorInvalid, PathError, "path/invalid") +DEFINE_SIMPLE_EXCEPTION_NOINNER(PathErrorInternal, PathError, "path") + /// @class Path // Internal representation of all paths in aegisub. class Path { public: + // For unit testing. + friend class PathTest; /// Constructor Path(const std::string &file, const std::string& default_path); @@ -36,6 +44,37 @@ public: /// Destructor ~Path(); + /// @brief Get a path, this is automatically decoded. + /// @param name Path to get + /// @return Full path name in UTF-8 + const std::string Get(const char *name); + + /// @brief Set a path, this will be automaticalled encoded if a cookie matches. + /// @param[in] name Path name to save to. + void Set(const char *name, const std::string &path); + + /// @brief Set a list of paths + /// @param name Path name. + /// @param out[out] Map to load list into + void ListGet(const char *name, std::vector &out); + + /// @brief Set a list of paths. + /// @param name Path name. + /// @param list List to set. + void ListSet(const char *name, std::vector list); + + /// @brief Get the default 'open' directory when no alternative is available. + /// @return Directory + /// This returns several different values based on OS: + /// Windows: Documents folder + /// OS X: ~/Documents + /// Unix: ~ or Documents folder if set in the environment + const std::string Default(); + + /// @brief Decode a path + /// @param path Decode a path in-place. + const void Decode(std::string &path); + private: /// Location of path config file. const std::string path_file; @@ -43,14 +82,30 @@ private: /// Internal default config. const std::string path_default; + /// @brief Encode a path. + /// @param path Encode a path in-place. + /// ^CONFIG - Configuration directory (not changable) + /// ^USER - Users home directory + /// ^DATA - Aegisub data files + /// ^VIDEO - Last opened video directory + /// ^SUBTITLE - Last opened subtitle directory + /// ^AUDIO - Last opened audio directory + void Encode(std::string &path); + /// Options object. Options *opt; - const char *Data(); ///< Shared resources - const char *Doc(); ///< Documents - const char *User(); ///< User config directory - const char *Locale(); ///< Locale files - const char *Temp(); ///< Temporary storage + /// @brief Locale files + /// @return Locale location + /// This is directly assessibly as the Locale directory will never change on any platform. + const std::string Locale(); + +protected: + const std::string Data(); ///< Shared resources + const std::string Config(); ///< Configuration directory + const std::string Doc(); ///< Documents + const std::string User(); ///< User config directory + const std::string Temp(); ///< Temporary storage }; } // namespace agi diff --git a/aegisub/libaegisub/unix/path.cpp b/aegisub/libaegisub/unix/path.cpp index 4820340de..69d38317d 100644 --- a/aegisub/libaegisub/unix/path.cpp +++ b/aegisub/libaegisub/unix/path.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2010, Amar Takhar +// Copyright (c) 2010-2011, Amar Takhar // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -18,46 +18,37 @@ /// @brief Common paths. /// @ingroup libaegisub -#include "acconf.h" +#include "../commit/acconf.h" +#include #include namespace agi { -const char *Path::Data() { - std::string tmp; - tmp.assign(INSTALL_PREFIX); - tmp.append("-"); - tmp.append(AEGISUB_VERSION_DATA); - return tmp.c_str(); +const std::string Path::Data() { + return DIR_DATA; } -const char *Path::Doc() { - std::string tmp; - tmp.assign(INSTALL_PREFIX); - tmp.append("-"); - tmp.append(AEGISUB_VERSION_DATA); - return tmp.c_str(); +const std::string Path::Doc() { + return DIR_DOC; } -const char *Path::User() { - std::string tmp; - tmp.assign("~/.aegisub-"); - tmp.append(AEGISUB_VERSION_DATA); - return tmp.c_str(); +const std::string Path::User() { + return "~/"; } -const char *Path::Locale() { - std::string tmp; - tmp.assign("~/.aegisub-"); - tmp.append(AEGISUB_VERSION_DATA); - return tmp.c_str(); +const std::string Path::Locale() { + std::string tmp("~/.aegisub-"); + return tmp.append(AEGISUB_VERSION_DATA); } +const std::string Path::Config() { + std::string tmp("~/.aegisub-"); + return tmp.append(AEGISUB_VERSION_DATA); +} -const char *Path::Temp() { - const char *tmp = "/tmp"; - return tmp; +const std::string Path::Temp() { + return "/tmp/"; } } // namespace agi