class Roby::GUI::LogDisplay

Main UI for log display

It includes

Attributes

available_displays[R]

Registered plan displays

It is a mapping from the displayed name (shown to the users) to the name of the underlying class

btn_create_display[R]

The Qt::PushButton object that allows to create new displays

displays[R]

The set of displays that have been created so far

It is managed as a mapping from the view class name to an array of views. The array can contain nil elements. This is used to restore configurations across software restarts (i.e. the index is used as an ID for the widget)

history_widget[R]

The history widget

lbl_info[R]

The label widget that is used to display information/warning messages

menu_displays[R]

The menu button to create new displays

plan_rebuilder[R]

The PlanRebuilder object that gets the data

Public Class Methods

from_file(filename, plan_rebuilder = nil) click to toggle source

Creates a new display that will display the information present in filename

plan_rebuilder, if given, will be used to rebuild a complete data structure based on the information in filename

# File lib/roby/gui/log_display.rb, line 194
def self.from_file(filename, plan_rebuilder = nil)
    view = new(plan_rebuilder)
    view.open(filename)
    view
end
new(parent = nil, plan_rebuilder = nil) click to toggle source
Calls superclass method
# File lib/roby/gui/log_display.rb, line 42
def initialize(parent = nil, plan_rebuilder = nil)
    super

    plan_rebuilder ||= DRoby::PlanRebuilder.new
    @plan_rebuilder = plan_rebuilder

    @displays = Hash.new { |h, k| h[k] = Array.new }

    @btn_create_display = Qt::PushButton.new("New Display", self)
    @lbl_info = Qt::Label.new(self)
    @history_widget = PlanRebuilderWidget.new(self, plan_rebuilder)
    @layout = Qt::VBoxLayout.new(self)
    @layout.add_widget(@btn_create_display)
    @layout.add_widget(@lbl_info)
    @layout.add_widget(@history_widget)

    Qt::Object.connect(history_widget, SIGNAL('sourceChanged()'),
                       self, SLOT('updateWindowTitle()'))
    Qt::Object.connect(history_widget, SIGNAL('info(QString)'),
                       self, SLOT('info(QString)'))
    Qt::Object.connect(history_widget, SIGNAL('warn(QString)'),
                       self, SLOT('warn(QString)'))

    btn_create_display.text = "New Display"
    @menu_displays = Qt::Menu.new(@btn_create_display)
    self.class.available_displays.each do |name, klass_name|
        action = menu_displays.addAction(name)
        action.setData(Qt::Variant.new(klass_name))
    end
    btn_create_display.setMenu(menu_displays)
    menu_displays.connect(SIGNAL('triggered(QAction*)')) do |action|
        create_display(action.data.toString)
    end

    resize(300, 500)
end

Public Instance Methods

allocate_id(klass_name) click to toggle source
# File lib/roby/gui/log_display.rb, line 90
def allocate_id(klass_name)
    displays[klass_name].size
end
apply_options(options) click to toggle source
# File lib/roby/gui/log_display.rb, line 241
def apply_options(options)
    (options['plugins'] || Array.new).each do |plugin_name|
        begin
            Roby.app.using plugin_name
        rescue ArgumentError => e
            Roby.warn "the display configuration file mentions the #{plugin_name} plugin, but it is not available on this system. Some information might not be displayed"
        end
    end

    filters = options['plan_rebuilder'] || Hash.new
    apply_widget_state(options['main'] || Hash.new, self)
    (options['views'] || Array.new).each do |view_options|
        id = view_options['id']
        klass_name = view_options["class"]
        if w = display_from_id(klass_name, id)
            if w.class.name != klass_name
                next
            end
        else
            if !(w = create_display(klass_name, id))
                next
            end
        end
        apply_widget_state(view_options, w)
        if w.respond_to?(:apply_options)
            w.apply_options(view_options)
        end
    end
end
apply_widget_state(options, widget) click to toggle source
# File lib/roby/gui/log_display.rb, line 235
def apply_widget_state(options, widget)
    if geom = options['geometry']
        widget.set_geometry(*geom)
    end
end
connect(client, options = Hash.new) click to toggle source

Displays the data incoming from client

client is assumed to be a {DRoby::Logfile::Client} instance

update_period is, in seconds, the period at which the display will check whether there is new data on the port.

# File lib/roby/gui/log_display.rb, line 185
def connect(client, options = Hash.new)
    history_widget.connect(client, options)
end
connect_display(history_widget, view) click to toggle source
# File lib/roby/gui/log_display.rb, line 142
def connect_display(history_widget, view)
    if history_widget.start_time && history_widget.current_time
        view.update_time_range(history_widget.start_time, history_widget.current_time)
        view.update_display_time(history_widget.display_time)
    end
    Qt::Object.connect(history_widget, SIGNAL('appliedSnapshot(QDateTime)'),
                       view, SLOT('setDisplayTime(QDateTime)'))
    Qt::Object.connect(history_widget, SIGNAL('liveUpdate(QDateTime)'),
                       view, SLOT('setCurrentTime(QDateTime)'))
    Qt::Object.connect(history_widget, SIGNAL('sourceChanged()'),
                       view, SLOT('updateWindowTitle()'))
end
create_all_displays() click to toggle source
# File lib/roby/gui/log_display.rb, line 84
def create_all_displays
    self.class.available_displays.each do |user_name, klass_name|
        create_display(klass_name)
    end
end
create_display(name, id = nil) click to toggle source
# File lib/roby/gui/log_display.rb, line 98
def create_display(name, id = nil)
    # Check whether +klass_name+ is not a user-visible string
    self.class.available_displays.each do |user_name, klass_name|
        if user_name.downcase == name.downcase
            name = klass_name
            break
        end
    end

    id ||= allocate_id(name)
    if displays[name][id]
        raise ArgumentError, "there is already a view of type #{name} with ID #{id}"
    end

    klass = begin constant(name)
            rescue NameError => e
                Roby.warn "cannot create display of class #{name}: #{e}"
                return
            end

    log_display = self
    view = klass.new(@history_widget)
    view.singleton_class.class_eval do
        define_method :closeEvent do |event|
            log_display.remove_display(name, id)
            event.accept
        end
    end
    if view.respond_to?(:live=)
        view.live = false
    end
    connect_display(history_widget, view)
    view.setAttribute(Qt::WA_QuitOnClose, false)

    view.show
    displays[name][id] = view
end
disconnect_display(history_widget, view) click to toggle source
# File lib/roby/gui/log_display.rb, line 155
def disconnect_display(history_widget, view)
    Qt::Object.disconnect(history_widget, SIGNAL('appliedSnapshot(QDateTime)'),
                       view, SLOT('setDisplayTime(QDateTime)'))
    Qt::Object.disconnect(history_widget, SIGNAL('liveUpdate(QDateTime)'),
                       view, SLOT('setCurrentTime(QDateTime)'))
    Qt::Object.disconnect(history_widget, SIGNAL('sourceChanged()'),
                       view, SLOT('updateWindowTitle()'))
end
display_from_id(klass_name, id) click to toggle source
# File lib/roby/gui/log_display.rb, line 94
def display_from_id(klass_name, id)
    displays[klass_name][id]
end
info(message) click to toggle source
# File lib/roby/gui/log_display.rb, line 164
def info(message)
    lbl_info.text = message
end
load_options(path) click to toggle source
# File lib/roby/gui/log_display.rb, line 200
def load_options(path)
    if new_options = YAML.load(File.read(path))
        apply_options(new_options)
    end
end
open(filename) click to toggle source

Opens filename and reads the data from there

# File lib/roby/gui/log_display.rb, line 175
def open(filename)
    history_widget.open(filename)
end
remove_display(name, id) click to toggle source
# File lib/roby/gui/log_display.rb, line 136
def remove_display(name, id)
    view = displays[name][id]
    displays[name][id] = nil
    disconnect_display(history_widget, view)
end
save_options() click to toggle source
# File lib/roby/gui/log_display.rb, line 206
def save_options
    options = Hash.new
    options['main'] = Hash.new
    options['plugins'] = Roby.app.plugins.map(&:first)
    save_widget_state(options['main'], self)
    options['views'] = Array.new
    displays.each do |klass_name, views|
        views.each_with_index do |view, id|
            next if !view
            view_options = Hash.new
            view_options["class"] = view.class.name
            view_options['id'] = id
            save_widget_state(view_options, view)

            if view.respond_to?(:save_options)
                view_options.merge!(view.save_options)
            end
            options['views'] << view_options
        end
    end
    options
end
save_widget_state(options, widget) click to toggle source
# File lib/roby/gui/log_display.rb, line 229
def save_widget_state(options, widget)
    options['geometry'] =
        [widget.geometry.x, widget.geometry.y,
            widget.geometry.width, widget.geometry.height]
end
updateWindowTitle() click to toggle source
# File lib/roby/gui/log_display.rb, line 79
def updateWindowTitle
    self.window_title = history_widget.window_title
end
warn(message) click to toggle source
# File lib/roby/gui/log_display.rb, line 169
def warn(message)
    lbl_info.setText("<font color=\"red\">#{message}</font>")
end