Reset to the platform-specific default option values rather than the global defaults

Originally committed to SVN as r6692.
This commit is contained in:
Thomas Goyne 2012-04-11 04:10:56 +00:00
parent 4cafedb14e
commit bdafd8f201
3 changed files with 31 additions and 63 deletions

View file

@ -122,7 +122,7 @@ void Options::LoadConfig(std::istream& stream, bool ignore_errors) {
LOG_E("option/load") << "json::Exception: " << e.what(); LOG_E("option/load") << "json::Exception: " << e.what();
} }
ConfigVisitor config_visitor(values, "", ignore_errors); ConfigVisitor config_visitor(values, "", ignore_errors, !ignore_errors);
config_root.Accept(config_visitor); config_root.Accept(config_visitor);
} }

View file

@ -26,19 +26,20 @@
#ifndef LAGI_PRE #ifndef LAGI_PRE
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include <memory>
#endif #endif
#include <libaegisub/colour.h> #include <libaegisub/colour.h>
#include <libaegisub/log.h> #include <libaegisub/log.h>
#include <libaegisub/option_value.h> #include <libaegisub/option_value.h>
#include <libaegisub/scoped_ptr.h>
namespace agi { namespace agi {
ConfigVisitor::ConfigVisitor(OptionValueMap &val, const std::string &member_name, bool ignore_errors) ConfigVisitor::ConfigVisitor(OptionValueMap &val, const std::string &member_name, bool ignore_errors, bool replace)
: values(val) : values(val)
, name(member_name) , name(member_name)
, ignore_errors(ignore_errors) , ignore_errors(ignore_errors)
, replace(replace)
{ {
} }
@ -57,13 +58,13 @@ void ConfigVisitor::Visit(const json::Object& object) {
name += "/"; name += "/";
for (; index != index_end; ++index) { for (; index != index_end; ++index) {
ConfigVisitor config_visitor(values, name + index->first, ignore_errors); ConfigVisitor config_visitor(values, name + index->first, ignore_errors, replace);
index->second.Accept(config_visitor); index->second.Accept(config_visitor);
} }
} }
template<class OptionValueType, class ValueType> template<class OptionValueType, class ValueType>
OptionValue *ConfigVisitor::ReadArray(json::Array const& src, std::string const& array_type, void (OptionValueType::*set_list)(const std::vector<ValueType>&)) { OptionValue *ConfigVisitor::ReadArray(json::Array const& src, std::string const& array_type, void (OptionValueType::*)(const std::vector<ValueType>&)) {
std::vector<ValueType> arr; std::vector<ValueType> arr;
arr.reserve(src.size()); arr.reserve(src.size());
@ -82,9 +83,7 @@ OptionValue *ConfigVisitor::ReadArray(json::Array const& src, std::string const&
arr.push_back(obj.begin()->second); arr.push_back(obj.begin()->second);
} }
OptionValueType *ret = new OptionValueType(name); return new OptionValueType(name, arr);
(ret->*set_list)(arr);
return ret;
} }
void ConfigVisitor::Visit(const json::Array& array) { void ConfigVisitor::Visit(const json::Array& array) {
@ -145,57 +144,18 @@ void ConfigVisitor::AddOptionValue(OptionValue* opt) {
return; return;
} }
if (!values.count(name)) { if (!values.count(name))
values[name] = opt;
else if (replace) {
delete values[name];
values[name] = opt; values[name] = opt;
return;
} }
else {
try {
// Ensure than opt is deleted at the end of this function even if the Set // Ensure than opt is deleted at the end of this function even if the Set
// method throws // method throws
std::auto_ptr<OptionValue> auto_opt(opt); agi::scoped_ptr<OptionValue> auto_opt(opt);
values[name]->Set(opt);
try {
switch (opt->GetType()) {
case OptionValue::Type_String:
values[name]->SetString(opt->GetString());
break;
case OptionValue::Type_Int:
values[name]->SetInt(opt->GetInt());
break;
case OptionValue::Type_Double:
values[name]->SetDouble(opt->GetDouble());
break;
case OptionValue::Type_Colour:
values[name]->SetColour(opt->GetColour());
break;
case OptionValue::Type_Bool:
values[name]->SetBool(opt->GetBool());
break;
case OptionValue::Type_List_String:
values[name]->SetListString(opt->GetListString());
break;
case OptionValue::Type_List_Int:
values[name]->SetListInt(opt->GetListInt());
break;
case OptionValue::Type_List_Double:
values[name]->SetListDouble(opt->GetListDouble());
break;
case OptionValue::Type_List_Colour:
values[name]->SetListColour(opt->GetListColour());
break;
case OptionValue::Type_List_Bool:
values[name]->SetListBool(opt->GetListBool());
break;
}
} }
catch (agi::OptionValueError const& e) { catch (agi::OptionValueError const& e) {
if (ignore_errors) if (ignore_errors)
@ -204,4 +164,5 @@ void ConfigVisitor::AddOptionValue(OptionValue* opt) {
throw; throw;
} }
} }
}
} // namespace agi } // namespace agi

View file

@ -35,9 +35,16 @@ DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueSingle, OptionJsonValueError, "op
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueNull, OptionJsonValueError, "options/value") DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueNull, OptionJsonValueError, "options/value")
class ConfigVisitor : public json::ConstVisitor { class ConfigVisitor : public json::ConstVisitor {
/// Option map being populated
OptionValueMap &values; OptionValueMap &values;
/// Option name prefix to add to read names
std::string name; std::string name;
/// Log errors rather than throwing them, for when loading user config files
/// (as a bad user config file shouldn't make the program fail to start)
bool ignore_errors; bool ignore_errors;
/// Replace existing options rather than changing their value, so that the
/// default value is changed to the new one
bool replace;
template<class ErrorType> template<class ErrorType>
void Error(const char *message); void Error(const char *message);
@ -47,7 +54,7 @@ class ConfigVisitor : public json::ConstVisitor {
void AddOptionValue(OptionValue* opt); void AddOptionValue(OptionValue* opt);
public: public:
ConfigVisitor(OptionValueMap &val, const std::string &member_name, bool ignore_errors = false); ConfigVisitor(OptionValueMap &val, const std::string &member_name, bool ignore_errors = false, bool replace = false);
void Visit(const json::Array& array); void Visit(const json::Array& array);
void Visit(const json::Object& object); void Visit(const json::Object& object);