diff --git a/CMakeLists.txt b/CMakeLists.txt index ea4059c4..39c0e789 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(PIP) set(PIP_MAJOR 3) -set(PIP_MINOR 9) -set(PIP_REVISION 1) +set(PIP_MINOR 10) +set(PIP_REVISION 0) set(PIP_SUFFIX ) set(PIP_COMPANY SHS) set(PIP_DOMAIN org.SHS) diff --git a/libs/main/io_devices/pidir.cpp b/libs/main/io_devices/pidir.cpp index d950dec1..066c14a8 100644 --- a/libs/main/io_devices/pidir.cpp +++ b/libs/main/io_devices/pidir.cpp @@ -184,6 +184,16 @@ PIString PIDir::relative(const PIString & path) const { } +PIString PIDir::absolute(const PIString & path) const { + PIFile::FileInfo fi(path); + if (fi.isAbsolute()) return path; + PIString ret = absolutePath(); + if (!ret.endsWith(separator) && !path.startsWith(separator)) ret += separator; + PIDir td(ret + path); + return td.cleanPath().path(); +} + + PIDir & PIDir::setDir(const PIString & path) { path_ = path; #ifdef WINDOWS @@ -547,3 +557,30 @@ bool PIDir::renameDir(const PIString & path, const PIString & new_name) { printf("[PIDir] renameDir(\"%s\", \"%s\") error: %s\n", path.data(), new_name.data(), errorString().data()); return false; } + + +PIDir::CurrentDirOverrider::CurrentDirOverrider(const PIString & path) { + save(PIFile::fileInfo(path)); +} + + +PIDir::CurrentDirOverrider::CurrentDirOverrider(const PIFile::FileInfo & info) { + save(info); +} + + +void PIDir::CurrentDirOverrider::restore() { + if (!active) return; + active = false; + PIDir::setCurrent(prev_cd); +} + + +void PIDir::CurrentDirOverrider::save(const PIFile::FileInfo & info) { + prev_cd = PIDir::current().path(); + PIString p = info.isDir() ? info.path : info.dir(); + if (info.isAbsolute()) + PIDir::setCurrent(p); + else + PIDir::setCurrent(PIDir::current().path() + PIDir::separator + p); +} diff --git a/libs/main/io_devices/pidir.h b/libs/main/io_devices/pidir.h index 88e58b99..5391c8c0 100644 --- a/libs/main/io_devices/pidir.h +++ b/libs/main/io_devices/pidir.h @@ -85,6 +85,10 @@ public: //! \~russian Возвращает путь "path" относительно этой директории PIString relative(const PIString & path) const; + //! \~english Returns relative to this directory path "path" as absolute path + //! \~russian Возвращает путь "path" относительно этой директории в виде абсолютного пути + PIString absolute(const PIString & path) const; + //! \~english Set this directory path to simplified "path" //! \~russian Устанавливает путь директории упрощённым "path" PIDir & setDir(const PIString & path); @@ -173,6 +177,34 @@ public: //! \~russian Устанавливает путь директории "dir" текущим путём приложения static bool setCurrent(const PIDir & dir) { return setCurrent(dir.path()); } + + //! \ingroup IO + //! \~\brief + //! \~english Temporarily change working directory. + //! \~russian Временная смена рабочей директории. + class PIP_EXPORT CurrentDirOverrider { + public: + //! \~english Change working directory dir or file with relative or absolute path "path" + //! \~russian Меняет рабочую директорию на другую директорию или файл с относительным или абсолютным путём "path" + CurrentDirOverrider(const PIString & path); + + //! \~english Change working directory to dir or file "info" + //! \~russian Меняет рабочую директорию на директорию или файл "info" + CurrentDirOverrider(const PIFile::FileInfo & info); + + ~CurrentDirOverrider() { restore(); } + + //! \~english Restore previous working directory + //! \~russian Восстанавливает предыдущую рабочую директорию + void restore(); + + private: + void save(const PIFile::FileInfo & info); + PIString prev_cd; + bool active = true; + }; + + private: static bool makeDir(const PIString & path); static bool removeDir(const PIString & path); @@ -195,6 +227,7 @@ inline bool operator!=(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) return (v0.path != v1.path); } + //! \relatesalso PICout //! \~english Output operator to \a PICout //! \~russian Оператор вывода в \a PICout