def __init__(self): super(BlaPreferences.Keybindings, self).__init__( "Global keybindings") from blakeys import BlaKeys blakeys = BlaKeys() actions = [ ("Play/Pause", "playpause"), ("Pause", "pause"), ("Stop", "stop"), ("Previous track", "previous"), ("Next track", "next"), ("Volume up", "volup"), ("Volume down", "voldown"), ("Mute", "mute") ] bindings = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) for label, action in actions: accel = blacfg.getstring("keybindings", action) bindings.append([label, accel]) treeview = gtk.TreeView() treeview.set_property("rules_hint", True) treeview.insert_column_with_attributes( -1, "Action", gtk.CellRendererText(), text=0) def edited(renderer, path, key, mod, *args): action = actions[int(path)][-1] accel = gtk.accelerator_name(key, mod) blakeys.bind(action, accel) bindings.set_value(bindings.get_iter(path), 1, accel) blacfg.set("keybindings", action, accel) def cleared(renderer, path): bindings.set_value(bindings.get_iter(path), 1, None) action = actions[int(path)][-1] blakeys.unbind(blacfg.getstring("keybindings", action)) blacfg.set("keybindings", action, "") renderer = gtk.CellRendererAccel() renderer.set_property("editable", True) renderer.connect("accel_edited", edited) renderer.connect("accel_cleared", cleared) treeview.insert_column_with_attributes( -1, "Binding", renderer, text=1) treeview.set_model(bindings) sw = BlaScrolledWindow() sw.set_shadow_type(gtk.SHADOW_IN) sw.add(treeview) self.pack_start(sw, expand=True) if not blakeys.can_bind(): label = gtk.Label() label.set_markup( "<b>Note</b>: The <i>keybinder</i> module is not " "available on the system.\nAs a result, the settings on " "this page will have no effect.") self.pack_start(label, expand=False, padding=20)
def __init__(self, is_editable, playlist_manager): super(BlaMetadataViewer, self).__init__(spacing=blaconst.WIDGET_SPACING) model = gtk.ListStore(gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT) self._treeview = BlaMetadataViewer.TreeView(model, is_editable=is_editable) self._treeview.set_reorderable(False) self._treeview.set_rubber_banding(True) self._treeview.set_property("rules_hint", True) # Name column r = gtk.CellRendererText() self._treeview.insert_column_with_data_func(-1, "Name", r, self.__cdf_name) # Value column r = gtk.CellRendererText() r.set_property("ellipsize", pango.ELLIPSIZE_END) r.set_property("editable", is_editable) self._treeview.insert_column_with_data_func(-1, "Value", r, self.__cdf_value) if is_editable: def editing_started(renderer, editable, path): self._treeview.set_cursor(path) model = self._treeview.get_model() # Remove the "Varies between tracks" label. if model[path][1] is None: editable.set_text("") r.connect("editing_started", editing_started) def edited(renderer, path, text): row = self._treeview.get_model()[path] identifier = row[0] if row[1] != text: row[1] = text self.emit("value_changed", identifier, text) r.connect("edited", edited) for column in self._treeview.get_columns(): column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) # Wrap the treeview. sw = BlaScrolledWindow() sw.add(self._treeview) self._pb = gtk.ProgressBar() self._pb.set_visible(False) self.pack_start(sw, expand=True) self.pack_start(self._pb, expand=False) playlist_manager.connect_object("selection_changed", BlaMetadataViewer._update_model, self) self._uris = [] sw.show_all() self.show()
def __init__(self): super(BlaRadio, self).__init__(spacing=3) hbox = gtk.HBox(spacing=3) entry = gtk.Entry() entry.connect( "activate", lambda *x: self.__add_station(entry.get_text())) hbox.pack_start(entry, expand=True) button = gtk.Button("Add") button.connect( "clicked", lambda *x: self.__add_station(entry.get_text())) hbox.pack_start(button, expand=False) button = gtk.Button("Remove") button.connect("clicked", self.__remove_stations) hbox.pack_start(button, expand=False) def open_(*args): diag = gtk.FileChooserDialog( "Select files", action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) diag.set_local_only(True) response = diag.run() filename = diag.get_filename() diag.destroy() if response == gtk.RESPONSE_OK and filename: filename = filename.strip() filename and self.__add_station(filename) button = gtk.Button("Open...") button.connect("clicked", open_) hbox.pack_start(button, expand=False) model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) self.__treeview = blaguiutils.BlaTreeViewBase() self.__treeview.set_model(model) self.__treeview.set_enable_search(True) self.__treeview.set_rubber_banding(True) self.__treeview.set_property("rules_hint", True) # Playing column r = gtk.CellRendererPixbuf() self.__treeview.insert_column_with_attributes( -1, "Playing", r, stock_id=0) r.set_property("stock-size", gtk.ICON_SIZE_MENU) r.set_property("xalign", 0.5) self.__treeview.get_columns()[-1].set_alignment(0.5) # The remaining columns def cell_data_func(column, renderer, model, iterator, identifier): renderer.set_property("text", model[iterator][1][identifier]) columns = [ ("Organization", "organization"), ("Station", "station"), ("URI", "uri"), ("Location", "location") ] for header, identifier in columns: r = gtk.CellRendererText() r.set_property("ellipsize", pango.ELLIPSIZE_END) c = gtk.TreeViewColumn(header) c.set_resizable(True) c.set_expand(True) c.pack_start(r) c.set_cell_data_func(r, cell_data_func, identifier) self.__treeview.append_column(c) sw = BlaScrolledWindow() sw.set_shadow_type(gtk.SHADOW_IN) sw.add(self.__treeview) self.pack_start(hbox, expand=False) self.pack_start(sw, expand=True) self.__treeview.enable_model_drag_dest( [("radio", gtk.TARGET_OTHER_APP, 0), ("text/uri-list", gtk.TARGET_OTHER_APP, 1), ("text/plain", gtk.TARGET_OTHER_APP, 2), ("TEXT", gtk.TARGET_OTHER_APP, 3), ("STRING", gtk.TARGET_OTHER_APP, 4), ("COMPOUND_TEXT", gtk.TARGET_OTHER_APP, 5), ("UTF8_STRING", gtk.TARGET_OTHER_APP, 6)], gtk.gdk.ACTION_COPY) self.__treeview.enable_model_drag_source( gtk.gdk.BUTTON1_MASK, [("radio", gtk.TARGET_SAME_WIDGET, 0)], gtk.gdk.ACTION_MOVE) self.__treeview.connect("drag_data_get", self.__drag_data_get) self.__treeview.connect("drag_data_received", self.__drag_data_recv) self.__treeview.connect("popup", self.__popup_menu) self.__treeview.connect( "row_activated", lambda treeview, path, column: self.__get_station(path)) self.__treeview.connect("key_press_event", self.__key_press_event) player.connect_object("get_station", BlaRadio.__get_station, self) player.connect_object("state_changed", BlaRadio.__update_rows, self) blaplay.bla.register_for_cleanup(self) self.show_all()
def __init__(self, parent): super(BlaFileBrowser, self).__init__() self.__pixbufs = { "directory": self.__get_pixbuf(gtk.STOCK_DIRECTORY), "file": self.__get_pixbuf(gtk.STOCK_FILE) } self.__history = BlaFileBrowser.History() vbox = gtk.VBox() # The toolbar table = gtk.Table(rows=1, columns=6, homogeneous=False) buttons = [ (gtk.STOCK_GO_BACK, lambda *x: self.__update_from_history(backwards=True)), (gtk.STOCK_GO_UP, lambda *x: self.__update_directory( os.path.dirname(self.__directory))), (gtk.STOCK_GO_FORWARD, lambda *x: self.__update_from_history(backwards=False)), (gtk.STOCK_HOME, lambda *x: self.__update_directory(os.path.expanduser("~"))) ] def add_button(icon, callback, idx): button = gtk.Button() button.add( gtk.image_new_from_stock(icon, gtk.ICON_SIZE_SMALL_TOOLBAR)) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", callback) table.attach(button, idx, idx+1, 0, 1, xoptions=not gtk.EXPAND) idx = 0 for icon, callback in buttons: add_button(icon, callback, idx) idx += 1 # Add the entry field separately. self.__entry = gtk.Entry() self.__entry.connect( "activate", lambda *x: self.__update_directory(self.__entry.get_text())) def key_press_event_entry(entry, event): if (blagui.is_accel(event, "Escape") or blagui.is_accel(event, "<Ctrl>L")): self.__entry.select_region(-1, -1) self.__treeview.grab_focus() return True elif (blagui.is_accel(event, "Up") or blagui.is_accel(event, "Down")): return True return False self.__entry.connect("key_press_event", key_press_event_entry) table.attach(self.__entry, idx, idx+1, 0, 1) idx += 1 add_button(gtk.STOCK_REFRESH, lambda *x: self.__update_directory(refresh=True), idx) vbox.pack_start(table, expand=False, fill=False) # The treeview self.__treeview = BlaTreeView(parent=parent, multicol=True, browser_id=blaconst.BROWSER_FILESYSTEM) self.__treeview.set_enable_search(True) self.__treeview.set_search_column(2) self.__treeview.enable_model_drag_source( gtk.gdk.BUTTON1_MASK, [blagui.DND_TARGETS[blagui.DND_URIS]], gtk.gdk.ACTION_COPY) self.__treeview.connect_object( "drag_data_get", BlaFileBrowser.__drag_data_get, self) def key_press_event(treeview, event): if blagui.is_accel(event, "<Ctrl>L"): self.__entry.grab_focus() return True return False self.__treeview.connect("key_press_event", key_press_event) model = gtk.ListStore(*self.__layout) self.__filt = model.filter_new() self.__filt.set_visible_func(self.__visible_func) self.__treeview.set_model(self.__filt) self.__directory = blacfg.getstring("general", "filesystem.directory") # Name column c = gtk.TreeViewColumn("Name") c.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) c.set_resizable(True) c.set_expand(True) c.set_fixed_width(1) r = gtk.CellRendererPixbuf() r.set_property("xalign", 0.0) c.pack_start(r, expand=False) c.add_attribute(r, "pixbuf", 1) r = gtk.CellRendererText() r.set_property("xalign", 0.0) c.pack_start(r) # TODO: Use a cdf instead. c.add_attribute(r, "text", 2) r.set_property("ellipsize", pango.ELLIPSIZE_END) self.__treeview.append_column(c) # TODO: turn this into nemo's size column (for files, display the size, # for directories the number of items) # Last modified column c = gtk.TreeViewColumn() c.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) c.set_resizable(True) title = "Last modified" label = gtk.Label(title) width = label.create_pango_layout(title).get_pixel_size()[0] c.set_title(title) r = gtk.CellRendererText() r.set_property("ellipsize", pango.ELLIPSIZE_END) c.pack_start(r) c.set_cell_data_func(r, self.__last_modified_cb) c.set_min_width(width + 12 + r.get_property("xpad")) self.__treeview.append_column(c) self.__treeview.connect("row_activated", self.__open) self.__update_directory(self.__directory) self.__treeview.columns_autosize() sw = BlaScrolledWindow() sw.add(self.__treeview) vbox.pack_start(sw, expand=True) # The search bar hbox = gtk.HBox() hbox.pack_start(gtk.Label("Filter:"), expand=False, padding=2) self.__filter_entry = gtk.Entry() self.__filter_entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, gtk.STOCK_CLEAR) self.__filter_entry.connect( "icon_release", lambda *x: x[0].delete_text(0, -1)) self.__filter_entry.connect( "changed", self.__filter_parameters_changed) self.__filter_entry.connect( "activate", lambda *x: self.__filt.refilter()) hbox.pack_start(self.__filter_entry, expand=True) button = gtk.Button() button.add( gtk.image_new_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)) button.connect("clicked", lambda *x: self.__filt.refilter()) hbox.pack_start(button, expand=False) vbox.pack_start(hbox, expand=False) self.pack_start(vbox)
def __init__(self, parent): super(BlaLibraryBrowser, self).__init__() self.__treeview = BlaTreeView(parent=parent, multicol=False, browser_id=blaconst.BROWSER_LIBRARY) self.__treeview.set_headers_visible(False) column = gtk.TreeViewColumn() column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) self.__treeview.append_column(column) self.__treeview.connect("row_collapsed", self.__row_collapsed) self.__treeview.connect("row_expanded", self.__row_expanded) self.__treeview.enable_model_drag_source( gtk.gdk.BUTTON1_MASK, [blagui.DND_TARGETS[blagui.DND_LIBRARY]], gtk.gdk.ACTION_COPY) self.__treeview.connect_object( "drag_data_get", BlaLibraryBrowser.__drag_data_get, self) sw = BlaScrolledWindow() sw.add(self.__treeview) hbox = gtk.HBox() cb = gtk.combo_box_new_text() for label in ["directory", "artist", "artist - album", "album", "genre", "year"]: cb.append_text(label) cb.set_active(blacfg.getint("library", "organize.by")) cb.connect("changed", self.__organize_by_changed) alignment = gtk.Alignment() alignment.add(gtk.Label("Organize by:")) table = gtk.Table(rows=2, columns=1, homogeneous=False) table.attach(alignment, 0, 1, 0, 1, xpadding=2, ypadding=2) table.attach(cb, 0, 1, 1, 2) hbox.pack_start(table, expand=False) def queue_model_update(*args): self.__queue_model_update(blacfg.getint("library", "organize.by")) self.__entry = gtk.Entry() self.__entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, gtk.STOCK_CLEAR) self.__entry.connect( "icon_release", lambda *x: x[0].delete_text(0, -1)) self.__entry.connect("changed", self.__filter_parameters_changed) self.__entry.connect("activate", queue_model_update) button = gtk.Button() button.add( gtk.image_new_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)) button.connect("clicked", queue_model_update) alignment = gtk.Alignment() alignment.add(gtk.Label("Filter:")) table = gtk.Table(rows=2, columns=1, homogeneous=False) table.attach(alignment, 0, 1, 0, 1, xpadding=2, ypadding=2) hbox2 = gtk.HBox() hbox2.pack_start(self.__entry, expand=True) hbox2.pack_start(button, expand=False) table.attach(hbox2, 0, 1, 1, 2) hbox.pack_start(table) self.pack_start(sw, expand=True) self.pack_start(hbox, expand=False) self.update_treeview_style() self.update_tree_lines() def config_changed(cfg, section, key): if section == "library": if key == "custom.browser": self.update_treeview_style() elif key == "draw.tree.lines": self.update_tree_lines() blacfg.connect("changed", config_changed) library.connect("library_updated", queue_model_update) queue_model_update()
def __init__(self, views): super(BlaSidePane, self).__init__(spacing=blaconst.WIDGET_SPACING) notebook = gtk.Notebook() notebook.set_scrollable(True) # Set up the lyrics textview. self.__tv = gtk.TextView() self.__tv.set_size_request(self.__MIN_WIDTH, -1) self.__tv.set_editable(False) self.__tv.set_cursor_visible(False) self.__tv.set_wrap_mode(gtk.WRAP_WORD) self.__tv.set_justification(gtk.JUSTIFY_CENTER) sw = BlaScrolledWindow() sw.set_shadow_type(gtk.SHADOW_NONE) sw.add(self.__tv) sw.show_all() self.__style = self.__tv.get_modifier_style().copy() self.__tb = self.__tv.get_buffer() self.__tb.create_tag("bold", weight=pango.WEIGHT_BOLD) self.__tb.create_tag("large", scale=pango.SCALE_LARGE) self.__tb.create_tag("italic", style=pango.STYLE_ITALIC) self.__tag = self.__tb.create_tag("color") # Set up the view selector. viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_IN) self.__treeview = blaguiutils.BlaTreeViewBase( allow_empty_selection=False) self.__treeview.get_selection().set_mode(gtk.SELECTION_SINGLE) self.__treeview.set_headers_visible(False) self.__treeview.set_property("rules_hint", True) r = gtk.CellRendererText() r.set_property("ellipsize", pango.ELLIPSIZE_END) c = gtk.TreeViewColumn() c.pack_start(r, expand=True) c.add_attribute(r, "text", 0) r = gtk.CellRendererText() r.set_alignment(1.0, 0.5) c.pack_start(r, expand=False) def cell_data_func(column, renderer, model, iterator): count = model[iterator][1] renderer.set_property( "markup", "<i>(%d)</i>" % count if count > 0 else "") c.set_cell_data_func(r, cell_data_func) self.__treeview.append_column(c) viewport.add(self.__treeview) model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT) self.__treeview.set_model(model) [model.append([view.view_name, 0]) for view in views] selection = self.__treeview.get_selection() selection.select_path(blacfg.getint("general", "view")) self.__treeview.get_selection().connect( "changed", self.__selection_changed) self.cover_display = BlaSidePane.BlaCoverDisplay() hbox = gtk.HBox(spacing=blaconst.WIDGET_SPACING) hbox.pack_start(viewport, expand=True) hbox.pack_start(self.cover_display, expand=False, fill=True) notebook.append_page(BlaTagEditor(views[blaconst.VIEW_PLAYLISTS]), gtk.Label("Tags")) notebook.append_page(BlaProperties(views[blaconst.VIEW_PLAYLISTS]), gtk.Label("Properties")) notebook.append_page(sw, gtk.Label("Lyrics")) def switch_page(notebook, page, page_num): action_widget = notebook.get_action_widget(gtk.PACK_END) if action_widget.child is not None: action_widget.remove(action_widget.child) page = notebook.get_nth_page(page_num) blacfg.set("general", "metadata.view", page_num) if page_num == blaconst.METADATA_TAGS: widget = page.get_control_widget() elif page_num == blaconst.METADATA_LYRICS: button = gtk.Button() button.set_tooltip_text("Edit lyrics") button.set_relief(gtk.RELIEF_NONE) button.set_focus_on_click(False) button.add( gtk.image_new_from_stock(gtk.STOCK_EDIT, gtk.ICON_SIZE_MENU)) style = gtk.RcStyle() style.xthickness = style.ythickness = 0 button.modify_style(style) # TODO: Implement a widget to edit metadata. button.connect("clicked", lambda *x: False) button.show_all() widget = button action_widget.set_visible(False) return else: action_widget.set_visible(False) return action_widget.add(widget) action_widget.set_visible(True) action_widget.show_all() viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) notebook.set_action_widget(viewport, gtk.PACK_END) notebook.connect("switch_page", switch_page) page_num = blacfg.getint("general", "metadata.view") notebook.set_current_page(page_num) # Make sure the notebook's action widget gets initialized. switch_page(notebook, None, page_num) self.pack_start(notebook, expand=True) self.pack_start(hbox, expand=False) # Hook up the metadata callbacks. BlaSidePane.fetcher = blametadata.BlaFetcher() self.fetcher.connect_object( "lyrics", BlaSidePane.__update_lyrics, self) self.fetcher.connect_object( "cover", type(self.cover_display).update, self.cover_display) notebook.show() hbox.show_all() self.show()
def __init__(self): super(BlaPreferences.LibraryBrowsersSettings, self).__init__( "Library/Browsers") restrict_string = blacfg.getstring("library", "restrict.to") exclude_string = blacfg.getstring("library", "exclude") def destroy(*args): if (restrict_string != blacfg.getstring("library", "restrict.to") or exclude_string != blacfg.getstring("library", "exclude")): library.sync() self.connect("destroy", destroy) hbox = gtk.HBox(spacing=10) model = gtk.ListStore(gobject.TYPE_STRING) treeview = gtk.TreeView(model) treeview.set_property("rules_hint", True) r = gtk.CellRendererText() treeview.insert_column_with_attributes( -1, "Directories", r, text=0) sw = BlaScrolledWindow() sw.set_shadow_type(gtk.SHADOW_IN) sw.set_size_request(-1, 140) sw.add(treeview) directories = blacfg.getdotliststr("library", "directories") for f in directories: model.append([f]) table = gtk.Table(rows=2, columns=1) items = [ ("Add...", self.__add_directory), ("Remove", self.__remove_directory), ("Rescan all", self.__rescan_all) ] for idx, (label, callback) in enumerate(items): button = gtk.Button(label) button.connect("clicked", callback, treeview) table.attach(button, 0, 1, idx, idx+1, yoptions=not gtk.EXPAND) hbox.pack_start(sw, expand=True) hbox.pack_start(table, expand=False, fill=False) # Update library checkbutton update_library = gtk.CheckButton("Update library on startup") update_library.set_active( blacfg.getboolean("library", "update.on.startup")) update_library.connect( "toggled", lambda cb: blacfg.setboolean("library", "update.on.startup", cb.get_active())) # The file types restrict_to_entry = gtk.Entry() restrict_to_entry.set_tooltip_text( "Comma-separated list, works on filenames") restrict_to_entry.set_text( blacfg.getstring("library", "restrict.to")) restrict_to_entry.connect( "changed", lambda entry: blacfg.set("library", "restrict.to", entry.get_text())) exclude_entry = gtk.Entry() exclude_entry.set_tooltip_text( "Comma-separated list, works on filenames") exclude_entry.set_text( blacfg.getstring("library", "exclude")) exclude_entry.connect( "changed", lambda entry: blacfg.set("library", "exclude", entry.get_text())) pairs = [ (blaconst.ACTION_SEND_TO_CURRENT, "send to current playlist"), (blaconst.ACTION_ADD_TO_CURRENT, "add to current playlist"), (blaconst.ACTION_SEND_TO_NEW, "send to new playlist"), (blaconst.ACTION_EXPAND_COLLAPSE, "expand/collapse") ] # FIXME: Ugly!! actions = [""] * 4 for idx, label in pairs: actions[idx] = label comboboxes = [] def cb_changed(combobox, key): blacfg.set("library", "%s.action" % key, combobox.get_active()) for key in ["doubleclick", "middleclick", "return"]: cb = gtk.combo_box_new_text() map(cb.append_text, actions) if key == "return": cb.remove_text(3) cb.set_active(blacfg.getint("library", "%s.action" % key)) cb.connect("changed", cb_changed, key) comboboxes.append(cb) widgets = [restrict_to_entry, exclude_entry] + comboboxes labels = ["Restrict to", "Exclude", "Double-click", "Middle-click", "Return"] action_table = gtk.Table(rows=len(labels), columns=2, homogeneous=False) count = 0 for label, widget in zip(labels, widgets): label = gtk.Label("%s:" % label) label.set_alignment(xalign=0.0, yalign=0.5) action_table.attach(label, 0, 1, count, count+1, xoptions=gtk.FILL, xpadding=5) action_table.attach(widget, 1, 2, count, count+1) count += 1 hbox2 = gtk.HBox(spacing=10) draw_tree_lines = gtk.CheckButton("Draw tree lines in browsers") draw_tree_lines.set_active( blacfg.getboolean("library", "draw.tree.lines")) draw_tree_lines.connect("toggled", self.__tree_lines_changed) custom_library_browser = gtk.CheckButton( "Use custom treeview as library browser") custom_library_browser.set_active( blacfg.getboolean("library", "custom.browser")) custom_library_browser.connect( "toggled", self.__custom_library_browser_changed) hbox2.pack_start(draw_tree_lines) hbox2.pack_start(custom_library_browser) self.pack_start(hbox, expand=False) self.pack_start(update_library, expand=False) self.pack_start(action_table, expand=False) self.pack_start(hbox2, expand=False)