def scroll_to(scroll: Gtk.ScrolledWindow, target: Gtk.Widget, duration: int = 600) -> bool: """Animate the scroll for duration in milliseconds.""" target = target.get_allocation() adjustment = scroll.get_vadjustment() start_point = adjustment.get_value() page_size = adjustment.get_page_size() if start_point <= target.y \ and (target.y+target.height) <= (start_point+page_size): # If all parts of the target widget content are visible, # no need to animate the scroll. return False else: if target.y > start_point: # If the height of the target widget is greater than the # height of its container, scroll to the top-left coordinates # of the widget. Otherwise, scroll to the bottom-right # coordinates of the widget. if target.height > page_size: end_point = target.y else: end_point = min(adjustment.get_upper() - page_size, target.y + target.height - page_size) else: end_point = target.y # Stop the current animating when the same widget requested to be # animated again before it has finished animating scroll.end_point = end_point frame_clock = scroll.get_frame_clock() start_time = frame_clock.get_frame_time() end_time = start_time + 1000 * duration def animate(widget: Gtk.Widget, frame_clock: Gdk.FrameClock) -> bool: current_time = frame_clock.get_frame_time() if current_time < end_time \ and adjustment.get_value() != end_point \ and widget.end_point == end_point: t = (current_time - start_time) / (end_time - start_time) t = Animation.ease_out_cubic(t) adjustment.set_value(start_point + t * (end_point - start_point)) return GLib.SOURCE_CONTINUE else: return GLib.SOURCE_REMOVE scroll.add_tick_callback(animate) return False
def get_end_point( scroll: Gtk.ScrolledWindow, target: Gtk.Widget) -> int: talloc = target.get_allocation() adjustment = scroll.get_vadjustment() start_point = adjustment.get_value() page_size = adjustment.get_page_size() if start_point <= talloc.y \ and (talloc.y+talloc.height) <= (start_point+page_size): # If all parts of the target widget content are visible, # no need to animate the scroll. return -1 else: if talloc.y > start_point: # If the height of the target widget is greater than the # height of its container, scroll to the top-left # coordinates of the widget. Otherwise, scroll to the # bottom-right coordinates of the widget. if talloc.height > page_size: end_point = talloc.y else: end_point = min(adjustment.get_upper()-page_size, talloc.y+talloc.height-page_size) else: end_point = talloc.y return end_point
def init_plot_chart(scrolled_window: Gtk.ScrolledWindow, figure: Figure, canvas: FigureCanvas, axis: Axes) -> Any: axis.grid(True, linestyle=':') axis.margins(x=0, y=0.05) axis.set_facecolor('#00000000') axis.set_xlabel('Liquid temperature [°C]') axis.set_ylabel('Duty [%]') figure.subplots_adjust(top=1) canvas.set_size_request(400, 300) scrolled_window.add_with_viewport(canvas) # Returns a tuple of line objects, thus the comma lines = axis.plot([], [], 'o-', linewidth=3.0, markersize=10, antialiased=True) axis.set_ybound(lower=0, upper=105) axis.set_xbound(MIN_TEMP, MAX_TEMP) figure.canvas.draw() return lines
def add_tab(self, widget, tab_name, label): """Adds a tab object to the notebook.""" log.debug('add tab: %s', tab_name) self.tabs[tab_name] = widget scrolled = ScrolledWindow() scrolled.set_policy(PolicyType.AUTOMATIC, PolicyType.AUTOMATIC) scrolled.add(widget) self.notebook.insert_page(scrolled, Label(label=label), -1) scrolled.show_all() self.after_update()
class ReaderWindow(ApplicationWindow): __gtype_name__ = 'ReaderWindow' def __init__(self, **kwargs): super(ReaderWindow, self).__init__( title='Eearth Reader', **kwargs ) app = self.get_application() assert isinstance(app, EarthReaderApp) self.set_wmclass('Earth Reader', 'Earth Reader') self.set_icon_list(ICON_LIST) self.box = Box(spacing=0) self.add(self.box) subscriptions = SubscriptionTreeModel(app.stage) self.subscriptions_sidebar = ScrolledWindow() self.subscription_list = TreeView(subscriptions) cell_renderer = CellRendererText() subscription_column = TreeViewColumn('Title', cell_renderer, text=0) def cell_data_func(column, renderer, model, tree_iter, *args): if isinstance(model[tree_iter], Category): renderer.set_property('cell-background', 'silver') else: renderer.set_property('cell-background', None) subscription_column.set_cell_data_func(cell_renderer, cell_data_func) self.subscription_list.append_column(subscription_column) self.subscriptions_sidebar.add(self.subscription_list) self.box.pack_start(self.subscriptions_sidebar, expand=True, fill=True, padding=0) entries_store = dummy_entries() entry_column = TreeViewColumn('Title', CellRendererText(), text=0) self.entry_list_box = ScrolledWindow() self.entry_list = TreeView(entries_store) self.entry_list.append_column(entry_column) self.entry_list_box.add(self.entry_list) self.box.pack_start(self.entry_list_box, expand=True, fill=True, padding=0) self.content_view = WebView() self.box.pack_start(self.content_view, expand=True, fill=True, padding=0)
def animate( scroll: Gtk.ScrolledWindow, frame_clock: Gdk.FrameClock, target: Gtk.Widget) -> bool: current_time = frame_clock.get_frame_time() adjustment = scroll.get_vadjustment() start_point = adjustment.get_value() end_point = get_end_point(scroll, target) if current_time < end_time \ and end_point != -1 \ and adjustment.get_value() != end_point: t = (current_time-start_time) / (end_time-start_time) t = Animation.ease_out_cubic(t) adjustment.set_value(start_point + t*(end_point-start_point)) return GLib.SOURCE_CONTINUE else: scroll.anime_id = None return GLib.SOURCE_REMOVE
def scroll_to_end(widget: Gtk.ScrolledWindow) -> bool: """Scrolls to the end of a GtkScrolledWindow. Args: widget (GtkScrolledWindow) Returns: bool: The return value is False so it can be used with GLib.idle_add. """ adj_v = widget.get_vadjustment() if adj_v is None: # This can happen when the Widget is already destroyed when called # from GLib.idle_add return False max_scroll_pos = adj_v.get_upper() - adj_v.get_page_size() adj_v.set_value(max_scroll_pos) adj_h = widget.get_hadjustment() adj_h.set_value(0) return False
def at_the_end(widget: Gtk.ScrolledWindow) -> bool: """Determines if a Scrollbar in a GtkScrolledWindow is at the end. Args: widget (GtkScrolledWindow) Returns: bool: The return value is True if at the end, False if not. """ adj_v = widget.get_vadjustment() max_scroll_pos = adj_v.get_upper() - adj_v.get_page_size() return adj_v.get_value() == max_scroll_pos
def init_plot_chart(scrolled_window: Gtk.ScrolledWindow, figure: Figure, canvas: FigureCanvas, axis: Axes) -> Any: axis.grid(True, linestyle=':') axis.margins(x=0, y=0.05) temp_label = Gtk.Label() scrolled_window.add(temp_label) text_color = rgba_to_hex(temp_label.get_style_context().get_color( Gtk.StateType.NORMAL)) text_color_alpha = text_color[:-2] + '80' scrolled_window.remove(temp_label) axis.set_facecolor('#00000000') axis.set_xlabel('Temperature [°C]', color=text_color) axis.set_ylabel('Duty [%]', color=text_color) axis.tick_params(colors=text_color, grid_color=text_color_alpha) for spine in axis.spines.values(): spine.set_edgecolor(text_color_alpha) figure.subplots_adjust(top=1) canvas.set_size_request(400, 300) scrolled_window.add_with_viewport(canvas) # Returns a tuple of line objects, thus the comma lines = axis.plot([], [], 'o-', linewidth=3.0, markersize=10, antialiased=True, color=GRAPH_COLOR_HEX) axis.set_ybound(lower=-5, upper=105) axis.set_xbound(MIN_TEMP, MAX_TEMP) figure.canvas.draw() return lines
def _setSubtitleTreeView(self) -> None: """ Sets the scrolled window and a tree view for subtitles info. :return: """ self._subtitles_treeview = TreeView() self._subtitles_treeview.set_grid_lines(TreeViewGridLines.BOTH) scrl_wnd: ScrolledWindow = ScrolledWindow() scrl_wnd.set_hexpand(True) scrl_wnd.set_vexpand(True) scrl_wnd.add(self._subtitles_treeview) self._subtitles_grid.attach(scrl_wnd, 0, 1, 1, 1)
def __init__(self, win, parser='rst', writer='html4', style=''): super(Renderer, self).__init__() scrolled = ScrolledWindow.new(None, None) scrolled.set_policy(PolicyType.AUTOMATIC, PolicyType.AUTOMATIC) self.sb = scrolled.get_vscrollbar() self.add(scrolled) self.webview = WebView() self.webview.connect("mouse-target-changed", self.on_mouse) scrolled.add(self.webview) self.label = Label() self.label.set_halign(Align.START) self.label.set_valign(Align.END) self.add_overlay(self.label) self.set_writer(writer) self.set_parser(parser) self.style = style self.tab_width = 8 self.__win = win
def init_plot_chart(scrolled_window: Gtk.ScrolledWindow, figure: Figure, canvas: FigureCanvas, axis: Axes) -> Any: # 3.4.1 display workaround: axis.patch.set_visible(False) temp_window = Gtk.Window() style = temp_window.get_style_context() bg_colour = style.get_background_color( Gtk.StateType.NORMAL).to_color().to_floats() color_converter = ColorConverter() color_converter.to_rgba(bg_colour) figure.patch.set_facecolor(bg_colour) # correct text and line colors temp_label = Gtk.Label() scrolled_window.add(temp_label) text_color = rgba_to_hex(temp_label.get_style_context().get_color( Gtk.StateType.NORMAL)) text_color_alpha = text_color[:-2] + '80' scrolled_window.remove(temp_label) axis.grid(True, linestyle=':') axis.margins(x=0, y=0.05) axis.set_xlabel('Liquid temperature [°C]', color=text_color) axis.set_ylabel('Duty [%]', color=text_color) axis.tick_params(colors=text_color, grid_color=text_color_alpha) for spine in axis.spines.values(): spine.set_edgecolor(text_color_alpha) figure.subplots_adjust(top=1) canvas.set_size_request(400, 300) scrolled_window.add_with_viewport(canvas) # Returns a tuple of line objects, thus the comma lines = axis.plot([], [], 'o-', linewidth=3.0, markersize=10, antialiased=True) axis.set_ybound(lower=0, upper=105) axis.set_xbound(MIN_TEMP, MAX_TEMP) figure.canvas.draw() return lines
def _setSentenceRelated(self) -> None: """ Sets up the sentence editing widgets related. Also initialize both text buffers. :return: """ box: Box = Box() self._main_box.pack_start(box, False, True, 0) box.set_orientation(Orientation.VERTICAL) setMargin(box, 5) toolbar: Toolbar = Toolbar() box.pack_start(toolbar, False, True, 0) toolbar.set_halign(Align.END) setMargin(toolbar, 5) lbl: Label = Label() lbl.set_markup('<i><b>Front</b></i>') box.pack_start(lbl, False, True, 0) lbl.set_halign(Align.START) setMargin(lbl, 5) scrl_wnd: ScrolledWindow = ScrolledWindow() scrl_wnd.set_hexpand(True) scrl_wnd.set_vexpand(True) textview: TextView = TextView() scrl_wnd.add(textview) box.pack_start(scrl_wnd, False, True, 0) self._textbuffer_front = textview.get_buffer() lbl2: Label = Label() lbl2.set_halign(Align.START) lbl2.set_markup('<i><b>Back</b></i>') box.pack_start(lbl2, False, True, 0) setMargin(lbl2, 5) scrl_wnd2: ScrolledWindow = ScrolledWindow() scrl_wnd2.set_hexpand(True) scrl_wnd2.set_vexpand(True) textview2: TextView = TextView() scrl_wnd2.add(textview2) box.pack_end(scrl_wnd2, False, True, 0) self._textbuffer_back = textview2.get_buffer() # this depends on the text buffer to be initialized self._setToolbarColorButton(toolbar) toolbar.insert(SeparatorToolItem(), 3) self._setToolbarUnderlineButton(toolbar) self._setToolbarBoldButton(toolbar) self._setToolbarItalicButton(toolbar) toolbar.insert(SeparatorToolItem(), 7) self._setToolbarTagRemoverButton(toolbar)
def start_playback(wdg): # Create GStreamer instance self.gst = GStreamer() self.gst.set_playback('gapless') self.gst.player.connect('about-to-finish', self.song_nearly_ended) self.gst.stop() self.current_song = False self.current_album = False # Prepare buttons self.btn_playpause = wdg[0][7] self.btn_previous = wdg[0][5] self.btn_next = wdg[0][8] self.btn_stop = wdg[0][6] self.btn_previous.connect('clicked', self.previous_pressed) self.btn_stop.connect('clicked', self.stop_pressed) self.btn_playpause.connect('clicked', self.play_pressed) self.btn_next.connect('clicked', self.next_pressed) self.btn_player = wdg[0][9] self.headerbar = wdg[0][0] # Create the player box and popover gtkpla = join(self.functions.datadir, 'glade', 'playerbar.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gtkpla) basebox = win.get_object('playerbox') wdg[0][0].add(basebox) self.player_event = win.get_object('player_event') self.player_event.set_size_request(32, 32) self.player_button_img = win.get_object('image_cover') self.player_event.connect('button-press-event', self.show_player) default = join(self.functions.datadir, 'image', 'logo_head_big.png') cover_px = Pixbuf.new_from_file_at_scale(default, 20, 20, True) self.player_button_img.set_from_pixbuf(cover_px) self.player_event.set_sensitive(False) self.player_scalab = win.get_object('label_scale') self.player_scalab.set_markup('<span size="small">00:00</span>') self.player_sca = win.get_object('scale') self.player_sca.connect('change-value', self.on_change_value) self.player_sca.set_sensitive(False) # Create the player popover gtkpla = join(self.functions.datadir, 'glade', 'playerpopover.ui') win = gtk_builder() win.add_from_file(gtkpla) hbox = win.get_object('box-player') self.player_img = win.get_object('image') self.player_pop = Popover.new(self.player_event) self.player_pop.set_size_request(200, 200) self.player_pop.add(hbox) self.lyrics_button = wdg[1].get_object('tool-lyrics') self.lyrics_pop = Popover.new(self.lyrics_button) self.lyrics_pop.set_size_request(400, 600) box = Box(1, 0) self.lyrics_swin = ScrolledWindow() lyrics_tview = TextView() lyrics_tview.set_editable(False) self.lyrics_buffer = TextBuffer() lyrics_tview.set_buffer(self.lyrics_buffer) self.lyrics_swin.add(lyrics_tview) box.add(self.lyrics_swin) self.lyrics_wait = Spinner() self.lyrics_wait.props.active = True box.add(self.lyrics_wait) self.lyrics_pop.add(box) def show_lyrics(widget): if self.current_song: title = self.current_song.title artist = self.current_song.artist album = self.current_song.album filename = self.current_song.filename sn = self.functions.get_hash(title, artist) lyrics_file = join(self.userconf.datadir, '%s.lyrics' % sn) lyrics = self.lyrics_downloader.get_lyrics(title, artist, True) self.lyrics_pop.show_all() if lyrics is not None: self.lyrics_wait.hide() self.lyrics_swin.show() self.lyrics_buffer.set_text(lyrics) else: self.lyrics_swin.hide() self.lyrics_wait.show() self.lyrics_buffer.set_text('') self.lyrics_button.connect('clicked', show_lyrics) self.lyrics_button.set_sensitive(False)
class Player: def __init__(self, extensionsloader): self.extensions = extensionsloader self.module = {'name': 'Player'} self.config = {} self.functions = Functions() self.userconf = ConfigLoader() self.lyrics_downloader = LyricsDownloader() def start_playback(wdg): # Create GStreamer instance self.gst = GStreamer() self.gst.set_playback('gapless') self.gst.player.connect('about-to-finish', self.song_nearly_ended) self.gst.stop() self.current_song = False self.current_album = False # Prepare buttons self.btn_playpause = wdg[0][7] self.btn_previous = wdg[0][5] self.btn_next = wdg[0][8] self.btn_stop = wdg[0][6] self.btn_previous.connect('clicked', self.previous_pressed) self.btn_stop.connect('clicked', self.stop_pressed) self.btn_playpause.connect('clicked', self.play_pressed) self.btn_next.connect('clicked', self.next_pressed) self.btn_player = wdg[0][9] self.headerbar = wdg[0][0] # Create the player box and popover gtkpla = join(self.functions.datadir, 'glade', 'playerbar.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gtkpla) basebox = win.get_object('playerbox') wdg[0][0].add(basebox) self.player_event = win.get_object('player_event') self.player_event.set_size_request(32, 32) self.player_button_img = win.get_object('image_cover') self.player_event.connect('button-press-event', self.show_player) default = join(self.functions.datadir, 'image', 'logo_head_big.png') cover_px = Pixbuf.new_from_file_at_scale(default, 20, 20, True) self.player_button_img.set_from_pixbuf(cover_px) self.player_event.set_sensitive(False) self.player_scalab = win.get_object('label_scale') self.player_scalab.set_markup('<span size="small">00:00</span>') self.player_sca = win.get_object('scale') self.player_sca.connect('change-value', self.on_change_value) self.player_sca.set_sensitive(False) # Create the player popover gtkpla = join(self.functions.datadir, 'glade', 'playerpopover.ui') win = gtk_builder() win.add_from_file(gtkpla) hbox = win.get_object('box-player') self.player_img = win.get_object('image') self.player_pop = Popover.new(self.player_event) self.player_pop.set_size_request(200, 200) self.player_pop.add(hbox) self.lyrics_button = wdg[1].get_object('tool-lyrics') self.lyrics_pop = Popover.new(self.lyrics_button) self.lyrics_pop.set_size_request(400, 600) box = Box(1, 0) self.lyrics_swin = ScrolledWindow() lyrics_tview = TextView() lyrics_tview.set_editable(False) self.lyrics_buffer = TextBuffer() lyrics_tview.set_buffer(self.lyrics_buffer) self.lyrics_swin.add(lyrics_tview) box.add(self.lyrics_swin) self.lyrics_wait = Spinner() self.lyrics_wait.props.active = True box.add(self.lyrics_wait) self.lyrics_pop.add(box) def show_lyrics(widget): if self.current_song: title = self.current_song.title artist = self.current_song.artist album = self.current_song.album filename = self.current_song.filename sn = self.functions.get_hash(title, artist) lyrics_file = join(self.userconf.datadir, '%s.lyrics' % sn) lyrics = self.lyrics_downloader.get_lyrics(title, artist, True) self.lyrics_pop.show_all() if lyrics is not None: self.lyrics_wait.hide() self.lyrics_swin.show() self.lyrics_buffer.set_text(lyrics) else: self.lyrics_swin.hide() self.lyrics_wait.show() self.lyrics_buffer.set_text('') self.lyrics_button.connect('clicked', show_lyrics) self.lyrics_button.set_sensitive(False) # Acquire the songs tree def acquire_tree(st): self.songs_tree = st self.extensions.connect('OnSongsTreeCreated', acquire_tree) self.extensions.connect('OnBluemindoStarted', start_playback) self.extensions.connect('OnPlayNewSong', self.on_play_new_song) self.extensions.connect('OnPlayNewAlbum', self.on_play_new_album) self.extensions.connect('OnAbortPlayback', self.on_abort_playback) self.extensions.connect('OnPlayPressed', self.play_pressed) self.extensions.connect('OnStopPressed', self.stop_pressed) self.extensions.connect('OnNextPressed', self.next_pressed) self.extensions.connect('OnPreviousPressed', self.previous_pressed) def previous_pressed(self, wdg=None): if self.current_album: # We are listening an album: move to previous song album_items = len(self.current_album.tracks) - 1 a = -1 for sng in self.current_album.tracks: a += 1 if sng.track == self.current_song.track: item_in_album = a if item_in_album > 0: self.on_play_new_song(self.current_album.tracks[item_in_album - 1]) else: self.stop_pressed(None) else: # We were a listening to a single song, try to ask another one self.extensions.load_event('AskPreviousSong', self.current_song) def stop_pressed(self, wdg=None): # Aborting playback cur = self.gst.getnow() self.gst.stop() # Update global vars self.current_song = False self.current_album = False # Update file current_playing = join(self.userconf.datadir, 'current-playing') if exists(current_playing): os_remove(current_playing) # Update user interface self.btn_playpause.set_image(Image.new_from_gicon(ThemedIcon( name='media-playback-start-symbolic'), IconSize.BUTTON)) self.headerbar.props.subtitle = '' default = join(self.functions.datadir, 'image', 'logo_head_big.png') cover_px = Pixbuf.new_from_file_at_scale(default, 20, 20, True) self.player_button_img.set_from_pixbuf(cover_px) self.player_event.set_sensitive(False) self.lyrics_button.set_sensitive(False) self.player_sca.set_sensitive(False) # Do we have to send the signal? if wdg is not None: self.extensions.load_event('OnStopPressed') def play_pressed(self, wdg=None): # Get GStreamer status, don't do anything if playser is stopped first_state = self.gst.getstatus() if first_state == 'STOP': return # Toggles play/pause self.gst.playpause(None) new_state = self.gst.getstatus() # Update user interface if new_state == 'PAUSED': self.btn_playpause.set_image(Image.new_from_gicon(ThemedIcon( name='media-playback-start-symbolic'), IconSize.BUTTON)) else: self.btn_playpause.set_image(Image.new_from_gicon(ThemedIcon( name='media-playback-pause-symbolic'), IconSize.BUTTON)) def next_pressed(self, wdg=None): if self.current_album: # We are listening an album: move to next song album_items = len(self.current_album.tracks) - 1 a = -1 for sng in self.current_album.tracks: a += 1 if sng.track == self.current_song.track: item_in_album = a if item_in_album < album_items: self.on_play_new_song(self.current_album.tracks[item_in_album + 1]) else: self.stop_pressed(None) else: # We were a listening to a single song, try to ask another one self.extensions.load_event('AskNextSong', self.current_song) def on_abort_playback(self): self.stop_pressed(None) def on_play_new_song(self, song): # Guess ReplayGain mode if hasattr(song, 'rg_mode_guess') and song.rg_mode_guess == 'album': self.gst.change_rg_mode('album') else: if not self.current_album: self.gst.change_rg_mode('track') else: if song in self.current_album.tracks: self.gst.change_rg_mode('album') else: self.current_album = False self.gst.change_rg_mode('track') # Play the song cur = self.gst.getnow() self.gst.playpause(song.filename) # Update global vars self.current_song = song # Update user interface self.btn_playpause.set_image(Image.new_from_gicon(ThemedIcon( name='media-playback-pause-symbolic'), IconSize.BUTTON)) title = song.title artist = song.artist album = song.album filename = song.filename self.headerbar.props.subtitle = title + ' - ' + artist default = join(self.functions.datadir, 'image', 'logo_head_big.png') bdir = join(self.userconf.datadir, 'modules', 'player', 'covers') cover = join(bdir, self.functions.get_hash(album, artist)) if isfile(cover): cover_px = Pixbuf.new_from_file_at_scale(cover, 32, 32, True) else: cover_px = Pixbuf.new_from_file_at_scale(default, 20, 20, True) self.player_button_img.set_from_pixbuf(cover_px) self.player_event.set_sensitive(True) self.lyrics_button.set_sensitive(True) # Update file current_playing = join(self.userconf.datadir, 'current-playing') file_ = open(current_playing, 'w') file_.write(title + ' - ' + artist + ' (from: ' + album + ')') file_.close() # Update player informations if isfile(cover): cover_px = Pixbuf.new_from_file_at_scale(cover, 200, 200, True) else: cover_px = Pixbuf.new_from_file_at_scale(default, 120, 120, True) self.player_img.set_from_pixbuf(cover_px) # Create the scale self.player_sca.set_sensitive(True) self.player_sca.set_range(0, float(song.length)) timeout_add(500, self.scale_timer) # Download lyrics thread = Thread(group=None, target=self.lyrics_downloader.get_lyrics, name='lyrics', args=(title, artist)) thread.start() # Send notification to extensions about this new song self.extensions.load_event('HasStartedSong', song) def on_play_new_album(self, album): self.current_album = album self.on_play_new_song(album.tracks[0]) def song_nearly_ended(self, *args): idle_add(self.next_pressed, True) def show_player(self, widget, ka): self.player_pop.show_all() def scale_timer(self): pos = self.gst.getposition() position = int(self.gst.getposition() / 1000000000) self.player_scalab.set_markup('<span size="small">' + self.functions.human_length(position) + '</span>') self.player_sca.set_value(position) return True def on_change_value(self, widget, scroll, value): seconds = int(value) self.gst.seek(seconds)
def scroll_to( scroll: Gtk.ScrolledWindow, target: Gtk.Widget, duration: int = 600) -> bool: """Animate the scroll for duration in milliseconds.""" def get_end_point( scroll: Gtk.ScrolledWindow, target: Gtk.Widget) -> int: talloc = target.get_allocation() adjustment = scroll.get_vadjustment() start_point = adjustment.get_value() page_size = adjustment.get_page_size() if start_point <= talloc.y \ and (talloc.y+talloc.height) <= (start_point+page_size): # If all parts of the target widget content are visible, # no need to animate the scroll. return -1 else: if talloc.y > start_point: # If the height of the target widget is greater than the # height of its container, scroll to the top-left # coordinates of the widget. Otherwise, scroll to the # bottom-right coordinates of the widget. if talloc.height > page_size: end_point = talloc.y else: end_point = min(adjustment.get_upper()-page_size, talloc.y+talloc.height-page_size) else: end_point = talloc.y return end_point frame_clock = scroll.get_frame_clock() start_time = frame_clock.get_frame_time() end_time = start_time + 1000*duration if hasattr(scroll, 'anime_id') \ and scroll.anime_id: scroll.remove_tick_callback(scroll.anime_id) def animate( scroll: Gtk.ScrolledWindow, frame_clock: Gdk.FrameClock, target: Gtk.Widget) -> bool: current_time = frame_clock.get_frame_time() adjustment = scroll.get_vadjustment() start_point = adjustment.get_value() end_point = get_end_point(scroll, target) if current_time < end_time \ and end_point != -1 \ and adjustment.get_value() != end_point: t = (current_time-start_time) / (end_time-start_time) t = Animation.ease_out_cubic(t) adjustment.set_value(start_point + t*(end_point-start_point)) return GLib.SOURCE_CONTINUE else: scroll.anime_id = None return GLib.SOURCE_REMOVE scroll.anime_id = scroll.add_tick_callback(animate, target) return False
def __init__(self, entity, *args, new=False, **kwargs): ScrolledWindow.__init__(self, *args, **kwargs) claims = entity['claims'] if not 'P18' in claims: self.image.set_visible(False) for i, P in enumerate(claims): download_light(P, self.load_property, i) N = len(claims[P]) if N > 5: frame = ScrolledWindow() frame.height = 36 * 6 frame.set_min_content_height(frame.height) else: frame = Frame() frame.set_shadow_type(2) frame.set_visible(True) values = Values() values.connect("reference-toggled", self.reference_toggled_cb, frame) frame.add(values) self.statements.attach(frame, 1, i, 3, 1) for claim in claims[P]: claim = claim.toJSON() self.load_value_async(claim, values)