def __init__(self, device): self.device = device self.id = device.id tab_type = device.tab_type self.type = u'device-%s' % tab_type if tab_type == 'audio': self.titlebar_class = itemlistwidgets.DeviceMusicTitlebar else: self.titlebar_class = itemlistwidgets.DeviceVideosTitlebar itemlistcontroller.AudioVideoItemsController.__init__(self) if (u'%s_sort_state' % tab_type) in device.database: sort_key, ascending = device.database[u'%s_sort_state' % tab_type] for view in self.views.keys(): self.on_sort_changed(self, sort_key, ascending, view) if (u'%s_view' % tab_type) in device.database: view_name = device.database[u'%s_view' % tab_type] if view_name == u'list': view_type = WidgetStateStore.get_list_view_type() else: view_type = WidgetStateStore.get_standard_view_type() elif tab_type == 'audio': view_type = WidgetStateStore.get_list_view_type() else: view_type = WidgetStateStore.get_standard_view_type() self.set_view(None, view_type) self.titlebar.connect('list-view-clicked', self.save_view, 'list') self.titlebar.connect('normal-view-clicked', self.save_view, 'normal')
def update_view_menu_state(): # Error checking for display != None done below in try/except block display = app.display_manager.get_current_display() main_menu = NSApp().mainMenu() # XXX: should be using the tag to prevent interface and locale breakages view_menu = main_menu.itemAtIndex_(6) try: key = (display.type, display.id) except AttributeError: view_menu.setHidden_(True) return view_menu.setHidden_(False) enabled = app.widget_state.get_columns_enabled( display.type, display.id, display.controller.selected_view) for column in WidgetStateStore.get_toggleable_columns(): menu_item = VIEW_ITEM_MAP[column] hidden = not column in WidgetStateStore.get_columns_available( display.type, display.id, display.controller.selected_view) menu_item.setHidden_(hidden) if hidden: continue if column in enabled: state = NSOnState else: state = NSOffState menu_item.setState_(state)
def test_view_types(self): # test that all view types are different view_types = (WidgetStateStore.get_list_view_type(), WidgetStateStore.get_standard_view_type(), WidgetStateStore.get_album_view_type()) for i in range(len(view_types)): for j in range(i + 1, len(view_types)): self.assertNotEqual(view_types[i], view_types[j])
def handle_repeat(self, obj): if app.playback_manager.repeat == WidgetStateStore.get_repeat_playlist(): self.repeat.set_image('repeat-on') self.queue_redraw() elif app.playback_manager.repeat == WidgetStateStore.get_repeat_track(): self.repeat.set_image('repeat-1') self.queue_redraw() else: self.repeat.set_image('repeat') self.queue_redraw()
def find_next_item(self, not_skipped_by_user=True): #if track repeat is on and the user doesn't skip, #shuffle doesn't matter if ((self.repeat == WidgetStateStore.get_repeat_track() and not_skipped_by_user)): return self.currently_playing elif ((not self.shuffle and self.repeat == WidgetStateStore.get_repeat_playlist() and self.is_playing_last_item())): return self._find_playable(self.model.get_first_info()) elif (self.shuffle and self.repeat == WidgetStateStore.get_repeat_off() or self.shuffle and self.repeat == WidgetStateStore.get_repeat_track()): next_item = self.next_shuffle_item() if next_item is None: self.shuffle_upcoming = self.generate_upcoming_shuffle_items() self.shuffle_history = [] return None #stop playback else: # Remove currently playing item from history if it # was removed from the playlist. if not self.shuffle_history: logging.info('find_next_item: shuffle history empty: ' 'case 1') else: if self._is_playing_filtered_item(): self.shuffle_history.pop() self.shuffle_history.append(next_item.id) return next_item elif self.shuffle and WidgetStateStore.get_repeat_playlist(): next_item = self.next_shuffle_item() if next_item is None: #populate with new items self.shuffle_upcoming = self.generate_upcoming_shuffle_items() next_item = self.next_shuffle_item() if next_item is None: #17492 - nothing playable in list return None # Remove currently playing item from history if it # was removed from the playlist. if not self.shuffle_history: logging.info('find_next_item: shuffle history empty: case 2') else: if self._is_playing_filtered_item(): self.shuffle_history.pop() self.shuffle_history.append(next_item.id) return next_item else: if self._is_playing_filtered_item(): return self.model.get_first_info() else: next_item = self.model.get_next_info(self.currently_playing.id) return self._find_playable(next_item)
def _update_view_menu(self): display = app.display_manager.get_current_display() # using hasattr because not all displays have ids and types # TODO: refactor the display type / id system if not (hasattr(display, 'type') and hasattr(display, 'id')): return enabled = set(app.widget_state.get_sorts_enabled(display.type, display.id)) checks = dict(('ToggleColumn-' + column, column in enabled) for column in WidgetStateStore.get_columns()) self.emit('checked-changed', 'ListView', checks) for column in WidgetStateStore.get_columns_available(display.type): self.enabled_groups.add('column-%s' % column)
def _init_widget(self): toolbar = self.build_header_toolbar() self.selected_view = app.widget_state.get_selected_view(self.type, self.id) self.widget = itemlistwidgets.ItemContainerWidget(toolbar, self.selected_view) self.build_widget() list_view = WidgetStateStore.get_list_view_type() self.views[list_view] = self.build_list_view() self.expand_or_contract_item_details() standard_view = WidgetStateStore.get_standard_view_type() standard_view_widget = itemlistwidgets.StandardView( self.item_list, self.build_renderer()) self.views[standard_view] = standard_view_widget standard_view_background = widgetset.SolidBackground( standard_view_widget.BACKGROUND_COLOR) standard_view_background.add(widgetutil.pad(standard_view_widget, top=10, bottom=10)) # set up member attrs to easily get our list/standard view widgets self.list_item_view = self.views[list_view] self.standard_item_view = self.views[standard_view] self.standard_view_toolbar = toolbar standard_view_scroller = widgetset.Scroller(False, True) standard_view_scroller.add(standard_view_background) self.widget.vbox[standard_view].pack_start( standard_view_scroller, expand=True) self.views[standard_view].set_scroller(standard_view_scroller) standard_view_scroller.set_background_color( standard_view_widget.BACKGROUND_COLOR) toolbar.connect_weak('sort-changed', self.on_sort_changed, standard_view) self.widget.item_details.expander_button.connect_weak('clicked', self.on_item_details_expander_clicked) self.list_item_view.connect_weak('sort-changed', self.on_sort_changed, list_view) self.titlebar.connect_weak('list-view-clicked', self.set_view, list_view) self.titlebar.connect_weak('normal-view-clicked', self.set_view, standard_view) self.titlebar.connect_weak('resume-playing', self.on_resume_playing) self.standard_item_view.renderer.signals.connect_weak( 'throbber-drawn', self.on_throbber_drawn)
def toggle_filter(self, filter_): self._filter = WidgetStateStore.toggle_filter(self._filter, filter_) self.video_only = WidgetStateStore.is_view_video_filter(self._filter) self.audio_only = WidgetStateStore.is_view_audio_filter(self._filter) self.movies_only = WidgetStateStore.is_view_movies_filter(self._filter) self.shows_only = WidgetStateStore.is_view_shows_filter(self._filter) self.clips_only = WidgetStateStore.is_view_clips_filter(self._filter) self.podcasts_only = WidgetStateStore.is_view_podcasts_filter(self._filter) self.unwatched_only = WidgetStateStore.has_unwatched_filter( self._filter) self.downloaded_only = WidgetStateStore.has_downloaded_filter( self._filter) self.non_feed_only = WidgetStateStore.has_non_feed_filter( self._filter) self._recalculate_hidden_items()
def _update_view_menu(self): display = app.display_manager.get_current_display() # using hasattr because not all displays have ids and types # TODO: refactor the display type / id system if not (hasattr(display, 'type') and hasattr(display, 'id')): return enabled = set( app.widget_state.get_sorts_enabled(display.type, display.id)) checks = dict(('ToggleColumn-' + column, column in enabled) for column in WidgetStateStore.get_columns()) self.emit('checked-changed', 'ListView', checks) for column in WidgetStateStore.get_columns_available(display.type): self.enabled_groups.add('column-%s' % column)
def toggle_filter(self, filter_): self._filter = WidgetStateStore.toggle_filter(self._filter, filter_) self.video_only = WidgetStateStore.is_view_video_filter(self._filter) self.audio_only = WidgetStateStore.is_view_audio_filter(self._filter) self.movies_only = WidgetStateStore.is_view_movies_filter(self._filter) self.shows_only = WidgetStateStore.is_view_shows_filter(self._filter) self.clips_only = WidgetStateStore.is_view_clips_filter(self._filter) self.podcasts_only = WidgetStateStore.is_view_podcasts_filter( self._filter) self.unwatched_only = WidgetStateStore.has_unwatched_filter( self._filter) self.downloaded_only = WidgetStateStore.has_downloaded_filter( self._filter) self.non_feed_only = WidgetStateStore.has_non_feed_filter(self._filter) self._recalculate_hidden_items()
def _init_widget(self): itemlistcontroller.SimpleItemListController._init_widget(self) standard_view = WidgetStateStore.get_standard_view_type() # 17408: the hotspot handler in the standard view need access to the # playlist id to be able to ditch an item. self.views[standard_view].playlist_id = self.id self.make_drop_handler()
def select_next_item(self, skipped_by_user=False): if (self.repeat == WidgetStateStore.get_repeat_track() and not skipped_by_user): next_item = self.currently_playing else: next_item = self.navigation_strategy.next_item() self._change_currently_playing(next_item)
def update_columns_enabled(self): sorts = app.widget_state.get_sorts_enabled(self.type, self.id) widths = app.widget_state.get_column_widths(self.type, self.id, WidgetStateStore.get_list_view_type()) self.list_item_view.column_widths.update(widths) self.list_item_view.update_sorts(sorts) self.standard_view_toolbar.update_sorts(sorts)
def save_columns(self): """Save enabled columns, column order, and column widths""" columns, widths = self.list_item_view.get_column_state() app.widget_state.set_sorts_enabled(self.type, self.id, columns) list_view_type = WidgetStateStore.get_list_view_type() app.widget_state.update_column_widths( self.type, self.id, list_view_type, widths)
def _get_view_menu(): menu = list() toggleable = WidgetStateStore.get_toggleable_columns() for name in sorted(toggleable, key=COLUMN_LABELS.get): groups = ['column-%s' % name] label = COLUMN_LABELS[name] handler_name = make_column_toggle_handler(name) menu.append(CheckMenuItem(label, handler_name, 'ListView', groups=groups)) return menu
def should_resume(self): if self.force_resume: return True if self.shuffle == True or self.repeat != WidgetStateStore.get_repeat_off(): return False currently_playing = self.playlist.currently_playing return self.item_resume_policy(currently_playing)
def test_default_column_widths(self): # test that all available columns have widths set for them # calculate all columns that available for some display/view # combination available_columns = set() display_id = None # this isn't used yet, just set it to a dummy value for display_type in self.display_types: for view_type in (WidgetStateStore.get_list_view_type(), WidgetStateStore.get_standard_view_type(), WidgetStateStore.get_album_view_type()): available_columns.update( WidgetStateStore.get_columns_available( display_type, display_id, view_type)) # make sure that we have widths for those columns self.assertEqual(available_columns, set(WidgetStateStore.DEFAULT_COLUMN_WIDTHS.keys()))
def _get_view_menu(): menu = list() toggleable = WidgetStateStore.get_toggleable_columns() for name in sorted(toggleable, key=COLUMN_LABELS.get): groups = ['column-%s' % name] label = COLUMN_LABELS[name] handler_name = make_column_toggle_handler(name) menu.append( CheckMenuItem(label, handler_name, 'ListView', groups=groups)) return menu
def should_resume(self): if self.force_resume: return True if(self.shuffle == True or self.repeat != WidgetStateStore.get_repeat_off()): return False currently_playing = self.playlist.currently_playing return self.item_resume_policy(currently_playing)
def toggle_repeat(self): if self.repeat == WidgetStateStore.get_repeat_playlist(): self.set_repeat(WidgetStateStore.get_repeat_track()) elif self.repeat == WidgetStateStore.get_repeat_track(): self.set_repeat(WidgetStateStore.get_repeat_off()) elif self.repeat == WidgetStateStore.get_repeat_off(): self.set_repeat(WidgetStateStore.get_repeat_playlist()) #handle unknown values else: self.set_repeat(WidgetStateStore.get_repeat_off())
def _create_navigation_strategy(self): if self.item_list.item_in_list(self.currently_playing.id): initial_item = self.currently_playing else: initial_item = None repeat = (self.repeat == WidgetStateStore.get_repeat_playlist()) if self.shuffle: self.navigation_strategy = ShuffleNavigationStrategy( initial_item, self.item_list, repeat) else: self.navigation_strategy = LinearNavigationStrategy( initial_item, self.item_list, repeat)
def __init__(self): self._sorter = DEFAULT_SORT self.model = widgetset.InfoListModel(self._sorter.sort_key, self._sorter.reverse) self.video_only = self.audio_only = False self.movies_only = self.shows_only = False self.clips_only = self.podcasts_only = False self.new_only = False self.unwatched_only = False self.downloaded_only = False self.non_feed_only = False self.resort_on_update = False self._hidden_items = {} self._filter = WidgetStateStore.get_view_all_filter()
def generate_upcoming_shuffle_items(self): if not self.shuffle: return [] elif self.repeat == WidgetStateStore.get_repeat_off() or self.repeat == WidgetStateStore.get_repeat_track(): # random order items = self.get_all_playable_items() shuffle(items) # do not include currently playing item if self.currently_playing: try: items.remove(self.currently_playing.id) except ValueError: pass return items elif self.repeat == WidgetStateStore.get_repeat_playlist(): # random items items = self.get_all_playable_items() if items: return self.random_sequence(items, self.currently_playing.id) else: return [] else: return []
def update_view_menu_state(): display = app.display_manager.get_current_display() main_menu = NSApp().mainMenu() # XXX: should be using the tag to prevent interface and locale breakages view_menu = main_menu.itemAtIndex_(6) try: key = (display.type, display.id) except AttributeError: view_menu.setHidden_(True) return view_menu.setHidden_(False) enabled = app.widget_state.get_sorts_enabled(display.type, display.id) for column in WidgetStateStore.get_toggleable_columns(): menu_item = VIEW_ITEM_MAP[column] hidden = not column in WidgetStateStore.get_columns_available(display.type) menu_item.setHidden_(hidden) if hidden: continue if column in enabled: state = NSOnState else: state = NSOffState menu_item.setState_(state)
def generate_upcoming_shuffle_items(self): if not self.shuffle: return [] elif (self.repeat == WidgetStateStore.get_repeat_off() or self.repeat == WidgetStateStore.get_repeat_track()): #random order items = self.get_all_playable_items() shuffle(items) #do not include currently playing item if self.currently_playing: try: items.remove(self.currently_playing.id) except ValueError: pass return items elif self.repeat == WidgetStateStore.get_repeat_playlist(): #random items items = self.get_all_playable_items() if items: return self.random_sequence(items, self.currently_playing.id) else: return [] else: return []
def __init__(self, item_tracker, start_id): signals.SignalEmitter.__init__(self, "position-changed", "playing-info-changed") self.item_tracker = item_tracker self.model = item_tracker.item_list.model self._tracker_callbacks = [ item_tracker.connect("items-will-change", self._on_items_will_change), item_tracker.connect("items-changed", self._on_items_changed), item_tracker.connect("items-removed-from-source", self._on_items_removed_from_source), ] self.repeat = WidgetStateStore.get_repeat_off() self.shuffle = False self.shuffle_history = [] self.currently_playing = None self.shuffle_upcoming = self.generate_upcoming_shuffle_items() self._pick_initial_item(start_id)
def build_list_view(self): """Build the list view widget for this controller.""" list_view_type = WidgetStateStore.get_list_view_type() columns = app.widget_state.get_sorts_enabled(self.type, self.id) list_view_widths = app.widget_state.get_column_widths( self.type, self.id, list_view_type) column_renderers = self.build_column_renderers() list_view = itemlistwidgets.ListView(self.item_list, column_renderers, columns, list_view_widths) scroller = widgetset.Scroller(True, True) scroller.add(list_view) # make the min-width for list view match standard view scroller.set_size_request(600, -1) self.widget.vbox[list_view_type].pack_start(scroller, expand=True) return list_view
def __init__(self, item_tracker, start_id): signals.SignalEmitter.__init__(self, 'position-changed', 'playing-info-changed') self.item_tracker = item_tracker self.model = item_tracker.item_list.model self._tracker_callbacks = [ item_tracker.connect('items-will-change', self._on_items_will_change), item_tracker.connect('items-changed', self._on_items_changed), item_tracker.connect('items-removed-from-source', self._on_items_removed_from_source) ] self.repeat = WidgetStateStore.get_repeat_off() self.shuffle = False self.shuffle_history = [] self.currently_playing = None self.shuffle_upcoming = self.generate_upcoming_shuffle_items() self._pick_initial_item(start_id)
def _update_view_menu(self): display = app.display_manager.get_current_display() # fetch the enabled/available columns for this display if display is None: # no display? return column_info = display.get_column_info() if column_info is None: # display doesn't support togglable columns return columns_enabled = set(column_info[0]) columns_available = column_info[1] # make available columns user selectable for column in columns_available: self.enabled_groups.add('column-%s' % column) # check the currently enabled columns checks = dict(('ToggleColumn-' + column, column in columns_enabled) for column in WidgetStateStore.get_toggleable_columns()) self.emit('checked-changed', 'ListView', checks)
def find_previous_item(self): if self.shuffle: if not self.shuffle_history: return None current_item = self.shuffle_history.pop() # Only add the currently playing item to upcoming shuffle items # if it exists in the playlist if not self._is_playing_filtered_item(): self.shuffle_upcoming.append(current_item) return self.prev_shuffle_item() elif (not self.shuffle and self.repeat == WidgetStateStore.get_repeat_playlist() and self.is_playing_first_item()): last_item = self._find_playable(self.model.get_last_info(), True) return last_item else: if self._is_playing_filtered_item(): return None else: prev_item = self.model.get_prev_info(self.currently_playing.id) return self._find_playable(prev_item, backwards=True)
def __init__(self): signals.SignalEmitter.__init__(self) self.player = None self.video_display = None self.removing_video_display = False self.detached_window = None self.previous_left_width = 0 self.previous_left_widget = None self.is_fullscreen = False self.is_playing = False self.is_playing_audio = False self.is_paused = False self.is_suspended = False self.shuffle = False self.repeat = WidgetStateStore.get_repeat_off() self.open_finished = False self.open_successful = False self.playlist = None self.mark_as_watched_timeout = None self.update_timeout = None self.manual_item_list = None self.selected_tab_list = self.selected_tabs = None self.presentation_mode = 'fit-to-bounds' self.create_signal('will-start') self.create_signal('selecting-file') self.create_signal('playing-info-changed') self.create_signal('cant-play-file') self.create_signal('will-play') self.create_signal('did-start-playing') self.create_signal('will-play-attached') self.create_signal('will-play-detached') self.create_signal('will-pause') self.create_signal('will-stop') self.create_signal('did-stop') self.create_signal('will-fullscreen') self.create_signal('playback-did-progress') self.create_signal('update-shuffle') self.create_signal('update-repeat')
def get_column_info(self): available = WidgetStateStore.get_columns_available(self.type, self.id, self.controller.selected_view) enabled = app.widget_state.get_columns_enabled(self.type, self.id, self.controller.selected_view) return enabled, available
def setUp(self): MiroTestCase.setUp(self) self.display_types = set(WidgetStateStore.get_display_types())
def test_view_types(self): self.assertNotEqual(WidgetStateStore.get_list_view_type(), WidgetStateStore.get_standard_view_type())
def setUp(self): MiroTestCase.setUp(self) self.display_types = set(WidgetStateStore.get_display_types()) self.columns = set() for display_type in self.display_types: self.columns.update(WidgetStateStore.get_columns_available(display_type))