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,63 +144,25 @@ 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 {
// Ensure than opt is deleted at the end of this function even if the Set try {
// method throws // Ensure than opt is deleted at the end of this function even if the Set
std::auto_ptr<OptionValue> auto_opt(opt); // method throws
agi::scoped_ptr<OptionValue> auto_opt(opt);
try { values[name]->Set(opt);
switch (opt->GetType()) { }
case OptionValue::Type_String: catch (agi::OptionValueError const& e) {
values[name]->SetString(opt->GetString()); if (ignore_errors)
break; LOG_E("option/load/config_visitor") << "Error loading option from user configuration: " << e.GetChainedMessage();
else
case OptionValue::Type_Int: throw;
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) {
if (ignore_errors)
LOG_E("option/load/config_visitor") << "Error loading option from user configuration: " << e.GetChainedMessage();
else
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);