def __init__(self): widgetset.SolidBackground.__init__(self, itemlistwidgets.StandardView.BACKGROUND_COLOR) bg = widgetutil.RoundedSolidBackground(widgetutil.WHITE) vbox = widgetset.VBox() title = widgetset.HBox() logo = imagepool.get_image_display(resources.path("images/icon-search_large.png")) title.pack_start(widgetutil.align_middle(logo)) label = widgetset.Label(self.TITLE) label.set_bold(True) label.set_size(widgetutil.font_scale_from_osx_points(30)) title.pack_start(widgetutil.align_middle(label, left_pad=5)) vbox.pack_start(widgetutil.align_center(title, bottom_pad=20)) desc = widgetset.Label(self.DESC) vbox.pack_start(widgetutil.align_center(desc, bottom_pad=40)) engine_width = int((desc.get_width() - 30) / 2) engine_widgets = self.build_engine_widgets() for widgets in engine_widgets[:-1]: # widgets with borders hbox = widgetset.HBox(spacing=30) for widget in widgets: widget.set_size_request(engine_width, 45) hbox.pack_start(widget, expand=True) vbox.pack_start(hbox) hbox = widgetset.HBox(spacing=30) for widget in engine_widgets[-1]: # has no border widget.set_has_border(False) widget.set_size_request(engine_width, 45) hbox.pack_start(widget, expand=True) vbox.pack_start(hbox) bg.add(widgetutil.pad(vbox, 45, 45, 45, 45)) self.add(widgetutil.align(bg, xalign=0.5, top_pad=50))
def __init__(self): widgetset.VBox.__init__(self) if not app.sharing_manager.mdns_present: sharing_broken = SharingBroken() sharing_broken.connect('install-clicked', self.daap_install_clicked) self.pack_start(widgetutil.align_center(sharing_broken)) title = widgetset.HBox() logo = widgetset.ImageDisplay( imagepool.get(resources.path('images/icon-connect_large.png'))) title.pack_start(widgetutil.align_middle(logo)) label = widgetset.Label(_("Connect")) label.set_size(widgetutil.font_scale_from_osx_points(30)) label.set_bold(True) title.pack_start(widgetutil.align_middle(label, left_pad=5)) self.pack_start( widgetutil.align_center(title, top_pad=30, bottom_pad=20)) bottom = widgetset.VBox() self._build_daap_section(bottom) self._build_sync_section(bottom) self._build_app_store_section(bottom) self._build_android_section(bottom) self.pack_start(widgetutil.align_center(bottom)) self.callback_handle = app.backend_config_watcher.connect_weak( 'changed', self.on_config_changed)
def __init__(self): widgetset.VBox.__init__(self) if not app.sharing_manager.mdns_present: sharing_broken = SharingBroken() sharing_broken.connect('install-clicked', self.daap_install_clicked) self.pack_start(widgetutil.align_center(sharing_broken)) title = widgetset.HBox() logo = widgetset.ImageDisplay(imagepool.get( resources.path('images/icon-connect_large.png'))) title.pack_start(widgetutil.align_middle(logo)) label = widgetset.Label(_("Connect")) label.set_size(widgetutil.font_scale_from_osx_points(30)) label.set_bold(True) title.pack_start(widgetutil.align_middle(label, left_pad=5)) self.pack_start(widgetutil.align_center(title, top_pad=30, bottom_pad=20)) bottom = widgetset.VBox() self._build_daap_section(bottom) self._build_sync_section(bottom) self._build_app_store_section(bottom) self._build_android_section(bottom) self.pack_start(widgetutil.align_center(bottom))
def __init__(self, engine): widgetset.Background.__init__(self) hbox = widgetset.HBox(spacing=15) self.pack(hbox, imagepool.get_image_display(searchengines.icon_path_for_engine(engine))) label = widgetset.Label(engine.title) label.set_size(widgetutil.font_scale_from_osx_points(14)) label.set_bold(True) self.pack(hbox, widgetutil.align_left(label), expand=True) self.add(hbox) self.has_border = True
def __init__(self, engine): widgetset.Background.__init__(self) hbox = widgetset.HBox(spacing=15) self.pack(hbox, imagepool.get_image_display( searchengines.icon_path_for_engine(engine))) label = widgetset.Label(engine.title) label.set_size(widgetutil.font_scale_from_osx_points(14)) label.set_bold(True) self.pack(hbox, widgetutil.align_left(label), expand=True) self.add(hbox) self.has_border = True
def __init__(self): self.device = None widgetset.VBox.__init__(self) self.button_row = segmented.SegmentedButtonsRow() for key, name in ( ('main', _('Main')), ('podcasts', _('Podcasts')), ('playlists', _('Playlists')), ('settings', _('Settings'))): button = DeviceTabButtonSegment(key, name, self._tab_clicked) self.button_row.add_button(name.lower(), button) self.button_row.set_active('main') self.pack_start(widgetutil.align_center( self.button_row.make_widget(), top_pad=50)) self.tabs = {} self.tab_container = widgetset.Background() self.pack_start(self.tab_container, expand=True) label_size = widgetutil.font_scale_from_osx_points(16) vbox = widgetset.VBox() label = widgetset.Label(_("Drag individual video and audio files " "onto the device in the sidebar to copy " "them.")) label.set_size(label_size) vbox.pack_start(widgetutil.align_center(label, top_pad=50)) label = widgetset.Label(_("Use these options and the tabs above for " "automatic syncing.")) label.set_size(label_size) vbox.pack_start(widgetutil.align_center(label, top_pad=10)) self.device_size = SizeWidget() self.device_size.sync_button.connect('clicked', self.sync_clicked) self.pack_end(self.device_size) self.sync_container = widgetset.Background() self.pack_end(widgetutil.align_center(self.sync_container)) self.add_tab('main', vbox) self.add_tab('podcasts', widgetutil.align_center(PodcastSyncWidget())) self.add_tab('playlists', widgetutil.align_center(PlaylistSyncWidget())) self.add_tab('settings', widgetutil.align_center(DeviceSettingsWidget()))
def __init__(self): self.device = None widgetset.VBox.__init__(self) self.button_row = segmented.SegmentedButtonsRow() for key, name in (('main', _('Main')), ('podcasts', _('Podcasts')), ('playlists', _('Playlists')), ('settings', _('Settings'))): button = DeviceTabButtonSegment(key, name, self._tab_clicked) self.button_row.add_button(name.lower(), button) self.button_row.set_active('main') self.pack_start( widgetutil.align_center(self.button_row.make_widget(), top_pad=50)) self.tabs = {} self.tab_container = widgetset.Background() self.pack_start(self.tab_container, expand=True) label_size = widgetutil.font_scale_from_osx_points(16) vbox = widgetset.VBox() label = widgetset.Label( _("Drag individual video and audio files " "onto the device in the sidebar to copy " "them.")) label.set_size(label_size) vbox.pack_start(widgetutil.align_center(label, top_pad=50)) label = widgetset.Label( _("Use these options and the tabs above for " "automatic syncing.")) label.set_size(label_size) vbox.pack_start(widgetutil.align_center(label, top_pad=10)) self.device_size = SizeWidget() self.device_size.sync_button.connect('clicked', self.sync_clicked) self.pack_end(self.device_size) self.sync_container = widgetset.Background() self.pack_end(widgetutil.align_center(self.sync_container)) self.add_tab('main', vbox) self.add_tab('podcasts', widgetutil.align_center(PodcastSyncWidget())) self.add_tab('playlists', widgetutil.align_center(PlaylistSyncWidget())) self.add_tab('settings', widgetutil.align_center(DeviceSettingsWidget()))
def __init__(self): widgetset.VBox.__init__(self) title = widgetset.HBox() logo = widgetset.ImageDisplay( imagepool.get(resources.path('images/icon-playlist_large.png'))) title.pack_start(widgetutil.align_middle(logo)) label = widgetset.Label(_("Playlists")) label.set_size(widgetutil.font_scale_from_osx_points(30)) label.set_bold(True) title.pack_start(widgetutil.align_middle(label, left_pad=5)) self.pack_start( widgetutil.align_center(title, top_pad=30, bottom_pad=20)) bottom = widgetset.VBox() self._build_add_playlist_section(bottom) self.pack_start(widgetutil.align_center(bottom))
class ListViewRendererText(widgetset.ItemListRendererText): """Renderer for list view columns that are just plain text""" bold = False color = widgetutil.BLACK font_size = widgetutil.font_scale_from_osx_points(11) min_width = 50 right_aligned = False def __init__(self): widgetset.ItemListRendererText.__init__(self) self.set_bold(self.bold) self.set_color(self.color) self.set_font_scale(self.font_size) if self.right_aligned: self.set_align('right') def get_value(self, info): return getattr(info, self.attr_name)
def __init__(self): widgetset.VBox.__init__(self) title = widgetset.HBox() logo = widgetset.ImageDisplay(imagepool.get( resources.path('images/icon-playlist_large.png'))) title.pack_start(widgetutil.align_middle(logo)) label = widgetset.Label(_("Playlists")) label.set_size(widgetutil.font_scale_from_osx_points(30)) label.set_bold(True) title.pack_start(widgetutil.align_middle(label, left_pad=5)) self.pack_start(widgetutil.align_center( title, top_pad=30, bottom_pad=20)) bottom = widgetset.VBox() self._build_add_playlist_section(bottom) self.pack_start(widgetutil.align_center(bottom))
def __init__(self, tab_type, selected_tabs): Display.__init__(self) self.type = tab_type self.child_count = self.folder_count = self.folder_child_count = 0 tab_list = app.tabs[tab_type] for tab in selected_tabs: if hasattr(tab, "is_folder") and tab.is_folder: self.folder_count += 1 self.folder_child_count += tab_list.get_child_count(tab.id) else: self.child_count += 1 vbox = widgetset.VBox(spacing=20) label = self._make_label(tab_type, selected_tabs) label.set_size(widgetutil.font_scale_from_osx_points(30)) label.set_bold(True) label.set_color((0.3, 0.3, 0.3)) vbox.pack_start(widgetutil.align_center(label)) vbox.pack_start(widgetutil.align_center(self._make_buttons(tab_type))) self.widget = widgetutil.align_middle(vbox)
def __init__(self, tab_type, selected_tabs): Display.__init__(self) self.type = tab_type self.child_count = self.folder_count = self.folder_child_count = 0 tab_list = app.tabs[tab_type] for tab in selected_tabs: if hasattr(tab, "is_folder") and tab.is_folder: self.folder_count += 1 self.folder_child_count += tab_list.get_child_count(tab.id) else: self.child_count += 1 vbox = widgetset.VBox(spacing=20) label = self._make_label(tab_type, selected_tabs) label.set_size(widgetutil.font_scale_from_osx_points(30)) label.set_bold(True) label.set_color((0.3, 0.3, 0.3)) vbox.pack_start(widgetutil.align_center(label)) vbox.pack_start(widgetutil.align_center( self._make_buttons(tab_type))) self.widget = widgetutil.align_middle(vbox)
class ListViewRenderer(widgetset.ItemListRenderer): """Renderer for more complex list view columns. This class is useful for renderers that use the cellpack.Layout class. """ font_size = widgetutil.font_scale_from_osx_points(11) default_text_color = widgetutil.BLACK selected_text_color = widgetutil.WHITE min_width = 5 min_height = 16 # 21px total - 5px spacing def hotspot_test(self, style, layout_manager, x, y, width, height): layout = self.layout_all(layout_manager, width, height, False) hotspot_info = layout.find_hotspot(x, y) if hotspot_info is None: return None hotspot, x, y = hotspot_info return hotspot def get_size(self, style, layout_manager): layout_manager.set_font(self.font_size) height = max(self.min_height, layout_manager.current_font.line_height()) return (self.min_width, height) def render(self, context, layout_manager, selected, hotspot, hover): layout = self.layout_all(layout_manager, context.width, context.height, selected) layout.draw(context) def layout_all(self, layout_manager, width, height, selected): """Layout the contents of this cell Subclasses must implement this method :param layout_manager: LayoutManager object :param width: width of the area to lay the cell out in :param height: height of the area to lay the cell out in :returns: cellpack.Layout object """ raise NotImplementedError()
def __init__(self): widgetset.SolidBackground.__init__( self, itemlistwidgets.StandardView.BACKGROUND_COLOR) bg = widgetutil.RoundedSolidBackground(widgetutil.WHITE) vbox = widgetset.VBox() title = widgetset.HBox() logo = imagepool.get_image_display( resources.path('images/icon-search_large.png')) title.pack_start(widgetutil.align_middle(logo)) label = widgetset.Label(self.TITLE) label.set_bold(True) label.set_size(widgetutil.font_scale_from_osx_points(30)) title.pack_start(widgetutil.align_middle(label, left_pad=5)) vbox.pack_start(widgetutil.align_center(title, bottom_pad=20)) desc = widgetset.Label(self.DESC) vbox.pack_start(widgetutil.align_center(desc, bottom_pad=40)) engine_width = int((desc.get_width() - 30) / 2) engine_widgets = self.build_engine_widgets() for widgets in engine_widgets[:-1]: # widgets with borders hbox = widgetset.HBox(spacing=30) for widget in widgets: widget.set_size_request(engine_width, 45) hbox.pack_start(widget, expand=True) vbox.pack_start(hbox) hbox = widgetset.HBox(spacing=30) for widget in engine_widgets[-1]: # has no border widget.set_has_border(False) widget.set_size_request(engine_width, 45) hbox.pack_start(widget, expand=True) vbox.pack_start(hbox) bg.add(widgetutil.pad(vbox, 45, 45, 45, 45)) self.add(widgetutil.align(bg, xalign=0.5, top_pad=50))
class MultiRowAlbumRenderer(widgetset.ItemListRenderer): """Renderer for album view.""" IGNORE_PADDING = True DRAW_BACKGROUND = False IMAGE_MARGIN_TOP = 4 IMAGE_MARGIN_BOTTOM = 3 IMAGE_MARGIN_LEFT = 7 IMAGE_MARGIN_RIGHT = 6 MIN_TEXT_WIDTH = 78 TEXT_PADDING_RIGHT = 6 TRACK_NUMBER_MARGIN_RIGHT = 13 BACKGROUND_COLOR = widgetutil.WHITE TEXT_COLOR = widgetutil.BLACK TRACK_TEXT_COLOR = widgetutil.css_to_color('#969696') BOTTOM_LINE_COLOR = widgetutil.css_to_color('#dddddd') FONT_SIZE = widgetutil.font_scale_from_osx_points(11) min_width = 260 def __init__(self): widgetset.ItemListRenderer.__init__(self) self._render_strategy = _StandardRenderStrategy() self._setup_default_image_map() def _setup_default_image_map(self): """Setup the _default_image_map attribute. _default_image_map maps the default images for things to a default image that looks better in album view. """ # check if we're using one of the default image files and switch to an # album-view-specific default file in that case mappings = [ ('thumb-default-audio.png', 'album-view-default-audio.png'), ('thumb-default-video.png', 'album-view-default-video.png'), ('icon-podcast-small.png', 'album-view-default-podcast.png'), ('icon-watched-folder.png', 'album-view-watched-folder.png'), ] self._default_image_map = {} for src, dest in mappings: src_path = resources.path('images/%s' % src) dest_path = resources.path('images/%s' % dest) self._default_image_map[src_path] = dest_path def get_image_path(self): image_path = self._render_strategy.get_image_path( self.info, self.get_first_info()) if image_path in self._default_image_map: return self._default_image_map[image_path] else: return image_path def get_album(self): return self._render_strategy.get_album(self.info, self.get_first_info()) def get_artist(self): return self._render_strategy.get_artist(self.info, self.get_first_info()) def get_track_number(self): return self._render_strategy.get_track_number(self.info, self.get_first_info()) def get_current_row(self): return self.group_info[0] def get_total_rows(self): return self.group_info[1] def get_first_info(self): return self.group_info[2] def switch_mode(self, new_mode): """Switch which mode we use to render the album art. Currently there are 3 modes: - 'standard' -- standard view of the data - 'feed' -- use feed info instead of album info - 'video' -- mode for the all videos tab """ if new_mode == 'standard': self._render_strategy = _StandardRenderStrategy() elif new_mode == 'feed': self._render_strategy = _FeedRenderStrategy() elif new_mode == 'video': self._render_strategy = _VideoRenderStrategy() else: raise ValueError("Unknown mode: %s" % new_mode) def get_size(self, style, layout_manager): # return 0 for height because we render to multiple columns. We let # the other columns determin the row height return self.min_width, 0 def hotspot_test(self, style, layout_manager, x, y, width, height): return 'album-click' def render(self, context, layout_manager, selected, hotspot, hover): if not self.sanity_check_before_render(context): return # draw our background color behind everything. We need this in case # there's transparency in our album art context.set_color(self.BACKGROUND_COLOR) context.rectangle(0, 0, context.width, context.height) context.fill() self.calc_album_art_size(context) self.render_album_art(context) self.render_track_number(context, layout_manager) self.render_album_or_artist(context, layout_manager) def sanity_check_before_render(self, context): """Do some sanity checking before starting to render things. Returns True if we're okay to render, False if we should bail """ if self.group_info is None: # we can't render if group_info isn't set logging.warn("group_info is None in MultiRowAlbumRenderer") return False if context.height == 0: # not sure how this would happen, but we need to avoid # divide-by-zero errors if it does logging.warn("row height is 0 in MultiRowAlbumRenderer") return False return True def calc_album_art_size(self, context): """Calculate how big we are going to draw album art. This is currently big enough so it fits in 6 rows with the top/bottom padding. """ self.album_art_size = context.height * 6 self.album_art_size -= (self.IMAGE_MARGIN_TOP + self.IMAGE_MARGIN_BOTTOM) def make_album_art(self, context): """Make an image to draw as album art. Returns ImageSurface to draw or None if we don't have anything """ if self.get_total_rows() < 6: # don't draw album art if we have less than 6 items in the group return None album_art_path = self.get_image_path() if album_art_path is None: return None return imagepool.get_surface( album_art_path, size=(self.album_art_size, self.album_art_size), invalidator=util.mtime_invalidator(album_art_path)) def render_album_art(self, context): album_art = self.make_album_art(context) if (album_art is not None and self.cell_contains_album_art(context, album_art)): self.render_album_art_slice(context, album_art) def cell_contains_album_art(self, context, album_art): """Does this cell contain a portion of the album art? """ album_art_bottom = album_art.height + self.IMAGE_MARGIN_TOP cell_top = self.get_current_row() * context.height cell_bottom = cell_top + context.height return (cell_bottom > self.IMAGE_MARGIN_TOP and cell_top < album_art_bottom) def render_album_art_slice(self, context, image): """Render the slice of the album art for this cell.""" if context.width < image.width: # not enough width to draw return # setup variables to track where we are copying from and to dest_x = self.IMAGE_MARGIN_LEFT width = image.width dest_y = 0 height = context.height src_x = 0 src_y = self.get_current_row() * context.height - self.IMAGE_MARGIN_TOP if src_y < 0: # The cell is contains the top padding for our image. # move dest_y and src_y down dest_y -= src_y src_y = 0 # descrease height height -= dest_y src_y_bottom = src_y + height if src_y_bottom > image.height: # The cell is contains the bottom padding for our image. # decrease height extra_space = src_y_bottom - image.height height -= extra_space # draw our image slice if height > 0: image.draw_rect(context, dest_x, dest_y, src_x, src_y, width, height) def render_album_or_artist(self, context, layout_manager): x = (self.album_art_size + self.IMAGE_MARGIN_LEFT + self.IMAGE_MARGIN_RIGHT) if self.get_current_row() == 0: text = self.get_artist() bold = True elif self.get_current_row() == 1: text = self.get_album() bold = False else: return width = self.album_artist_text_end - x if width < 10: # don't try to render if we have a really small, or negative # amount of space return # setup a textbox for the text layout_manager.set_font(self.FONT_SIZE, bold=bold) layout_manager.set_text_color(self.TEXT_COLOR) textbox = layout_manager.textbox(text) # truncate the textbox to the area we have in a cell. textbox.set_wrap_style('truncated-char') textbox.set_width(width) # middle-align the text to line-up with the other cells line_height = textbox.font.line_height() y = (context.height - line_height) / 2.0 # okay, ready to draw textbox.draw(context, x, y, width, line_height) def render_track_number(self, context, layout_manager): # setup a textbox for the text layout_manager.set_font(self.FONT_SIZE) layout_manager.set_text_color(self.TRACK_TEXT_COLOR) textbox = layout_manager.textbox(str(self.get_track_number())) # place the text on the right-side of the cell text_width, text_height = textbox.get_size() x = context.width - self.TEXT_PADDING_RIGHT - text_width # middle-align the text to line-up with the other cells y = (context.height - text_height) // 2 # okay, ready to draw textbox.draw(context, x, y, text_width, text_height) self.album_artist_text_end = x - self.TEXT_PADDING_RIGHT
def __init__(self): self.device = None widgetset.VBox.__init__(self) self.button_row = segmented.SegmentedButtonsRow() for key, name in ( ('main', _('Main')), ('podcasts', _('Podcasts')), ('playlists', _('Playlists')), ('settings', _('Settings'))): button = DeviceTabButtonSegment(key, name, self._tab_clicked) self.button_row.add_button(name.lower(), button) self.button_row.set_active('main') self.pack_start(widgetutil.align_center( self.button_row.make_widget(), top_pad=50)) self.tabs = {} self.tab_container = widgetset.Background() self.pack_start(self.tab_container, expand=True) label_size = widgetutil.font_scale_from_osx_points(16) vbox = widgetset.VBox() label = widgetset.Label(_("Drag individual video and audio files " "onto the device in the sidebar to copy " "them.")) label.set_size(label_size) vbox.pack_start(widgetutil.align_center(label, top_pad=50)) label = widgetset.Label(_("Use these options and the tabs above for " "automatic syncing.")) label.set_size(label_size) vbox.pack_start(widgetutil.align_center(label, top_pad=10)) self.auto_sync = widgetset.Checkbox(_("Sync automatically?")) self.auto_sync.connect('toggled', self._auto_sync_changed) vbox.pack_start(widgetutil.align_center(self.auto_sync, top_pad=20)) max_fill_label = _( "Don't fill more than %(count)i percent of the " "free space on my device", {'count': id(self)}) checkbox_label, text_label = max_fill_label.split(unicode(id(self)), 1) self.max_fill_enabled = widgetset.Checkbox(checkbox_label) self.max_fill_enabled.connect('toggled', self._max_fill_enabled_changed) self.max_fill_percent = widgetset.TextEntry() self.max_fill_percent.set_size_request(50, -1) self.max_fill_percent.connect('focus-out', self._max_fill_percent_changed) label = widgetset.Label(text_label) vbox.pack_start(widgetutil.align_center( widgetutil.build_hbox([self.max_fill_enabled, self.max_fill_percent, label], 0), top_pad=10)) self.auto_fill = widgetset.Checkbox( _("After syncing my selections in the tabs above, " "fill remaining space with:")) self.auto_fill.connect('toggled', self._auto_fill_changed) vbox.pack_start(widgetutil.align_center(self.auto_fill, top_pad=20)) names = [ (_('Newest Music'), u'recent_music'), (_('Random Music'), u'random_music'), (_('Most Played Songs'), u'most_played_music'), (_('New Playlists'), u'new_playlists'), (_('Most Recent Podcasts'), u'recent_podcasts')] longest = max(names, key=lambda x: len(x[0]))[0] width = widgetset.Label(longest).get_width() less_label = widgetset.Label(_('Less').upper()) less_label.set_size(label_size / 2) more_label = widgetset.Label(_('More').upper()) more_label.set_size(label_size / 2) label_hbox = widgetutil.build_hbox([ less_label, widgetutil.pad(more_label, left=(200 - less_label.get_width() - more_label.get_width()))], padding=0) label_hbox.set_size_request(200, -1) scrollers = [widgetutil.align_right(label_hbox, right_pad=20)] self.auto_fill_sliders = {} for name, setting in names: label = widgetutil.align_right(widgetset.Label(name)) label.set_size_request(width, -1) dragger = AutoFillSlider() dragger.connect('released', self._auto_fill_slider_changed, setting) self.auto_fill_sliders[setting] = dragger hbox = widgetutil.build_hbox([label, dragger], 20) scrollers.append(hbox) vbox.pack_start(widgetutil.align_center( widgetutil.build_vbox(scrollers, 10))) self.device_size = SizeWidget() self.device_size.sync_button.connect('clicked', self.sync_clicked) self.pack_end(self.device_size) self.sync_container = widgetset.Background() self.pack_end(widgetutil.align_center(self.sync_container)) self.add_tab('main', vbox) self.add_tab('podcasts', widgetutil.align_center(PodcastSyncWidget())) self.add_tab('playlists', widgetutil.align_center(PlaylistSyncWidget())) self.add_tab('settings', widgetutil.align_center(DeviceSettingsWidget()))