class Ui::InstanciateComposition

Widget that allows to instanciate a composition step by step

Attributes

engine[R]
main[R]
model[R]

The model

parent_engine[R]
parent_window[R]
plan[R]
robot[R]
selection[R]

The disambiguation selection

system_model[R]

Public Class Methods

format_selection(actual_selection) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 76
def self.format_selection(actual_selection)
    list = []
    actual_selection.explicit.each do |from, to|
        from = selection_to_string(from, true)
        to   = selection_to_string(to, false)
        list << "#{from} => #{to}"
    end
    actual_selection.defaults.each do |obj|
        list << selection_to_string(obj, false)
    end

    "use(#{list.join(",\n  ")})"
end
new(system_model, robot, main = nil, parent_engine = nil) click to toggle source
Calls superclass method
# File lib/orocos/roby/gui/instanciate_composition.rb, line 19
def initialize(system_model, robot, main = nil, parent_engine = nil)
    super(main)
    @selection = Orocos::RobyPlugin::DependencyInjection.new

    Qt::Object.connect(self, SIGNAL('selectedObject(QVariant&,QPoint&)'),
                       self, SLOT('selectedTask(QVariant&,QPoint&)'))

    @parent_window = main
    @system_model = system_model
    @parent_engine = parent_engine || Roby.app.orocos_engine
    @robot = robot
    @plan   = Roby::Plan.new
    @engine = Orocos::RobyPlugin::Engine.new(plan, system_model, robot)
end
selection_to_string(selection, array_is_path) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 47
def self.selection_to_string(selection, array_is_path)
    case selection
    when Orocos::RobyPlugin::ProvidedDataService
        "#{selection.model.short_name}.#{selection.full_name}"
    when Orocos::RobyPlugin::DeviceInstance
        selection.name
    when Class
        if selection.respond_to?(:short_name)
            selection.short_name
        else
            selection.name
        end
    when String
        "\"#{selection}\""
    when NilClass
        'nil'
    when Array
        if array_is_path
            "\"#{selection.join(".")}\""
        else
            "[#{selection.map { |s| selection_to_string(s) }.join(", ")}]"
        end
    when Orocos::RobyPlugin::InstanceRequirements
        to_ruby(selection.base_models.first, selection.selections, nil)
    else
        raise NotImplementedError, "cannot convert #{selection.class} to a Ruby syntax"
    end
end
to_ruby(model, actual_selection, name) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 99
def self.to_ruby(model, actual_selection, name)
    if name
        options = ", :as => #{name}"
    end
    result = ["add(#{model.short_name}#{options})"]
    result << "  " + format_selection(actual_selection)
    result.join(".\n")
end
to_ruby_define(model, actual_selection, name) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 90
def self.to_ruby_define(model, actual_selection, name)
    if !name
        raise ArgumentError, "definitions must have a name"
    end
    result = ["define('#{name}', #{model.short_name})"]
    result << "  " + format_selection(actual_selection)
    result.join(".\n")
end

Public Instance Methods

actual_selection() click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 38
def actual_selection
    self.selection.dup
end
compute() click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 116
def compute
    engine.clear
    plan.clear

    if model
        begin
            Orocos::RobyPlugin::Composition.strict_specialization_selection = false
            @main = engine.add_mission(model).use(selection)

            parent_engine.deployments.each do |host, names|
                names.each do |n|
                    @engine.use_deployment(n, :on => host)
                end
            end

            engine.prepare
            engine.instanciate
            plan.static_garbage_collect
        ensure
            Orocos::RobyPlugin::Composition.strict_specialization_selection = true
        end
    end
end
disable_updates() click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 140
def disable_updates; @updates_disabled = true end
display_svg(filename) click to toggle source
Calls superclass method
# File lib/orocos/roby/gui/instanciate_composition.rb, line 281
def display_svg(filename)
    items = super
    items.find_all { |it| it.respond_to?(:task) }.
        each do |item|
            item.extend ComposerSvgItem
        end
    items
end
enable_updates() click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 141
def enable_updates; @updates_disabled = false end
model=(model) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 110
def model=(model)
    @model = model
    selection.clear
    update
end
root_task() click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 34
def root_task
    main.task
end
selectedTask(_task, click_pos) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 222
def selectedTask(_task, click_pos)
    task = _task.value
    models =
        if task.respond_to?(:proxied_data_services)
            task.proxied_data_services
        else [task.model]
        end

    system_candidates, device_candidates = selection_candidates_for(models)

    roles = root_task.role_paths(task)
    current_selection = roles.find_all do |role_name|
        selection.explicit[role_name]
    end

    menu = Qt::Menu.new

    device_candidates = device_candidates.to_a.sort_by(&:first)
    system_candidates = system_candidates.to_a.sort_by(&:first)
    if device_candidates.empty? && system_candidates.empty? && current_selection.empty?
        action = menu.add_action('No available selection')
        action.enabled = false
    end

    deselection = Hash.new
    current_selection.each do |role_name|
        text = "Don't use for #{role_name}"
        deselection[text] = role_name
        menu.add_action(text)
    end

    selection = Hash.new
    if !device_candidates.empty?
        menu.add_separator.text = "Devices"
        device_candidates.each do |name, m|
            selection[name] = m
            menu.add_action(name)
        end
    end
    if !system_candidates.empty?
        menu.add_separator.text = "Models"
        system_candidates.each do |name, m|
            selection[name] = m
            menu.add_action(name)
        end
    end
    return unless action = menu.exec(click_pos)

    if selected_model = selection[action.text]
        role = roles.min_by(&:size)
        self.selection.explicit[role] = selected_model
    elsif deselected_role = deselection[action.text]
        self.selection.explicit.delete(deselected_role)
    end

    update
end
selection_candidates_for(models) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 163
def selection_candidates_for(models)
    # Get the task's role. We can safely assume the task
    # has only one parent and is used for only one role
    # in this parent
    device_candidates = Hash.new
    robot.devices.values.find_all do |dev|
        dev.service.fullfills?(models)
    end.each do |dev|
        device_candidates[dev.name] = dev
    end

    if models.empty?
        return Hash.new, device_candidates
    end

    candidates = models.map do |m|
        engine.service_allocation_candidates[m] || ValueSet.new
    end.map(&:to_value_set).inject(&:&)

    # We now have to take care about ambiguity ... I.e.
    # either use faceted selection or explicit service
    # selection when needed
    system_candidates = Hash.new
    candidates.each do |model|
        disambiguation = []
        models.each do |expected_model|
            available_services =
                model.find_all_services_from_type(expected_model)
            if available_services.size == 1
                next
            else
                disambiguation << available_services
            end
        end

        # If there are multiple candidates, check if they have all a
        # different model. In this case, use the .as() mechanism.
        # Otherwise, we have to use the service name
        if disambiguation.size > 1
            raise NotImplementedError
        end
        disambiguation = disambiguation.first
        if !disambiguation
            system_candidates[model.short_name] = model
        elsif disambiguation.map(&:model).to_value_set == disambiguation.size
            disambiguation.each do |service|
                system_candidates["#{model.short_name}.as(#{service.model.short_name})"] = service
            end
        else
            disambiguation.each do |service|
                system_candidates[service.short_name] = service
            end

        end
    end

    return system_candidates, device_candidates
end
to_ruby(actual_selection = nil, name = nil) click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 42
def to_ruby(actual_selection = nil, name = nil)
    InstanciateComposition.to_ruby(
        model, actual_selection || self.actual_selection, name)
end
update() click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 145
def update
    return if updates_disabled?

    begin
        compute
        update_view
    rescue Exception => e
        display_error("Failed to deploy the required system network", e)
    end
    emit updated()
end
update_view() click to toggle source
Calls superclass method
# File lib/orocos/roby/gui/instanciate_composition.rb, line 157
def update_view
    super(plan, engine)
end
updates_disabled?() click to toggle source
# File lib/orocos/roby/gui/instanciate_composition.rb, line 142
def updates_disabled?; !!@updates_disabled end