Module: Ruber::SettingsContainer

Included in:
AbstractProject, ConfigManager
Defined in:
lib/ruber/settings_container.rb

Overview

TODO:

Change all names referring to “option” to use the word “setting” instead

TODO:

Replace instance variables used by classes mixing-in this (for example, @dialog_class)

Module which allows including classes to store and retrieve settings and provides an interface (but not the implentation, which is a backend’s job) to write the settings to a file. It’s a part of the <a href=“../file.settings_framework.html”>Ruber Settings Framework</a>

Settings are divided into groups, and each settings has a name, so any of them can be accessed using the @[group, name]@ pair. Each group can contain multiple settings, obviously all with different names (of course, you can have settings with the same name in different groups).

To read or write a setting, you must first add it, using the #add_setting method. This method takes what we call a _settings object_, that is an object describing a setting. Among other things, a setting object provides information about the name of the setting, the group it belongs to and the default value, that is the value to use for the setting if the user hasn’t changed it.

The user can change the value of the settings added to a container using the dialog returned by the #dialog method. This dialog is a sublcass of @KDE::PageDialog@, to which plugins can add the widgets needed to change their settings (see #add_widget). The dialog is only created when the #dialog method is called and is destroyed every time a widget is added or removed to it.

This module knows nothing about the way the data is stored to file, so it needs a backend to do the reading/writing. Refer to “the ruber settings framework documentation”:../file.settings_framework.html#backends for the interface a backend class must provide.

Notes:

  • classes mixing-in this module must call #setup_container before using the

functionality it provides. Usually, this can be done from the class’s @initialize@ method

  • the values of the options in the backend aren’t updated when they are changed

using the []= method, but only when the #write method is called.

  • if you want to store a value of a custom class in a settings file, make sure

you require the file the class is defined in before creating the instance of @SettingsContainer@ associated with the configuration file (not before accessing it). This is because some backends (for example the YAML backend) create all the objects stored in it on creation

h3. Instance variables

There are some instance variables which classes mixing-in this module may set to tune the behaviour of the module. They are:

  • @@base_dir@: this variable can be set to a path to use as base for settings

representing a relative path. For example, if this variable is set to @/home/myhome/@, a setting with value @/home/myhome/somefile@ will be stored simply as @somefile@

  • @@dialog_class@: the class to instantiate to create the dialog. It must be a

subclass of SettingsDialog. If this variable isn’t set, SettingsDialog will be used.

with method calls which may be overridden

Defined Under Namespace

Classes: Proxy

Instance Method Summary collapse

Instance Method Details

#[](group) ⇒ SettingsContainer::Proxy #[](group, name) ⇒ Object #[](group, name, mode) ⇒ Object

Returns the value of a setting been added, except in the case of one argument, where the Proxy object is always returned

Overloads:

  • #[](group) ⇒ SettingsContainer::Proxy

    Returns a Proxy object associated with a group

    Parameters:

    • group (Symbol)

      the name of the group

    Returns:

  • #[](group, name) ⇒ Object

    value is returned

    Parameters:

    • group (Symbol)

      the group the setting belongs to

    • name (Symbol)

      the name of the setting

    Returns:

    • (Object)

      the value of the setting. If it has never been set, the default

  • #[](group, name, mode) ⇒ Object

    or a @Pathname@, it is considered as a path relative to the base directory. The absolute path, obtained by joining the base directory with the value of the setting is then returned value is returned

    Parameters:

    • group (Symbol)

      the group the setting belongs to

    • name (Symbol)

      the name of the setting

    • mode (Symbol)

      if either @:abs@ or @absolute@, and if the setting is a @string@

    Returns:

    • (Object)

      the value of the setting. If it has never been set, the default

Raises:

  • IndexError if an option corresponding to the given group and name hasn’t



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/ruber/settings_container.rb', line 283

def [](*args)
  group, name, path_opt = args
  return Proxy.new self, group unless name
  res = @options.fetch([group, name]) do
    raise IndexError, "An option called #{name} belonging to group #{group} doesn't exist"
  end
  if @base_directory and (path_opt == :abs or path_opt == :absolute)
# The call to File.expand_path is used to avoid returning names as /base/dir/.
# if the value of the options were .
    if res.is_a? String
      res = File.expand_path(File.join(@base_directory, res))
    elsif res.is_a? Pathname
      res = (Pathname.new(@base_directory) + res).cleanpath
    end
  end
  res
end

#[]=(group, name, value) ⇒ Object

Changes the value of a setting

If the new value is a string containing an absolute path, the corresponding setting object has a @relative_path@ method which returns true and the base directory is not nil, the string will be trasformed into a path relative to the base directory before being stored.

to the object

Parameters:

  • group (Symbol)

    the group the setting belongs to

  • name (Symbol)

    the name of the setting

  • value (Object)

    the new value of the setting

Returns:

Raises:

  • (IndexError)

    if a setting with the given name and group haven’t been added



316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/ruber/settings_container.rb', line 316

def []=(group, name, value)
  full_name = [group, name]
  opt = @known_options.fetch(full_name) do
    raise IndexError, "No option called #{name} and belonging to group #{group} exists"
  end
  if value.is_a? String and (opt.relative_path rescue false) and @base_directory
    path = Pathname.new value
    dir = Pathname.new @base_directory
    value = path.relative_path_from( dir).to_s rescue value
  end
  @options[full_name] = value
end

#add_setting(opt) ⇒ nil Also known as: add_option

Adds a setting to the container

Note: this method also deletes the configuration dialog, so a new one will be created the next time it’s needed

following methods:

  • @name@: takes no arguments and returns a symbol corresponding to the name of the setting

  • @group@: takes no arguments and returns a symbol corresponding to the group the setting belongs to

  • @default@: takes one argument of class @Binding@ and returns the default value

to use for the setting

If the object also has a @relative_path@ method and that method returns true, then the setting will be treated a a path relative to the base directory already exists

Parameters:

  • the (Object)

    settings object describing the setting to add. It must have the three

Returns:

  • (nil)

Raises:

  • ArgumentError if an option with the same name nad belonging to the same group



208
209
210
211
212
213
214
215
216
217
# File 'lib/ruber/settings_container.rb', line 208

def add_setting opt
  full_name = [opt.group, opt.name]
  if @known_options[full_name]
    raise ArgumentError, "An option with name #{opt.name} belonging to group #{opt.group} already exists"
  end
  @known_options[full_name] = opt
  @options[full_name] = @backend[opt]
  delete_dialog
  nil
end

#add_widget(w) ⇒ nil

Instructs the container to add a widget to the associated dialog

The widget won’t be immediately added to the dialog. This method only gives the container information about the widget to insert in the dialog. The widget itself will only be created and inserted in the dialog when it will first be shown.

This method resets the dialog.

below

Parameters:

  • w (Object)

    the object describing the widget. It must have the methods documented

Options Hash (w):

  • caption (String)

    the name of the page the widget should be put into. If the page doesn’t exist in the dialog, it will be added. Otherwise, the widget will be added to the one already existing in the page

  • class_obj (Class) — default: nil

    the class of the widget to create. The class’s @initialize@ method must take no parameters. Either this method or the @code@ method must not be nil

  • code (String) — default: nil

    a piece of ruby code which, when executed in the @TOPLEVEL_BINDING@, will return the widget to add to the dialog. Either this method or the @class_obje@ method must not be nil. If both are not nil, this method will have the precedence

  • pixmap (String) — default: ''

    the path of the pixmap to associate to the page

Returns:

  • (nil)

See Also:



383
384
385
386
387
# File 'lib/ruber/settings_container.rb', line 383

def add_widget w
  @widgets << w
  delete_dialog
  nil
end

#default(group, name) ⇒ Object

The default value for a given setting

the value returned by the @relative_path@ method of the setting object (if it exists)

Parameters:

  • group (Sybmol)

    the group the setting belongs to

  • the (String)

    name of the setting

Returns:

  • (Object)

    the default value for the setting, without taking into account

Raises:

  • @IndexError@ if a setting with the given name and group hasn’t been added



339
340
341
342
343
344
# File 'lib/ruber/settings_container.rb', line 339

def default group, name
  opt = @known_options.fetch([group, name]) do
    raise IndexError, "No option called #{name} and belonging to group #{group} exists"
  end
  opt.default
end

#dialogQt::Dialog

The dialog associated with the container

If a dialog has already been created, it will be returned. Otherwise, another dialog will be created and filled with the widgets added to the container

The dialog will be an instance of the class stored in the @@dialog_class@ instance variable.

Returns:

  • (Qt::Dialog)

    the dialog associated with the container.

See Also:



415
416
417
# File 'lib/ruber/settings_container.rb', line 415

def dialog
  @dialog ||= @dialog_class.new self, @known_options.values, @widgets, @dialog_title
end

#has_setting?(group, name) ⇒ Boolean Also known as: has_option?

Whether a given setting has been added to the container

Parameters:

  • group (Symbol)

    the name the setting belongs to

  • name (Symbol)

    the name of the setting

Returns:

  • (Boolean)

    true if the setting had already been added and false otherwise



251
252
253
# File 'lib/ruber/settings_container.rb', line 251

def has_setting? group, name
  !@known_options[[group, name]].nil?
end

#relative_path?(group, name) ⇒ Boolean

Whether a setting should be considered a relative path or not

name has a @relative_path@ method and it returns true and false otherwise

Parameters:

  • group (Sybmol)

    the group the setting belongs to

  • the (String)

    name of the setting

Returns:

  • (Boolean)

    true if the settings object corresponding to group and



354
355
356
# File 'lib/ruber/settings_container.rb', line 354

def relative_path? group, name
  @known_options[[group, name]].relative_path.to_bool rescue false
end

#remove_setting(group, name) ⇒ nil #remove_setting(obj) ⇒ nil Also known as: remove_option

Removes a setting

Note: this method also deletes the configuration dialog, so a new one will be created the next time it’s needed

Overloads:

  • #remove_setting(group, name) ⇒ nil

    Parameters:

    • group (Symbol)

      the group the setting belongs to

    • name (Symbol)

      the name of the setting to remove

    Returns:

    • (nil)
  • #remove_setting(obj) ⇒ nil

    Parameters:

    Returns:

    • (nil)


235
236
237
238
239
240
241
242
# File 'lib/ruber/settings_container.rb', line 235

def remove_setting *args
  group, name = if args.size == 1 then [args[0].group, args[0].name]
  else args
  end
  @known_options.delete [group, name]
  @options.delete [group, name]
  delete_dialog
end

#remove_widget(w) ⇒ nil

Removes a widget from the dialog

If the dialog doesn’t contain the widget, nothing is done. Otherwise, the dialog will be deleted

Parameters:

  • w (Qt::Widget)

    the widget to remove

Returns:

  • (nil)


398
399
400
401
# File 'lib/ruber/settings_container.rb', line 398

def remove_widget w
  deleted = @widgets.delete w
  delete_dialog if deleted
end

#writenil

Writes the settings to file

If you need to modify the content of an option before writing (for example because it contains a value which can only be read if a specific plugin has been loaded), override this method and change the value of the option, then return the hash.

Returns:

  • (nil)


428
429
430
431
# File 'lib/ruber/settings_container.rb', line 428

def write
  @backend.write collect_options
  nil
end