def build_widget(self): vb = Gtk.VBox() l = Gtk.Label(label=self.label) vb.pack_start(l, False, True, 0) hb = Gtk.HBox() eb = Gtk.EventBox() ar = Gtk.Arrow(Gtk.ArrowType.LEFT, Gtk.ShadowType.IN) ar.set_tooltip_text( _("Click to see more frames or scroll with the mouse wheel")) eb.connect('button-press-event', lambda b, e: self.update_offset(-1)) eb.add(ar) hb.pack_start(eb, False, True, 0) r = None for i in range(self.count): r = TimestampRepresentation(0, None, self.controller, width=self.frame_width, visible_label=True, precision=0) r.add_class("frameselector_frame") r.add_class("frameselector_frame_%s" % self.border_mode) self.frames.append(r) r.connect("clicked", self.select_time) def enter_bookmark(widget, event): widget.add_class('frameselector_selected') return False def leave_bookmark(widget, event): widget.remove_class('frameselector_selected') return False r.connect('enter-notify-event', enter_bookmark) r.connect('leave-notify-event', leave_bookmark) hb.pack_start(r, False, True, 0) hb.connect("draw", self.check_size) eb = Gtk.EventBox() ar = Gtk.Arrow(Gtk.ArrowType.RIGHT, Gtk.ShadowType.IN) ar.set_tooltip_text( _("Click to see more frames or scroll with the mouse wheel")) eb.connect('button-press-event', lambda b, e: self.update_offset(+1)) eb.add(ar) hb.pack_start(eb, False, True, 0) vb.add(hb) vb.set_events(Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.KEY_PRESS_MASK) vb.connect('scroll-event', self.handle_scroll_event) vb.connect('key-press-event', self.handle_key_press) self.update_timestamp(self.timestamp) return vb
def build_widget(self): vb=gtk.VBox() buttons = gtk.HBox() b=gtk.Button(stock=gtk.STOCK_REFRESH) b.set_tooltip_text(_("Refresh missing snapshots")) b.connect("clicked", lambda b: self.refresh_snapshots()) buttons.pack_start(b, expand=True) vb.pack_start(buttons, expand=False) l = gtk.Label(_("Click on a frame to select its time.")) vb.pack_start(l, expand=False) hb=gtk.HBox() ar = gtk.Arrow(gtk.ARROW_LEFT, gtk.SHADOW_IN) ar.set_tooltip_text(_("Scroll to see more frames")) hb.pack_start(ar, expand=False) r = None for i in xrange(self.count): border = GenericColorButtonWidget('border') border.default_size=(3, 110) border.local_color=self.black_color if r is not None: # Previous TimestampRepresentation -> right border r.right_border = border r = TimestampRepresentation(0, self.controller, width=100, visible_label=True, epsilon=30) self.frames.append(r) r.connect("clicked", self.select_time) r.left_border = border hb.pack_start(border, expand=False) hb.pack_start(r, expand=False) # Last right border border = GenericColorButtonWidget('border') border.default_size=(3, 110) border.local_color=self.black_color r.right_border = border hb.pack_start(border, expand=False) ar = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_IN) ar.set_tooltip_text(_("Scroll to see more frames")) hb.pack_start(ar, expand=False) hb.set_style(get_color_style(hb, 'black', 'black')) hb.connect('scroll-event', self.handle_scroll_event) hb.connect('key-press-event', self.handle_key_press) vb.add(hb) self.update_timestamp(self.timestamp) return vb
def build_widget(self): vb=Gtk.VBox() l = Gtk.Label(label=self.label) vb.pack_start(l, False, True, 0) hb=Gtk.HBox() eb = Gtk.EventBox() ar = Gtk.Arrow(Gtk.ArrowType.LEFT, Gtk.ShadowType.IN) ar.set_tooltip_text(_("Click to see more frames or scroll with the mouse wheel")) eb.connect('button-press-event', lambda b,e: self.update_offset(-1)) eb.add(ar) hb.pack_start(eb, False, True, 0) r = None for i in range(self.count): r = TimestampRepresentation(0, None, self.controller, width=self.frame_width, visible_label=True, precision=0) r.add_class("frameselector_frame") r.add_class("frameselector_frame_%s" % self.border_mode) self.frames.append(r) r.connect("clicked", self.select_time) def enter_bookmark(widget, event): widget.add_class('frameselector_selected') return False def leave_bookmark(widget, event): widget.remove_class('frameselector_selected') return False r.connect('enter-notify-event', enter_bookmark) r.connect('leave-notify-event', leave_bookmark) hb.pack_start(r, False, True, 0) hb.connect("draw", self.check_size) eb = Gtk.EventBox() ar = Gtk.Arrow(Gtk.ArrowType.RIGHT, Gtk.ShadowType.IN) ar.set_tooltip_text(_("Click to see more frames or scroll with the mouse wheel")) eb.connect('button-press-event', lambda b,e: self.update_offset(+1)) eb.add(ar) hb.pack_start(eb, False, True, 0) vb.add(hb) vb.set_events(Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.KEY_PRESS_MASK) vb.connect('scroll-event', self.handle_scroll_event) vb.connect('key-press-event', self.handle_key_press) self.update_timestamp(self.timestamp) return vb
class TimeAdjustment: """TimeAdjustment widget. Note: time values are integers in milliseconds. """ def __init__(self, value=0, controller=None, videosync=False, editable=True, compact=False, callback=None): self.value=value self.controller=controller self.sync_video=videosync # Small increment self.small_increment=config.data.preferences['scroll-increment'] # Large increment self.large_increment=config.data.preferences['second-scroll-increment'] self.image=None self.editable=editable self.compact=compact # Callback is a method which will be called *before* setting # the new value. If it returns False, then the new value will # not be used. self.callback=callback self.widget=self.make_widget() self.update_display() def make_widget(self): def refresh_snapshot(item): self.image.refresh_snapshot() return True def image_button_clicked(button): event=gtk.get_current_event() if event.state & gtk.gdk.CONTROL_MASK: self.use_current_position(button) return True else: self.play_from_here(button) return True def image_button_press(button, event): if event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS: # Display the popup menu menu = gtk.Menu() item = gtk.MenuItem(_("Refresh snapshot")) item.connect('activate', refresh_snapshot) menu.append(item) menu.show_all() menu.popup(None, None, None, 0, gtk.get_current_event_time()) return True return False def make_button(incr_value, pixmap): """Helper function to build the buttons.""" b=gtk.Button() i=gtk.Image() i.set_from_file(config.data.advenefile( ( 'pixmaps', pixmap) )) # FIXME: to re-enable # The proper way is to do #b.set_image(i) # but it works only on linux, gtk 2.10 # and is broken on windows and mac al=gtk.Alignment() al.set_padding(0, 0, 0, 0) al.add(i) b.add(al) b.connect('clicked', self.update_value_cb, incr_value) if incr_value < 0: tip=_("Decrement value by %.2f s") % (incr_value / 1000.0) else: tip=_("Increment value by %.2f s") % (incr_value / 1000.0) b.set_tooltip_text(tip) return b vbox=gtk.VBox() hbox=gtk.HBox() hbox.set_homogeneous(False) if self.editable: vb=gtk.VBox() b=make_button(-self.large_increment, "2leftarrow.png") vb.pack_start(b, expand=False) b=make_button(-self.small_increment, "1leftarrow.png") vb.pack_start(b, expand=False) hbox.pack_start(vb, expand=False) if self.compact: width=50 else: width=100 self.image=TimestampRepresentation(self.value, self.controller, width, epsilon=1000/25, visible_label=False) self.image.connect('button-press-event', image_button_press) self.image.connect('clicked', image_button_clicked) self.image.set_tooltip_text(_("Click to play\nControl+click to set to current time\Scroll to modify value (with control/shift)\nRight-click to invalidate screenshot")) hbox.pack_start(self.image, expand=False) if self.editable: vb=gtk.VBox() b=make_button(self.large_increment, "2rightarrow.png") vb.pack_start(b, expand=False) b=make_button(self.small_increment, "1rightarrow.png") vb.pack_start(b, expand=False) hbox.pack_start(vb, expand=False) hb = gtk.HBox() if self.editable: self.entry=gtk.Entry() # Default width of the entry field self.entry.set_width_chars(len(helper.format_time(0.0))) self.entry.connect('activate', self.convert_entered_value) self.entry.connect('focus-out-event', self.convert_entered_value) self.entry.set_editable(self.editable) hb.pack_start(self.entry, expand=False) else: self.entry=None if self.editable: current_pos=gtk.Button() i=gtk.Image() i.set_from_file(config.data.advenefile( ( 'pixmaps', 'set-to-now.png') )) current_pos.set_tooltip_text(_("Set to current player position")) current_pos.add(i) current_pos.connect('clicked', self.use_current_position) hb.pack_start(current_pos, expand=False) vbox.pack_start(hbox, expand=False) vbox.pack_start(hb, expand=False) hb.set_style(self.image.box.get_style()) #self.entry.set_style(self.image.box.get_style()) vbox.set_style(self.image.box.get_style()) vbox.show_all() hb.set_no_show_all(True) hbox.set_no_show_all(True) self.image.label.hide() hb.show() def handle_scroll_event(button, event): if event.state & gtk.gdk.CONTROL_MASK: i=config.data.preferences['scroll-increment'] elif event.state & gtk.gdk.SHIFT_MASK: i=config.data.preferences['second-scroll-increment'] else: # 1 frame i=1000/25 if event.direction == gtk.gdk.SCROLL_DOWN or event.direction == gtk.gdk.SCROLL_LEFT: incr=-i elif event.direction == gtk.gdk.SCROLL_UP or event.direction == gtk.gdk.SCROLL_RIGHT: incr=i v=self.value v += incr if self.callback and not self.callback(v): return True self.value=v self.update_display() return True if self.editable: # The widget can receive drops from annotations vbox.connect('drag-data-received', self.drag_received) vbox.drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_ALL, config.data.drag_type['annotation'] + config.data.drag_type['timestamp'], gtk.gdk.ACTION_LINK) vbox.connect('scroll-event', handle_scroll_event) vbox.show_all() return vbox def drag_received(self, widget, context, x, y, selection, targetType, time): if targetType == config.data.target_type['annotation']: source_uri=unicode(selection.data, 'utf8').split('\n')[0] source=self.controller.package.get(source_uri) if self.callback and not self.callback(source.begin): return True self.value = source.begin self.update_display() elif targetType == config.data.target_type['timestamp']: data=decode_drop_parameters(selection.data) v=long(float(data['timestamp'])) if self.callback and not self.callback(v): return True self.value=v self.update_display() else: print "Unknown target type for drop: %d" % targetType return True def drag_sent(self, widget, context, selection, targetType, eventTime): """Handle the drag-sent event. """ if targetType == config.data.target_type['timestamp']: selection.set(selection.target, 8, encode_drop_parameters(timestamp=self.value)) return True elif targetType in ( config.data.target_type['text-plain'], config.data.target_type['TEXT'], config.data.target_type['STRING'] ): selection.set(selection.target, 8, helper.format_time(self.value)) return True return False def play_from_here(self, button): if self.controller.player.status == self.controller.player.PauseStatus: self.controller.update_status("set", self.value) elif self.controller.player.status != self.controller.player.PlayingStatus: self.controller.update_status("start", self.value) self.controller.update_status("set", self.value) return True def use_current_position(self, button): v=self.controller.player.current_position_value if self.callback and not self.callback(v): return True self.value=v self.update_display() return True def update_snapshot(self, button): # FIXME: to implement print "Not implemented yet." pass # Static values used in numericTime _hour = r'(?P<hour>\d+)' _minute = r'(?P<minute>\d+)' _second = r'(?P<second>\d+(\.\d+))' _time = _hour + r':' + _minute + r'(:' + _second + r')?' _timeRE = re.compile(_time, re.I) def numericTime(self, s): """Converts a time string into a long value. This function is inspired from the numdate.py example script from the egenix mxDateTime package. If the input string s is a valid time expression of the form hh:mm:ss.sss or hh:mm:ss or hh:mm, return the corresponding value in milliseconds (float), else None """ if s is None: return None dt = None match = TimeAdjustment._timeRE.search(s) if match is not None: hh = int(match.group('hour')) mm = int(match.group('minute')) second = match.group('second') if second: ss = float(second) else: ss = 0.0 dt=int(1000 * (ss + (60 * mm) + (3600 * hh))) return dt def convert_entered_value(self, *p): t=self.entry.get_text() v=self.numericTime(t) if v is not None and v != self.value: v=self.check_bound_value(v) if self.callback and not self.callback(v): return False self.value = v if self.sync_video: self.controller.move_position(self.value, relative=False) self.update_display() return False def check_bound_value(self, value): if value < 0: value = 0 elif (self.controller.cached_duration > 0 and value > self.controller.cached_duration): value = self.controller.cached_duration return value def update(self): self.update_display() def update_display(self): """Updates the value displayed in the entry according to the current value.""" self.entry.set_text(helper.format_time(self.value)) self.image.value=self.value def update_value_cb(self, widget, increment): if not self.editable: return True v=self.check_bound_value(self.value + increment) if self.callback and not self.callback(v): return True self.value=v if self.sync_video: self.controller.move_position(self.value, relative=False) self.update_display() return True def get_widget(self): return self.widget def get_value(self): return self.value
class TimeAdjustment: """TimeAdjustment widget. Note: time values are integers in milliseconds. """ def __init__(self, value=0, controller=None, videosync=False, editable=True, compact=False, callback=None): self.value = value self.controller = controller self.sync_video = videosync # Small increment self.small_increment = config.data.preferences['scroll-increment'] # Large increment self.large_increment = config.data.preferences[ 'second-scroll-increment'] self.image = None self.editable = editable self.compact = compact # Callback is a method which will be called *before* setting # the new value. If it returns False, then the new value will # not be used. self.callback = callback self.widget = self.make_widget() self.update_display() def make_widget(self): def refresh_snapshot(item): self.image.refresh_snapshot() return True def image_button_clicked(button): event = Gtk.get_current_event() if event.get_state().state & Gdk.ModifierType.CONTROL_MASK: self.use_current_position(button) return True else: self.play_from_here(button) return True def image_button_press(button, event): if event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS: # Display the popup menu menu = Gtk.Menu() item = Gtk.MenuItem(_("Refresh snapshot")) item.connect('activate', refresh_snapshot) menu.append(item) menu.show_all() menu.popup_at_pointer(None) return True return False def make_button(incr_value, pixmap): """Helper function to build the buttons.""" b = Gtk.Button() i = Gtk.Image() i.set_from_file(config.data.advenefile(('pixmaps', pixmap))) b.set_image(i) def increment_value_cb(widget, increment): self.set_value(self.value + increment) return True b.connect('clicked', increment_value_cb, incr_value) if incr_value < 0: tip = _("Decrement value by %.2f s") % (incr_value / 1000.0) else: tip = _("Increment value by %.2f s") % (incr_value / 1000.0) b.set_tooltip_text(tip) return b vbox = Gtk.VBox() hbox = Gtk.HBox() hbox.set_homogeneous(False) if self.editable: vb = Gtk.VBox() b = make_button(-self.large_increment, "2leftarrow.png") vb.pack_start(b, False, True, 0) b = make_button(-self.small_increment, "1leftarrow.png") vb.pack_start(b, False, True, 0) hbox.pack_start(vb, False, True, 0) if self.compact: width = 50 else: width = 100 self.image = TimestampRepresentation(self.value, None, self.controller, width, visible_label=False, callback=self.set_value) self.image.connect('button-press-event', image_button_press) self.image.connect('clicked', image_button_clicked) self.image.set_tooltip_text( _("Click to play\nControl+click to set to current time\nScroll to modify value (with control/shift)\nRight-click to invalidate screenshot" )) hbox.pack_start(self.image, False, True, 0) if self.editable: vb = Gtk.VBox() b = make_button(self.large_increment, "2rightarrow.png") vb.pack_start(b, False, True, 0) b = make_button(self.small_increment, "1rightarrow.png") vb.pack_start(b, False, True, 0) hbox.pack_start(vb, False, True, 0) hb = Gtk.HBox() if self.editable: self.entry = Gtk.Entry() self.entry.set_tooltip_text( _("Enter a timecode.\nAn integer value will be considered as milliseconds.\nA float value (12.2) will be considered as seconds.\nHH:MM:SS.sss values are possible." )) # Default width of the entry field self.entry.set_width_chars(len(helper.format_time(0.0))) self.entry.connect('activate', self.convert_entered_value) self.entry.connect('focus-out-event', self.convert_entered_value) self.entry.set_editable(self.editable) hb.pack_start(self.entry, False, True, 0) else: self.entry = None if self.editable: current_pos = Gtk.Button() i = Gtk.Image() i.set_from_file( config.data.advenefile(('pixmaps', 'set-to-now.png'))) current_pos.set_tooltip_text(_("Set to current player position")) current_pos.add(i) current_pos.connect('clicked', self.use_current_position) hb.pack_start(current_pos, False, True, 0) vbox.pack_start(hbox, False, True, 0) vbox.pack_start(hb, False, True, 0) hb.set_style(self.image.box.get_style()) #self.entry.set_style(self.image.box.get_style()) vbox.set_style(self.image.box.get_style()) vbox.show_all() hb.set_no_show_all(True) hbox.set_no_show_all(True) self.image.label.hide() hb.show() def handle_scroll_event(button, event): if event.get_state() & Gdk.ModifierType.CONTROL_MASK: i = config.data.preferences['scroll-increment'] elif event.get_state() & Gdk.ModifierType.SHIFT_MASK: i = config.data.preferences['second-scroll-increment'] else: # 1 frame i = self.controller.frame2time(1) if event.direction == Gdk.ScrollDirection.DOWN or event.direction == Gdk.ScrollDirection.LEFT: incr = -i elif event.direction == Gdk.ScrollDirection.UP or event.direction == Gdk.ScrollDirection.RIGHT: incr = i if not self.set_value(self.value + incr): return True return True if self.editable: # The widget can receive drops from annotations vbox.connect('drag-data-received', self.drag_received) vbox.drag_dest_set( Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.ALL, config.data.get_target_types('annotation', 'timestamp'), Gdk.DragAction.LINK) vbox.connect('scroll-event', handle_scroll_event) vbox.show_all() return vbox def drag_received(self, widget, context, x, y, selection, targetType, time): if targetType == config.data.target_type['annotation']: source_uri = str(selection.get_data(), 'utf8').split('\n')[0] source = self.controller.package.annotations.get(source_uri) self.set_value(source.fragment.begin) elif targetType == config.data.target_type['timestamp']: data = decode_drop_parameters(selection.get_data().decode('utf-8')) v = int(float(data['timestamp'])) self.set_value(v) else: logger.warning("Unknown target type for drop: %d", targetType) return True def drag_sent(self, widget, context, selection, targetType, eventTime): """Handle the drag-sent event. """ if targetType == config.data.target_type['timestamp']: selection.set(selection.get_target(), 8, encode_drop_parameters(timestamp=self.value)) return True elif targetType in (config.data.target_type['text-plain'], config.data.target_type['TEXT'], config.data.target_type['STRING']): selection.set(selection.get_target(), 8, helper.format_time(self.value)) return True return False def play_from_here(self, button): self.controller.update_status("seek", self.value) return True def use_current_position(self, button): self.set_value(self.controller.player.current_position_value) return True def update_snapshot(self, button): # FIXME: to implement logger.warning("Not implemented yet.") pass def convert_entered_value(self, *p): t = self.entry.get_text() v = helper.parse_time(t) if v is not None and v != self.value: if not self.set_value(v): return False return False def check_bound_value(self, value): if value < 0 or value is None: value = 0 elif (self.controller.cached_duration > 0 and value > self.controller.cached_duration): value = self.controller.cached_duration return value def update(self): self.update_display() def update_display(self): """Updates the value displayed in the entry according to the current value.""" self.entry.set_text(helper.format_time(self.value)) self.image.value = self.value def get_widget(self): return self.widget def get_value(self): return self.value def set_value(self, v): """Set the new value. The method does various consistency checks, and can leave the value unset if a callback is defined and returns False. """ if self.value == v: return True v = self.check_bound_value(v) if self.callback and not self.callback(v): return False self.value = v self.update_display() if self.sync_video: self.controller.update_status("seek", self.value) return True
class TimeAdjustment: """TimeAdjustment widget. Note: time values are integers in milliseconds. """ def __init__(self, value=0, controller=None, videosync=False, editable=True, compact=False, callback=None): self.value=value self.controller=controller self.sync_video=videosync # Small increment self.small_increment=config.data.preferences['scroll-increment'] # Large increment self.large_increment=config.data.preferences['second-scroll-increment'] self.image=None self.editable=editable self.compact=compact # Callback is a method which will be called *before* setting # the new value. If it returns False, then the new value will # not be used. self.callback=callback self.widget=self.make_widget() self.update_display() def make_widget(self): def refresh_snapshot(item): self.image.refresh_snapshot() return True def image_button_clicked(button): event=gtk.get_current_event() if event.state & gtk.gdk.CONTROL_MASK: self.use_current_position(button) return True else: self.play_from_here(button) return True def image_button_press(button, event): if event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS: # Display the popup menu menu = gtk.Menu() item = gtk.MenuItem(_("Refresh snapshot")) item.connect('activate', refresh_snapshot) menu.append(item) menu.show_all() menu.popup(None, None, None, 0, gtk.get_current_event_time()) return True return False def make_button(incr_value, pixmap): """Helper function to build the buttons.""" b=gtk.Button() i=gtk.Image() i.set_from_file(config.data.advenefile( ( 'pixmaps', pixmap) )) # FIXME: to re-enable # The proper way is to do #b.set_image(i) # but it works only on linux, gtk 2.10 # and is broken on windows and mac al=gtk.Alignment() al.set_padding(0, 0, 0, 0) al.add(i) b.add(al) def increment_value_cb(widget, increment): self.set_value(self.value + increment) return True b.connect('clicked', increment_value_cb, incr_value) if incr_value < 0: tip=_("Decrement value by %.2f s") % (incr_value / 1000.0) else: tip=_("Increment value by %.2f s") % (incr_value / 1000.0) b.set_tooltip_text(tip) return b vbox=gtk.VBox() hbox=gtk.HBox() hbox.set_homogeneous(False) if self.editable: vb=gtk.VBox() b=make_button(-self.large_increment, "2leftarrow.png") vb.pack_start(b, expand=False) b=make_button(-self.small_increment, "1leftarrow.png") vb.pack_start(b, expand=False) hbox.pack_start(vb, expand=False) if self.compact: width=50 else: width=100 self.image=TimestampRepresentation(self.value, self.controller, width, epsilon=1000/config.data.preferences['default-fps'], visible_label=False, callback=self.set_value) self.image.connect('button-press-event', image_button_press) self.image.connect('clicked', image_button_clicked) self.image.set_tooltip_text(_("Click to play\nControl+click to set to current time\nScroll to modify value (with control/shift)\nRight-click to invalidate screenshot")) hbox.pack_start(self.image, expand=False) if self.editable: vb=gtk.VBox() b=make_button(self.large_increment, "2rightarrow.png") vb.pack_start(b, expand=False) b=make_button(self.small_increment, "1rightarrow.png") vb.pack_start(b, expand=False) hbox.pack_start(vb, expand=False) hb = gtk.HBox() if self.editable: self.entry=gtk.Entry() self.entry.set_tooltip_text(_("Enter a timecode.\nAn integer value will be considered as milliseconds.\nA float value (12.2) will be considered as seconds.\nHH:MM:SS.sss values are possible.")) # Default width of the entry field self.entry.set_width_chars(len(helper.format_time(0.0))) self.entry.connect('activate', self.convert_entered_value) self.entry.connect('focus-out-event', self.convert_entered_value) self.entry.set_editable(self.editable) hb.pack_start(self.entry, expand=False) else: self.entry=None if self.editable: current_pos=gtk.Button() i=gtk.Image() i.set_from_file(config.data.advenefile( ( 'pixmaps', 'set-to-now.png') )) current_pos.set_tooltip_text(_("Set to current player position")) current_pos.add(i) current_pos.connect('clicked', self.use_current_position) hb.pack_start(current_pos, expand=False) vbox.pack_start(hbox, expand=False) vbox.pack_start(hb, expand=False) hb.set_style(self.image.box.get_style()) #self.entry.set_style(self.image.box.get_style()) vbox.set_style(self.image.box.get_style()) vbox.show_all() hb.set_no_show_all(True) hbox.set_no_show_all(True) self.image.label.hide() hb.show() def handle_scroll_event(button, event): if event.state & gtk.gdk.CONTROL_MASK: i=config.data.preferences['scroll-increment'] elif event.state & gtk.gdk.SHIFT_MASK: i=config.data.preferences['second-scroll-increment'] else: # 1 frame i=1000 / config.data.preferences['default-fps'] if event.direction == gtk.gdk.SCROLL_DOWN or event.direction == gtk.gdk.SCROLL_LEFT: incr=-i elif event.direction == gtk.gdk.SCROLL_UP or event.direction == gtk.gdk.SCROLL_RIGHT: incr=i if not self.set_value(self.value + incr): return True return True if self.editable: # The widget can receive drops from annotations vbox.connect('drag-data-received', self.drag_received) vbox.drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_ALL, config.data.drag_type['annotation'] + config.data.drag_type['timestamp'], gtk.gdk.ACTION_LINK) vbox.connect('scroll-event', handle_scroll_event) vbox.show_all() return vbox def drag_received(self, widget, context, x, y, selection, targetType, time): if targetType == config.data.target_type['annotation']: source_uri=unicode(selection.data, 'utf8').split('\n')[0] source=self.controller.package.annotations.get(source_uri) self.set_value(source.fragment.begin) elif targetType == config.data.target_type['timestamp']: data=decode_drop_parameters(selection.data) v=long(float(data['timestamp'])) self.set_value(v) else: print "Unknown target type for drop: %d" % targetType return True def drag_sent(self, widget, context, selection, targetType, eventTime): """Handle the drag-sent event. """ if targetType == config.data.target_type['timestamp']: selection.set(selection.target, 8, encode_drop_parameters(timestamp=self.value)) return True elif targetType in ( config.data.target_type['text-plain'], config.data.target_type['TEXT'], config.data.target_type['STRING'] ): selection.set(selection.target, 8, helper.format_time(self.value)) return True return False def play_from_here(self, button): self.controller.update_status("set", self.value) return True def use_current_position(self, button): self.set_value(self.controller.player.current_position_value) return True def update_snapshot(self, button): # FIXME: to implement print "Not implemented yet." pass def convert_entered_value(self, *p): t=unicode(self.entry.get_text()) v=helper.parse_time(t) if v is not None and v != self.value: if not self.set_value(v): return False return False def check_bound_value(self, value): if value < 0 or value is None: value = 0 elif (self.controller.cached_duration > 0 and value > self.controller.cached_duration): value = self.controller.cached_duration return value def update(self): self.update_display() def update_display(self): """Updates the value displayed in the entry according to the current value.""" self.entry.set_text(helper.format_time(self.value)) self.image.value=self.value def get_widget(self): return self.widget def get_value(self): return self.value def set_value(self, v): """Set the new value. The method does various consistency checks, and can leave the value unset if a callback is defined and returns False. """ if self.value == v: return True v = self.check_bound_value(v) if self.callback and not self.callback(v): return False self.value=v self.update_display() if self.sync_video: self.controller.move_position(self.value, relative=False) return True
def create_timestamp_mark(self, timestamp, it): def popup_goto (b): self.controller.update_status(status="seek", position=b.value) return True b=self.textview.get_buffer() b.begin_user_action() anchor=b.create_child_anchor(it) # Create the mark representation child=TimestampRepresentation(timestamp, None, self.controller, width=self.options['snapshot-size'], visible_label=False) child.anchor=anchor child.connect('clicked', popup_goto) child.popup_menu=None child.connect('button-press-event', self.mark_button_press_cb, anchor, child) b.end_user_action() def handle_scroll_event(button, event): if not (event.get_state() & Gdk.ModifierType.CONTROL_MASK): return False if event.get_state() & Gdk.ModifierType.SHIFT_MASK: i='second-scroll-increment' else: i='scroll-increment' if event.direction == Gdk.ScrollDirection.DOWN or event.direction == Gdk.ScrollDirection.RIGHT: button.value -= config.data.preferences[i] elif event.direction == Gdk.ScrollDirection.UP or event.direction == Gdk.ScrollDirection.LEFT: button.value += config.data.preferences[i] button.set_tooltip_text("%s" % helper.format_time(button.value)) # FIXME: find a way to do this in the new Gtk.Tooltip API? #if self.tooltips.active_tips_data is None: # button.emit('show-help', Gtk.WIDGET_HELP_TOOLTIP) self.timestamp_play = button.value button.grab_focus() return True def mark_key_release_cb(button, event, anchor=None, child=None): """Handler for key release on timestamp mark. """ # Control key released. Goto the position if we were scrolling a mark if self.timestamp_play is not None and (event.get_state() & Gdk.ModifierType.CONTROL_MASK): # self.timestamp_play contains the new value, but child.timestamp # as well. So we can use popup_goto self.timestamp_play = None popup_goto(child) return True return False child.connect('scroll-event', handle_scroll_event) child.connect('key-release-event', mark_key_release_cb, anchor, child) child.set_tooltip_text("%s" % helper.format_time(timestamp)) child.value=timestamp child.ignore=False self.update_mark(child) child.show_all() child.label.set_no_show_all(True) child.label.hide() self.textview.add_child_at_anchor(child, anchor) self.marks.append(child) self.marks.sort(key=lambda a: a.value) return child
def build_widget(self): vb=gtk.VBox() l = gtk.Label(self.label) vb.pack_start(l, expand=False) hb=gtk.HBox() eb = gtk.EventBox() ar = gtk.Arrow(gtk.ARROW_LEFT, gtk.SHADOW_IN) ar.set_tooltip_text(_("Click to see more frames or scroll with the mouse wheel")) eb.connect('button-press-event', lambda b,e: self.update_offset(-1)) eb.add(ar) hb.pack_start(eb, expand=False) r = None for i in xrange(self.count): border = GenericColorButtonWidget('border') border.default_size=(3, 110) border.local_color=self.black_color if r is not None: # Previous TimestampRepresentation -> right border r.right_border = border r = TimestampRepresentation(0, self.controller, width=100, visible_label=True, epsilon=(1000 / config.data.preferences['default-fps'] - 10)) self.frames.append(r) r.connect("clicked", self.select_time) r.left_border = border def enter_bookmark(widget, event): if self.border_mode == 'left': b=widget.left_border elif self.border_mode == 'right': b=widget.right_border b.old_color = b.local_color b.set_color(self.mouseover_color) return False def leave_bookmark(widget, event): if self.border_mode == 'left': b=widget.left_border elif self.border_mode == 'right': b=widget.right_border b.set_color(b.old_color) return False if self.border_mode in ('left', 'right'): r.connect('enter-notify-event', enter_bookmark) r.connect('leave-notify-event', leave_bookmark) hb.pack_start(border, expand=False) hb.pack_start(r, expand=False) # Last right border border = GenericColorButtonWidget('border') border.default_size=(3, 110) border.local_color=self.black_color r.right_border = border hb.pack_start(border, expand=False) eb = gtk.EventBox() ar = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_IN) ar.set_tooltip_text(_("Click to see more frames or scroll with the mouse wheel")) eb.connect('button-press-event', lambda b,e: self.update_offset(+1)) eb.add(ar) hb.pack_start(eb, expand=False) hb.set_style(get_color_style(hb, 'black', 'black')) hb.connect('scroll-event', self.handle_scroll_event) hb.connect('key-press-event', self.handle_key_press) vb.add(hb) self.update_timestamp(self.timestamp) return vb
class BookmarkWidget: default_comment=_("Comment here") def __init__(self, controller=None, timestamp=0, comment=None, display_comments=False, width=None): self.controller=controller self.value=timestamp if comment is None: comment=self.default_comment self.comment=comment self.comment_entry=None self.display_comments=display_comments self.width=width self.widget=self.build_widget() def update(self): self.image.value=self.value if self.comment_entry is not None: self.comment_entry.get_buffer().set_text(self.comment) return True def build_widget(self): self.image=TimestampRepresentation(self.value, None, self.controller, comment_getter=lambda: self.comment, width=self.width, precision=config.data.preferences['bookmark-snapshot-precision']) self.image.connect('clicked', self.image.goto_and_refresh) if self.display_comments: hbox=Gtk.HBox() self.comment_entry=Gtk.TextView() # Hook the completer component completer=Completer(textview=self.comment_entry, controller=self.controller, element=self.comment_entry.get_buffer(), indexer=self.controller.package._indexer) self.comment_entry.set_wrap_mode(Gtk.WrapMode.WORD) fd=Pango.FontDescription('sans %d' % config.data.preferences['timeline']['font-size']) self.comment_entry.modify_font(fd) b=self.comment_entry.get_buffer() b.set_text(self.comment) def focus_in_event(wid, event): if b.get_text(*b.get_bounds() + (False,)) == self.default_comment: b.set_text('') return False self.comment_entry.connect('focus-in-event', focus_in_event) def focus_out_event(wid, event): if b.get_text(*b.get_bounds() + (False,)) == '': b.set_text(self.default_comment) return False self.comment_entry.connect('focus-out-event', focus_out_event) def update_comment(buf): self.comment=buf.get_text(*buf.get_bounds() + (False,)) return True b.connect('changed', update_comment) #self.comment_entry.set_size_request(config.data.preferences['bookmark-snapshot-width'], -1) sw=Gtk.ScrolledWindow() sw.add(self.comment_entry) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER) hbox.pack_start(self.image, False, True, 0) hbox.pack_start(sw, True, True, 0) hbox.show_all() return hbox else: return self.image
class BookmarkWidget(object): default_comment=_("Comment here") def __init__(self, controller=None, timestamp=0, comment=None, display_comments=False, width=None): self.controller=controller self.value=timestamp if comment is None: comment=self.default_comment self.comment=comment self.comment_entry=None self.display_comments=display_comments self.width=width self.widget=self.build_widget() def update(self): self.image.value=self.value if self.comment_entry is not None: self.comment_entry.get_buffer().set_text(self.comment) return True def build_widget(self): self.image=TimestampRepresentation(self.value, None, self.controller, comment_getter=lambda: self.comment, width=self.width, precision=config.data.preferences['bookmark-snapshot-precision']) self.image.connect('clicked', self.image.goto_and_refresh) if self.display_comments: hbox=Gtk.HBox() self.comment_entry=Gtk.TextView() # Hook the completer component completer=Completer(textview=self.comment_entry, controller=self.controller, element=self.comment_entry.get_buffer(), indexer=self.controller.package._indexer) self.comment_entry.set_wrap_mode(Gtk.WrapMode.WORD) fd=Pango.FontDescription('sans %d' % config.data.preferences['timeline']['font-size']) self.comment_entry.modify_font(fd) b=self.comment_entry.get_buffer() b.set_text(self.comment) def focus_in_event(wid, event): if b.get_text(*b.get_bounds() + (False,)) == self.default_comment: b.set_text('') return False self.comment_entry.connect('focus-in-event', focus_in_event) def focus_out_event(wid, event): if b.get_text(*b.get_bounds() + (False,)) == '': b.set_text(self.default_comment) return False self.comment_entry.connect('focus-out-event', focus_out_event) def update_comment(buf): self.comment=buf.get_text(*buf.get_bounds() + (False,)) return True b.connect('changed', update_comment) #self.comment_entry.set_size_request(config.data.preferences['bookmark-snapshot-width'], -1) sw=Gtk.ScrolledWindow() sw.add(self.comment_entry) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER) hbox.pack_start(self.image, False, True, 0) hbox.pack_start(sw, True, True, 0) hbox.show_all() return hbox else: return self.image
def create_timestamp_mark(self, timestamp, it): def popup_goto (b): self.controller.update_status(status="seek", position=b.value) return True b=self.textview.get_buffer() b.begin_user_action() if self.options['mark-prefix']: b.insert(it, unescape_string(self.options['mark-prefix'])) anchor=b.create_child_anchor(it) if self.options['mark-suffix']: b.insert(it, unescape_string(self.options['mark-suffix'])) # Create the mark representation child=TimestampRepresentation(timestamp, None, self.controller, width=self.options['snapshot-size'], visible_label=False) child.anchor=anchor child.connect('clicked', popup_goto) child.popup_menu=None child.connect('button-press-event', self.mark_button_press_cb, anchor, child) b.end_user_action() def handle_scroll_event(button, event): if not (event.get_state() & Gdk.ModifierType.CONTROL_MASK): return False if event.get_state() & Gdk.ModifierType.SHIFT_MASK: i='second-scroll-increment' else: i='scroll-increment' if event.direction == Gdk.ScrollDirection.DOWN or event.direction == Gdk.ScrollDirection.RIGHT: button.value -= config.data.preferences[i] elif event.direction == Gdk.ScrollDirection.UP or event.direction == Gdk.ScrollDirection.LEFT: button.value += config.data.preferences[i] button.set_tooltip_text("%s" % helper.format_time(button.value)) # FIXME: find a way to do this in the new Gtk.Tooltip API? #if self.tooltips.active_tips_data is None: # button.emit('show-help', Gtk.WIDGET_HELP_TOOLTIP) self.timestamp_play = button.value button.grab_focus() return True def mark_key_release_cb(button, event, anchor=None, child=None): """Handler for key release on timestamp mark. """ # Control key released. Goto the position if we were scrolling a mark if self.timestamp_play is not None and (event.get_state() & Gdk.ModifierType.CONTROL_MASK): # self.timestamp_play contains the new value, but child.timestamp # as well. So we can use popup_goto self.timestamp_play = None popup_goto(child) return True return False child.connect('scroll-event', handle_scroll_event) child.connect('key-release-event', mark_key_release_cb, anchor, child) child.set_tooltip_text("%s" % helper.format_time(timestamp)) child.value=timestamp child.ignore=False self.update_mark(child) child.show_all() child.label.set_no_show_all(True) child.label.hide() self.textview.add_child_at_anchor(child, anchor) self.marks.append(child) self.marks.sort(key=lambda a: a.value) return child