Class: Roby::GUI::ChronicleWidget
- Defined in:
- lib/roby/gui/chronicle_widget.rb
Overview
Widget to display tasks on a chronicle (i.e. timelines)
Use ChronicleView when using a PlanRebuilderWidget
The following interactions are available:
* CTRL + wheel: change time scale
* ALT + wheel: horizontal scroll
* wheel: vertical scroll
* double-click: task info view
Defined Under Namespace
Classes: TaskLayout
Constant Summary collapse
- SCALES =
[1, 2, 5, 10, 20, 30, 60, 90, 120, 300, 600, 1200, 1800, 3600].freeze
- TIMELINE_GRAY_PEN =
Qt::Pen.new(Qt::Color.new("gray"))
- TIMELINE_BLACK_PEN =
Qt::Pen.new(Qt::Color.new("black"))
Instance Attribute Summary collapse
-
#all_job_info ⇒ Object
Job information about all known tasks.
-
#all_tasks ⇒ Object
All known tasks.
-
#base_time ⇒ Object
The startup time.
-
#current_tasks ⇒ Object
readonly
The set of tasks that should currently be managed by the view.
-
#current_time ⇒ Object
The system’s current time.
-
#display_point ⇒ Object
The point (in pixels) where the current display time should be located on the display.
-
#display_time ⇒ Object
The time that is currently at the middle of the view.
-
#displayed_time_range ⇒ (Time,Time)?
readonly
The range, in absolute time, currently visible in the view.
-
#filter ⇒ Object
Inclusion filter on task names.
-
#filter_out ⇒ Object
Exclusion filter on task names.
-
#layout_cache ⇒ Hash<Task,TaskLayout>
readonly
Per-task visual layout information.
-
#live_update_margin ⇒ Object
readonly
How many pixels should there be between the ‘now’ line and the right side, in pixels.
-
#messages_per_task ⇒ Object
readonly
Per-task messages to be displayed.
-
#pixel_to_time ⇒ Object
readonly
Scale factor to convert seconds to pixels.
-
#position_to_task ⇒ Object
readonly
An ordered set of [y, task], where
yis the position in Y of the bottom of a task line andtaskthe corresponding task object. -
#reverse_sort ⇒ Object
writeonly
Whether the order defined by #sort_mode should be inverted.
-
#scheduler_state ⇒ Schedulers::State
Scheduler information.
-
#show_mode ⇒ Object
High-level filter on the list of shown tasks.
-
#sort_mode ⇒ Object
The current sorting mode.
-
#start_line ⇒ Object
The index of the task that is currently at the top of the view.
-
#task_height ⇒ Object
The base height of a task line.
-
#task_layout ⇒ Object
readonly
The task layout as computed in the last call to #paintEvent.
-
#task_separation ⇒ Object
The separation, in pixels, between tasks.
-
#time_scale ⇒ Object
Internal representation of the desired time scale.
-
#time_to_pixel ⇒ Object
readonly
Scale factor to convert seconds to pixels.
Instance Method Summary collapse
-
#add_tasks_info(tasks, job_info) ⇒ Object
Add information to the chronicle for the next display update.
- #clear ⇒ Object
- #clear_tasks_info ⇒ Object
- #contents_height ⇒ Object
- #current_tasks_dirty? ⇒ Boolean
-
#initialize(parent = nil) ⇒ ChronicleWidget
constructor
A new instance of ChronicleWidget.
- #invalidate_current_tasks ⇒ Object
-
#invalidate_layout_cache ⇒ Object
private
Clears #layout_cache because parameters changed that require to recompute the task layouts.
- #lay_out_task(fm, task) ⇒ Object
- #live=(flag) ⇒ Object
- #massage_slot_time_argument(time, default) ⇒ Object
- #mouseDoubleClickEvent(event) ⇒ Object
- #paint_tasks(painter, fm, layout, top_y) ⇒ Object
- #paint_timeline(painter, fm) ⇒ Object
- #paintEvent(event) ⇒ Object
- #remove_tasks(tasks) ⇒ Object
- #resizeEvent(event) ⇒ Object
-
#restrict_to_jobs=(set) ⇒ Object
Sets whether only the toplevel job tasks should be shown.
-
#restrict_to_jobs? ⇒ Boolean
True if only the action’s toplevel tasks are shown.
-
#reverse_sort? ⇒ Boolean
Whether the order defined by #sort_mode should be inverted.
- #setCurrentTime(time = nil) ⇒ Object
- #setDisplayTime(time = nil) ⇒ Object
- #task_timeline_title(task) ⇒ Object
- #timeline_height ⇒ Object
-
#update_base_time(time) ⇒ Object
private
Update the time at the start of the chronicle.
- #update_current_tasks(force: false) ⇒ Object
-
#update_current_time(time) ⇒ Object
private
Update the time at the end of the chronicle.
- #update_display_point ⇒ Object
-
#update_display_time(time) ⇒ Object
private
Update the currently displayed time.
- #update_displayed_time_range ⇒ Object
- #update_scroll_ranges ⇒ Object
-
#update_time_range(start_time, current_time) ⇒ Object
private
Updates the start and current time.
-
#wheelEvent(event) ⇒ Object
Event handler for wheel event.
Constructor Details
#initialize(parent = nil) ⇒ ChronicleWidget
Returns a new instance of ChronicleWidget.
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/roby/gui/chronicle_widget.rb', line 222 def initialize(parent = nil) super(parent) @layout_cache = {} = Hash.new { |h, k| h[k] = [] } @current_tasks = [] @current_tasks_dirty = true self.time_scale = 10 @task_height = 10 @task_separation = 10 @live_update_margin = 10 @start_line = 0 @all_tasks = Set.new @all_job_info = {} @scheduler_state = Schedulers::State.new @task_layout = [] @sort_mode = :start_time @reverse_sort = false @show_mode = :all @show_future_events = true @live = true @track_current_time = true = false @display_point = .size.width - live_update_margin = Qt::Widget.new pal = Qt::Palette.new(.palette) pal.setColor(Qt::Palette::Background, Qt::Color.new("white")) .setAutoFillBackground(true) .setPalette(pal) self. = .connect(SIGNAL("sliderMoved(int)")) do value = .value self.track_current_time = live? && (value == .maximum) time = base_time + Float(value) * pixel_to_time update_display_time(time) emit timeChanged(time - base_time) end .connect(SIGNAL("sliderPressed()")) do self. = true end .connect(SIGNAL("sliderReleased()")) do self.track_current_time = live? && (.value == .maximum) self. = false update_scroll_ranges end .connect(SIGNAL("valueChanged(int)")) do value = .value if value < current_tasks.size self.start_line = value update end end end |
Instance Attribute Details
#all_job_info ⇒ Object
Job information about all known tasks
97 98 99 |
# File 'lib/roby/gui/chronicle_widget.rb', line 97 def all_job_info @all_job_info end |
#all_tasks ⇒ Object
All known tasks
93 94 95 |
# File 'lib/roby/gui/chronicle_widget.rb', line 93 def all_tasks @all_tasks end |
#base_time ⇒ Object
The startup time
82 83 84 |
# File 'lib/roby/gui/chronicle_widget.rb', line 82 def base_time @base_time end |
#current_tasks ⇒ Object (readonly)
The set of tasks that should currently be managed by the view.
It is updated in #update(), i.e. when the view gets something to display
108 109 110 |
# File 'lib/roby/gui/chronicle_widget.rb', line 108 def current_tasks @current_tasks end |
#current_time ⇒ Object
The system’s current time
80 81 82 |
# File 'lib/roby/gui/chronicle_widget.rb', line 80 def current_time @current_time end |
#display_point ⇒ Object
The point (in pixels) where the current display time should be located on the display
76 77 78 |
# File 'lib/roby/gui/chronicle_widget.rb', line 76 def display_point @display_point end |
#display_time ⇒ Object
The time that is currently at the middle of the view
78 79 80 |
# File 'lib/roby/gui/chronicle_widget.rb', line 78 def display_time @display_time end |
#displayed_time_range ⇒ (Time,Time)? (readonly)
The range, in absolute time, currently visible in the view
465 466 467 |
# File 'lib/roby/gui/chronicle_widget.rb', line 465 def displayed_time_range @displayed_time_range end |
#filter ⇒ Object
Inclusion filter on task names
If it contains a regular expression, only the task names that match the expression will be displayed
195 196 197 |
# File 'lib/roby/gui/chronicle_widget.rb', line 195 def filter @filter end |
#filter_out ⇒ Object
Exclusion filter on task names
If it contains a regular expression, the task names that match the expression will not be displayed
208 209 210 |
# File 'lib/roby/gui/chronicle_widget.rb', line 208 def filter_out @filter_out end |
#layout_cache ⇒ Hash<Task,TaskLayout> (readonly)
Per-task visual layout information
158 159 160 |
# File 'lib/roby/gui/chronicle_widget.rb', line 158 def layout_cache @layout_cache end |
#live_update_margin ⇒ Object (readonly)
How many pixels should there be between the ‘now’ line and the right side, in pixels
73 74 75 |
# File 'lib/roby/gui/chronicle_widget.rb', line 73 def live_update_margin @live_update_margin end |
#messages_per_task ⇒ Object (readonly)
Per-task messages to be displayed
161 162 163 |
# File 'lib/roby/gui/chronicle_widget.rb', line 161 def end |
#pixel_to_time ⇒ Object (readonly)
Scale factor to convert seconds to pixels
pixel = time_to_pixel * time
69 70 71 |
# File 'lib/roby/gui/chronicle_widget.rb', line 69 def pixel_to_time @pixel_to_time end |
#position_to_task ⇒ Object (readonly)
An ordered set of [y, task], where y is the position in Y of the bottom of a task line and task the corresponding task object
It is updated on display
113 114 115 |
# File 'lib/roby/gui/chronicle_widget.rb', line 113 def position_to_task @position_to_task end |
#reverse_sort=(value) ⇒ Object (writeonly)
Whether the order defined by #sort_mode should be inverted
138 139 140 |
# File 'lib/roby/gui/chronicle_widget.rb', line 138 def reverse_sort=(value) @reverse_sort = value end |
#scheduler_state ⇒ Schedulers::State
Scheduler information
101 102 103 |
# File 'lib/roby/gui/chronicle_widget.rb', line 101 def scheduler_state @scheduler_state end |
#show_mode ⇒ Object
High-level filter on the list of shown tasks. Can either be :all, :running, :current. Defaults to :all
In :all mode, all tasks that are included in a plan in a certain point in time are displayed.
In :running mode, only the tasks that are running within the display time window are shown.
In :current mode, only the tasks that have emitted events within the display time window are shown
In :in_range mode, only the tasks that would display something within the display time window are shown
153 154 155 |
# File 'lib/roby/gui/chronicle_widget.rb', line 153 def show_mode @show_mode end |
#sort_mode ⇒ Object
The current sorting mode. Can be :start_time or :last_event. Defaults to :start_time
In :start mode, the tasks are sorted by the time at which they started. In :last_event, by the time of the last event emitted before the current displayed time: it shows the last active tasks first)
121 122 123 |
# File 'lib/roby/gui/chronicle_widget.rb', line 121 def sort_mode @sort_mode end |
#start_line ⇒ Object
The index of the task that is currently at the top of the view. It is an index in #current_tasks
89 90 91 |
# File 'lib/roby/gui/chronicle_widget.rb', line 89 def start_line @start_line end |
#task_height ⇒ Object
The base height of a task line
84 85 86 |
# File 'lib/roby/gui/chronicle_widget.rb', line 84 def task_height @task_height end |
#task_layout ⇒ Object (readonly)
The task layout as computed in the last call to #paintEvent
103 104 105 |
# File 'lib/roby/gui/chronicle_widget.rb', line 103 def task_layout @task_layout end |
#task_separation ⇒ Object
The separation, in pixels, between tasks
86 87 88 |
# File 'lib/roby/gui/chronicle_widget.rb', line 86 def task_separation @task_separation end |
#time_scale ⇒ Object
Internal representation of the desired time scale. Don’t use it directly, but use #time_to_pixel or #pixel_to_time
36 37 38 |
# File 'lib/roby/gui/chronicle_widget.rb', line 36 def time_scale @time_scale end |
#time_to_pixel ⇒ Object (readonly)
Scale factor to convert seconds to pixels
pixels = time_to_pixel * time
64 65 66 |
# File 'lib/roby/gui/chronicle_widget.rb', line 64 def time_to_pixel @time_to_pixel end |
Instance Method Details
#add_tasks_info(tasks, job_info) ⇒ Object
Add information to the chronicle for the next display update
345 346 347 348 349 350 351 352 353 354 |
# File 'lib/roby/gui/chronicle_widget.rb', line 345 def add_tasks_info(tasks, job_info) tasks.each do |t| if base_time && t.addition_time < base_time update_base_time(t.addition_time) end end all_tasks.merge(tasks) all_job_info.merge!(job_info) end |
#clear ⇒ Object
874 875 876 877 |
# File 'lib/roby/gui/chronicle_widget.rb', line 874 def clear all_tasks.clear all_job_info.clear end |
#clear_tasks_info ⇒ Object
313 314 315 316 317 |
# File 'lib/roby/gui/chronicle_widget.rb', line 313 def clear_tasks_info all_tasks.clear all_job_info.clear self.scheduler_state = Schedulers::State.new end |
#contents_height ⇒ Object
363 364 365 366 367 368 369 370 371 372 |
# File 'lib/roby/gui/chronicle_widget.rb', line 363 def contents_height update_current_tasks display_start, display_end = displayed_time_range fm = Qt::FontMetrics.new(font) height = current_tasks.inject(0) do |h, t| h + lay_out_task(fm, t).height(display_start, display_end) end height + current_tasks.size * task_separation + timeline_height end |
#current_tasks_dirty? ⇒ Boolean
471 472 473 |
# File 'lib/roby/gui/chronicle_widget.rb', line 471 def current_tasks_dirty? @current_tasks_dirty end |
#invalidate_current_tasks ⇒ Object
467 468 469 |
# File 'lib/roby/gui/chronicle_widget.rb', line 467 def invalidate_current_tasks @current_tasks_dirty = true end |
#invalidate_layout_cache ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Clears #layout_cache because parameters changed that require to recompute the task layouts
167 168 169 |
# File 'lib/roby/gui/chronicle_widget.rb', line 167 def invalidate_layout_cache layout_cache.clear end |
#lay_out_task(fm, task) ⇒ Object
736 737 738 739 740 741 |
# File 'lib/roby/gui/chronicle_widget.rb', line 736 def lay_out_task(fm, task) layout = layout_cache[task] ||= TaskLayout.new(task, base_time, time_to_pixel, fm) layout. = .fetch(task, []) layout.update layout end |
#live=(flag) ⇒ Object
26 27 28 29 |
# File 'lib/roby/gui/chronicle_widget.rb', line 26 def live=(flag) @live = flag self.track_current_time = live? && (value == .maximum) end |
#massage_slot_time_argument(time, default) ⇒ Object
550 551 552 553 554 555 556 557 558 559 |
# File 'lib/roby/gui/chronicle_widget.rb', line 550 def massage_slot_time_argument(time, default) # Convert from QDateTime to allow update() to be a slot if time.kind_of?(Qt::DateTime) Time.at(Float(time.toMSecsSinceEpoch) / 1000) elsif !time default else time end end |
#mouseDoubleClickEvent(event) ⇒ Object
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 |
# File 'lib/roby/gui/chronicle_widget.rb', line 879 def mouseDoubleClickEvent(event) click_y = event.pos.y layout = task_layout.find { |layout| layout.top_y < click_y && layout.top_y + layout.height > click_y } if layout unless @info_view @info_view = ObjectInfoView.new Qt::Object.connect(@info_view, SIGNAL("selectedTime(QDateTime)"), self, SIGNAL("selectedTime(QDateTime)")) end if @info_view.display(layout.task) @info_view.activate end end event.accept end |
#paint_tasks(painter, fm, layout, top_y) ⇒ Object
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 |
# File 'lib/roby/gui/chronicle_widget.rb', line 743 def paint_tasks(painter, fm, layout, top_y) current_point = Integer((current_time - base_time) * time_to_pixel) display_offset = Integer(display_point - (display_time - base_time) * time_to_pixel) display_start_time, display_end_time = displayed_time_range view_height = .size.height text_height = fm.height text_ascent = fm.ascent text_descent = fm.descent update_current_tasks current_tasks[start_line..-1]&.each do |task| break if top_y > view_height task_layout = lay_out_task(fm, task) add_point, start_point, end_point, finalization_point = task_layout.add_point, task_layout.start_point, task_layout.end_point, task_layout.finalization_point state = task_layout.state task = task_layout.task event_height = task_layout.event_height task_line_height = event_height if events = task_layout.events_in_range(display_start_time, display_end_time) task_line_height += events.max_by { |_, _, y, _| y }[2] end if task_height > task_line_height task_line_height = task_height end # Paint the pending stage, i.e. before the task started top_task_line = top_y painter.brush = TASK_BRUSHES[:pending] painter.pen = TASK_PENS[:pending] painter.drawRect( add_point + display_offset, top_task_line, (start_point || finalization_point || current_point) - add_point, task_line_height) if start_point painter.brush = TASK_BRUSHES[:running] painter.pen = TASK_PENS[:running] painter.drawRect( start_point + display_offset, top_task_line, (end_point || current_point) - start_point, task_line_height) if state && state != :running # Final state is shown by "eating" a few pixels at the task painter.brush = TASK_BRUSHES[state] painter.pen = TASK_PENS[state] painter.drawRect( end_point - 2 + display_offset, top_task_line, 4, task_height) end end # Display the emitted events event_baseline = top_task_line + event_height / 2 events&.each do |_, x, y, text| x += display_offset y += event_baseline painter.brush, painter.pen = EVENT_STYLES[EVENT_CONTROLABLE | EVENT_EMITTED] painter.drawEllipse(Qt::Point.new(x, y), EVENT_CIRCLE_RADIUS, EVENT_CIRCLE_RADIUS) painter.pen = EVENT_NAME_PEN painter.drawText(Qt::Point.new(x + 2 * EVENT_CIRCLE_RADIUS, y), text) end # Add the title painter.pen = TASK_NAME_PEN title_baseline = top_task_line + task_line_height + text_ascent task_layout.title ||= task_timeline_title(task) painter.drawText(Qt::Point.new(0, title_baseline), task_layout.title) # And finally display associated messages = title_baseline + text_height painter.pen = TASK_MESSAGE_PEN task_layout..each do |msg| += text_height painter.drawText(Qt::Point.new(TASK_MESSAGE_MARGIN, ), msg) end top_y = + text_descent end end |
#paint_timeline(painter, fm) ⇒ Object
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 |
# File 'lib/roby/gui/chronicle_widget.rb', line 583 def paint_timeline(painter, fm) text_height = fm.height window_size = .size # Display the current cycle time central_label = Roby.format_time(display_time) central_label_width = fm.width(central_label) central_time_max = display_point + central_label_width / 2 if central_time_max + 3 > window_size.width central_time_max = window_size.width - 3 end central_time_min = central_time_max - central_label_width if central_time_min < 3 central_time_min = 3 central_time_max = central_time_min + central_label_width end painter.pen = TIMELINE_GRAY_PEN painter.drawText(central_time_min, text_height, central_label) painter.drawRect(central_time_min - 2, 0, central_label_width + 4, text_height + 2) # First, decide on the scale. We compute a "normal" text width # for the time labels, and check what would be a round time-step min_step_size = pixel_to_time * 1.5 * central_label_width step_size = SCALES.find do |scale| scale > min_step_size end step_size ||= SCALES.last # Now display the timeline itself. If a normal ruler collides # with the current time, just ignore it start_time, end_time = displayed_time_range painter.pen = TIMELINE_BLACK_PEN ruler_base_time = (start_time.to_f / step_size).floor * step_size ruler_base_x = (ruler_base_time - start_time.to_f) * time_to_pixel step_count = ((end_time.to_f - ruler_base_time) / step_size).ceil step_count.times do |i| time = step_size * i + ruler_base_time pos = step_size * i * time_to_pixel + ruler_base_x time_as_text = Roby.format_time(Time.at(time)) time_as_text_width = fm.width(time_as_text) min_x = pos - time_as_text_width / 2 max_x = pos + time_as_text_width / 2 if central_time_min > max_x || central_time_max < min_x painter.drawText(min_x, text_height, time_as_text) end painter.drawLine(pos, text_height + fm.descent, pos, text_height + fm.descent + TIMELINE_RULER_LINE_LENGTH) end end |
#paintEvent(event) ⇒ Object
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 |
# File 'lib/roby/gui/chronicle_widget.rb', line 835 def paintEvent(event) return unless display_time painter = Qt::Painter.new() font = painter.font font.point_size = 8 painter.font = font fm = Qt::FontMetrics.new(font) update_current_tasks paint_timeline(painter, fm) paint_tasks(painter, fm, task_layout, timeline_height) # Draw the "zero" line painter.pen = TIMELINE_GRAY_PEN painter.drawLine(display_point, fm.height + 2, display_point, size.height) ensure painter&.end end |
#remove_tasks(tasks) ⇒ Object
356 357 358 359 360 361 |
# File 'lib/roby/gui/chronicle_widget.rb', line 356 def remove_tasks(tasks) tasks.each do |t| all_tasks.delete(t) all_job_info.delete(t) end end |
#resizeEvent(event) ⇒ Object
440 441 442 443 444 445 446 447 448 449 |
# File 'lib/roby/gui/chronicle_widget.rb', line 440 def resizeEvent(event) if track_current_time? @display_point = event.size.width - live_update_margin elsif display_time && current_time update_display_point end update_displayed_time_range invalidate_current_tasks event.accept end |
#restrict_to_jobs=(set) ⇒ Object
Sets whether only the toplevel job tasks should be shown
185 186 187 188 189 |
# File 'lib/roby/gui/chronicle_widget.rb', line 185 def restrict_to_jobs=(set) @restrict_to_jobs = set setDisplayTime update end |
#restrict_to_jobs? ⇒ Boolean
Returns true if only the action’s toplevel tasks are shown.
182 |
# File 'lib/roby/gui/chronicle_widget.rb', line 182 attr_predicate :restrict_to_jobs? |
#reverse_sort? ⇒ Boolean
Whether the order defined by #sort_mode should be inverted
133 134 135 |
# File 'lib/roby/gui/chronicle_widget.rb', line 133 def reverse_sort? !!@reverse_sort end |
#setCurrentTime(time = nil) ⇒ Object
572 573 574 575 576 577 578 579 |
# File 'lib/roby/gui/chronicle_widget.rb', line 572 def setCurrentTime(time = nil) time = massage_slot_time_argument(time, current_time) return unless time update_base_time(time) unless base_time update_current_time(time) update end |
#setDisplayTime(time = nil) ⇒ Object
561 562 563 564 565 566 567 568 569 |
# File 'lib/roby/gui/chronicle_widget.rb', line 561 def setDisplayTime(time = nil) time = massage_slot_time_argument(time, display_time) return unless time update_base_time(time) unless base_time update_current_time(time) unless current_time update_display_time(time) update end |
#task_timeline_title(task) ⇒ Object
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 |
# File 'lib/roby/gui/chronicle_widget.rb', line 855 def task_timeline_title(task) text = task.to_s return text unless (job_task = all_job_info[task]) job_text = ["[#{job_task.job_id}]"] job_text << job_task.job_name if job_task.respond_to?(:action_model) if job_task.action_model job_text << job_task.action_model.name.to_s end arg_s = (job_task.action_arguments || {}) .map { |k, v| "#{k}: #{v}" } job_text << "(#{arg_s.join(', ')})" text = "#{job_text.join(' ')} / #{text}" end text end |
#timeline_height ⇒ Object
830 831 832 833 |
# File 'lib/roby/gui/chronicle_widget.rb', line 830 def timeline_height fm = Qt::FontMetrics.new(font) fm.height + fm.descent + TIMELINE_RULER_LINE_LENGTH end |
#update_base_time(time) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Update the time at the start of the chronicle
388 389 390 391 392 |
# File 'lib/roby/gui/chronicle_widget.rb', line 388 def update_base_time(time) @base_time = time invalidate_current_tasks invalidate_layout_cache end |
#update_current_tasks(force: false) ⇒ Object
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
# File 'lib/roby/gui/chronicle_widget.rb', line 475 def update_current_tasks(force: false) return if !force && !current_tasks_dirty? current_tasks = all_tasks.dup if restrict_to_jobs? current_tasks = all_job_info.keys.to_set end if filter current_tasks = current_tasks.find_all { |t| t.to_s =~ filter } end if filter_out current_tasks.delete_if { |t| t.to_s =~ filter_out } end started_tasks, pending_tasks = current_tasks.partition(&:start_time) if sort_mode == :last_event not_yet_started, started_tasks = started_tasks.partition { |t| t.start_time > display_time } current_tasks = started_tasks.sort_by do |t| last_event = nil t.history.each do |ev| if ev.time < display_time last_event = ev else break end end last_event.time end current_tasks = current_tasks.reverse current_tasks.concat(not_yet_started.sort_by(&:start_time)) if show_mode == :all current_tasks .concat(pending_tasks.sort_by(&:addition_time)) end else current_tasks = (started_tasks + pending_tasks).sort_by { |t| t.start_time || t.addition_time } end start_time, end_time = displayed_time_range if start_time && (show_mode == :running || show_mode == :current) current_tasks = current_tasks.find_all do |t| (t.start_time && t.start_time < end_time) && (!t.end_time || t.end_time > start_time) end if show_mode == :current current_tasks = current_tasks.find_all do |t| t.history.any? { |ev| ev.time > start_time && ev.time < end_time } end end end tasks_in_range, tasks_outside_range = current_tasks.partition do |t| (t.addition_time <= end_time) && (!t.finalization_time || t.finalization_time >= start_time) end if reverse_sort? tasks_in_range = tasks_in_range.reverse tasks_outside_range = tasks_outside_range.reverse end @current_tasks_dirty = false if show_mode == :in_range @current_tasks = tasks_in_range else @current_tasks = tasks_in_range + tasks_outside_range end .setRange(0, current_tasks.size) end |
#update_current_time(time) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Update the time at the end of the chronicle
396 397 398 399 400 401 402 403 404 405 406 407 |
# File 'lib/roby/gui/chronicle_widget.rb', line 396 def update_current_time(time) @current_time = time unless base_time update_base_time(time) end if !display_time || track_current_time? update_display_time(time) else update_scroll_ranges invalidate_current_tasks end end |
#update_display_point ⇒ Object
428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/roby/gui/chronicle_widget.rb', line 428 def update_display_point display_point = .size.width - live_update_margin - (current_time - display_time) * time_to_pixel display_point_min = .size.width / 2 if display_point < display_point_min display_point = display_point_min end @display_point = Integer(display_point) update_displayed_time_range invalidate_current_tasks end |
#update_display_time(time) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Update the currently displayed time
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'lib/roby/gui/chronicle_widget.rb', line 411 def update_display_time(time) @display_time = time unless base_time update_base_time(time) end _, end_time = displayed_time_range update_display_point unless update_scroll_ranges .value = time_to_pixel * (display_time - base_time) end invalidate_current_tasks end |
#update_displayed_time_range ⇒ Object
451 452 453 454 455 456 457 458 459 |
# File 'lib/roby/gui/chronicle_widget.rb', line 451 def update_displayed_time_range if display_time display_point = self.display_point window_width = .size.width start_time = display_time - display_point * pixel_to_time end_time = start_time + window_width * pixel_to_time @displayed_time_range = [start_time, end_time] end end |
#update_scroll_ranges ⇒ Object
898 899 900 901 902 903 904 905 906 907 908 909 |
# File 'lib/roby/gui/chronicle_widget.rb', line 898 def update_scroll_ranges .setRange(0, current_tasks.size - 1) line_max = current_tasks.empty? ? 0 : current_tasks.size - 1 @start_line = [line_max, @start_line].compact.min return if if base_time && current_time && display_time .value = time_to_pixel * (display_time - base_time) .setRange(0, time_to_pixel * (current_time - base_time)) .setPageStep(size.width / 4) end end |
#update_time_range(start_time, current_time) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Updates the start and current time
377 378 379 380 381 382 383 384 |
# File 'lib/roby/gui/chronicle_widget.rb', line 377 def update_time_range(start_time, current_time) if start_time update_base_time(start_time) end if current_time update_current_time(current_time) end end |
#wheelEvent(event) ⇒ Object
Event handler for wheel event
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/roby/gui/chronicle_widget.rb', line 283 def wheelEvent(event) if event.modifiers != Qt::ControlModifier # Don't let the user scroll with the mouse if vertical # scrolling is off if == Qt::ScrollBarAlwaysOff event.ignore return else return super end end # See documentation of wheelEvent degrees = event.delta / 8.0 num_steps = degrees / 15 old = self.time_scale new = old + num_steps if new == 0 if old > 0 self.time_scale = -1 else self.time_scale = 1 end else self.time_scale = new end event.accept end |