def __init__(self, extensionsloader): self.extensions = extensionsloader self.module = {'name': 'Explorer'} self.functions = Functions() self.userconf = ConfigLoader() self.songs_tree = {} self.albums = {} # Create the Albums view def launch_explorer(wdg): self.widgets = wdg self.aview = AlbumsView(self.widgets, self.extensions) self.search = Search(self.widgets, self.aview) self.filter = Filter(self.widgets, self.aview) # Populate the view self.populate() # Connect to signals def repopulate(wdg): self.extensions.load_event('OnAbortPlayback') self.populate(True) self.widgets[0][3].connect('clicked', repopulate) self.extensions.connect('OnBluemindoStarted', launch_explorer) self.extensions.connect('AskShuffleSong', self.shuffle_song_asked)
def __init__(self,method,url,data=None,cookies=None,headers=None): config = ConfigLoader() url_pre = config.get('api','url_pre') try: if method == 'get': self.resp = requests.get(url=url_pre+url, params=data, cookies=cookies, headers=headers) elif method == 'post': self.resp = requests.post(url=url_pre+url, data=data, cookies=cookies, headers=headers) elif method == 'delete': self.resp = requests.delete(url=url_pre+url, data=data, cookies=cookies, headers=headers) except Exception as e: raise e
def __init__(self): if Functions.ref2 is None: Functions.ref2 = 42 self.userconf = ConfigLoader() # Just set the data and the locale dir if isdir('../data') and isfile('../locale/bluemindo.pot'): self.datadir = '../data' self.localedir = '../locale' else: self.datadir = '/usr/share/bluemindo' self.localedir = '/usr/share/locale'
class Context: config = ConfigLoader() # 投资人测试数据 normal_user = config.get('basic', 'normal_user') normal_pwd = config.get('basic', 'normal_pwd') normal_member_id = config.get('basic', 'normal_member_id') # 管理员测试数据 admin_user = config.get('basic', 'admin_user') admin_pwd = config.get('basic', 'admin_pwd') # 借款人测试数据 loan_member_id = config.get('basic', 'loan_member_id')
class Context: config = ConfigLoader() normal_user = config.get('basic','normal_user') normal_pwd = config.get('basic','normal_pwd') normal_member_id = config.get('basic','normal_member_id') admin_user = config.get('basic','admin_user') admin_pwd = config.get('basic','admin_pwd') loan_member_id = config.get('basic','loan_member_id') unnormal_member_id = config.get('basic','unnormal_member_id')
def __init__(self, method, url, data=None, cookies=None, headers=None): config1 = ConfigLoader() url_pre = config1.get_conf_str("api", "url_pre") url = url_pre + url try: if method == "get": self.resp = requests.get(url=url, params=data, cookies=cookies, headers=headers) elif method == "pose": self.resp = requests.post(url=url, data=data, cookies=cookies, headers=headers) elif method == "delete": self.resp = requests.delete(url=url, data=data, cookies=cookies, headers=headers) except Exception as e: raise e
def __init__(self): config = ConfigLoader() host = config.get('mysql', 'host') port = config.getint('mysql', 'port') # port 是一个数值 user = config.get('mysql', 'usr') password = config.get('mysql', 'pwd') # 异常处理 self.mysql = pymysql.connect(host=host, user=user, password=password, port=port, cursorclass=pymysql.cursors.DictCursor)
class WebServices(object): """A class to handles many WebServices.""" config = ConfigLoader() functions = Functions() lock = Lock() def get_xml(self, url): """This function downloads a file and returns an ElementTree object.""" req = urlopen(url) content = req.read() return ElementTree.fromstring(content) def get_html(self, url): """This function downloads a file and returns its content.""" req = urlopen(url) content = req.read() return content
def __init__(self): config = ConfigLoader() host = config.get_conf_str("mysql", "host") port = config.get_conf_int("mysql", "port") user = config.get_conf_str("mysql", "user") pwd = config.get_conf_str("mysql", "pwd") charset = str(config.get_conf_str("mysql", "charset")) # 异常处理 try: self.mysql = pymysql.connect( host=host, user=user, password=pwd, database=None, port=port, cursorclass=pymysql.cursors.DictCursor, charset='utf8') # 返回字典对象 except Exception as e: print("Mysql connect failed!")
def __init__(self, widgets, aview): self.widgets = widgets self.functions = Functions() self.userconf = ConfigLoader() # GUI self.filter_button = self.widgets[1].get_object('tool-filter') self.filter_button.connect('clicked', self.on_button_clicked) gladefile = join(self.functions.datadir, 'glade', 'filterbar.ui') self.fbox = gtk_builder() self.fbox.set_translation_domain('bluemindo') self.fbox.add_from_file(gladefile) self.filter_box = self.fbox.get_object('infobar') wdg_place = self.widgets[1].get_object('filter-emplacement') wdg_place.add(self.filter_box) self.fbox.get_object('label_filter').set_text(_('Filter the results:')) # Create ComboBoxes self.genre_fstore = ListStore(int, str) self.genre_fcombo = self.fbox.get_object('combobox-genre') self.genre_fcombo.set_model(self.genre_fstore) renderer_text = CellRendererText() self.genre_fcombo.pack_start(renderer_text, True) self.genre_fcombo.set_entry_text_column(1) self.genre_fcombo.add_attribute(renderer_text, 'text', 1) self.year_fstore = ListStore(int, str) self.year_fcombo = self.fbox.get_object('combobox-year') self.year_fcombo.set_model(self.year_fstore) renderer_text = CellRendererText() self.year_fcombo.pack_start(renderer_text, True) self.year_fcombo.set_entry_text_column(1) self.year_fcombo.add_attribute(renderer_text, 'text', 1)
def __init__(self): config = ConfigLoader() host = config.get('mysql', 'host') port = config.getint('mysql', 'port') user = config.get('mysql', 'usr') password = config.get('mysql', 'pwd') #自行添加异常处理 try: self.mysql = pymysql.connect( host=host, user=user, password=password, port=port, cursorclass=pymysql.cursors.DictCursor) #建立连接 print('数据库连接成功!') except AssertionError as e: print('数据库连接失败!', e) raise e
def __init__(self, widgets, extensions): self.widgets = widgets self.extensions = extensions self.functions = Functions() self.userconf = ConfigLoader() self.dblclick = None # Create the IconView self.albumview = self.widgets[1].get_object('albumview') self.albummodel = ListStore(Pixbuf, str, str, str, int, str, str) self.albumview.set_pixbuf_column(0) self.albumview.set_markup_column(1) self.albumview.set_column_spacing(0) self.albumview.set_spacing(0) self.albumview.set_item_width(100) self.albumview.set_property('activate-on-single-click', False) # Add a filter to the ListStore model self.albumfilter = self.albummodel.filter_new(None) self.remove_filter_data() self.matched = False def filter_visible(model, iter, data): usrf = self.widgets[1].get_object('searchentry').get_text() search_a = model.get_value(iter, 3) search_b = model.get_value(iter, 2) pre_result = False if self.matched: usrf_a = self.matched[0] usrf_b = self.matched[1] if usrf_b == 'blm.!ARTIST!': if usrf_a.lower() == search_b.lower(): # Matched an artist pre_result = True else: if (usrf_a.lower() == search_a.lower() and usrf_b.lower() == search_b.lower()): # Matched an album pre_result = True else: if len(model) > 0: if (usrf.lower() in search_a.lower() or usrf.lower() in search_b.lower()): # Found an element (artist or album name is close) pre_result = True else: # No element founded at all, return False anyway return False # Apply filters fdg = self.filter_data['genre'] fdy = self.filter_data['year'] # Filter results by genres if fdg is not None and fdg != model.get_value(iter, 5): pre_result = False # Filter results by years if fdy is not None and fdy != model.get_value(iter, 6): pre_result = False # Return the final result return pre_result self.albumfilter.set_visible_func(filter_visible) self.albumview.set_model(self.albumfilter) # Connect to signals def grab_entry_focus(widget, event): key = event.string if (key.lower() in 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,' 'x,y,z,0,1,2,3,4,5,6,7,8,9'.split(',')): self.widgets[1].get_object('searchentry').grab_focus() self.widgets[1].get_object('searchentry').set_text(key) self.widgets[1].get_object('searchentry').set_position(-1) self.albumview.connect('key-press-event', grab_entry_focus) self.albumview.connect('selection_changed', self.on_selection_changed)
class Explorer: def __init__(self, extensionsloader): self.extensions = extensionsloader self.module = {'name': 'Explorer'} self.functions = Functions() self.userconf = ConfigLoader() self.songs_tree = {} self.albums = {} # Create the Albums view def launch_explorer(wdg): self.widgets = wdg self.aview = AlbumsView(self.widgets, self.extensions) self.search = Search(self.widgets, self.aview) self.filter = Filter(self.widgets, self.aview) # Populate the view self.populate() # Connect to signals def repopulate(wdg): self.extensions.load_event('OnAbortPlayback') self.populate(True) self.widgets[0][3].connect('clicked', repopulate) self.extensions.connect('OnBluemindoStarted', launch_explorer) self.extensions.connect('AskShuffleSong', self.shuffle_song_asked) def populate(self, force_scan=False): threads_enter() # Do we have a working directory or not? if self.userconf.config['Explorer']['folder'] == '': fcdialog = FileChooserDialog( title=_('Open your music directory'), action=FileChooserAction.SELECT_FOLDER, buttons=(_('Select'), ResponseType.OK)) fcdialog.set_transient_for(self.widgets[0][11]) response = fcdialog.run() if response == ResponseType.OK: foldername = fcdialog.get_filename() self.userconf.update_key('Explorer', 'folder', foldername) force_scan = True else: print("Bluemindo can't work without opening a music " + "directory. Exiting…") exit(0) fcdialog.destroy() # Call database musicdb = MusicDatabase(self.userconf.config['Explorer']['folder']) # Do we scan for new files? if (bool(int(self.userconf.config['Explorer']['scan_at_startup'])) or force_scan): def do_scan(): # Freeze user interface gldfile = join(self.functions.datadir, 'glade', 'loading.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gldfile) box_content = win.get_object('box1') # Create an interface to help the user waiting for the job bluemindo = join(self.functions.datadir, 'image', 'bluemindo.png') img = win.get_object('image') cover_px = Pixbuf.new_from_file(bluemindo) idle_add(img.set_from_pixbuf, cover_px) idle_add( win.get_object('label').set_markup, '<span size="x-large"><b>' + _('Reloading music database.') + '</b></span>') idle_add(self.widgets[0][2].set_sensitive, False) idle_add(self.widgets[0][3].set_sensitive, False) idle_add(self.widgets[0][5].set_sensitive, False) idle_add(self.widgets[0][6].set_sensitive, False) idle_add(self.widgets[0][7].set_sensitive, False) idle_add(self.widgets[0][8].set_sensitive, False) idle_add(self.widgets[1].get_object('box1').add, box_content) lbl = win.get_object('label_info') idle_add(lbl.set_text, _('Starting… Prepares to search for new files.')) # Update GUI box_content.show_all() self.widgets[1].get_object('box2').hide() # Do the scanning pb = win.get_object('progressbar') musicdb.scan(lbl, pb) # Show original GUI idle_add(self.widgets[0][2].set_sensitive, True) idle_add(self.widgets[0][3].set_sensitive, True) idle_add(box_content.hide) idle_add(self.widgets[1].get_object('box2').show_all) idle_add(self.create_view) thread = Thread(group=None, target=do_scan, name='scanning', args=()) thread.start() else: self.create_view() threads_leave() def create_view(self): # Call database musicdb = MusicDatabase(self.userconf.config['Explorer']['folder']) self.database = musicdb.load() self.albums_tree = [] album_names = [] album_iter = {} # Activate player buttons self.widgets[0][5].set_sensitive(True) self.widgets[0][6].set_sensitive(True) self.widgets[0][7].set_sensitive(True) self.widgets[0][8].set_sensitive(True) # Create the tree artists→albums→songs def unique(seq, keepstr=True): """This function ensures there are only unique values.""" t = type(seq) if t in (str, str): t = (list, ''.join)[bool(keepstr)] seen = [] return t(c for c in seq if not (c in seen or seen.append(c))) # Create the songs tree songs_tree = {} artists = [] albums = [] albums_dl = [] for result in self.database: artists.append(result[1]) albums.append((result[1], result[2])) artists = unique(artists) albums = unique(albums) for a in artists: songs_tree[a] = {} for a in albums: songs_tree[a[0]][a[1]] = [] # Add songs for result in self.database: songs_tree[result[1]][result[2]].append(result) # Sort songs for artist in songs_tree.values(): for album in artist.values(): album.sort(key=lambda student: student[3]) self.songs_tree = songs_tree i = 0 for art in self.songs_tree: for alb in self.songs_tree[art]: album_names.append(alb) self.albums_tree.append({'album': alb, 'artist': art}) i = i + 1 # Sort everything self.albums_tree.sort(key=lambda item: item['album'].lower()) self.albums_tree.sort(key=lambda item: item['artist'].lower()) # Send the music tree to all extensions self.extensions.load_event('OnSongsTreeCreated', self.songs_tree) # Launch explorer GUI self.search.generate_autocompletion(artists, albums, self.songs_tree) self.aview.populate_albums(self.albums_tree, self.albums, self.songs_tree, self.search) self.filter.launch(self.albums_tree, self.songs_tree, self.aview) def shuffle_song_asked(self): if len(self.database) > 1: index = randrange(len(self.database)) song_inf = self.database[index] song = Song(filename=song_inf[8]) self.extensions.load_event('OnPlayNewSong', song)
def __init__(self, widgets, aview): self.widgets = widgets self.aview = aview self.albumview = aview.albumview self.albumfilter = aview.albumfilter self.matched = aview.matched self.functions = Functions() self.userconf = ConfigLoader() # Create the autocompletion columns self.completion_model = ListStore(Pixbuf, str, str, str, str, str, str, str) ecomplet = EntryCompletion() ecomplet.set_model(self.completion_model) pixbufcell = CellRendererPixbuf() ecomplet.pack_start(pixbufcell, False) ecomplet.add_attribute(pixbufcell, 'pixbuf', 0) markupcell = CellRendererText() markupcell.props.xpad = 10 ecomplet.pack_start(markupcell, True) ecomplet.add_attribute(markupcell, 'markup', 1) markupcell = CellRendererText() markupcell.props.xpad = 5 ecomplet.pack_start(markupcell, False) ecomplet.add_attribute(markupcell, 'markup', 2) pixbufcell = CellRendererPixbuf() ecomplet.pack_start(pixbufcell, False) ecomplet.add_attribute(pixbufcell, 'icon_name', 3) ecomplet.props.text_column = 4 def matched(widget, model, iter): item = model[iter] data_a = item[4] data_b = item[5] self.aview.matched = [data_a, data_b] self.albumfilter.refilter() if data_b == 'blm.!ARTIST!': # Matched an artist: show albums return False elif exists(data_b): # Matched a song: queue to playlist sng = Song(filename=item[5]) self.aview.queue(sng) # Go back to empty search self.aview.matched = False searchentry = widget.get_entry() searchentry.set_text('') return True #elif len(self.albumfilter) == 1: else: # Matched an album: load it in a panel album = Album(data_b, data_a, self.songs_tree) if hasattr(album, 'name'): self.aview.on_album_matched(album) # Go back to empty search self.aview.matched = False searchentry = widget.get_entry() searchentry.set_text('') return True ecomplet.connect('match-selected', matched) searchentry = self.widgets[1].get_object('searchentry') searchentry.set_completion(ecomplet) searchentry.grab_focus() def do_filter(widget): self.albumfilter.refilter() self.aview.matched = False searchentry.connect('changed', do_filter) self.searchentry = searchentry
do_excel = DoExcel(contants.case_file) # 实例化一个DoExcel对象 sheet_names = do_excel.get_sheet_names() # 获取Excel文件中全部sheet名称,返回为一个列表 print("sheet名称列表:",sheet_names) cases_list = ['login', 'register'] # 定义一个执行测试用例的列表 # 根据sheet_names 分别取到全部用例来执行 for sheet_name in sheet_names: # 获取login的所有测试用例,返回的是一个cases列表,列表里面是多个Case类实例,每个实例的属性对应Excel表中每列的值 if sheet_name in cases_list: #如果当前的这个sheet_name不在可执行的case_list里面,就不执行 cases = do_excel.get_cases(sheet_name) print(sheet_name+' 测试用例个数:', len(cases)) for case in cases: # 遍历测试用例列表,每进for一次,就取一个case实例 print("case信息:", case.__dict__) # 打印case信息 对象的内置的私有方法 # data = eval(case.data) # Excel里面取到data是一个字符串,使用eval函数将字符串转换成字典 data = json.loads(case.data) config = ConfigLoader() url_pre = config.get('api','url_pre') url = url_pre + case.url resp = Request(method=case.method, url=url, data=data) # 通过封装的Request类来完成接口的调用 print('status_code:', resp.get_status_code()) # 打印响应码 resp_dict = resp.get_json() # 获取请求响应,字典 # 通过json.dumps函数将字典转换成格式化后的字符串 resp_text = json.dumps(resp_dict, ensure_ascii=False, indent=4) print('response: ', resp_text) # 打印响应 if case.expected == resp.get_text(): print("result : PASS") do_excel.write_result_by_case_id(sheet_name=sheet_name,case_id=case.case_id, actual=resp.get_text(),result='PASS') else: print("result : FAIL")
class Functions(object): ref = None ref2 = None def __new__(cls, *args, **kws): # Singleton if cls.ref is None: cls.ref = object.__new__(cls) return cls.ref def __init__(self): if Functions.ref2 is None: Functions.ref2 = 42 self.userconf = ConfigLoader() # Just set the data and the locale dir if isdir('../data') and isfile('../locale/bluemindo.pot'): self.datadir = '../data' self.localedir = '../locale' else: self.datadir = '/usr/share/bluemindo' self.localedir = '/usr/share/locale' def get_hash(self, str1, str2): """Just return the hash for given strings""" md5 = md5_new() md5.update(str1.encode('utf-8')) md5.update(str2.encode('utf-8')) return str(md5.hexdigest()) def view_encode(self, string, limit=25): if (len(string)) > limit: string = string[:limit] + '…' string = markup_escape_text(string) return string def unescape(string): """Unescape an escaped string with markup_escape_text.""" _str = xml_unescape(string, {''': "'", '"': '"'}) return _str def human_length(self, length): """Return the length in a human-readable way""" lg0 = int(length / 60) lg1 = int(length % 60) if lg0 >= 0 and lg0 < 10: lg0 = '0' + str(lg0) if lg1 >= 0 and lg1 < 10: lg1 = '0' + str(lg1) lg = str(lg0) + ':' + str(lg1) return lg def clear_html(self, text, only_bold=False): """Return the text without html""" if text.startswith('<b>') and text.endswith('</b>'): text = text[3:-4] if not only_bold: if text.startswith('<span size="small">'): text = text[19:-7] return text def open_bluemindo(self, window): """Handle the Bluemindo's window open and change width, height and position on the screen.""" width = int(self.userconf.config['Window']['width']) height = int(self.userconf.config['Window']['height']) window.resize(width, height) x = int(self.userconf.config['Window']['x']) y = int(self.userconf.config['Window']['y']) window.move(x, y) def close_bluemindo(self, window, quit=True): """This function is called when the Bluemindo's main window is closed.""" # Backup window width, height and position if window is not None and window.get_properties('visible')[0]: width = window.get_size()[0] height = window.get_size()[1] x = window.get_position()[0] y = window.get_position()[1] self.userconf.update_key('Window', 'width', str(width)) self.userconf.update_key('Window', 'height', str(height)) self.userconf.update_key('Window', 'x', str(x)) self.userconf.update_key('Window', 'y', str(y)) # Delete the socket file and quit GTK if quit: SOCKET_NAME = '/tmp/bluemindo' if exists(SOCKET_NAME): remove(SOCKET_NAME) pid_filename = join(self.datadir, 'pid') if isfile(pid_filename): remove(pid_filename) current_playing = join(self.datadir, 'current-playing') if isfile(current_playing): remove(current_playing) print('The dolphin has plunge!') idle_add(gtk_main_quit) # Hide window else: if window.get_properties('visible')[0]: window.hide()
def __init__(self): self.config = ConfigLoader()
# it under the terms of the GNU General Public License as published by # the Free Software Foundation version 3 of the License. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from os.path import join, exists import sqlite3 as sqlite from common.config import ConfigLoader config = ConfigLoader() class SQLite(object): def __init__(self): sqlfile = join(config.datadir, 'songs.db') if not exists(sqlfile): database_exist = False else: database_exist = True self.cx = sqlite.connect(sqlfile) self.cur = self.cx.cursor() self.cx.text_factory = str if not database_exist:
class Playlist: def __init__(self, extensionsloader): self.extensions = extensionsloader self.module = {'name': 'Playlist'} self.functions = Functions() self.userconf = ConfigLoader() self.config = {} rpt = self.userconf.config['Playlist']['repeat'] self.config['repeat'] = bool(int(rpt)) shf = self.userconf.config['Playlist']['shuffle'] self.config['shuffle'] = bool(int(shf)) shm = self.userconf.config['Playlist']['shuffle_mode'] self.config['shuffle_mode'] = shm self.lastfm = LastFm() self.playlists_mgmnt = Playlists() self.playlist_content = {} self.playlist_identifier = 0 self.playlist_current = None self.current_playlist_id = 0 self.user_playlists = {} self.last_user_playlist = None self.similar_artists = [] self.is_in_similar_thread = False # Create the Playlist view def launch_playlist(wdg): self.widgets = wdg[1] self.playlist_label = self.widgets.get_object('label_playlist') self.playlist_repeat = self.widgets.get_object('tool-repeat') self.playlist_shuffle = self.widgets.get_object('tool-shuffle') self.playlist_clean = self.widgets.get_object('tool-clean') self.playlist_combo = self.widgets.get_object('combo-playlist') self.playlist_save = self.widgets.get_object('tool-saveplaylist') self.playlist_lyrics = self.widgets.get_object('tool-lyrics') self.playlist_tree = self.widgets.get_object('treeview_playlist') self.playlist_tree.set_headers_visible(False) self.playlist_tree.props.reorderable = True self.playlist_tree.connect('key_press_event', self.key_pressed) self.playlist_tree.connect('row_activated', self.row_activated) self.liststore = ListStore(str, str, str, str, int) self.playlist_tree.set_model(self.liststore) renderer_pix = CellRendererPixbuf() column_pixbuf = TreeViewColumn('1', renderer_pix, icon_name=0) column_pixbuf.set_fixed_width(18) self.playlist_tree.append_column(column_pixbuf) renderer_text = CellRendererText() column_text = TreeViewColumn('2', renderer_text, markup=1) column_text.props.expand = True column_text.props.max_width = 192 self.playlist_tree.append_column(column_text) column_text = TreeViewColumn('3', renderer_text, markup=2) column_text.set_fixed_width(40) self.playlist_tree.append_column(column_text) self.repeat_btn = self.widgets.get_object('tool-repeat') if self.config['repeat']: self.repeat_btn.set_active(True) self.repeat_btn.connect('clicked', self.toggle, 'repeat') self.shuffle_btn = self.widgets.get_object('tool-shuffle') if self.config['shuffle']: self.shuffle_btn.set_active(True) self.shuffle_btn.connect('clicked', self.toggle, 'shuffle') def clean_wdg(widget): # Clean playlist self.clean() # Show popover if self.current_playlist_id > 3: self.clean_btn.set_sensitive(True) self.clean_pop.show_all() self.clean_btn = self.widgets.get_object('tool-clean') self.clean_btn.connect('clicked', clean_wdg) self.clean_pop = Popover.new(self.clean_btn) self.clean_pop.set_size_request(100, 30) gtkpla = join(self.functions.datadir, 'glade', 'plist-del-pop.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gtkpla) hbox = win.get_object('box-playlist') lbl = win.get_object('label') lbl.set_text(_('Do you also want to remove the playlist?')) btn = win.get_object('del-btn') btn.set_label(_('Delete')) btn.connect('clicked', self.delete_playlist) self.clean_pop.add(hbox) # Populate combobox self.combolist = ListStore(int, str) self.combobox = self.widgets.get_object('combobox') self.combobox.set_model(self.combolist) self.combobox.set_popup_fixed_width(False) self.combobox.props.expand = False renderer_text = CellRendererText() renderer_text.props.ellipsize = EllipsizeMode.END self.combobox.pack_start(renderer_text, True) self.combobox.set_entry_text_column(1) self.combobox.add_attribute(renderer_text, 'text', 1) self.combolist.append([0, _('Current')]) self.combolist.append([1, _('Top 50 songs')]) self.combolist.append([2, _('Top 10 albums')]) playlists = self.playlists_mgmnt.get_playlists() if len(playlists) > 0: self.combolist.append([3, '']) item_id = 3 playlists.sort(key=lambda it: it[1]) for item in playlists: item_id += 1 self.combolist.append([item_id, item]) self.user_playlists[item_id] = item self.last_user_playlist = item_id def combo_sep(model, iter): if model[iter][0] == 3: return True self.combobox.set_row_separator_func(combo_sep) def on_combo_changed(widget): path = widget.get_active() item_id = self.combolist[path][0] # First, clean the playlist self.clean(None) # Second, populate the playlist if item_id > 0: self.populate(item_id) # Then, update playlist identifier self.current_playlist_id = item_id # Show delete/remove button if the playlist is from the user if item_id > 3: self.clean_btn.set_sensitive(True) self.combobox.set_active(0) self.combobox.connect('changed', on_combo_changed) self.tool_save = self.widgets.get_object('tool-saveplaylist') self.tool_save.connect('clicked', self.save_playlist) self.save_pop = Popover.new(self.tool_save) self.save_pop.set_size_request(100, 30) gtkpla = join(self.functions.datadir, 'glade', 'plist-add-pop.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gtkpla) hbox = win.get_object('box-playlist') self.save_pop.add(hbox) self.save_entry = win.get_object('save-entry') self.save_entry.connect('key_press_event', self.save_playlist_key) self.save_btn = win.get_object('save-btn') self.save_btn.connect('clicked', self.save_playlist_button) self.save_btn.set_label(_('Save')) self.clean_btn.set_sensitive(False) self.tool_save.set_sensitive(False) # Acquire the songs tree def acquire_tree(st): self.songs_tree = st self.extensions.connect('OnBluemindoStarted', launch_playlist) self.extensions.connect('OnSongsTreeCreated', acquire_tree) self.extensions.connect('OnSongQueued', self.on_new_song_queued) self.extensions.connect('OnAlbumQueued', self.on_new_album_queued) self.extensions.connect('AskPreviousSong', self.ask_previous_song) self.extensions.connect('AskNextSong', self.ask_next_song) self.extensions.connect('HasStartedSong', self.song_started) def toggle(self, widget, action): if action == 'repeat' and self.config['repeat']: self.config['repeat'] = False self.repeat_btn.set_active(False) self.userconf.update_key('Playlist', 'repeat', str(int(False))) elif action == 'repeat' and not self.config['repeat']: self.config['repeat'] = True self.repeat_btn.set_active(True) self.userconf.update_key('Playlist', 'repeat', str(int(True))) elif action == 'shuffle' and self.config['shuffle']: self.config['shuffle'] = False self.shuffle_btn.set_active(False) self.userconf.update_key('Playlist', 'shuffle', str(int(False))) elif action == 'shuffle' and not self.config['shuffle']: self.config['shuffle'] = True self.shuffle_btn.set_active(True) self.userconf.update_key('Playlist', 'shuffle', str(int(True))) def row_activated(self, widget, path, column): item_iter = self.liststore.get_iter(path) # Get the founded element. item_identifier = self.liststore.get_value(item_iter, 4) current_item = self.playlist_content[item_identifier] # The element is a song. if self.playlist_content[item_identifier].kind == 'song': self.playlist_current = [item_iter, item_identifier, None] self.extensions.load_event('OnPlayNewSong', current_item) # The element is an album. else: self.extensions.load_event('OnAbortPlayback') sng = self.playlist_content[item_identifier].tracks[0] self.playlist_current = [item_iter, item_identifier, 0] self.extensions.load_event('OnPlayNewSong', sng) def key_pressed(self, widget, eventkey): if eventkey.get_keyval()[1] == KEY_Delete: # Delete an item from the playlist selection = self.playlist_tree.get_selection() selected = selection.get_selected_rows() liststore = selected[0] listpath = selected[1] if len(listpath) > 0: selpath = listpath[0] playlist_identifier = liststore[selpath][4] # Are we removing the currently playing item? if self.playlist_current is not None: item_iter, item_path, item_in_album = self.playlist_current if selpath == TreePath.new_from_string(str(item_path)): self.playlist_current = None # Removal del self.playlist_content[playlist_identifier] del liststore[selpath] def clean(self, data=None): self.playlist_content = {} self.playlist_identifier = 0 self.playlist_current = None self.liststore.clear() # Update GUI self.clean_btn.set_sensitive(False) self.tool_save.set_sensitive(False) def populate(self, playlist_id): if playlist_id in (1, 2): # Automatic playlists based on listening stats if playlist_id == 1: tb = 'stats_songs' lm = 50 elif playlist_id == 2: tb = 'stats_albums' lm = 10 result = [] txt = ('select * from %s order by tracks desc limit %u' % (tb, lm)) sql = SQLite() cur = sql.execute(txt) for sg in cur: result.append(sg) sql.close() for item in result: if playlist_id == 1: sng = Song(filename=item[0]) if hasattr(sng, 'title'): self.on_new_song_queued(sng) elif playlist_id == 2: album_name = item[0] for it in self.songs_tree: if album_name in self.songs_tree[it]: self.on_new_album_queued(Album(it, album_name, self.songs_tree)) break elif playlist_id > 3: # User-created playlists user_plist = self.user_playlists[playlist_id] plist = self.playlists_mgmnt.load_playlist(user_plist) for item in plist: sng = Song(filename=item) if hasattr(sng, 'title'): self.on_new_song_queued(sng) def delete_playlist(self, widget): if self.current_playlist_id > 3: user_plist = self.user_playlists[self.current_playlist_id] self.playlists_mgmnt.delete_playlist(user_plist) # Delete the playlist from the list del self.user_playlists[self.current_playlist_id] cblid = 0 for item in self.combolist: if item[0] == self.current_playlist_id: del self.combolist[cblid] break cblid += 1 # Move back to "Current" playlist self.combobox.set_active(0) def save_playlist_key(self, widget, eventkey): if eventkey.get_keyval()[1] == KEY_Return: self.save_playlist_button(None) def save_playlist_button(self, widget): user_entry = self.save_entry.get_text() user_entry = user_entry.replace('\\', '-') user_entry = user_entry.replace('/', '-') user_entry = user_entry.replace('*', '-') user_entry = user_entry.replace('|', '-') if len(user_entry) > 0: rtn_value = self.playlists_mgmnt.create_new_playlist(user_entry) if rtn_value: self.save_pop.hide() # Add playlist to GUI if self.last_user_playlist is None: self.combolist.append([3, '']) self.last_user_playlist = 3 self.last_user_playlist += 1 self.combolist.append([self.last_user_playlist, user_entry]) self.user_playlists[self.last_user_playlist] = user_entry # Write the playlist self.write_playlist(user_entry) # Select the new playlist self.combobox.set_active(self.last_user_playlist) def save_playlist(self, widget): if self.current_playlist_id < 3: # Create a new playlist self.save_entry.set_text('') self.save_pop.show_all() elif self.current_playlist_id > 3: # Update an existing playlist user_plist = self.user_playlists[self.current_playlist_id] self.write_playlist(user_plist) def write_playlist(self, user_plist): plist_content = [] for item in self.liststore: item_id = item[4] plist_content.append(self.playlist_content[item_id]) self.playlists_mgmnt.write_playlist(user_plist, plist_content) def on_new_song_queued(self, song_info): title = song_info.title artist = song_info.artist album = song_info.album filename = song_info.filename length = self.functions.human_length(song_info.length) self.liststore.append(('audio-x-generic-symbolic', '<b>' + self.functions.view_encode(title, 99) + '</b>\n' + self.functions.view_encode(artist), '<span foreground="grey">' + length + '</span>', filename, self.playlist_identifier)) self.playlist_content[self.playlist_identifier] = song_info self.playlist_identifier += 1 # Update GUI self.clean_btn.set_sensitive(True) self.tool_save.set_sensitive(True) def on_new_album_queued(self, album_info): artist = album_info.artist album = album_info.name songs_count = str(len(album_info.tracks)) + ' ♫' self.liststore.append(('media-optical-symbolic', '<b>' + self.functions.view_encode(album, 99) + '</b>\n' + self.functions.view_encode(artist), '<span foreground="grey">' + songs_count + '</span>', '[album]', self.playlist_identifier)) self.playlist_content[self.playlist_identifier] = album_info self.playlist_identifier += 1 # Update GUI self.clean_btn.set_sensitive(True) self.tool_save.set_sensitive(True) def ask_next_song(self, current_song): self.ask_for_a_song(True, current_song) def ask_previous_song(self, current_song): self.ask_for_a_song(False, current_song) def ask_for_a_song(self, next=True, current_song=None): def walk_in_playlist(item_iter, next=True): base_item_iter = item_iter if item_iter is None: # Find first song. item_iter = self.liststore.get_iter_first() elif next: # Find next song. path = self.liststore.get_path(self.playlist_current[0]) path_int = int(path.to_string()) max_id = len(self.playlist_content) - 1 if (path_int + 1 <= max_id): # There is a song to launch! item_iter = self.liststore.get_iter(path_int + 1) else: # There is no song to launch! if not self.config['repeat']: self.extensions.load_event('OnAbortPlayback') return else: item_iter = self.liststore.get_iter_first() elif not next: # Find previous song. path = self.liststore.get_path(self.playlist_current[0]) path_int = int(path.to_string()) max_id = len(self.playlist_content) - 1 if (path_int -1 >= 0): # There is a song to launch. item_iter = self.liststore.get_iter(path_int - 1) else: # There is no song to launch! if not self.config['repeat']: self.extensions.load_event('OnAbortPlayback') return else: item_iter = self.liststore.get_iter_from_string(str(max_id)) # Get the founded element. item_identifier = self.liststore.get_value(item_iter, 4) current_item = self.playlist_content[item_identifier] def launch_founded_item(item_identifier, item_iter, current_item): # The element is a song. if self.playlist_content[item_identifier].kind == 'song': self.playlist_current = [item_iter, item_identifier, None] self.extensions.load_event('OnPlayNewSong', current_item) # The element is an album. else: self.extensions.load_event('OnAbortPlayback') sng = self.playlist_content[item_identifier].tracks[0] sng.rg_mode_guess = 'album' self.playlist_current = [item_iter, item_identifier, 0] self.extensions.load_event('OnPlayNewSong', sng) # Are we currently listening from an album? if base_item_iter is not None: kind = self.playlist_content[self.playlist_current[1]].kind if kind == 'album': base_item_identifier = self.liststore.get_value(base_item_iter, 4) tracks = self.playlist_content[self.playlist_current[1]].tracks max_sng = len(tracks) - 1 if next: if self.playlist_current[2] < max_sng: item_in_album = self.playlist_current[2] + 1 else: return launch_founded_item(item_identifier, item_iter, current_item) elif not next: if self.playlist_current[2] - 1 > -1: item_in_album = self.playlist_current[2] - 1 else: return launch_founded_item(item_identifier, item_iter, current_item) sng = self.playlist_content[base_item_identifier].tracks[item_in_album] sng.rg_mode_guess = 'album' self.playlist_current = [base_item_iter, base_item_identifier, item_in_album] self.extensions.load_event('OnPlayNewSong', sng) return launch_founded_item(item_identifier, item_iter, current_item) if len(self.playlist_content) == 0: # Playlist is empty. if not self.config['shuffle']: # Shuffle disabled: abort playback. self.extensions.load_event('OnAbortPlayback') else: # Shuffle enabled. if self.config['shuffle_mode'] == 'random': # Random mode: seek for shuffle song. self.extensions.load_event('AskShuffleSong') elif self.config['shuffle_mode'] == 'similar': # Similar mode: seek for a similar song. if len(self.similar_artists) == 0: # No similar song founded: seek for any one. self.extensions.load_event('AskShuffleSong') return # Choose one song in the list of similar artists index = randrange(len(self.similar_artists)) artist = self.similar_artists[index] mdb = MusicDatabase(None) songs_list = mdb.load_from_artist(artist) if len(songs_list) > 1: index = randrange(len(songs_list)) song = songs_list[index] sng = Song(filename=song[8]) print ('[SIMILAR] Playing a song from ' + sng.artist) self.extensions.load_event('OnPlayNewSong', sng) else: self.extensions.load_event('AskShuffleSong') else: # Playlist is not empty, walk in it! if self.playlist_current is None: # Currently no current item in playlist, choose the first one! walk_in_playlist(None) else: # The current playling song is in the playlist! if next: walk_in_playlist(self.playlist_current[0]) else: walk_in_playlist(self.playlist_current[0], False) def song_started(self, song): # First, try to download a few similar artists names if self.config['shuffle_mode'] == 'similar': def download_similars(): threads_enter() art = self.lastfm.get_similar_artists(song.artist) self.similar_artists = [] mdb = MusicDatabase(None) for artist in art: if mdb.artist_exists(artist): self.similar_artists.append(artist) self.is_in_similar_thread = False threads_leave() if not self.is_in_similar_thread: self.is_in_similar_thread = True thread = Thread(group=None, target=download_similars, name='similars', args=()) thread.start() # Second, update statistics for this song song.increment_statistics() alb = Album(song.artist, song.album, self.songs_tree) alb.increment_statistics() # Then, highlight currently playing song/album if it's in playlist if self.playlist_current is not None: # Currently playing item is in the playlist item_iter, item_path, item_in_album = self.playlist_current # Remove marker of all items for item in self.liststore: current_label = item[1] if current_label[:2] == '◎ ': item[1] = current_label[2:] # Add marker on one item current_label = self.liststore[item_iter][1] if current_label[:2] != '◎ ': self.liststore[item_iter][1] = '◎ ' + current_label
def __init__(self, extensionsloader): self.extensions = extensionsloader self.module = {'name': 'Player'} self.config = {} self.functions = Functions() self.userconf = ConfigLoader() self.lyrics_downloader = LyricsDownloader() def start_playback(wdg): # Create GStreamer instance self.gst = GStreamer() self.gst.set_playback('gapless') self.gst.player.connect('about-to-finish', self.song_nearly_ended) self.gst.stop() self.current_song = False self.current_album = False # Prepare buttons self.btn_playpause = wdg[0][7] self.btn_previous = wdg[0][5] self.btn_next = wdg[0][8] self.btn_stop = wdg[0][6] self.btn_previous.connect('clicked', self.previous_pressed) self.btn_stop.connect('clicked', self.stop_pressed) self.btn_playpause.connect('clicked', self.play_pressed) self.btn_next.connect('clicked', self.next_pressed) self.btn_player = wdg[0][9] self.headerbar = wdg[0][0] # Create the player box and popover gtkpla = join(self.functions.datadir, 'glade', 'playerbar.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gtkpla) basebox = win.get_object('playerbox') wdg[0][0].add(basebox) self.player_event = win.get_object('player_event') self.player_event.set_size_request(32, 32) self.player_button_img = win.get_object('image_cover') self.player_event.connect('button-press-event', self.show_player) default = join(self.functions.datadir, 'image', 'logo_head_big.png') cover_px = Pixbuf.new_from_file_at_scale(default, 20, 20, True) self.player_button_img.set_from_pixbuf(cover_px) self.player_event.set_sensitive(False) self.player_scalab = win.get_object('label_scale') self.player_scalab.set_markup('<span size="small">00:00</span>') self.player_sca = win.get_object('scale') self.player_sca.connect('change-value', self.on_change_value) self.player_sca.set_sensitive(False) # Create the player popover gtkpla = join(self.functions.datadir, 'glade', 'playerpopover.ui') win = gtk_builder() win.add_from_file(gtkpla) hbox = win.get_object('box-player') self.player_img = win.get_object('image') self.player_pop = Popover.new(self.player_event) self.player_pop.set_size_request(200, 200) self.player_pop.add(hbox) self.lyrics_button = wdg[1].get_object('tool-lyrics') self.lyrics_pop = Popover.new(self.lyrics_button) self.lyrics_pop.set_size_request(400, 600) box = Box(1, 0) self.lyrics_swin = ScrolledWindow() lyrics_tview = TextView() lyrics_tview.set_editable(False) self.lyrics_buffer = TextBuffer() lyrics_tview.set_buffer(self.lyrics_buffer) self.lyrics_swin.add(lyrics_tview) box.add(self.lyrics_swin) self.lyrics_wait = Spinner() self.lyrics_wait.props.active = True box.add(self.lyrics_wait) self.lyrics_pop.add(box) def show_lyrics(widget): if self.current_song: title = self.current_song.title artist = self.current_song.artist album = self.current_song.album filename = self.current_song.filename sn = self.functions.get_hash(title, artist) lyrics_file = join(self.userconf.datadir, '%s.lyrics' % sn) lyrics = self.lyrics_downloader.get_lyrics(title, artist, True) self.lyrics_pop.show_all() if lyrics is not None: self.lyrics_wait.hide() self.lyrics_swin.show() self.lyrics_buffer.set_text(lyrics) else: self.lyrics_swin.hide() self.lyrics_wait.show() self.lyrics_buffer.set_text('') self.lyrics_button.connect('clicked', show_lyrics) self.lyrics_button.set_sensitive(False) # Acquire the songs tree def acquire_tree(st): self.songs_tree = st self.extensions.connect('OnSongsTreeCreated', acquire_tree) self.extensions.connect('OnBluemindoStarted', start_playback) self.extensions.connect('OnPlayNewSong', self.on_play_new_song) self.extensions.connect('OnPlayNewAlbum', self.on_play_new_album) self.extensions.connect('OnAbortPlayback', self.on_abort_playback) self.extensions.connect('OnPlayPressed', self.play_pressed) self.extensions.connect('OnStopPressed', self.stop_pressed) self.extensions.connect('OnNextPressed', self.next_pressed) self.extensions.connect('OnPreviousPressed', self.previous_pressed)
def __init__(self, extensionsloader): self.extensions = extensionsloader self.module = {'name': 'Playlist'} self.functions = Functions() self.userconf = ConfigLoader() self.config = {} rpt = self.userconf.config['Playlist']['repeat'] self.config['repeat'] = bool(int(rpt)) shf = self.userconf.config['Playlist']['shuffle'] self.config['shuffle'] = bool(int(shf)) shm = self.userconf.config['Playlist']['shuffle_mode'] self.config['shuffle_mode'] = shm self.lastfm = LastFm() self.playlists_mgmnt = Playlists() self.playlist_content = {} self.playlist_identifier = 0 self.playlist_current = None self.current_playlist_id = 0 self.user_playlists = {} self.last_user_playlist = None self.similar_artists = [] self.is_in_similar_thread = False # Create the Playlist view def launch_playlist(wdg): self.widgets = wdg[1] self.playlist_label = self.widgets.get_object('label_playlist') self.playlist_repeat = self.widgets.get_object('tool-repeat') self.playlist_shuffle = self.widgets.get_object('tool-shuffle') self.playlist_clean = self.widgets.get_object('tool-clean') self.playlist_combo = self.widgets.get_object('combo-playlist') self.playlist_save = self.widgets.get_object('tool-saveplaylist') self.playlist_lyrics = self.widgets.get_object('tool-lyrics') self.playlist_tree = self.widgets.get_object('treeview_playlist') self.playlist_tree.set_headers_visible(False) self.playlist_tree.props.reorderable = True self.playlist_tree.connect('key_press_event', self.key_pressed) self.playlist_tree.connect('row_activated', self.row_activated) self.liststore = ListStore(str, str, str, str, int) self.playlist_tree.set_model(self.liststore) renderer_pix = CellRendererPixbuf() column_pixbuf = TreeViewColumn('1', renderer_pix, icon_name=0) column_pixbuf.set_fixed_width(18) self.playlist_tree.append_column(column_pixbuf) renderer_text = CellRendererText() column_text = TreeViewColumn('2', renderer_text, markup=1) column_text.props.expand = True column_text.props.max_width = 192 self.playlist_tree.append_column(column_text) column_text = TreeViewColumn('3', renderer_text, markup=2) column_text.set_fixed_width(40) self.playlist_tree.append_column(column_text) self.repeat_btn = self.widgets.get_object('tool-repeat') if self.config['repeat']: self.repeat_btn.set_active(True) self.repeat_btn.connect('clicked', self.toggle, 'repeat') self.shuffle_btn = self.widgets.get_object('tool-shuffle') if self.config['shuffle']: self.shuffle_btn.set_active(True) self.shuffle_btn.connect('clicked', self.toggle, 'shuffle') def clean_wdg(widget): # Clean playlist self.clean() # Show popover if self.current_playlist_id > 3: self.clean_btn.set_sensitive(True) self.clean_pop.show_all() self.clean_btn = self.widgets.get_object('tool-clean') self.clean_btn.connect('clicked', clean_wdg) self.clean_pop = Popover.new(self.clean_btn) self.clean_pop.set_size_request(100, 30) gtkpla = join(self.functions.datadir, 'glade', 'plist-del-pop.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gtkpla) hbox = win.get_object('box-playlist') lbl = win.get_object('label') lbl.set_text(_('Do you also want to remove the playlist?')) btn = win.get_object('del-btn') btn.set_label(_('Delete')) btn.connect('clicked', self.delete_playlist) self.clean_pop.add(hbox) # Populate combobox self.combolist = ListStore(int, str) self.combobox = self.widgets.get_object('combobox') self.combobox.set_model(self.combolist) self.combobox.set_popup_fixed_width(False) self.combobox.props.expand = False renderer_text = CellRendererText() renderer_text.props.ellipsize = EllipsizeMode.END self.combobox.pack_start(renderer_text, True) self.combobox.set_entry_text_column(1) self.combobox.add_attribute(renderer_text, 'text', 1) self.combolist.append([0, _('Current')]) self.combolist.append([1, _('Top 50 songs')]) self.combolist.append([2, _('Top 10 albums')]) playlists = self.playlists_mgmnt.get_playlists() if len(playlists) > 0: self.combolist.append([3, '']) item_id = 3 playlists.sort(key=lambda it: it[1]) for item in playlists: item_id += 1 self.combolist.append([item_id, item]) self.user_playlists[item_id] = item self.last_user_playlist = item_id def combo_sep(model, iter): if model[iter][0] == 3: return True self.combobox.set_row_separator_func(combo_sep) def on_combo_changed(widget): path = widget.get_active() item_id = self.combolist[path][0] # First, clean the playlist self.clean(None) # Second, populate the playlist if item_id > 0: self.populate(item_id) # Then, update playlist identifier self.current_playlist_id = item_id # Show delete/remove button if the playlist is from the user if item_id > 3: self.clean_btn.set_sensitive(True) self.combobox.set_active(0) self.combobox.connect('changed', on_combo_changed) self.tool_save = self.widgets.get_object('tool-saveplaylist') self.tool_save.connect('clicked', self.save_playlist) self.save_pop = Popover.new(self.tool_save) self.save_pop.set_size_request(100, 30) gtkpla = join(self.functions.datadir, 'glade', 'plist-add-pop.ui') win = gtk_builder() win.set_translation_domain('bluemindo') win.add_from_file(gtkpla) hbox = win.get_object('box-playlist') self.save_pop.add(hbox) self.save_entry = win.get_object('save-entry') self.save_entry.connect('key_press_event', self.save_playlist_key) self.save_btn = win.get_object('save-btn') self.save_btn.connect('clicked', self.save_playlist_button) self.save_btn.set_label(_('Save')) self.clean_btn.set_sensitive(False) self.tool_save.set_sensitive(False) # Acquire the songs tree def acquire_tree(st): self.songs_tree = st self.extensions.connect('OnBluemindoStarted', launch_playlist) self.extensions.connect('OnSongsTreeCreated', acquire_tree) self.extensions.connect('OnSongQueued', self.on_new_song_queued) self.extensions.connect('OnAlbumQueued', self.on_new_album_queued) self.extensions.connect('AskPreviousSong', self.ask_previous_song) self.extensions.connect('AskNextSong', self.ask_next_song) self.extensions.connect('HasStartedSong', self.song_started)