def submit_track(self, player): if (not blacfg.getstring("lastfm", "user") or not self.get_session_key(create=True)): return gobject.source_remove(self.__tid) # We request track submission on track changes. We don't have to check # here if a track passes the ignore settings as this is done when the # __uri attribute of the instance is set further down below. self.__submit_last_track() self.__elapsed = 0 self.__iterations = 0 track = player.get_track() if not track or player.radio or player.video: return if self.__passes_ignore(track): self.__uri = track.uri self.__start_time = int(time.time()) self.__tid = gobject.timeout_add(1000, self.__query_status) else: self.__uri = None artist, title = track[ARTIST], track[TITLE] if artist and title: item = "%s - %s" % (artist, title) else: item = os.path.basename(track.uri) print_d("Not submitting \"%s\" to the scrobbler queue" % item)
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): if not self.can_bind(): return for action in self.__ACTIONS.iterkeys(): accel = blacfg.getstring("keybindings", action) if accel: self.bind(action, accel)
def __get_filter(): # This returns a filter function which URIs have to pass in order # for them to be considered in the library browser. def get_regexp(string): tokens = [t.replace(".", "\.").replace("*", ".*") for t in map(str.strip, string.split(","))] return re.compile(r"(%s)" % "|".join(tokens)) restrict_re = get_regexp( blacfg.getstring("library", "restrict.to").strip()) exclude_string = blacfg.getstring("library", "exclude").strip() if exclude_string: exclude_re = get_regexp(exclude_string) def filt(s): return restrict_re.match(s) and not exclude_re.match(s) else: filt = restrict_re.match return filt
def __init__(self): super(BlaPreferences.LastfmSettings, self).__init__("last.fm") self.connect("destroy", self.__save) scrobble = gtk.CheckButton("Enable scrobbling") scrobble.set_active(blacfg.getboolean("lastfm", "scrobble")) scrobble.connect("toggled", self.__scrobble_changed) self.__user_entry = gtk.Entry() self.__user_entry.set_text(blacfg.getstring("lastfm", "user")) self.__ignore_entry = gtk.Entry() self.__ignore_entry.set_text( blacfg.getstring("lastfm", "ignore.pattern")) self.__ignore_entry.set_tooltip_text("Comma-separated list") nowplaying = gtk.CheckButton("Submit \"Listening now\" messages") nowplaying.set_active(blacfg.getboolean("lastfm", "now.playing")) nowplaying.connect("toggled", self.__nowplaying_changed) count = 0 pairs = [ ("Username", self.__user_entry), ("Ignore pattern", self.__ignore_entry) ] table = gtk.Table(rows=len(pairs), columns=2, homogeneous=False) count = 0 for label, widget in pairs: label = gtk.Label("%s:" % label) label.set_alignment(xalign=0.0, yalign=0.5) table.attach(label, 0, 1, count, count+1, xoptions=gtk.FILL, xpadding=5) table.attach(widget, 1, 2, count, count+1) count += 1 self.pack_start(scrobble, expand=False) self.pack_start(table, expand=False) self.pack_start(nowplaying, expand=False)
def __change_location(self, button, location): diag = blaguiutils.BlaDialog(title="Change location") # Country list country = blacfg.getstring("general", "events.country") entry1 = gtk.Entry() entry1.set_text(country) city = blacfg.getstring("general", "events.city") entry2 = gtk.Entry() entry2.set_text(city) table = gtk.Table(rows=2, columns=2, homogeneous=False) table.set_border_width(10) items = [("Country", entry1), ("City", entry2)] for idx, (label, entry) in enumerate(items): entry.connect( "activate", lambda *x: diag.response(gtk.RESPONSE_OK)) label = gtk.Label("%s:" % label) label.set_alignment(xalign=0.0, yalign=0.5) table.attach(label, idx, idx+1, 0, 1) table.attach(entry, idx, idx+1, 1, 2) diag.vbox.pack_start(table) diag.show_all() response = diag.run() if response == gtk.RESPONSE_OK: country = entry1.get_text() city = entry2.get_text() diag.destroy() if not city: location.set_markup("<i>Unspecified</i>") else: location.set_text( ", ".join([city, country] if country else [city])) blacfg.set("general", "events.country", country) blacfg.set("general", "events.city", city)
def __passes_ignore(self, track): tokens = map( str.strip, filter(None, blacfg.getstring("lastfm", "ignore.pattern").split(","))) res = [re.compile(t.decode("utf-8"), re.UNICODE | re.IGNORECASE) for t in tokens] for r in res: search = r.search for identifier in [ARTIST, TITLE]: if search(track[identifier]): return False return True
def create_popup_menu(track=None): user = blacfg.getstring("lastfm", "user") if not user: return None menu = gtk.Menu() # User profile m = gtk.MenuItem("View your profile") m.connect("activate", lambda *x: blautil.open_url("http://last.fm/user/%s" % user)) menu.append(m) # Love/Unlove song artist = title = track_label = None if track is None: track = player.get_track() try: artist = track[ARTIST].replace(" ", "+") title = track[TITLE].replace(" ", "+") except TypeError: return menu limit = 40 track_label = "%s - %s" % (track[ARTIST], track[TITLE]) if len(track_label) > limit: track_label = "%s..." % track_label[:limit] m = gtk.MenuItem("Love song \"%s\"" % track_label) m.connect("activate", lambda *x: love_unlove_song(track, unlove=False)) menu.append(m) m = gtk.MenuItem("Unlove song \"%s\"" % track_label) m.connect("activate", lambda *x: love_unlove_song(track, unlove=True)) menu.append(m) m = gtk.MenuItem("View song profile of \"%s\"" % track_label) m.connect( "activate", lambda *x: blautil.open_url("http://last.fm/music/%s/_/%s" % (artist, title))) menu.append(m) m = gtk.MenuItem("View artist profile of \"%s\"" % track[ARTIST]) m.connect( "activate", lambda *x: blautil.open_url("http://last.fm/music/%s" % artist)) menu.append(m) return menu
def get_new_releases(recommended=False): user = blacfg.getstring("lastfm", "user") if not user: return [] url = "%s&method=user.getNewReleases&user=%s&userecs=%d" % ( blaconst.LASTFM_BASEURL, user, int(recommended)) url = quote_url(url) response = get_response(url, "albums") if isinstance(response, ResponseError): print_d("Failed to get new releases: %s" % response) return None response = response.content return response["album"]
def enable_equalizer(self, state): values = None if state: try: values = blacfg.getlistfloat( "equalizer.profiles", blacfg.getstring("player", "equalizer.profile")) except: pass if not values: values = [0.0] * blaconst.EQUALIZER_BANDS try: for band, value in enumerate(values): self.__equalizer.set_property("band%d" % band, value) except AttributeError: pass
def __button_press_event(self, event): if event.button not in (1, 2, 3): return True try: path = self.__treeview.get_path_at_pos( *map(int, [event.x, event.y]))[0] except TypeError: return False model = self.__treeview.get_model() release = model[path][0] if not isinstance(release, BlaRelease): return True if event.button in (1, 2): if event.type in (gtk.gdk._2BUTTON_PRESS, gtk.gdk._3BUTTON_PRESS): return True return False release_url = release.release_url artist_url = release.artist_url items = [ ("View release page", lambda *x: blautil.open_url(release_url)), ("View artist profile", lambda *x: blautil.open_url(artist_url)) ] user = blacfg.getstring("lastfm", "user") if user: artist_history_url = os.path.basename(release.artist_url) artist_history_url = ( "http://www.last.fm/user/%s/library/music/%s" % (user, artist_history_url)) items.append(("View artist history", lambda *x: blautil.open_url(artist_history_url))) menu = gtk.Menu() for label, callback in items: m = gtk.MenuItem(label) m.connect("activate", callback) menu.append(m) menu.show_all() menu.popup(None, None, None, event.button, event.time) return False
def get_session_key(cls, create=False): session_key = blacfg.getstring("lastfm", "sessionkey") if session_key: return session_key if not create or cls.__requested_authorization: return None if not cls.__token: cls.__token = get_request_token() if not cls.__token: return None cls.__request_authorization() return None # FIXME: on start when there are unsubmitted scrobbles and no session # key but a user name the request auth window will pop up which # causes the statusbar to not update properly # TODO: check this more than once # We have a token, but it still might be unauthorized, i.e. we can't # create a session key from it. If that is the case ignore the # situation until the next start of blaplay. In order to avoid sending # requests to last.fm all the time we set an escape variable when we # encounter an unauthorized token. method = "auth.getSession" params = [ ("method", method), ("api_key", blaconst.LASTFM_APIKEY), ("token", cls.__token) ] api_signature = sign_api_call(params) string = "&".join(["%s=%s" % p for p in params]) url = "%s&api_sig=%s&%s" % ( blaconst.LASTFM_BASEURL, api_signature, string) response = get_response(url, "session") if isinstance(response, ResponseError): session_key = None cls.__requested_authorization = True else: session_key = response.content["key"] blacfg.set("lastfm", "sessionkey", session_key) return session_key
def love_unlove_song(track, unlove=False): if (not blacfg.getstring("lastfm", "user") or not track[ARTIST] or not track[TITLE]): return session_key = BlaScrobbler.get_session_key(create=True) if not session_key: return method = "track.unlove" if unlove else "track.love" params = [ ("method", method), ("api_key", blaconst.LASTFM_APIKEY), ("artist", track[ARTIST]), ("track", track[TITLE]), ("sk", session_key) ] # Sign API call. api_signature = sign_api_call(params) params.append(("api_sig", api_signature)) response = post_message(params) if isinstance(response, ResponseError): print_d("Failed to love/unlove song: %s" % response)
def __update_models(self): def set_sensitive(state): self.__hbox.set_sensitive(state) self.__treeview.set_sensitive(state) return False gobject.idle_add(set_sensitive, False) with self.__lock: images = set() active = blacfg.getint("general", "events.filter") limit = blacfg.getint("general", "events.limit") country = blacfg.getstring("general", "events.country") city = blacfg.getstring("general", "events.city") events = (blafm.get_events(limit=limit, recommended=True), blafm.get_events(limit=limit, recommended=False, country=country, city=city)) if events[0]: self.__count_recommended = len(events[0]) if events[1]: self.__count_all = len(events[1]) items = [ (blaconst.EVENTS_RECOMMENDED, events[0] or []), (blaconst.EVENTS_ALL, events[1] or []) ] for filt, events in items: model = gtk.ListStore(gobject.TYPE_PYOBJECT) previous_date = None for event in events: event = BlaEvent(event) date = event.date if previous_date != date: previous_date = date model.append( ["\n<span size=\"larger\"><b>%s</b></span>\n" % date]) model.append([event]) path = event.get_image() if path: images.add(path) self.__models[filt] = model # Get rid of images for events that don't show up anymore. for image in set(blautil.discover(blaconst.EVENTS)).difference( images): try: os.unlink(image) except OSError: pass gobject.idle_add(set_sensitive, True) # TODO: Only set the model when we verified that we successfully # retrieved event information. This avoids that we delete a # restored model. gobject.idle_add(self.__treeview.set_model, self.__models[active]) if active == blaconst.EVENTS_RECOMMENDED: count = self.__count_recommended else: count = self.__count_all gobject.idle_add( self.emit, "count_changed", blaconst.VIEW_EVENTS, count) return True
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)
def __init__(self): super(BlaEventBrowser, self).__init__() self.set_shadow_type(gtk.SHADOW_NONE) vbox = gtk.VBox() vbox.set_border_width(10) # Heading hbox = gtk.HBox() items = [ ("<b><span size=\"xx-large\">Events</span></b>", 0.0, 0.5, 0), ("<b><span size=\"x-small\">powered by</span></b>", 1.0, 1.0, 5) ] for markup, xalign, yalign, padding in items: label = gtk.Label() label.set_markup(markup) alignment = gtk.Alignment(xalign, yalign) alignment.add(label) hbox.pack_start(alignment, expand=True, fill=True, padding=padding) image = gtk.image_new_from_file(blaconst.LASTFM_LOGO) alignment = gtk.Alignment(1.0, 0.5) alignment.add(image) hbox.pack_start(alignment, expand=False) vbox.pack_start(hbox, expand=False) # Location hbox_location = gtk.HBox(spacing=5) label = gtk.Label() label.set_markup("<b>Location:</b>") location = gtk.Label() country = blacfg.getstring("general", "events.country") city = blacfg.getstring("general", "events.city") if not city: location.set_markup("<i>Unspecified</i>") else: location.set_text( ", ".join([city, country] if country else [city])) button = gtk.Button("Change location") button.set_focus_on_click(False) button.connect( "clicked", self.__change_location, location) for widget, padding in [(label, 0), (location, 0), (button, 5)]: alignment = gtk.Alignment(0.0, 0.5) alignment.add(widget) hbox_location.pack_start(alignment, expand=False, padding=padding) vbox.pack_start(hbox_location, expand=False) # Type selector self.__hbox = gtk.HBox(spacing=5) self.__hbox.set_border_width(10) items = [ ("Recommended events", blaconst.EVENTS_RECOMMENDED), ("All events", blaconst.EVENTS_ALL) ] active = blacfg.getint("general", "events.filter") radiobutton = None for label, filt in items: radiobutton = gtk.RadioButton(radiobutton, label) if filt == active: radiobutton.set_active(True) radiobutton.connect( "toggled", self.__filter_changed, filt, hbox_location) self.__hbox.pack_start(radiobutton, expand=False) button = gtk.Button("Refresh") button.set_focus_on_click(False) button.connect_object("clicked", BlaEventBrowser.__update_models, self) self.__hbox.pack_start(button, expand=False) vbox.pack_start(self.__hbox, expand=False) hbox = gtk.HBox(spacing=5) hbox.pack_start(gtk.Label("Maximum number of results:"), expand=False) limit = blacfg.getint("general", "events.limit") adjustment = gtk.Adjustment(limit, 1.0, 100.0, 1.0, 5.0, 0.0) spinbutton = gtk.SpinButton(adjustment) spinbutton.set_numeric(True) spinbutton.connect( "value_changed", lambda sb: blacfg.set("general", "events.limit", sb.get_value())) hbox.pack_start(spinbutton, expand=False) vbox.pack_start(hbox, expand=False) # Events list def cell_data_func_pixbuf(column, renderer, model, iterator): event = model[iterator][0] try: renderer.set_property("content", event.image) except AttributeError: renderer.set_property("content", event) def cell_data_func_text(column, renderer, model, iterator): event = model[iterator][0] # FIXME: Too much code in the try-block. try: limit = 8 markup = "<b>%s</b>\n%%s" % event.event_name artists = ", ".join(event.artists[:limit]) if len(event.artists) > limit: artists += ", and more" markup %= artists except AttributeError: markup = "" renderer.set_property("markup", markup.replace("&", "&")) def cell_data_func_text2(column, renderer, model, iterator): event = model[iterator][0] try: markup = "<b>%s</b>\n%s\n%s" % ( event.venue, event.city, event.country) except AttributeError: markup = "" renderer.set_property("markup", markup.replace("&", "&")) def cell_data_func_text3(column, renderer, model, iterator): event = model[iterator][0] markup = "" try: if event.cancelled: markup = "<span size=\"x-large\"><b>Cancelled</b></span>" except AttributeError: pass renderer.set_property("markup", markup.replace("&", "&")) self.__treeview = blaguiutils.BlaTreeViewBase( set_button_event_handlers=False) self.__treeview.set_rules_hint(True) self.__treeview.get_selection().set_mode(gtk.SELECTION_SINGLE) self.__treeview.set_headers_visible(False) # Image r = BlaCellRendererPixbuf() column = gtk.TreeViewColumn() column.pack_start(r, expand=False) column.set_cell_data_func(r, cell_data_func_pixbuf) # Title and artists r = gtk.CellRendererText() r.set_alignment(0.0, 0.0) r.set_property("wrap_mode", pango.WRAP_WORD) r.set_property("wrap_width", 350) column.pack_start(r, expand=False) column.set_cell_data_func(r, cell_data_func_text) # Location r = gtk.CellRendererText() r.set_alignment(0.0, 0.0) r.set_property("ellipsize", pango.ELLIPSIZE_END) column.pack_start(r) column.set_cell_data_func(r, cell_data_func_text2) # Event cancelled status r = gtk.CellRendererText() r.set_property("ellipsize", pango.ELLIPSIZE_END) column.pack_start(r) column.set_cell_data_func(r, cell_data_func_text3) self.__treeview.append_column(column) self.__treeview.connect("row_activated", self.__row_activated) self.__treeview.connect_object( "key_press_event", BlaEventBrowser.__key_press_event, self) self.__treeview.connect_object( "button_press_event", BlaEventBrowser.__button_press_event, self) self.__models = map(gtk.ListStore, [gobject.TYPE_PYOBJECT] * 2) self.__treeview.set_model(self.__models[active]) vbox.pack_start(self.__treeview, expand=True, padding=10) self.add_with_viewport(vbox) self.show_all() if active == blaconst.EVENTS_RECOMMENDED: hbox_location.set_visible(False) blaplay.bla.register_for_cleanup(self)
def __set_file_chooser_directory(self, diag): directory = blacfg.getstring("general", "filechooser.directory") if not directory or not os.path.isdir: directory = os.path.expanduser("~") diag.set_current_folder(directory)
def destroy(*args): if (restrict_string != blacfg.getstring("library", "restrict.to") or exclude_string != blacfg.getstring("library", "exclude")): library.sync()
def __init__(self): super(BlaPreferences.PlayerSettings, self).__init__("Player") logarithmic_volume_scale = gtk.CheckButton( "Use logarithmic volume scale") logarithmic_volume_scale.set_active( blacfg.getboolean("player", "logarithmic.volume.scale")) logarithmic_volume_scale.connect( "toggled", self.__volume_scale_changed) state = blacfg.getboolean("player", "use.equalizer") self.__scales = [] use_equalizer = gtk.CheckButton("Use equalizer") use_equalizer.set_active(state) use_equalizer.connect("toggled", self.__use_equalizer_changed) self.__profiles_box = gtk.combo_box_new_text() self.__profiles_box.connect("changed", self.__profile_changed) old_profile = blacfg.getstring("player", "equalizer.profile") profiles = blacfg.get_keys("equalizer.profiles") for idx, profile in enumerate(profiles): self.__profiles_box.append_text(profile[0]) if profile[0] == old_profile: self.__profiles_box.set_active(idx) button_table = gtk.Table(rows=1, columns=3, homogeneous=True) new_profile_button = gtk.Button("New") new_profile_button.connect( "clicked", self.__new_profile, self.__profiles_box) delete_profile_button = gtk.Button("Delete") delete_profile_button.connect( "clicked", self.__delete_profile, self.__profiles_box) reset_profile_button = gtk.Button("Reset") reset_profile_button.connect_object( "clicked", BlaPreferences.PlayerSettings.__reset_profile, self) button_table.attach(new_profile_button, 0, 1, 0, 1, xpadding=2) button_table.attach(delete_profile_button, 1, 2, 0, 1, xpadding=2) button_table.attach(reset_profile_button, 2, 3, 0, 1, xpadding=2) self.__button_box = gtk.HBox() self.__button_box.pack_start( gtk.Label("Profiles:"), expand=False, padding=10) self.__button_box.pack_start(self.__profiles_box, expand=False) self.__button_box.pack_start( button_table, expand=False, padding=16) table = gtk.Table(rows=2, columns=2, homogeneous=False) table.set_row_spacings(2) table.attach(logarithmic_volume_scale, 0, 2, 0, 1, xpadding=2) table.attach(use_equalizer, 0, 1, 1, 2, xpadding=2) table.attach(self.__button_box, 1, 2, 1, 2, xpadding=2) self.__scale_box = gtk.HBox(homogeneous=True) bands = [29, 59, 119, 237, 474, 947, 1889, 3770, 7523, 15011] values = blacfg.getlistfloat("equalizer.profiles", old_profile) if not values: values = [0] * blaconst.EQUALIZER_BANDS for idx, val in enumerate(values): box = gtk.VBox(spacing=10) scale = gtk.VScale(gtk.Adjustment(val, -24., 12., 0.1)) scale.set_inverted(True) scale.set_update_policy(gtk.UPDATE_DISCONTINUOUS) scale.set_value(values[idx]) scale.set_digits(1) scale.set_draw_value(True) scale.set_value_pos(gtk.POS_BOTTOM) scale.connect("value_changed", self.__equalizer_value_changed, idx, self.__profiles_box) scale.connect("format_value", lambda *x: "%.1f dB" % x[-1]) self.__scales.append(scale) label = gtk.Label("%d Hz" % bands[idx]) box.pack_start(label, expand=False) box.pack_start(scale, expand=True) self.__scale_box.pack_start(box) self.pack_start(table, expand=False, padding=10) self.pack_start(self.__scale_box, expand=True) self.__use_equalizer_changed(use_equalizer)
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 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, "")