11#define PDEBUG(...)     Ase::debug ("prefs", __VA_ARGS__) 
   18  value (this, 
"value"),
 
   19  metadata (this, 
"metadata")
 
   26Property::get_name ()
 const 
   32Property::set_name (
const String &n)
 
   38Property::set_metadata (
const StringS &md)
 
   44PropertyImpl::PropertyImpl (
const Param ¶m, 
const PropertyGetter &getter,
 
   45                            const PropertySetter &setter, 
const PropertyLister &lister) :
 
   46  getter_ (getter), setter_ (setter), lister_ (lister)
 
   52using PrefsValueCallbackList = CallbackList<CString,const Value&>;
 
   61static CStringS notify_preference_queue;
 
   70static bool preferences_autosave = 
false;
 
   71static uint timerid_maybe_save_preferences = 0;
 
   74maybe_save_preferences()
 
   76  main_loop->clear_source (&timerid_maybe_save_preferences);
 
   77  if (preferences_autosave && notify_preference_queue.
empty())
 
   78    Preference::save_preferences();
 
   82notify_preference_listeners ()
 
   84  CStringS changed_prefs (notify_preference_queue.
begin(), notify_preference_queue.
end()); 
 
   85  notify_preference_queue.
clear(); 
 
   87  std::sort (changed_prefs.begin(), changed_prefs.end()); 
 
   88  changed_prefs.erase (
std::unique (changed_prefs.begin(), changed_prefs.end()), changed_prefs.end());
 
   90  PrefsMap &prefsmap = prefs_map();
 
   91  for (
auto cident : changed_prefs) {
 
   92    PrefsValue &pv = prefsmap[cident];
 
   93    (*pv.callbacks) (cident, pv.value);
 
   96  const auto callbacklist = prefs_callbacks; 
 
   97  (*callbacklist) (changed_prefs);
 
   98  if (preferences_autosave)
 
   99    main_loop->exec_once (577, &timerid_maybe_save_preferences, maybe_save_preferences);
 
  101    main_loop->clear_source (&timerid_maybe_save_preferences);
 
  105queue_notify_preference_listeners (
const CString &cident)
 
  109  const bool need_enqueue = notify_preference_queue.
empty();
 
  110  notify_preference_queue.
push_back (cident);
 
  112    main_loop->exec_now (notify_preference_listeners);
 
  115Preference::Preference (ParameterC parameter)
 
  117  parameter_ = parameter;
 
  118  PrefsMap &prefsmap = prefs_map(); 
 
  119  auto it = prefsmap.find (parameter_->cident);
 
  121  PrefsValue &pv = it->second;
 
  122  sigh_ = pv.callbacks->add_delcb ([
this] (
const String &ident, 
const Value &value) { emit_event (
"notify", ident); });
 
  125Preference::Preference (
const Param ¶m, 
const StringValueF &cb)
 
  129  PrefsMap &prefsmap = prefs_map();
 
  130  PrefsValue &pv = prefsmap[parameter_->cident];
 
  132  pv.parameter = parameter_;
 
  133  pv.value = pv.parameter->initial();
 
  134  pv.callbacks = PrefsValueCallbackList::make_shared();
 
  135  sigh_ = pv.callbacks->add_delcb ([
this] (
const String &ident, 
const Value &value) { emit_event (
"notify", ident); });
 
  136  queue_notify_preference_listeners (parameter_->cident);
 
  138    Connection connection = on_event (
"notify", [
this,cb] (
const Event &event) { cb (this->parameter_->cident, this->get_value()); });
 
  139    connection_ = 
new Connection (connection);
 
  143Preference::~Preference()
 
  146    connection_->disconnect();
 
  148    connection_ = 
nullptr;
 
  155Preference::get_value ()
 const 
  158  PrefsValue &pv = prefsmap[parameter_->cident];
 
 
  163Preference::set_value (
const Value &v)
 
  166  PrefsValue &pv = prefsmap[parameter_->cident];
 
  167  Value next = parameter_->constrain (v);
 
  168  const bool changed = next == pv.value;
 
  169  pv.value = std::move (next);
 
  170  queue_notify_preference_listeners (parameter_->cident); 
 
  171  this->value.notify();
 
 
  176Preference::get (
const String &ident)
 
  178  const CString cident = CString::lookup (ident);
 
  181  auto it = prefsmap.find (cident);
 
  188Preference::find (
const String &ident)
 
  190  const CString cident = CString::lookup (ident);
 
  192  PrefsMap &prefsmap = prefs_map();
 
  193  auto it = prefsmap.find (cident);
 
  195  PrefsValue &pv = it->second;
 
  196  return Preference::make_shared (pv.parameter);
 
  203  for (
const auto &e : prefs_map())
 
  204    strings.push_back (e.first);
 
  205  std::sort (strings.begin(), strings.end());
 
  210Preference::listen (
const std::function<
void(
const CStringS&)> &func)
 
  212  return prefs_callbacks->add_delcb (func);
 
  218  static const String anklangrc = Path::join (Path::config_home(), 
"anklang", 
"anklangrc.json");
 
  223Preference::load_preferences (
bool autosave)
 
  225  const String jsontext = Path::stringread (pathname_anklangrc());
 
  228  for (ValueField vf : precord) {
 
  229    PreferenceP pref = 
find (vf.name);
 
  230    PDEBUG (
"%s: %s %s=%s\n", __func__, pref ? 
"loading" : 
"ignoring", vf.name, vf.value->repr());
 
  232      pref->set_value (*vf.value);
 
  234  preferences_autosave = autosave;
 
  238Preference::save_preferences ()
 
  241  for (
auto ident : list())
 
  242    precord[ident] = get (ident);
 
  243  const String new_jsontext = 
json_stringify (precord, Writ::RELAXED | Writ::SKIP_EMPTYSTRING) + 
"\n";
 
  244  const String cur_jsontext = Path::stringread (pathname_anklangrc());
 
  245  if (new_jsontext != cur_jsontext) {
 
  246    PDEBUG (
"%s: %s\n", __func__, precord.repr());
 
  247    Path::stringwrite (pathname_anklangrc(), new_jsontext, 
true);
 
Compact, deduplicating string variant for constant strings.
 
Reentrant callback list with configurable arguments.
 
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
 
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
 
The Anklang C++ API namespace.
 
bool json_parse(const String &jsonstring, T &target)
Parse a well formed JSON string and assign contents to target.
 
std::string String
Convenience alias for std::string.
 
uint32_t uint
Provide 'uint' as convenience type.
 
String json_stringify(const T &source, Writ::Flags flags=Writ::Flags(0))
Create JSON string from source.
 
Value type used to interface with various property types.