diff --git a/src/lay/laySaltGrain.cc b/src/lay/laySaltGrain.cc index feac7ab16..de0eccf6a 100644 --- a/src/lay/laySaltGrain.cc +++ b/src/lay/laySaltGrain.cc @@ -141,6 +141,12 @@ static tl::XMLStruct xml_struct ("salt-grain", ) ); +bool +SaltGrain::is_readonly () const +{ + return QFileInfo (tl::to_qstring (path ())).isWritable (); +} + void SaltGrain::load (const std::string &p) { diff --git a/src/lay/laySaltGrain.h b/src/lay/laySaltGrain.h index 644521750..b86a0e0e7 100644 --- a/src/lay/laySaltGrain.h +++ b/src/lay/laySaltGrain.h @@ -212,6 +212,11 @@ public: m_dependencies.push_back (dep); } + /** + * @brief Returns true, if the collection is read-only + */ + bool is_readonly () const; + /** * @brief Loads the data from a given file * This method will *not* set the path. diff --git a/src/lay/laySaltGrains.cc b/src/lay/laySaltGrains.cc index b44c7c05d..1d8306176 100644 --- a/src/lay/laySaltGrains.cc +++ b/src/lay/laySaltGrains.cc @@ -22,6 +22,7 @@ #include "laySaltGrains.h" #include "tlString.h" +#include "tlFileUtils.h" #include #include @@ -68,16 +69,21 @@ SaltGrains::add_collection (const SaltGrains &collection) m_collections.push_back (collection); } -void -SaltGrains::remove_collection (collection_iterator iter) +bool +SaltGrains::remove_collection (collection_iterator iter, bool with_files) { // NOTE: this is kind of inefficient, but in order to maintain the const iterator semantics this approach is required for (collections_type::iterator i = m_collections.begin (); i != m_collections.end (); ++i) { if (i == iter) { + if (with_files && !tl::rm_dir_recursive (tl::to_qstring (path ()))) { + return false; + } m_collections.erase (i); - break; + return true; } } + + return false; } void @@ -86,16 +92,21 @@ SaltGrains::add_grain (const SaltGrain &grain) m_grains.push_back (grain); } -void -SaltGrains::remove_grain (grain_iterator iter) +bool +SaltGrains::remove_grain (grain_iterator iter, bool with_files) { // NOTE: this is kind of inefficient, but in order to maintain the const iterator semantics this approach is required for (grains_type::iterator i = m_grains.begin (); i != m_grains.end (); ++i) { if (i == iter) { + if (with_files && !tl::rm_dir_recursive (tl::to_qstring (path ()))) { + return false; + } m_grains.erase (i); - break; + return true; } } + + return false; } bool @@ -104,6 +115,12 @@ SaltGrains::is_empty () const return m_collections.empty () && m_grains.empty (); } +bool +SaltGrains::is_readonly () const +{ + return QFileInfo (tl::to_qstring (path ())).isWritable (); +} + SaltGrains SaltGrains::from_path (const std::string &path, const std::string &prefix) { diff --git a/src/lay/laySaltGrains.h b/src/lay/laySaltGrains.h index a2ff4ea98..f47b897fb 100644 --- a/src/lay/laySaltGrains.h +++ b/src/lay/laySaltGrains.h @@ -130,8 +130,10 @@ public: /** * @brief Removes the collection given by the collection iterator + * If "with_files" is true, also the folder and all sub-folders will be removed + * @return true, if the remove was successful. */ - void remove_collection (collection_iterator iter); + bool remove_collection (collection_iterator iter, bool with_files = false); /** * @brief Gets the grains (leaf nodes) which are members of this collection (begin iterator) @@ -156,14 +158,21 @@ public: /** * @brief Removes the grain given by the grain iterator + * If "with_files" is true, also the files and the folder will be removed. + * @return true, if the remove was successful. */ - void remove_grain (grain_iterator iter); + bool remove_grain (grain_iterator iter, bool with_files = false); /** * @brief Gets a value indicating whether the collection is empty */ bool is_empty () const; + /** + * @brief Returns true, if the collection is read-only + */ + bool is_readonly () const; + /** * @brief Scan grains from a given path * This will scan the grains found within this path and return a collection containing diff --git a/src/tl/tl.pro b/src/tl/tl.pro index 95f8f9870..39a9e5713 100644 --- a/src/tl/tl.pro +++ b/src/tl/tl.pro @@ -39,7 +39,8 @@ SOURCES = \ tlVariant.cc \ tlXMLParser.cc \ tlXMLWriter.cc \ - tlFileSystemWatcher.cc + tlFileSystemWatcher.cc \ + tlFileUtils.cc HEADERS = \ tlAlgorithm.h \ @@ -81,7 +82,8 @@ HEADERS = \ tlXMLParser.h \ tlXMLWriter.h \ tlFileSystemWatcher.h \ - tlCommon.h + tlCommon.h \ + tlFileUtils.h INCLUDEPATH = DEPENDPATH = diff --git a/src/tl/tlFileUtils.cc b/src/tl/tlFileUtils.cc new file mode 100644 index 000000000..518bb7989 --- /dev/null +++ b/src/tl/tlFileUtils.cc @@ -0,0 +1,54 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "tlFileUtils.h" + +#include +#include + +namespace tl +{ + +bool +rm_dir_recursive (const QString &path) +{ + QDir dir (path); + QStringList entries = dir.entryList (QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); + for (QStringList::const_iterator e = entries.begin (); e != entries.end (); ++e) { + QFileInfo fi (dir.absoluteFilePath (*e)); + if (fi.isDir ()) { + if (! rm_dir_recursive (fi.filePath ())) { + return false; + } + if (! dir.rmdir (*e)) { + return false; + } + } else if (fi.isFile ()) { + if (! dir.remove (*e)) { + return false; + } + } + } + return true; +} + +} diff --git a/src/tl/tlFileUtils.h b/src/tl/tlFileUtils.h new file mode 100644 index 000000000..01c171a99 --- /dev/null +++ b/src/tl/tlFileUtils.h @@ -0,0 +1,40 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_tlFileUtils +#define HDR_tlFileUtils + +#include "tlCommon.h" +#include + +namespace tl +{ + +/** + * @brief Recursively remove the given directory, the files from that directory and all sub-directories + * @return True, if successful. False otherwise. + */ +bool TL_PUBLIC rm_dir_recursive (const QString &path); + +} + +#endif diff --git a/src/unit_tests/laySaltGrain.cc b/src/unit_tests/laySaltGrain.cc index 581eda8f5..fabfab2fd 100644 --- a/src/unit_tests/laySaltGrain.cc +++ b/src/unit_tests/laySaltGrain.cc @@ -23,6 +23,7 @@ #include "laySaltGrain.h" #include "laySaltGrains.h" +#include "tlFileUtils.h" #include "utHead.h" #include @@ -134,28 +135,6 @@ static std::string grains_to_string (const lay::SaltGrains &gg) return res; } -static bool empty_dir (const QString &path) -{ - QDir dir (path); - QStringList entries = dir.entryList (QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); - for (QStringList::const_iterator e = entries.begin (); e != entries.end (); ++e) { - QFileInfo fi (dir.absoluteFilePath (*e)); - if (fi.isDir ()) { - if (! empty_dir (fi.filePath ())) { - return false; - } - if (! dir.rmdir (*e)) { - return false; - } - } else if (fi.isFile ()) { - if (! dir.remove (*e)) { - return false; - } - } - } - return true; -} - TEST (3) { const QString grain_spec_file = QString::fromUtf8 ("grain.xml"); @@ -171,7 +150,7 @@ TEST (3) QDir dir_cc (dir_c.filePath (QString::fromUtf8 ("c"))); QDir dir_ccv (dir_cc.filePath (QString::fromUtf8 ("v"))); - tl_assert (empty_dir (tmp_dir.path ())); + tl_assert (tl::rm_dir_recursive (tmp_dir.path ())); lay::SaltGrains gg; gg = lay::SaltGrains::from_path (tl::to_string (tmp_dir.path ()));