2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined( INCLUDED_PREFERENCEDICTIONARY_H )
23 #define INCLUDED_PREFERENCEDICTIONARY_H
25 #include "preferencesystem.h"
27 #include "stream/stringstream.h"
28 #include "generic/callback.h"
29 #include "versionlib.h"
32 class PreferenceDictionary : public PreferenceSystem {
33 class PreferenceEntry {
34 Property<const char *> m_cb;
36 PreferenceEntry(const Property<const char *> &cb)
41 void importString(const char *string)
46 void exportString(const Callback<void(const char *)> &importer)
52 typedef std::map<CopiedString, PreferenceEntry> PreferenceEntries;
53 PreferenceEntries m_preferences;
55 typedef std::map<CopiedString, CopiedString> PreferenceCache;
56 PreferenceCache m_cache;
59 typedef PreferenceEntries::iterator iterator;
63 return m_preferences.begin();
68 return m_preferences.end();
71 iterator find(const char *name)
73 return m_preferences.find(name);
76 void registerPreference(const char *name, const Property<const char *> &cb)
78 m_preferences.insert(PreferenceEntries::value_type(name, PreferenceEntry(cb)));
79 PreferenceCache::iterator i = m_cache.find(name);
80 if (i != m_cache.end()) {
81 cb.set(i->second.c_str());
86 void importPref(const char *name, const char *value)
88 PreferenceEntries::iterator i = m_preferences.find(name);
89 if (i != m_preferences.end()) {
90 (*i).second.importString(value);
93 m_cache.insert(PreferenceCache::value_type(name, value));
98 inline void XMLPreference_importString(XMLImporter &importer, const char *value)
100 importer.write(value, string_length(value));
103 typedef ReferenceCaller<XMLImporter, void(const char *), XMLPreference_importString> XMLPreferenceImportStringCaller;
105 class XMLPreferenceDictionaryExporter : public XMLExporter {
106 class XMLQPrefElement : public XMLElement {
107 const char *m_version;
109 XMLQPrefElement(const char *version) : m_version(version)
113 const char *name() const
118 const char *attribute(const char *name) const
120 if (string_equal(name, "version")) {
126 void forEachAttribute(XMLAttrVisitor &visitor) const
128 visitor.visit("version", m_version);
132 class XMLPreferenceElement : public XMLElement {
135 XMLPreferenceElement(const char *name)
140 const char *name() const
145 const char *attribute(const char *name) const
147 if (string_equal(name, "name")) {
153 void forEachAttribute(XMLAttrVisitor &visitor) const
155 visitor.visit("name", m_name);
159 typedef PreferenceDictionary PreferenceEntries;
160 PreferenceEntries &m_preferences;
161 const char *m_version;
163 XMLPreferenceDictionaryExporter(PreferenceDictionary &preferences, const char *version)
164 : m_preferences(preferences), m_version(version)
168 void exportXML(XMLImporter &importer)
170 importer.write("\n", 1);
172 XMLQPrefElement qpref_element(m_version);
173 importer.pushElement(qpref_element);
174 importer.write("\n", 1);
176 for (PreferenceEntries::iterator i = m_preferences.begin(); i != m_preferences.end(); ++i) {
177 XMLPreferenceElement epair_element((*i).first.c_str());
179 importer.pushElement(epair_element);
181 (*i).second.exportString(XMLPreferenceImportStringCaller(importer));
183 importer.popElement(epair_element.name());
184 importer.write("\n", 1);
187 importer.popElement(qpref_element.name());
188 importer.write("\n", 1);
192 class XMLPreferenceDictionaryImporter : public XMLImporter {
201 xml_state_t(ETag tag)
208 StringOutputStream m_ostream;
211 typedef std::vector<xml_state_t> xml_stack_t;
212 xml_stack_t m_xml_stack;
214 typedef PreferenceDictionary PreferenceEntries;
215 PreferenceEntries &m_preferences;
218 XMLPreferenceDictionaryImporter(PreferenceDictionary &preferences, const char *version)
219 : m_preferences(preferences), m_version(version_parse(version))
223 void pushElement(const XMLElement &element)
225 if (m_xml_stack.empty()) {
226 if (string_equal(element.name(), "qpref")) {
227 Version dataVersion(version_parse(element.attribute("version")));
228 if (!version_compatible(m_version, dataVersion)) {
229 globalOutputStream() << "qpref import: data version " << dataVersion
230 << " is not compatible with code version " << m_version << "\n";
231 m_xml_stack.push_back(xml_state_t::tag_qpref_ignore);
233 globalOutputStream() << "qpref import: data version " << dataVersion
234 << " is compatible with code version " << m_version << "\n";
235 m_xml_stack.push_back(xml_state_t::tag_qpref);
241 switch (m_xml_stack.back().m_tag) {
242 case xml_state_t::tag_qpref:
243 if (string_equal(element.name(), "epair")) {
244 m_xml_stack.push_back(xml_state_t::tag_epair);
245 m_xml_stack.back().m_name = element.attribute("name");
250 case xml_state_t::tag_qpref_ignore:
251 if (string_equal(element.name(), "epair")) {
252 m_xml_stack.push_back(xml_state_t::tag_epair_ignore);
257 case xml_state_t::tag_epair:
258 case xml_state_t::tag_epair_ignore:
266 void popElement(const char *name)
268 if (m_xml_stack.back().m_tag == xml_state_t::tag_epair) {
269 m_preferences.importPref(m_xml_stack.back().m_name.c_str(), m_xml_stack.back().m_ostream.c_str());
271 m_xml_stack.pop_back();
274 std::size_t write(const char *buffer, std::size_t length)
276 return m_xml_stack.back().m_ostream.write(buffer, length);