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): 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 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
def build_event_box(self, obj_evt): # build the widget to present an event : # tooltip with event infos # image containing snapshot of the event # label with the time of the event corpsstr = '' entetestr = '' if obj_evt.content is not None: corpsstr = urllib.unquote(obj_evt.content.encode('utf-8')) ev_time = time.strftime("%H:%M:%S", time.localtime(obj_evt.time)) if self.options['time'] == 'activity': ev_time = helper.format_time_reference(obj_evt.activity_time) if obj_evt.name in self.events_names or obj_evt.name in self.operations_names: if ECACatalog.event_names[obj_evt.name]: entetestr = "%s : %s" % (ev_time, ECACatalog.event_names[obj_evt.name]) else: entetestr = "%s : %s" % (ev_time, "Event not described") if obj_evt.concerned_object['id']: entetestr = entetestr + ' (%s)' % obj_evt.concerned_object['id'] elif obj_evt.name in self.incomplete_operations_names.keys(): comp = '' ob = self.controller.package.get_element_by_id(obj_evt.concerned_object['id']) #print "%s %s %s" % (self.controller.package, obj_evt.concerned_object['id'], ob) if isinstance(ob, advene.model.annotation.Annotation): comp = _('of an annotation (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.annotation.Relation): comp = _('of a relation (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.schema.AnnotationType): comp = _('of an annotation type (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.schema.RelationType): comp = _('of a relation type (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.schema.Schema): comp = _('of a schema (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.view.View): comp = _('of a view (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.package.Package): comp = _('of a package (%s)') % obj_evt.concerned_object['id'] else: comp = _('of an unknown item (%s)') % obj_evt.concerned_object['id'] #print "%s" % ob entetestr = "%s : %s %s" % (ev_time, self.incomplete_operations_names[obj_evt.name], comp) else: print "unlabelled event : %s" % obj_evt.name entetestr = "%s : %s" % (ev_time, obj_evt.name) entete = gtk.Label(entetestr.encode("UTF-8")) hb = gtk.HBox() tr = TimestampRepresentation(obj_evt.movietime, self.controller, 50, 0, None , False) if tr is not None: hb.pack_start(tr, expand=False) hb.pack_start(gtk.VSeparator(), expand=False) hb.pack_start(entete, expand=False) if corpsstr != "": hb.set_tooltip_text(corpsstr) return hb
def build_action_box(self, obj_evt): # build the widget to present an event : # tooltip with event infos # image containing snapshot of the event # label with the time of the event act = obj_evt.name act_begin = time.strftime("%H:%M:%S", time.localtime(obj_evt.time[0])) if self.options['time'] == 'activity': act_begin = helper.format_time_reference(obj_evt.activity_time[0]) entetestr = "%s : %s" % (act_begin, act) corpsstr = "" for op in obj_evt.operations: op_time = time.strftime("%H:%M:%S", time.localtime(op.time)) if self.options['time'] == 'activity': op_time = helper.format_time_reference(op.activity_time) if op.concerned_object['name'] is None: corpsstr += urllib.parse.unquote(op_time + " : " + op.name + "\n") else: corpsstr += urllib.parse.unquote(op_time + " : " + op.name + " ( " + op.concerned_object['name'] + " : " + op.concerned_object['id'] + " )\n") entete = Gtk.Label(label=entetestr.encode("UTF-8")) hb = Gtk.HBox() box = Gtk.EventBox() tr = TimestampRepresentation(obj_evt.movietime, None, self.controller, 50, 0, None, False) if tr is not None: hb.pack_start(tr, False, True, 0) hb.pack_start(Gtk.VSeparator(), False, False, 0) if corpsstr != "": hb.set_tooltip_text(corpsstr) def box_pressed(w, event, ops): if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS: #FIXME : need to change details in another way self.filters['objects'] = [] self.filters['objects'].extend(ops) self.options['detail'] = 'operations' self.DetB.set_label('operations') #FIXME color change of the reset button when applying a filter self.filter_active(True) self.receive(self.tracer.trace) return box.add(entete) box.connect('button-press-event', box_pressed, obj_evt.operations) hb.pack_start(box, False, True, 0) return hb
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 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
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
def build_operation_box(self, obj_evt): # build the widget to present an event : # tooltip with event infos # image containing snapshot of the event # label with the time of the event corpsstr = '' if obj_evt.content is not None: corpsstr = urllib.unquote(obj_evt.content.encode('utf-8')) ev_time = time.strftime("%H:%M:%S", time.localtime(obj_evt.time)) if self.options['time'] == 'activity': ev_time = helper.format_time_reference(obj_evt.activity_time) if obj_evt.name in self.operations_names: if ECACatalog.event_names[obj_evt.name]: entetestr = "%s : %s" % (ev_time, ECACatalog.event_names[obj_evt.name]) else: entetestr = "%s : %s" % (ev_time, "Operation not described") if obj_evt.concerned_object['id']: entetestr = entetestr + ' (%s)' % obj_evt.concerned_object['id'] elif obj_evt.name in self.incomplete_operations_names.keys(): comp = '' # store type of item in the trace ob = self.controller.package.get_element_by_id(obj_evt.concerned_object['id']) #print "%s %s %s" % (self.controller.package, obj_evt.concerned_object['id'], ob) if isinstance(ob, advene.model.annotation.Annotation): comp = _('of an annotation (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.annotation.Relation): comp = _('of a relation (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.schema.AnnotationType): comp = _('of an annotation type (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.schema.RelationType): comp = _('of a relation type (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.schema.Schema): comp = _('of a schema (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.view.View): comp = _('of a view (%s)') % obj_evt.concerned_object['id'] elif isinstance(ob,advene.model.package.Package): comp = _('of a package (%s)') % obj_evt.concerned_object['id'] else: comp = _('of an unknown item (%s)') % obj_evt.concerned_object['id'] entetestr = "%s : %s %s" % (ev_time, self.incomplete_operations_names[obj_evt.name], comp) else: print "unlabelled event : %s" % obj_evt.name entetestr = "%s : %s" % (ev_time, obj_evt.name) entete = gtk.Label(entetestr.encode("UTF-8")) hb = gtk.HBox() box = gtk.EventBox() tr = TimestampRepresentation(obj_evt.movietime, self.controller, 50, 0, None , False) if tr is not None: hb.pack_start(tr, expand=False) hb.pack_start(gtk.VSeparator(), expand=False) if corpsstr != "": box.set_tooltip_text(corpsstr) def box_pressed(w, event, id): #print "%s %s" % (id, mtime) if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: if id is not None: obj = self.controller.package.get_element_by_id(id) if obj is not None: #Need to edit the item #print obj self.controller.gui.edit_element(obj) else: print "item %s no longuer exists" % id return box.add(entete) box.connect('button-press-event', box_pressed, obj_evt.concerned_object['id']) hb.pack_start(box, expand=False) return hb
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 build_widget(self): v = gtk.VBox() self.label = {} self.sw = {} h = gtk.HBox() self.label['title'] = gtk.Label() h.pack_start(self.label['title'], expand=False) v.pack_start(h, expand=False) h = gtk.HBox() self.label['begin'] = gtk.Label() h.pack_start(self.label['begin'], expand=False) l = gtk.Label(' - ') h.pack_start(l, expand=False) self.label['end'] = gtk.Label() h.pack_start(self.label['end'], expand=False) v.pack_start(h, expand=False) def handle_motion(widget, event): if isinstance(self.annotation, Annotation): i = self.label['image'] i.epsilon = self.annotation.fragment.duration / widget.allocation.width v = self.annotation.fragment.begin + i.epsilon * 20 * int( event.x / 20) i.set_value(v) return True def handle_leave(widget, event): if isinstance(self.annotation, Annotation): i = self.label['image'] i.epsilon = config.data.preferences[ 'bookmark-snapshot-precision'] i.set_value(self.annotation.fragment.begin) return True fr = gtk.Expander() fr.set_label(_("Screenshot")) self.label['image'] = TimestampRepresentation( -1, self.controller, width=config.data.preferences['drag-snapshot-width'], epsilon=config.data.preferences['bookmark-snapshot-precision'], visible_label=False) self.label['image'].add_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.LEAVE_NOTIFY_MASK) self.label['image'].connect('motion-notify-event', handle_motion) self.label['image'].connect('leave-notify-event', handle_leave) fr.add(self.label['image']) fr.set_expanded(True) v.pack_start(fr, expand=False) # Contents frame def handle_ok(b): b.hide() if isinstance(self.annotation, Annotation): self.controller.notify('EditSessionStart', element=self.annotation, immediate=True) self.annotation.content.data = self.label['contents'].get_text( ) self.controller.notify("AnnotationEditEnd", annotation=self.annotation) self.controller.notify('EditSessionEnd', element=self.annotation) return True hbox = gtk.HBox() hbox.pack_start(gtk.Label(_("Contents")), expand=False) ok_button = get_pixmap_button('small_ok.png', handle_ok) ok_button.set_relief(gtk.RELIEF_NONE) ok_button.set_tooltip_text(_("Validate")) ok_button.set_no_show_all(True) hbox.pack_start(ok_button, expand=False) f = gtk.Frame() f.set_label_widget(hbox) def contents_modified(buf): if buf.get_modified(): if not buf.ignore_modified: ok_button.show() else: ok_button.hide() return True c = self.label['contents'] = gtk.TextView() c.set_wrap_mode(gtk.WRAP_WORD_CHAR) c.get_buffer().ignore_modified = False c.get_buffer().connect('modified-changed', contents_modified) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.add(c) def set_text(widget, t): b = widget.get_buffer() b.ignore_modified = True b.delete(*b.get_bounds()) b.set_text(t) b.set_modified(False) b.ignore_modified = False return True c.set_text = set_text.__get__(c) def get_text(widget): b = widget.get_buffer() return b.get_text(*b.get_bounds()) c.get_text = get_text.__get__(c) self.sw['contents'] = sw def handle_keypress(widget, event): if (event.keyval == gtk.keysyms.Return and event.state & gtk.gdk.CONTROL_MASK and widget.get_buffer().get_modified()): handle_ok(ok_button) return True return False c.connect('key-press-event', handle_keypress) # Hook the completer component if hasattr(self.controller.package, '_indexer'): self.completer = Completer( textview=c, controller=self.controller, element=self.annotation, indexer=self.controller.package._indexer) image = self.label['imagecontents'] = gtk.Image() swi = gtk.ScrolledWindow() swi.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) swi.add_with_viewport(image) self.sw['imagecontents'] = swi vb = gtk.VBox() vb.add(sw) vb.add(swi) f.add(vb) v.add(f) v.show_all() image.hide() v.set_no_show_all(True) def annotation_drag_received_cb(widget, context, x, y, selection, targetType, time): """Handle the drop of an annotation. """ if targetType == config.data.target_type['annotation']: sources = [ self.controller.package.annotations.get(uri) for uri in unicode(selection.data, 'utf8').split('\n') ] if sources: self.set_annotation(sources[0]) return True return False # The button can receive drops (to display annotations) v.connect('drag-data-received', annotation_drag_received_cb) v.drag_dest_set( gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_ALL, config.data.drag_type['annotation'], gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_LINK | gtk.gdk.ACTION_MOVE) return v
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 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
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 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
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
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, self.controller, comment_getter=lambda: self.comment, width=self.width, epsilon=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.WRAP_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 unicode(b.get_text(*b.get_bounds())) == 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()) == '': b.set_text(self.default_comment) return False self.comment_entry.connect('focus-out-event', focus_out_event) def update_comment(buf): self.comment=unicode(buf.get_text(*buf.get_bounds())) 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.POLICY_AUTOMATIC, gtk.POLICY_NEVER) hbox.pack_start(self.image, expand=False) hbox.pack_start(sw, expand=True) hbox.show_all() return hbox else: return self.image
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
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, self.controller, comment_getter=lambda: self.comment, width=self.width, epsilon=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.WRAP_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 unicode( b.get_text(*b.get_bounds())) == 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()) == '': b.set_text(self.default_comment) return False self.comment_entry.connect('focus-out-event', focus_out_event) def update_comment(buf): self.comment = unicode(buf.get_text(*buf.get_bounds())) 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.POLICY_AUTOMATIC, gtk.POLICY_NEVER) hbox.pack_start(self.image, expand=False) hbox.pack_start(sw, expand=True) hbox.show_all() return hbox else: return self.image