From 949144681ad7f536732169351cab6d0612e9c566 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Wed, 8 May 2019 11:48:35 +0100 Subject: scripts/pybootchart: Port to python3 This updates the pybootchart code (used for viewing build timing profiles) to use python3. The bulk of the changes are to use gi instead of pygtk, i.e. port from gtk+2 to gtk+3. The main change is to make the bootchart widget inherit gtk.Scrollable and change the way the scrollbars are implemented to match the new method upstream. The drawing code used cairo already so can remain unchanged, Signed-off-by: Richard Purdie --- scripts/pybootchartgui/pybootchartgui/gui.py | 208 +++++++++++++-------------- 1 file changed, 103 insertions(+), 105 deletions(-) (limited to 'scripts/pybootchartgui/pybootchartgui/gui.py') diff --git a/scripts/pybootchartgui/pybootchartgui/gui.py b/scripts/pybootchartgui/pybootchartgui/gui.py index 7fedd232df..e1fe915563 100644 --- a/scripts/pybootchartgui/pybootchartgui/gui.py +++ b/scripts/pybootchartgui/pybootchartgui/gui.py @@ -13,64 +13,83 @@ # You should have received a copy of the GNU General Public License # along with pybootchartgui. If not, see . -import gobject -import gtk -import gtk.gdk -import gtk.keysyms +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk as gtk +from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import GObject as gobject +from gi.repository import GObject + from . import draw from .draw import RenderOptions -class PyBootchartWidget(gtk.DrawingArea): +class PyBootchartWidget(gtk.DrawingArea, gtk.Scrollable): __gsignals__ = { - 'expose-event': 'override', - 'clicked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gtk.gdk.Event)), + 'clicked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, Gdk.Event)), 'position-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT, gobject.TYPE_INT)), 'set-scroll-adjustments' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gtk.Adjustment, gtk.Adjustment)) } + hadjustment = GObject.property(type=Gtk.Adjustment, + default=Gtk.Adjustment(), + flags=GObject.PARAM_READWRITE) + hscroll_policy = GObject.property(type=Gtk.ScrollablePolicy, + default=Gtk.ScrollablePolicy.MINIMUM, + flags=GObject.PARAM_READWRITE) + vadjustment = GObject.property(type=Gtk.Adjustment, + default=Gtk.Adjustment(), + flags=GObject.PARAM_READWRITE) + vscroll_policy = GObject.property(type=Gtk.ScrollablePolicy, + default=Gtk.ScrollablePolicy.MINIMUM, + flags=GObject.PARAM_READWRITE) + def __init__(self, trace, options, xscale): gtk.DrawingArea.__init__(self) self.trace = trace self.options = options - self.set_flags(gtk.CAN_FOCUS) + self.set_can_focus(True) - self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK) + self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK) self.connect("button-press-event", self.on_area_button_press) self.connect("button-release-event", self.on_area_button_release) - self.add_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_RELEASE_MASK) + self.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK) self.connect("motion-notify-event", self.on_area_motion_notify) self.connect("scroll-event", self.on_area_scroll_event) self.connect('key-press-event', self.on_key_press_event) - self.connect('set-scroll-adjustments', self.on_set_scroll_adjustments) self.connect("size-allocate", self.on_allocation_size_changed) self.connect("position-changed", self.on_position_changed) + self.connect("draw", self.on_draw) + self.zoom_ratio = 1.0 self.xscale = xscale self.x, self.y = 0.0, 0.0 self.chart_width, self.chart_height = draw.extents(self.options, self.xscale, self.trace) - self.hadj = None - self.vadj = None - self.hadj_changed_signal_id = None - self.vadj_changed_signal_id = None - - def do_expose_event(self, event): - cr = self.window.cairo_create() - - # set a clip region for the expose event - cr.rectangle( - event.area.x, event.area.y, - event.area.width, event.area.height - ) - cr.clip() - self.draw(cr, self.get_allocation()) - return False - - def draw(self, cr, rect): + self.our_width, self.our_height = self.chart_width, self.chart_height + + self.hadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + self.vadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + self.vadj.connect('value-changed', self.on_adjustments_changed) + self.hadj.connect('value-changed', self.on_adjustments_changed) + + def bound_vals(self): + self.x = max(0, self.x) + self.y = max(0, self.y) + self.x = min(self.chart_width - self.our_width, self.x) + self.y = min(self.chart_height - self.our_height, self.y) + + def on_draw(self, darea, cr): + # set a clip region + #cr.rectangle( + # self.x, self.y, + # self.chart_width, self.chart_height + #) + #cr.clip() cr.set_source_rgba(1.0, 1.0, 1.0, 1.0) cr.paint() cr.scale(self.zoom_ratio, self.zoom_ratio) @@ -84,7 +103,7 @@ class PyBootchartWidget(gtk.DrawingArea): def zoom_image (self, zoom_ratio): self.zoom_ratio = zoom_ratio - self._set_scroll_adjustments (self.hadj, self.vadj) + self._set_scroll_adjustments() self.queue_draw() def zoom_to_rect (self, rect): @@ -122,126 +141,101 @@ class PyBootchartWidget(gtk.DrawingArea): def show_toggled(self, button): self.options.app_options.show_all = button.get_property ('active') self.chart_width, self.chart_height = draw.extents(self.options, self.xscale, self.trace) - self._set_scroll_adjustments(self.hadj, self.vadj) + self._set_scroll_adjustments() self.queue_draw() POS_INCREMENT = 100 def on_key_press_event(self, widget, event): - if event.keyval == gtk.keysyms.Left: + if event.keyval == Gdk.keyval_from_name("Left"): self.x -= self.POS_INCREMENT/self.zoom_ratio - elif event.keyval == gtk.keysyms.Right: + elif event.keyval == Gdk.keyval_from_name("Right"): self.x += self.POS_INCREMENT/self.zoom_ratio - elif event.keyval == gtk.keysyms.Up: + elif event.keyval == Gdk.keyval_from_name("Up"): self.y -= self.POS_INCREMENT/self.zoom_ratio - elif event.keyval == gtk.keysyms.Down: + elif event.keyval == Gdk.keyval_from_name("Down"): self.y += self.POS_INCREMENT/self.zoom_ratio else: return False + self.bound_vals() self.queue_draw() self.position_changed() return True def on_area_button_press(self, area, event): if event.button == 2 or event.button == 1: - area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR)) + window = self.get_window() + window.set_cursor(Gdk.Cursor(Gdk.CursorType.FLEUR)) self.prevmousex = event.x self.prevmousey = event.y - if event.type not in (gtk.gdk.BUTTON_PRESS, gtk.gdk.BUTTON_RELEASE): + if event.type not in (Gdk.EventType.BUTTON_PRESS, Gdk.EventType.BUTTON_RELEASE): return False return False def on_area_button_release(self, area, event): if event.button == 2 or event.button == 1: - area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) + window = self.get_window() + window.set_cursor(Gdk.Cursor(Gdk.CursorType.ARROW)) self.prevmousex = None self.prevmousey = None return True return False def on_area_scroll_event(self, area, event): - if event.state & gtk.gdk.CONTROL_MASK: - if event.direction == gtk.gdk.SCROLL_UP: + if event.state & Gdk.CONTROL_MASK: + if event.direction == Gdk.SCROLL_UP: self.zoom_image(self.zoom_ratio * self.ZOOM_INCREMENT) return True - if event.direction == gtk.gdk.SCROLL_DOWN: + if event.direction == Gdk.SCROLL_DOWN: self.zoom_image(self.zoom_ratio / self.ZOOM_INCREMENT) return True return False def on_area_motion_notify(self, area, event): state = event.state - if state & gtk.gdk.BUTTON2_MASK or state & gtk.gdk.BUTTON1_MASK: + if state & Gdk.ModifierType.BUTTON2_MASK or state & Gdk.ModifierType.BUTTON1_MASK: x, y = int(event.x), int(event.y) # pan the image self.x += (self.prevmousex - x)/self.zoom_ratio self.y += (self.prevmousey - y)/self.zoom_ratio + self.bound_vals() self.queue_draw() self.prevmousex = x self.prevmousey = y self.position_changed() return True - def on_set_scroll_adjustments(self, area, hadj, vadj): - self._set_scroll_adjustments (hadj, vadj) - def on_allocation_size_changed(self, widget, allocation): self.hadj.page_size = allocation.width self.hadj.page_increment = allocation.width * 0.9 self.vadj.page_size = allocation.height self.vadj.page_increment = allocation.height * 0.9 + self.our_width = allocation.width + if self.chart_width < self.our_width: + self.our_width = self.chart_width + self.our_height = allocation.height + if self.chart_height < self.our_height: + self.our_height = self.chart_height + self._set_scroll_adjustments() def _set_adj_upper(self, adj, upper): - changed = False - value_changed = False - - if adj.upper != upper: - adj.upper = upper - changed = True - - max_value = max(0.0, upper - adj.page_size) - if adj.value > max_value: - adj.value = max_value - value_changed = True - - if changed: - adj.changed() - if value_changed: - adj.value_changed() - - def _set_scroll_adjustments(self, hadj, vadj): - if hadj == None: - hadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) - if vadj == None: - vadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) - - if self.hadj_changed_signal_id != None and \ - self.hadj != None and hadj != self.hadj: - self.hadj.disconnect (self.hadj_changed_signal_id) - if self.vadj_changed_signal_id != None and \ - self.vadj != None and vadj != self.vadj: - self.vadj.disconnect (self.vadj_changed_signal_id) - - if hadj != None: - self.hadj = hadj - self._set_adj_upper (self.hadj, self.zoom_ratio * self.chart_width) - self.hadj_changed_signal_id = self.hadj.connect('value-changed', self.on_adjustments_changed) - - if vadj != None: - self.vadj = vadj - self._set_adj_upper (self.vadj, self.zoom_ratio * self.chart_height) - self.vadj_changed_signal_id = self.vadj.connect('value-changed', self.on_adjustments_changed) + + if adj.get_upper() != upper: + adj.set_upper(upper) + + def _set_scroll_adjustments(self): + self._set_adj_upper (self.hadj, self.zoom_ratio * (self.chart_width - self.our_width)) + self._set_adj_upper (self.vadj, self.zoom_ratio * (self.chart_height - self.our_height)) def on_adjustments_changed(self, adj): - self.x = self.hadj.value / self.zoom_ratio - self.y = self.vadj.value / self.zoom_ratio + self.x = self.hadj.get_value() / self.zoom_ratio + self.y = self.vadj.get_value() / self.zoom_ratio self.queue_draw() def on_position_changed(self, widget, x, y): - self.hadj.value = x * self.zoom_ratio - self.vadj.value = y * self.zoom_ratio - -PyBootchartWidget.set_set_scroll_adjustments_signal('set-scroll-adjustments') + self.hadj.set_value(x * self.zoom_ratio) + #self.hadj.value_changed() + self.vadj.set_value(y * self.zoom_ratio) class PyBootchartShell(gtk.VBox): ui = ''' @@ -260,7 +254,7 @@ class PyBootchartShell(gtk.VBox): def __init__(self, window, trace, options, xscale): gtk.VBox.__init__(self) - self.widget = PyBootchartWidget(trace, options, xscale) + self.widget2 = PyBootchartWidget(trace, options, xscale) # Create a UIManager instance uimanager = self.uimanager = gtk.UIManager() @@ -275,12 +269,12 @@ class PyBootchartShell(gtk.VBox): # Create actions actiongroup.add_actions(( - ('Expand', gtk.STOCK_ADD, None, None, None, self.widget.on_expand), - ('Contract', gtk.STOCK_REMOVE, None, None, None, self.widget.on_contract), - ('ZoomIn', gtk.STOCK_ZOOM_IN, None, None, None, self.widget.on_zoom_in), - ('ZoomOut', gtk.STOCK_ZOOM_OUT, None, None, None, self.widget.on_zoom_out), - ('ZoomFit', gtk.STOCK_ZOOM_FIT, 'Fit Width', None, None, self.widget.on_zoom_fit), - ('Zoom100', gtk.STOCK_ZOOM_100, None, None, None, self.widget.on_zoom_100), + ('Expand', gtk.STOCK_ADD, None, None, None, self.widget2.on_expand), + ('Contract', gtk.STOCK_REMOVE, None, None, None, self.widget2.on_contract), + ('ZoomIn', gtk.STOCK_ZOOM_IN, None, None, None, self.widget2.on_zoom_in), + ('ZoomOut', gtk.STOCK_ZOOM_OUT, None, None, None, self.widget2.on_zoom_out), + ('ZoomFit', gtk.STOCK_ZOOM_FIT, 'Fit Width', None, None, self.widget2.on_zoom_fit), + ('Zoom100', gtk.STOCK_ZOOM_100, None, None, None, self.widget2.on_zoom_100), )) # Add the actiongroup to the uimanager @@ -290,29 +284,33 @@ class PyBootchartShell(gtk.VBox): uimanager.add_ui_from_string(self.ui) # Scrolled window - scrolled = gtk.ScrolledWindow() - scrolled.add(self.widget) + scrolled = gtk.ScrolledWindow(self.widget2.hadj, self.widget2.vadj) + scrolled.add(self.widget2) + + #scrolled.set_hadjustment() + #scrolled.set_vadjustment(self.widget2.vadj) + scrolled.set_policy(gtk.PolicyType.ALWAYS, gtk.PolicyType.ALWAYS) # toolbar / h-box hbox = gtk.HBox(False, 8) # Create a Toolbar toolbar = uimanager.get_widget('/ToolBar') - hbox.pack_start(toolbar, True, True) + hbox.pack_start(toolbar, True, True, 0) if not options.kernel_only: # Misc. options button = gtk.CheckButton("Show more") - button.connect ('toggled', self.widget.show_toggled) + button.connect ('toggled', self.widget2.show_toggled) button.set_active(options.app_options.show_all) - hbox.pack_start (button, False, True) + hbox.pack_start (button, False, True, 0) - self.pack_start(hbox, False) - self.pack_start(scrolled) + self.pack_start(hbox, False, True, 0) + self.pack_start(scrolled, True, True, 0) self.show_all() def grab_focus(self, window): - window.set_focus(self.widget) + window.set_focus(self.widget2) class PyBootchartWindow(gtk.Window): -- cgit 1.2.3-korg