def init_downlist_treeview(self): '''初始化下载列表''' # 替换掉glade那个占位页面 widgets = self.downlist_scrolledwindow.get_children() for widget in widgets: self.downlist_scrolledwindow.remove(widget) self.downlist_treeview = DownlistTreeview(self) self.downlist_scrolledwindow.add(self.downlist_treeview) self.downlist_scrolledwindow.show_all()
class GmBox(): def __init__(self): # 从glade文件构建widgets builder = gtk.Builder() builder.add_from_file(get_glade_file_path('gmbox.glade')) builder.connect_signals(self) for widget in builder.get_objects(): if issubclass(type(widget), gtk.Buildable): name = gtk.Buildable.get_name(widget) setattr(self, name, widget) # 全局变量 # 保存搜索结果列表缓存 self.result_pages = {} # 剪贴板对象 self.clipboard = gtk.Clipboard() # 初始化widgets的状态 self.init_mainwin() self.init_info_textview() self.init_category_treeview() self.init_screener_widgets() self.init_result_notebook() self.init_playlist_treeview() self.init_downlist_treeview() self.init_preferences_widgets() self.init_player_widgets() self.init_status_icon() # 初始化代理 self.init_proxy_setting() # 某些功能未完成,屏蔽掉 self.init_not_done_yet() # GUI 初始化函数 def init_mainwin(self): '''初始化主窗口''' # 窗口 self.mainwin.hided = False self.mainwin.set_title("百度音乐盒 - 0.1") self.mainwin.set_icon(ICON_DICT["gmbox"]) # 主面板 self.sidebar_vbox.hided = False self.info_vbox.hided = False self.info_vbox.hide() # 侧边栏 self.search_vbox.hided = False self.category_vbox.hided = False #self.screener_vbox.hided = False self.screener_vbox.hide() self.screener_vbox.hided = True def init_info_textview(self): '''初始化信息面板''' self.info_textview.modify_font(pango.FontDescription("Mono")) self.info_textview.set_editable(False) self.info_textbuffer = self.info_textview.get_buffer() def init_category_treeview(self): '''初始化分类列表''' # 替换掉glade那个占位页面 widgets = self.category_scrolledwindow.get_children() for widget in widgets: self.category_scrolledwindow.remove(widget) category_treeview = CategoryTreeview(self) self.category_scrolledwindow.add(category_treeview) self.category_scrolledwindow.show_all() def init_screener_widgets(self): '''初始化挑歌面板 有可能会被播放列表替代''' tempo_adjustment = gtk.Adjustment(value=50, upper=100) pitch_adjustment = gtk.Adjustment(value=50, upper=100) timbre_adjustment = gtk.Adjustment(value=50, upper=100) date_adjustment = gtk.Adjustment(value=50, upper=100) self.tempo_hscale.set_adjustment(tempo_adjustment) self.pitch_hscale.set_adjustment(pitch_adjustment) self.timbre_hscale.set_adjustment(timbre_adjustment) self.date_hscale.set_adjustment(date_adjustment) def init_result_notebook(self): '''初始化搜索结果notebook''' page_text = "空白" page_key = "empty" empty_result_page = ResultPage(self) empty_result_page_label = ResultPageLabel(empty_result_page, page_text, page_key) self.result_pages[page_key] = (empty_result_page, empty_result_page_label) # 替换掉glade那个占位页面 self.result_notebook.remove_page(0) self.result_notebook.append_page(empty_result_page, empty_result_page_label) def init_playlist_treeview(self): '''初始化播放列表''' # 替换掉glade那个占位页面 widgets = self.playlist_scrolledwindow.get_children() for widget in widgets: self.playlist_scrolledwindow.remove(widget) self.playlist_treeview = PlaylistTreeview(self) self.playlist_scrolledwindow.add(self.playlist_treeview) self.playlist_scrolledwindow.show_all() def init_downlist_treeview(self): '''初始化下载列表''' # 替换掉glade那个占位页面 widgets = self.downlist_scrolledwindow.get_children() for widget in widgets: self.downlist_scrolledwindow.remove(widget) self.downlist_treeview = DownlistTreeview(self) self.downlist_scrolledwindow.add(self.downlist_treeview) self.downlist_scrolledwindow.show_all() def init_preferences_widgets(self): '''初始化首选项对话框''' self.file_chooser_dialog = gtk.FileChooserDialog("选择一个文件", None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_OPEN, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) self.folder_chooser_dialog = gtk.FileChooserDialog("选择一个文件夹", None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_OPEN, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) load_config_file() self.update_player_widgets() self.update_preferences_widgets() def init_player_widgets(self): '''初始化内置播放器''' play_process_adjustment = gtk.Adjustment(value=0, upper=100) self.play_process_hscale.set_adjustment(play_process_adjustment) def init_status_icon(self): '''初始化通知区域图标''' self.status_icon = gtk.StatusIcon() self.status_icon.set_from_pixbuf(ICON_DICT["gmbox"]) self.status_icon.connect("activate", self.on_status_icon_activate) self.status_icon.set_visible(CONFIG["show_status_icon"]) def init_proxy_setting(self): ''' 初始化代理设置 ''' if CONFIG['use_http_proxy']: logger.debug("使用代理:http://%s", CONFIG['http_proxy_url']) os.environ['http_proxy'] = "http://%s" % CONFIG['http_proxy_url'] else: logger.debug("禁用代理") if "http_proxy" in os.environ: del os.environ['http_proxy'] def init_not_done_yet(self): '''初始化未完成的咚咚''' # 内置播放器mpg123在win下还没能用 if sys.platform == "win32": self.player_internal_radiobutton.set_sensitive(False) self.player_external_radiobutton.set_active(True) # 歌曲详情 self.view_detail_menuitem.hide() self.menuitem5.hide() cache_dir = CONFIG['cache_folder'] if not os.path.exists(cache_dir): os.mkdir(cache_dir) def update_preferences_widgets(self): '''更新首选项对话框widget状态''' # 常规 self.download_folder_entry.set_text(CONFIG["download_folder"]) self.filename_template_entry.set_text(CONFIG["filename_template"]) self.download_cover_checkbutton.set_active(CONFIG["download_cover"]) self.download_lyric_checkbutton.set_active(CONFIG["download_lyric"]) # 播放器 self.player_internal_radiobutton.set_active(CONFIG["player_use_internal"]) self.player_external_radiobutton.set_active(not CONFIG["player_use_internal"]) self.player_path_entry.set_text(CONFIG["player_path"]) self.player_single_entry.set_text(CONFIG["player_single"]) self.player_multi_entry.set_text(CONFIG["player_multi"]) # 下载程序 self.downloader_internal_radiobutton.set_active(CONFIG["downloader_use_internal"]) self.downloader_external_radiobutton.set_active(not CONFIG["downloader_use_internal"]) self.downloader_path_entry.set_text(CONFIG["downloader_path"]) self.downloader_single_entry.set_text(CONFIG["downloader_single"]) self.downloader_multi_entry.set_text(CONFIG["downloader_multi"]) self.downloader_mkdir_checkbutton.set_active(CONFIG["downloader_mkdir"]) # 杂项 self.show_status_icon_checkbutton.set_active(CONFIG["show_status_icon"]) self.use_http_proxy_checkbutton.set_active(CONFIG["use_http_proxy"]) self.http_proxy_url_entry.set_text(CONFIG["http_proxy_url"]) def update_status_icon(self): '''更新通知区域图标状态''' self.status_icon.set_visible(CONFIG["show_status_icon"]) def update_player_widgets(self): '''更新内置播放器widget状态''' # 如果不是使用内置播放器,则隐藏 if CONFIG["player_use_internal"]: self.player_vseparator.show() self.player_hbox.show() else: self.stop_internal_player() self.player_vseparator.hide() self.player_hbox.hide() def update_player_process_hscale(self): '''更新内置播放器进度条状态''' self.play_process_hscale.set_value(self.player.song.play_process) return self.player_running.isSet() def print_message(self, text): '''状态栏和信息面板显示信息''' def _print_message(): context_id = self.statusbar.get_context_id("context_id") self.statusbar.push(context_id, text) iter = self.info_textbuffer.get_end_iter() info_text = "%s %s\n" % (time.strftime("%H:%m:%S"), text) self.info_textbuffer.insert(iter, info_text) # 作为线程运行 gobject.idle_add(_print_message) def create_result_page(self, target, arg, page_text, page_key): '''创建搜索结果标签页''' def _get_result(callback): '''获取结果''' try: if arg is None: result = target() else: result = target(arg) error_text = None except StandardError as error: traceback.print_exc() result = None error_text = str(error) gobject.idle_add(callback, result, error_text) def _handle_result(result, error_text): '''处理结果''' if result is None: result_page.load_message("遇到错误:%s" % error_text) # 从结果缓存中移除出去 self.result_pages.pop(page_key) else: if isinstance(result, Songlist): length = len(result.songs) else: length = len(result.songlists) if length == 0: result_page.load_message("找不到和查询条件相符的音乐") else: result_page.load_result(result) # 添加第一个搜索结果标签页时,先删除原来的空白页 empty_result_page = self.result_pages["empty"][0] if self.result_notebook.page_num(empty_result_page) != -1: self.result_notebook.remove(empty_result_page) # 创建结果标签页 result_page = ResultPage(self) result_page_label = ResultPageLabel(result_page, page_text, page_key) result_page_label.connect("button-press-event", self.on_result_notebook_tab_button_press_event) self.result_pages[page_key] = (result_page, result_page_label) index = self.result_notebook.append_page(result_page, result_page_label) self.result_notebook.set_current_page(index) # 调用核心库获取结果 thread.start_new_thread(_get_result, (_handle_result,)) def find_result_page(self, page_key): '''从缓存搜索结果标签页''' # 切换到该页面 self.main_notebook.set_current_page(0) if self.result_pages.has_key(page_key): # 删除原来的空白页 empty_result_page = self.result_pages["empty"][0] if self.result_notebook.page_num(empty_result_page) != -1: self.result_notebook.remove(empty_result_page) # 从缓存取出标签页 result_page, result_page_label = self.result_pages[page_key] index = self.result_notebook.page_num(result_page) if index == -1: # 重新添加并显示出来 index = self.result_notebook.append_page(result_page, result_page_label) self.result_notebook.set_current_page(index) return True else: return False def do_search(self, text, type): '''处理搜索''' if type == "song": self.print_message('搜索歌曲"%s"...' % text) page_text = text page_key = "search_song:%s" % text if not self.find_result_page(page_key): self.create_result_page(Search, text, page_text, page_key) elif type == "album": self.print_message('搜索专辑"%s"...' % text) page_text = text page_key = "search_album:%s" % text if not self.find_result_page(page_key): self.create_result_page(DirSearch, text, page_text, page_key) else: self.print_message('搜索歌手“%s”。' % text) page_text = text page_key = "search_artist:%s" % text if not self.find_result_page(page_key): self.create_result_page(DirArtist, text, page_text, page_key) def do_chartlisting(self, name, chart_id, node_type): '''处理排行榜''' self.print_message('获取"%s"...' % name) page_text = name page_key = "chartlisting:%s" % chart_id if not self.find_result_page(page_key): if node_type == Song: self.create_result_page(Chartlisting, chart_id, page_text, page_key) def do_stylelisting(self, name, style_id, node_type): '''处理流派''' self.print_message('获取"%s"...' % name) page_text = name page_key = 'stylelisting:%s' % style_id if not self.find_result_page(page_key): if node_type == Song: self.create_result_page(Stylelisting, name, page_text, page_key) def do_tag(self, name, tag_type): '''处理标签''' if tag_type == Song: self.print_message('搜索歌曲标签“%s”。' % name) page_text = name page_key = "tag_song:%s" % name if not self.find_result_page(page_key): self.create_result_page(Taglisting, name, page_text, page_key) def do_channel(self, name, channel_id, channel_type): pass # def do_topiclistingdir(self): # '''处理专题列表''' # # self.print_message('获取最新专题。') # page_text = "最新专题" # page_key = "topiclistingdir" # if not self.find_result_page(page_key): # self.create_result_page(DirTopiclistingdir, None, page_text, page_key) # def do_similar(self, id, name): # '''处理相似歌曲''' # # self.print_message('获取“%s”的相似歌曲。' % name) # page_text = name # page_key = "similar:%s" % id # if not self.find_result_page(page_key): # self.create_result_page(Similar, id, page_text, page_key) # def do_artist_song(self, id, name): # '''处理热门歌曲''' # # self.print_message('获取“%s”的热门歌曲。' % name) # page_text = name # page_key = "artist_song:%s" % id # if not self.find_result_page(page_key): # self.create_result_page(ArtistSong, id, page_text, page_key) # # def do_artist_album(self, id, name): # '''处理艺术家专辑''' # # self.print_message('获取“%s”的专辑。' % name) # page_text = name # page_key = "artist_album:%s" % id # if not self.find_result_page(page_key): # self.create_result_page(DirArtistAlbum, id, page_text, page_key) # # def do_album(self, id, name): # self.print_message('获取专辑"%s"的歌曲。' % name) # page_text = name # page_key = "album:%s" % id # if not self.find_result_page(page_key): # self.create_result_page(Album, id, page_text, page_key) def popup_content_menu(self, songs, event, caller): '''弹出右键菜单''' self.selected_songs = songs # 显示所有菜单条目 self.playlist_menuitem.show() self.playlist_remove_menuitem.hide() self.playlist_clear_menuitem.hide() self.savelist_menuitem.hide() self.downlist_menuitem.show() self.downlist_remove_menuitem.hide() self.downlist_clear_menuitem.hide() # 不同页面使用隐藏某些菜单条目 if isinstance(caller, PlaylistTreeview): self.playlist_menuitem.hide() self.savelist_menuitem.show() self.playlist_remove_menuitem.show() self.playlist_clear_menuitem.show() if isinstance(caller, DownlistTreeview): self.downlist_menuitem.hide() self.savelist_menuitem.hide() self.downlist_remove_menuitem.show() self.downlist_clear_menuitem.show() if CONFIG["downloader_use_internal"]: self.downlist_menuitem.hide() if isinstance(caller, DownlistTreeview) and CONFIG["downloader_use_internal"]: self.down_menuitem.hide() # 可以显示出来了 self.content_menu.popup(None, None, None, event.button, event.time) def start_internal_player(self, song): '''启动播放器''' self.get_songs_urls([song], "stream") self.player_running = threading.Event() self.player_running.set() self.player = Player(song, self.player_running, self.internal_player_callback) Cacher(song).start() self.playlist_treeview.set_focus(song) self.print_message('正在播放 %s' % song.name) self.mainwin.set_title("%s-%s" % (song.name, song.artist_name)) self.player.start() self.player.song.play_status = "播放中" self.player.song.play_process = 0 self.playlist_treeview.queue_draw() self.playing = True self.play_button.set_label("暂停") # 定时更新进度条 gobject.timeout_add(1000, self.update_player_process_hscale) def stop_internal_player(self): '''停止播放器''' if hasattr(self, "player_running"): self.player_running.clear() self.player.song.play_status = "" self.player.song.play_process = 0 self.playlist_treeview.queue_draw() self.playing = False self.play_button.set_label("播放") def internal_player_callback(self, song): '''播放器回调函数,当一首歌播放完成时调用''' self.player.song.play_status = "" self.player.song.play_process = 0 self.playlist_treeview.queue_draw() song = self.playlist_treeview.get_next_song(song) self.start_internal_player(song) @handle_zero_length def play_songs(self, songs): '''播放歌曲''' self.add_to_playlist(songs) if CONFIG["player_use_internal"]: self.stop_internal_player() self.start_internal_player(songs[0]) else: # 使用外部播放器 thread.start_new_thread(self.start_external_player, (songs,)) @handle_zero_length def down_songs(self, songs): '''下载歌曲''' self.add_to_downlist(songs) # 选择下载程序 if CONFIG["downloader_use_internal"]: self.downlist_treeview.start_downloader() else: # 使用外部下载程序 thread.start_new_thread(self.start_external_downloader, (songs,)) @handle_zero_length def add_to_playlist(self, songs): '''添加到播放列表''' if CONFIG["player_use_internal"]: for song in songs: song.play_process = 0 song.play_status = "" else: for song in songs: song.play_status = "外部程序播放" self.playlist_treeview.append_songs(songs) self.print_message("已添加%d首歌曲到播放列表。" % len(songs)) @handle_zero_length def add_to_downlist(self, songs): '''添加到下载列表''' if CONFIG["downloader_use_internal"]: for song in songs: song.down_process = "0%" song.down_status = "等待中" else: for song in songs: song.down_process = "100%" song.down_status = "外部程序下载" self.downlist_treeview.append_songs(songs) self.print_message("已添加%d首歌曲到下载列表。" % len(songs)) def get_songs_urls(self, songs, url_type): '''获取歌曲地址''' urls = [] if url_type == "stream": for song in songs: if not hasattr(song, "listen_url"): self.print_message("正在获取“%s”的试听地址。" % song.name) song.load_song_link() if song.listen_url == "": self.print_message("获取“%s”试听地址失败,请稍后再试。" % song.name) else: urls.append(song.listen_url) elif url_type == "lyric": for song in songs: if not hasattr(song, "lyric_url"): self.print_message("正在获取“%s”的歌词地址。" % song.name) song.load_song_link() if song.lyric_url == "": self.print_message("获取“%s”歌词地址失败,请稍后再试。" % song.name) else: urls.append(song.lyric_url) else: # 下载地址 for song in songs: if not hasattr(song, "download_url"): self.print_message("正在获取“%s”的下载地址。" % song.name) song.load_download() if not song.download_url: self.print_message("获取“%s”下载地址失败,请稍后再试。" % song.name) else: urls.append(song.download_url[0][0]) return urls @handle_zero_length def start_external_player(self, songs): self.get_songs_urls(songs, "stream") player = CONFIG["player_path"] if player == "": self.print_message("未设置播放器。") return if len(songs) == 1: cmd = [player] cmd.extend(CONFIG["player_single"].split()) song = songs[0] url = song.song_url.decode("utf-8").encode(sys.getfilesystemencoding()) if "${URL}" in cmd: cmd[cmd.index("${URL}")] = url else: cmd = [player] cmd.extend(CONFIG["player_multi"].split()) urls = [] for song in songs: url = song.song_url.decode("utf-8").encode(sys.getfilesystemencoding()) urls.append(url) if "${URLS}" in cmd: index = cmd.index("${URLS}") temp_cmd = cmd[:index] temp_cmd.extend(urls) temp_cmd.extend(cmd[index + 1:]) cmd = temp_cmd self.print_message('发送%d个地址到播放器' % len(songs)) subprocess.Popen(cmd) @handle_zero_length def start_external_downloader(self, songs): self.get_songs_urls(songs, "download") self.get_songs_urls(songs, "stream") downloader = CONFIG["downloader_path"] if downloader == "": self.print_message("未设置下载程序。") return download_folder = CONFIG["download_folder"] if download_folder.endswith("/"): download_folder = download_folder[:-1] if len(songs) == 1: cmd = [downloader] cmd.extend(CONFIG["downloader_single"].split()) song = songs[0] url = song.downloadUrl.decode("utf-8").encode(sys.getfilesystemencoding()) if "${URL}" in cmd: cmd[cmd.index("${URL}")] = url # 构造保存文件的绝对路径 filename = CONFIG["filename_template"].replace("${ALBUM}", song.album) filename = filename.replace("${ARTIST}", song.artist) filename = filename.replace("${TITLE}", song.name) if "${TRACK}" in filename: filename = filename.replace("${TRACK}", song.providerId[-2:]) filepath = "%s/%s.mp3" % (download_folder, filename) if "${FILEPATH}" in cmd: cmd[cmd.index("${FILEPATH}")] = filepath if CONFIG['downloader_mkdir']: dirpath = os.path.dirname(filepath) logger.info("建立下载目录:%s", dirpath) if not os.path.exists(dirpath): os.makedirs(dirpath) logger.info("调用外部播放器:%s", cmd) subprocess.Popen(cmd, cwd=download_folder) else: cmd = [downloader] cmd.extend(CONFIG["downloader_multi"].split()) urls = [] for song in songs: url = song.downloadUrl.decode("utf-8").encode(sys.getfilesystemencoding()) urls.append(url) if "${URLS}" in cmd: index = cmd.index("${URLS}") temp_cmd = cmd[:index] temp_cmd.extend(urls) temp_cmd.extend(cmd[index + 1:]) cmd = temp_cmd print cmd subprocess.Popen(cmd, cwd=download_folder) def copy_url_to_clipboard(self, songs, url_type): '''复制歌曲地址到剪贴板''' def _get_url(callback): urls = self.get_songs_urls(songs, url_type) gobject.idle_add(callback, urls) def _handle_url(urls): # 粘贴到剪贴板 text = "\n".join(urls) self.clipboard.set_text(text) self.print_message("共复制%d个%s地址已复制到剪贴板。" % (len(urls), url_type_name)) self.copy_menuitem.set_sensitive(True) if url_type == "stream": url_type_name = "试听" elif url_type == "lyric": url_type_name = "歌词" else: # 下载地址 url_type_name = "下载" self.copy_menuitem.set_sensitive(False) self.print_message("正在获取%d首歌曲的%s地址。" % (len(songs), url_type_name)) thread.start_new_thread(_get_url, (_handle_url,)) def export_url_to_file(self, songs, url_type): '''输出地址到文件''' def _get_url(callback): '''获取地址''' urls = self.get_songs_urls(songs, url_type) gobject.idle_add(callback, urls) def _handle_url(urls): '''处理地址''' text = "\n".join(urls) # 输出到文件 if filename != "": fp = open(filename, "w") fp.write(text) self.print_message("共导出%d个%s地址到文件。" % (len(urls), url_type_name)) self.export_menuitem.set_sensitive(True) if url_type == "stream": url_type_name = "试听" elif url_type == "lyric": url_type_name = "歌词" else: # 下载地址 url_type_name = "下载" # 选择保存文件 filename = "" dialog = gtk.FileChooserDialog("选择一个文件", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_OPEN, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) response = dialog.run() if response == gtk.RESPONSE_OK: filename = dialog.get_filename() dialog.destroy() self.export_menuitem.set_sensitive(False) self.print_message("正在获取%d首歌曲的%s地址。" % (len(songs), url_type_name)) thread.start_new_thread(_get_url, (_handle_url,)) def set_artist_label_text(self): '''更新艺术家标签文本,挑歌面板里的''' if self.custom_artist_radiobutton.get_active(): markup_text = "<span size='small'>%s</span>" % self.custom_aritst_entry.get_text() self.artist_label.set_markup_with_mnemonic(markup_text) else: radiobuttons = self.artist_table.get_children() for radiobutton in radiobuttons: if radiobutton.get_active(): markup_text = "<span size='small'>%s</span>" % radiobutton.get_label() self.artist_label.set_markup_with_mnemonic(markup_text) break def set_genres_label_text(self): '''更新流派标签文本,挑歌面板里的''' checkbuttons = self.genres_table.get_children() checkbuttons.reverse() text = [] for checkbutton in checkbuttons: if checkbutton.get_active(): text.append(checkbutton.get_label()) markup_text = "<span size='small'>%s</span>" % ",".join(text) self.genres_label.set_markup_with_mnemonic(markup_text) def set_langs_label_text(self): '''更新语言标签文本,挑歌面板里的''' checkbuttons = self.langs_table.get_children() checkbuttons.reverse() text = [] for checkbutton in checkbuttons: if checkbutton.get_active(): text.append(checkbutton.get_label()) markup_text = "<span size='small'>%s</span>" % ",".join(text) self.langs_label.set_markup_with_mnemonic(markup_text) # widget回调函数 def on_search_entry_activate(self, widget, data=None): text = self.search_entry.get_text() if text == "": self.print_message("警告:查找字符串不能为空。") return if self.song_radiobutton.get_active(): search_type = "song" elif self.album_radiobutton.get_active(): search_type = "album" else: search_type = "artist" self.do_search(text, search_type) def on_search_entry_icon_press(self, widget, position, event, data=None): if position == gtk.ENTRY_ICON_SECONDARY: widget.set_text("") else: self.search_entry.emit("activate") def on_preferences_menuitem_activate(self, widget, data=None): self.update_preferences_widgets() response = self.preferences_dialog.run() if response == gtk.RESPONSE_OK: # 常规 CONFIG["download_folder"] = self.download_folder_entry.get_text() CONFIG["filename_template"] = self.filename_template_entry.get_text() CONFIG["player_use_internal"] = self.player_internal_radiobutton.get_active() CONFIG["downloader_use_internal"] = self.downloader_internal_radiobutton.get_active() CONFIG["download_cover"] = self.download_cover_checkbutton.get_active() CONFIG["download_lyric"] = self.download_lyric_checkbutton.get_active() # 播放器 CONFIG["player_path"] = self.player_path_entry.get_text() CONFIG["player_single"] = self.player_single_entry.get_text() CONFIG["player_multi"] = self.player_multi_entry.get_text() # 下载程序 CONFIG["downloader_path"] = self.downloader_path_entry.get_text() CONFIG["downloader_single"] = self.downloader_single_entry.get_text() CONFIG["downloader_multi"] = self.downloader_multi_entry.get_text() CONFIG["downloader_mkdir"]= self.downloader_mkdir_checkbutton.get_active() # 杂项 CONFIG["show_status_icon"] = self.show_status_icon_checkbutton.get_active() CONFIG["use_http_proxy"] = self.use_http_proxy_checkbutton.get_active() CONFIG["http_proxy_url"] = self.http_proxy_url_entry.get_text() # 更新一下状态 self.update_status_icon() self.update_player_widgets() # 保存设置到文件 save_config_file() self.preferences_dialog.hide() def on_sidebar_menuitem_toggled(self, widget, data=None): if self.sidebar_menuitem.get_active(): self.sidebar_vbox.show() self.sidebar_vbox.hided = False else: self.sidebar_vbox.hide() self.sidebar_vbox.hided = True def on_clear_info_menuitem_activate(self, widget, data=None): self.info_textbuffer.set_text("") def on_info_menuitem_toggled(self, widget, data=None): if self.info_menuitem.get_active(): self.info_vbox.show() self.info_vbox.hided = False else: self.info_vbox.hide() self.info_vbox.hided = True def on_about_menuitem_activate(self, widget, data=None): self.about_dialog.set_logo(ICON_DICT["gmbox"]) self.about_dialog.set_icon(ICON_DICT["gmbox"]) self.about_dialog.run() def on_about_dialog_response(self, widget, response_id, data=None): self.about_dialog.hide() def on_quit_menuitem_activate(self, widget, data=None): self.stop_internal_player() gtk.main_quit() def on_search_button_clicked(self, widget, data=None): if self.search_vbox.hided: self.search_vbox.show() self.search_arrow.set(gtk.ARROW_DOWN, gtk.SHADOW_NONE) self.search_vbox.hided = False else: self.search_vbox.hide() self.search_arrow.set(gtk.ARROW_RIGHT, gtk.SHADOW_NONE) self.search_vbox.hided = True def on_category_button_clicked(self, widget, data=None): if self.category_vbox.hided: self.category_vbox.show() self.category_arrow.set(gtk.ARROW_DOWN, gtk.SHADOW_NONE) self.category_vbox.hided = False else: self.category_vbox.hide() self.category_arrow.set(gtk.ARROW_RIGHT, gtk.SHADOW_NONE) self.category_vbox.hided = True def on_screener_button_clicked(self, widget, data=None): if self.screener_vbox.hided: self.screener_vbox.show() self.screener_arrow.set(gtk.ARROW_DOWN, gtk.SHADOW_NONE) self.screener_vbox.hided = False else: self.screener_vbox.hide() self.screener_arrow.set(gtk.ARROW_RIGHT, gtk.SHADOW_NONE) self.screener_vbox.hided = True def on_tempo_checkbutton_toggled(self, widget, data=None): status = self.tempo_checkbutton.get_active() self.tempo_label1.set_sensitive(status) self.tempo_label2.set_sensitive(status) self.tempo_hscale.set_sensitive(status) def on_pitch_checkbutton_toggled(self, widget, data=None): status = self.pitch_checkbutton.get_active() self.pitch_label1.set_sensitive(status) self.pitch_label2.set_sensitive(status) self.pitch_hscale.set_sensitive(status) def on_timbre_checkbutton_toggled(self, widget, data=None): status = self.timbre_checkbutton.get_active() self.timbre_label1.set_sensitive(status) self.timbre_label2.set_sensitive(status) self.timbre_hscale.set_sensitive(status) def on_date_checkbutton_toggled(self, widget, data=None): status = self.date_checkbutton.get_active() self.date_label1.set_sensitive(status) self.date_label2.set_sensitive(status) self.date_hscale.set_sensitive(status) def on_artist_checkbutton_toggled(self, widget, data=None): status = self.artist_checkbutton.get_active() self.artist_label.set_sensitive(status) self.artist_button.set_sensitive(status) if not status: markup_text = "<span size='small'>全部</span>" self.artist_label.set_markup_with_mnemonic(markup_text) else: self.set_artist_label_text() def on_genres_checkbutton_toggled(self, widget, data=None): status = self.genres_checkbutton.get_active() self.genres_label.set_sensitive(status) self.genres_button.set_sensitive(status) if not status: markup_text = "<span size='small'>全部</span>" self.genres_label.set_markup_with_mnemonic(markup_text) else: self.set_genres_label_text() def on_langs_checkbutton_toggled(self, widget, data=None): status = self.langs_checkbutton.get_active() self.langs_label.set_sensitive(status) self.langs_button.set_sensitive(status) if not status: markup_text = "<span size='small'>全部</span>" self.langs_label.set_markup_with_mnemonic(markup_text) else: self.set_langs_label_text() def on_custom_artist_radiobutton_toggled(self, widget, data=None): status = self.custom_artist_radiobutton.get_active() self.custom_aritst_entry.set_sensitive(status) def on_artist_button_clicked(self, widget, data=None): self.artist_dialog.run() self.set_artist_label_text() self.artist_dialog.hide() def on_genres_button_clicked(self, widget, data=None): self.genres_dialog.run() self.set_genres_label_text() self.genres_dialog.hide() def on_langs_button_clicked(self, widget, data=None): self.langs_dialog.run() self.set_langs_label_text() self.langs_dialog.hide() def on_apply_button_clicked(self, widget, data=None): args_dict = {} if self.tempo_checkbutton.get_active(): args_dict["tempo"] = str(self.tempo_hscale.get_value() / 100) if self.pitch_checkbutton.get_active(): args_dict["pitch"] = str(self.pitch_hscale.get_value() / 100) if self.timbre_checkbutton.get_active(): args_dict["timbre"] = str(self.timbre_hscale.get_value() / 100) if self.date_checkbutton.get_active(): #转换时间,3位小数,但是忽略小数点 # 例如 2010 年 #1262275200.0 --> 1262275200000 pos = (self.date_hscale.get_value() / 100) year_end = int(pos * (2010 - 1980) + 1980) args_dict["date_h"] = "%d000" % int(time.mktime(time.strptime(str(year_end), "%Y"))) if year_end == 1980: args_dict["date_l"] = "0" else: year_start = year_end - 3 args_dict["date_l"] = "%d000" % int(time.mktime(time.strptime(str(year_start), "%Y"))) if self.artist_checkbutton.get_active(): if self.custom_artist_radiobutton.get_active(): args_dict["artist"] = self.custom_aritst_entry.get_text() else: text = self.artist_label.get_text() if text != "": args_dict["artist_type"] = ARITST[text] if self.genres_checkbutton.get_active(): text = self.genres_label.get_text() if text != "": types = [] for name in text.split(","): types.append(GENRES[name]) args_dict["genres"] = ",".join(types) if self.langs_checkbutton.get_active(): text = self.langs_label.get_text() if text != "": langs = [] for name in text.split(","): langs.append(LANGS[name]) args_dict["langs"] = ",".join(langs) print args_dict self.do_screener(args_dict) def on_result_notebook_tab_button_press_event(self, widget, event, data=None): if event.type == gtk.gdk._2BUTTON_PRESS or event.button == 2: if self.result_notebook.get_n_pages() == 1: empty_result_page, empty_result_page_label = self.result_pages["empty"] if empty_result_page == self.result_notebook.get_nth_page(0): return else: self.result_notebook.append_page(empty_result_page, empty_result_page_label) index = self.result_notebook.page_num(widget.result_page) self.result_notebook.remove_page(index) def on_play_menuitem_activate(self, widget, data=None): self.play_songs(self.selected_songs) def on_down_menuitem_activate(self, widget, data=None): self.down_songs(self.selected_songs) def on_playlist_clear_menuitem_activate(self, widget, data=None): self.playlist_treeview.clear_songs() self.loaded_playlist = False def on_playlist_remove_menuitem_activate(self, widget, data=None): self.playlist_treeview.remove_songs(self.selected_songs) def on_downlist_remove_menuitem_activate(self, widget, data=None): self.downlist_treeview.remove_songs(self.selected_songs) def on_downlist_clear_menuitem_activate(self, widget, data=None): self.downlist_treeview.clear_songs() def on_playlist_menuitem_activate(self, widget, data=None): self.add_to_playlist(self.selected_songs) def on_downlist_menuitem_activate(self, widget, data=None): self.add_to_downlist(self.selected_songs) def on_savelist_menuitem_activate(self, widget, data = None): self.playlist_treeview.save_songs() def on_search_menuitem_activate(self, widget, data=None): for song in self.selected_songs: self.do_search(song.name.encode("utf8"), "song") def on_similar_menuitem_activate(self, widget, data=None): for song in self.selected_songs: self.do_similar(song.id, song.name) def on_album_menuitem_activate(self, widget, data=None): # 需要唯一的艺术家 ids = [] unique_songs = [] for song in self.selected_songs: song.load_detail() if song.albumId not in ids: ids.append(song.albumId) unique_songs.append(song) for song in unique_songs: self.do_album(song.albumId, song.album) def on_artist_hotsong_menuitem_activate(self, widget, data=None): # 需要唯一的艺术家 ids = [] unique_songs = [] for song in self.selected_songs: song.load_detail() if song.artistId not in ids: ids.append(song.artistId) unique_songs.append(song) for song in unique_songs: self.do_artist_song(song.artistId, song.artist) def on_artist_album_menuitem_activate(self, widget, data=None): # 需要唯一的艺术家 ids = [] unique_songs = [] for song in self.selected_songs: song.load_detail() if song.artistId not in ids: ids.append(song.artistId) unique_songs.append(song) for song in unique_songs: self.do_artist_album(song.artistId, song.artist) def on_copy_stream_url_menuitem_activate(self, widget, data=None): self.copy_url_to_clipboard(self.selected_songs, "stream") def on_copy_download_url_menuitem_activate(self, widget, data=None): self.copy_url_to_clipboard(self.selected_songs, "download") def on_copy_lyric_url_menuitem_activate(self, widget, data=None): self.copy_url_to_clipboard(self.selected_songs, "lyric") def on_export_stream_url_menuitem_activate(self, widget, data=None): self.export_url_to_file(self.selected_songs, "stream") def on_export_download_url_menuitem_activate(self, widget, data=None): self.export_url_to_file(self.selected_songs, "download") def on_export_lyric_url_menuitem_activate(self, widget, data=None): self.export_url_to_file(self.selected_songs, "lyric") def on_view_detail_menuitem_activate(self, widget, data=None): for song in self.selected_songs: print_song(song) #TODO: 加载歌曲详细信息 def on_result_page_button_clicked(self, widget, data=None): self.main_notebook.set_current_page(0) def on_playlist_page_button_clicked(self, widget, data=None): #TODO: 优化列表加载,更加模块化 if not hasattr(self, 'loaded_playlist') or self.loaded_playlist == False: list_path = get_playlist_path('default.xspf') if os.path.exists(list_path): pl = PlayList(None, list_path) id_list = pl.parse_xml() songset = SongSet(id_list) for song in songset.songs: song.icon = ICON_DICT['song'] self.add_to_playlist(songset.songs) self.loaded_playlist = True self.main_notebook.set_current_page(1) def on_downlist_page_button_clicked(self, widget, data=None): self.main_notebook.set_current_page(2) def on_play_button_clicked(self, widget, data=None): if hasattr(self, 'player_running') and self.player_running.isSet(): self.player.pause() self.playing = not self.playing if self.playing: self.play_button.set_label("暂停") else: self.play_button.set_label("播放") def on_stop_button_clicked(self, widget, data=None): self.stop_internal_player() def on_last_song_button_clicked(self, widget, data=None): song = self.playlist_treeview.get_last_song(self.player.song) self.stop_internal_player() self.start_internal_player(song) def on_next_song_button_clicked(self, widget, data=None): song = self.playlist_treeview.get_next_song(self.player.song) self.stop_internal_player() self.start_internal_player(song) def on_download_folder_button_clicked(self, widget, data=None): response = self.folder_chooser_dialog.run() if response == gtk.RESPONSE_OK: text = self.folder_chooser_dialog.get_filename() self.download_folder_entry.set_text(text) self.folder_chooser_dialog.hide() def on_player_path_button_clicked(self, widget, data=None): response = self.file_chooser_dialog.run() if response == gtk.RESPONSE_OK: text = self.file_chooser_dialog.get_filename() self.player_path_entry.set_text(text) self.file_chooser_dialog.hide() def on_downloader_path_button_clicked(self, widget, data=None): response = self.file_chooser_dialog.run() if response == gtk.RESPONSE_OK: text = self.file_chooser_dialog.get_filename() self.downloader_path_entry.set_text(text) self.file_chooser_dialog.hide() def on_status_icon_activate(self, widget, data=None): if self.mainwin.hided: self.mainwin.show() else: self.mainwin.hide() self.mainwin.hided = not self.mainwin.hided def on_mainwin_delete_event(self, widget, data=None): if CONFIG["show_status_icon"]: self.mainwin.hide() self.mainwin.hided = True return True else: self.stop_internal_player() gtk.main_quit()