1 #ifndef WS_WORKSPACE_DEF_H_INCLUDED
2 #define WS_WORKSPACE_DEF_H_INCLUDED
28 #include <boost/property_tree/xml_parser.hpp>
39 template <
class ProjectType, const std::
string& index_file>
41 const std::string& prefs_file)
43 m_path((path.length() > 0 && path.rfind(
'/') == path.length() - 1) ? path.substr(0, path.length()-1) : path),
44 m_prefs_file(prefs_file),
45 m_filesystem_watcher((m_path ==
"") ? index_file : m_path +
'/' + index_file, bind(&
Workspace<ProjectType, index_file>::Refresh, this))
47 const string workspace_file = (
m_path ==
"") ? index_file :
m_path +
'/' + index_file;
51 read_xml(workspace_file, p, trim_whitespace);
52 }
catch (xml_parser_error& e) {
53 throw Exception(
"Could not open \"" + workspace_file +
"\": Exception xml_parser_error: " + e.what());
58 }
catch (ptree_bad_path &) {
63 auto& projects = p.get_child(
"workspace.projects");
65 for (
auto& value : projects) {
66 auto& project_type = value.first;
67 auto& project_name = value.second.data();
68 auto project_path =
m_path +
'/' + project_name;
69 auto project = ProjectType::Constructor(project_type, project_path,
75 throw Exception(
"Could not create project of type \"" + project_type +
"\".");
79 }
catch (ptree_bad_path& e) {
80 throw Exception(
"File \"" + workspace_file +
"\": Exception ptree_bad_path: " + e.what());
84 template <
class ProjectType, const std::
string& index_file>
87 m_path(move(other.m_path)),
88 m_projects(move(other.m_projects)),
89 m_filesystem_watcher(move(other.m_filesystem_watcher))
93 template <
class ProjectType, const std::
string& index_file>
99 template <
class ProjectType, const std::
string& index_file>
105 template <
class ProjectType, const std::
string& index_file>
108 auto result_optional = m_user_data.get_child_optional(user);
109 if (result_optional) {
110 return result_optional.get();
112 auto& result = m_user_data.put_child(user, ptree());
117 template <
class ProjectType, const std::
string& index_file>
120 m_user_data.put_child(user, p);
124 template <
class ProjectType, const std::
string& index_file>
125 IWorkspace::ProjectIterator
128 return m_projects.begin();
131 template <
class ProjectType, const std::
string& index_file>
132 IWorkspace::ConstProjectIterator
135 return m_projects.begin();
138 template <
class ProjectType, const std::
string& index_file>
139 IWorkspace::ProjectIterator
142 return m_projects.end();
145 template <
class ProjectType, const std::
string& index_file>
146 IWorkspace::ConstProjectIterator
149 return m_projects.end();
152 template <
class ProjectType, const std::
string& index_file>
155 return begin()->second.Project();
158 template <
class ProjectType, const std::
string& index_file>
161 return begin()->second.Project();
164 template <
class ProjectType, const std::
string& index_file>
167 return (--end())->second.Project();
170 template <
class ProjectType, const std::
string& index_file>
173 return (--end())->second.Project();
176 template <
class ProjectType, const std::
string& index_file>
177 IWorkspace::ProjectIterator
180 return m_projects.find(name);
183 template <
class ProjectType, const std::
string& index_file>
184 IWorkspace::ConstProjectIterator
187 return m_projects.find(name);
191 template <
class ProjectType, const std::
string& index_file>
195 return m_projects.find(name) != end();
198 template <
class ProjectType, const std::
string& index_file>
201 auto it = m_projects.find(name);
202 if (it == m_projects.end())
203 throw Exception(
"No such project \"" + name +
"\" in workspace.");
204 return it->second.Project();
207 template <
class ProjectType, const std::
string& index_file>
210 auto it = m_projects.find(name);
211 if (it == m_projects.end())
212 throw Exception(
"No such project \"" + name +
"\" in workspace.");
213 return it->second.Project();
216 template <
class ProjectType, const std::
string& index_file>
217 IWorkspace::ProjectIterator
220 if (m_projects.find(name) != m_projects.end()) {
221 throw Exception(
"Cannot create project \"" + name
222 +
"\": Another project with the same name already exists.");
226 QDir d(QString::fromStdString(m_path));
227 if (!d.mkdir(QString::fromStdString(name))) {
231 return Add(type, name);
234 template <
class ProjectType, const std::
string& index_file>
235 IWorkspace::ProjectIterator
238 auto it = m_projects.find(project_name);
239 if (it != m_projects.end()) {
242 string project_path = m_path +
'/' + project_name;
243 auto result = m_projects.end();
244 auto project = ProjectType::Constructor(project_type, project_path,
245 m_prefs_file, shared_ptr<IWorkspace>(
this, [](
IWorkspace*){}));
247 result = m_projects.insert({project_name,
ProjectMapEntry(project, project_type)}).first;
249 throw Exception(
"Could not create project of type \"" + project_type +
"\".");
254 {Event::WorkspaceChanged::ProjectAdded, project_name});
258 template <
class ProjectType, const std::
string& index_file>
264 const string workspace_file = (m_path ==
"") ? index_file : m_path +
'/' + index_file;
268 read_xml(workspace_file, p, trim_whitespace);
269 }
catch (xml_parser_error& e) {
270 throw Exception(
"Could not open \"" + workspace_file +
"\": Exception xml_parser_error: " + e.what());
274 auto& projects = p.get_child(
"workspace.projects");
277 vector<string> to_delete(m_projects.size());
278 for (
auto& value : m_projects) {
280 for (
auto& compare : projects) {
281 if (compare.second.data() == value.first) {
287 to_delete.push_back(value.first);
290 for (
auto& filename : to_delete) {
291 m_projects.erase(filename);
296 for (
auto& value : projects) {
297 const string project_type = value.first;
298 const string project_name = value.second.data();
299 const string project_path = m_path +
'/' + project_name;
302 auto existing_project_it = m_projects.find(project_name);
303 if (existing_project_it == m_projects.end()) {
305 auto project = ProjectType::Constructor(project_type, project_path,
306 m_prefs_file, shared_ptr<IWorkspace>(
this, [](
IWorkspace*){}));
308 m_projects.insert({project_name,
ProjectMapEntry(project, project_type)});
311 throw Exception(
"Could not create project of type \"" + project_type +
"\".");
315 existing_project_it->second->Refresh();
318 }
catch (ptree_bad_path& e) {
319 throw Exception(
"File \"" + workspace_file +
"\": Exception ptree_bad_path: " + e.what());
323 template <
class ProjectType, const std::
string& index_file>
324 IWorkspace::ProjectIterator
327 auto it = m_projects.find(old_name);
328 if (it == m_projects.end())
329 throw Exception(
"No such project \"" + old_name +
"\".");
330 return Rename(it, new_name);
333 template <
class ProjectType, const std::
string& index_file>
334 IWorkspace::ProjectIterator
338 const string old_name = it->first;
339 const string new_path = m_path +
'/' + new_name;
341 if (!dir.rename(QString::fromStdString(it->second->GetPath()), QString::fromStdString(new_path))) {
342 throw Exception(
"Could not move directory \"" + it->second->GetPath() +
"\" to \"" + new_path +
"\".");
344 auto project_type = it->second.Type();
345 m_projects.erase(it);
346 ProjectMap::value_type v(new_name,
ProjectMapEntry((ProjectType::Constructor)(project_type,
347 new_path, m_prefs_file, shared_ptr<IWorkspace>(
this, [](
IWorkspace *){})), project_type));
348 auto result = m_projects.insert(v);
354 template <
class ProjectType, const std::
string& index_file>
357 auto it = m_projects.find(name);
358 if (it == m_projects.end())
359 throw Exception(
"No such project \"" + name +
"\".");
363 template <
class ProjectType, const std::
string& index_file>
367 string name = it->first;
369 QString dirname(QString::fromStdString(m_path +
'/' + it->first));
377 it->second.Project()->SetWatchingDirectory(
false);
381 function<bool(QString&)>
remove;
382 remove = [&
remove](
const QString& dirname)->
bool {
385 if (d.exists(dirname)) {
386 for (QFileInfo info : d.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) {
388 QString dirname = info.absoluteFilePath();
389 result =
remove(dirname);
392 result = QFile::remove(info.absoluteFilePath());
398 result = d.rmdir(dirname);
402 if (!
remove(dirname))
403 throw Exception(
"Could not remove directory \"" + m_path +
'/' + it->first +
"\".");
404 m_projects.erase(it);
409 template <
class ProjectType, const std::
string& index_file>
413 pt_workspace.put(
"workspace.projects",
"");
414 for (
auto& project : *
this) {
415 pt_workspace.add(
"workspace.projects.project", project.first);
417 pt_workspace.put_child(
"workspace.user_data", m_user_data);
418 write_xml(m_path +
'/' + index_file, pt_workspace, std::locale(), XmlWriterSettings::GetTab());
424 #endif // end_of_inclde_guard
virtual ProjectIterator begin()
Implementation of IPreferences.
virtual bool IsProject(const std::string &name) const
ProjectMap m_projects
Mapping from project name to project.
Namespace for miscellaneous utilities.
virtual std::shared_ptr< IProject > Get(const std::string &name)
Workspace(const std::string &path, const std::string &prefs_file)
Constructor.
std::string m_path
Path workspace was initialized with.
virtual ProjectIterator Rename(ProjectIterator, const std::string &new_name)
boost::property_tree::ptree m_user_data
GetUserData() with non-existing argument creates an empty user data.
Interface for workspace-like behavior.
Extremely simple Exception root class.
std::string m_prefs_file
Name of preferences file.
virtual std::shared_ptr< IProject > Back()
virtual const boost::property_tree::ptree & GetUserData(const std::string &user) const
virtual void Remove(ProjectIterator)
virtual void SetUserData(const std::string &user, const boost::property_tree::ptree &)
virtual ProjectIterator Add(const std::string &type, const std::string &name)
Abstraction of workspace on file system.
virtual const std::string & GetPath() const
virtual std::shared_ptr< IProject > Front()
Subject in Observer pattern.
virtual ProjectIterator end()
virtual const std::string & GetIndexFile() const
Header file for Exception class.
Xml writer settings class.
virtual ProjectIterator Find(const std::string &name)
Namespace for generic graphical shell for simulators.
virtual ProjectIterator New(const std::string &type, const std::string &name)