Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
    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