def initial_params(self): self.files = [] self.lock = None self.downloadDir = '' self.deleteFlag = False self.isPlaying = False self.playingList = Playlist() self.allPlaylistNames = [] self.mode = 0
def add_bunch_to_list(self): """向“在线试听”列表批量添加歌曲。""" selecteds = self.searchTable.selectedIndexes() if not len(selecteds): return self.added_items = [] playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistOnline) musicIdsInOnlineList = playlistTemp.get_items_queue() for index in selecteds: if index.column() == 0: row = index.row() musicId = self.searchTable.item(row, 4).text() if musicId not in musicIdsInOnlineList: musicName = self.searchTable.item(row, 1).text() artist = self.searchTable.item(row, 2).text() title = connect_as_title(artist, musicName) album = self.searchTable.item(row, 3).text() lrcPath = composite_lyric_path_use_title(title) if os.path.exists(lrcPath): os.remove(lrcPath) self.added_items.append([title, musicId]) playlistTemp.add_record(musicId, title, Configures.ZeroTime, album, Configures.NoLink, 0, musicId) if len(self.added_items): playlistTemp.commit_records() thread = DownloadLrcThread(self.added_items) thread.setDaemon(True) thread.setName("downloadLrc") thread.start() self.add_bunch_to_list_succeed.emit()
def add_items_to_new_playlist(self, name, selecteds): currentListName = self.listName if not selecteds: return playlistTemp = Playlist() for index in selecteds: row = index.row() if index.column() == 0: playlistTemp.add_item(self.playlist.get_item_from_queue(row), self.playlist.get_infos_at(row)) self.set_playlist_use_name(name) self.add_musics_from_other_playlist(playlistTemp) self.set_playlist_use_name(currentListName)
class PlaylistWidgetBasic(QTableWidget): def __init__(self, listName, parent=None): super(PlaylistWidgetBasic, self).__init__(parent) self.listName = '' self.playlist = Playlist() def get_playlist(self): return self.playlist.copy() def get_operating_playlist_name(self): """获取正在被操作的列表名""" return self.listName def fill_playlist_widget(self, playlist): self.clear_all_items() itemsList = playlist.get_items_queue() group = playlist.get_infos_group() for item in itemsList: title = group[item][0] time = group[item][1] self.add_record(title, time) def clear_all_items(self): while self.rowCount(): self.removeRow(0) def add_record(self, title, time): countRow = self.rowCount() titleItem = QTableWidgetItem(title) self.insertRow(countRow) self.setItem(countRow, 0, titleItem) self.setRowHeight(countRow, 31) def add_record_with_full_info(self, id, title, totalTime, album, path, size, musicId=Configures.LocalMusicId): self.playlist.add_record(id, title, totalTime, album, path, size, musicId) self.add_record(title, totalTime) def add_a_music(self, path): title, totalTime = self.playlist.add_item_from_path(path) self.add_record(title, totalTime)
def initial_params(self): self.playlist = None self.artistName = "Zheng-Yejian" self.clickPlayFlag = False # 用来标志一首歌是否是主动点击选中的 self.timerFlag = False self.timeStart = 0 self.timeSpan = 0 self.sourcePath = "" self.errorType = Configures.NoError self.currentSourceRow = -1 self.nearPlayedSongs = [] self.downloadDir = globalSettings.DownloadfilesPath self.songinfosManager = SonginfosManager() self.totalTime = Configures.ZeroTime self.playmode = Configures.PlaymodeRandom # 播放模式指示器 playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) self.lovedSongs = playlistTemp.get_titles()
def initial_params(self): self.playlist = None self.artistName = 'Zheng-Yejian' self.clickPlayFlag = False #用来标志一首歌是否是主动点击选中的 self.timerFlag = False self.timeStart = 0 self.timeSpan = 0 self.sourcePath = '' self.errorType = Configures.NoError self.currentSourceRow = -1 self.nearPlayedSongs = [] self.downloadDir = globalSettings.DownloadfilesPath self.songinfosManager = SonginfosManager() self.totalTime = Configures.ZeroTime self.playmode = Configures.PlaymodeRandom #播放模式指示器 playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) self.lovedSongs = playlistTemp.get_titles()
def mark_selected_as_favorite(self): selecteds = self.selectedIndexes() self.markedIndexes = [] playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) existsTitles = playlistTemp.get_titles() for index in selecteds: row = index.row() path = self.playlist.get_music_path_at(row) title = self.playlist.get_music_title_at(row) if index.column( ) == 0 and title not in existsTitles and os.path.exists(path): playlistTemp.add_item(self.playlist.get_item_from_queue(row), self.playlist.get_record_at(row)) self.markedIndexes.append(row) if len(self.markedIndexes): playlistTemp.commit_records() self.musics_marked_signal.emit()
def mark_selected_as_favorite(self): selecteds = self.selectedIndexes() self.markedIndexes = [] playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) existsTitles = playlistTemp.get_titles() for index in selecteds: row = index.row() path = self.playlist.get_music_path_at(row) title = self.playlist.get_music_title_at(row) if index.column() == 0 and title not in existsTitles and os.path.exists(path): playlistTemp.add_item(self.playlist.get_item_from_queue(row), self.playlist.get_record_at(row)) self.markedIndexes.append(row) if len(self.markedIndexes): playlistTemp.commit_records() self.musics_marked_signal.emit()
class PlaylistWidget(PlaylistWidgetBasic): play_music_at_row_signal = pyqtSignal(int) play_or_pause_signal = pyqtSignal(int) playing_list_changed_signal = pyqtSignal(str, str) musics_added_signal = pyqtSignal(bool) musics_removed_signal = pyqtSignal() musics_cleared_signal = pyqtSignal() musics_marked_signal = pyqtSignal() download_signal = pyqtSignal() show_artist_info_signal = pyqtSignal(str) show_song_info_signal = pyqtSignal(int) tag_values_changed_signal = pyqtSignal(int, str, str, str) playlist_changed_signal = pyqtSignal() def __init__(self, parent=None): super(PlaylistWidget, self).__init__(parent) self.songOperator = SongOperator(self) self.initial_params() self.set_attritutes() self.create_menu_items() self.create_connections() def create_connections(self): self.cellEntered.connect(self.cell_entered) self.customContextMenuRequested.connect(self.music_table_menu) self.selectAllAction.triggered.connect(self.select_all_rows) self.selectInvertAction.triggered.connect(self.select_invert_rows) self.selectNoneAction.triggered.connect(self.select_none_rows) self.copytoMenu.triggered.connect(self.copy_to_other_playlist) self.movetoMenu.triggered.connect(self.move_to_other_playlist) self.addMusicAction.triggered.connect(self.add_musics) self.markSelectedAsFavoriteAction.triggered.connect( self.mark_selected_as_favorite) self.removeAction.triggered.connect(self.remove_musics) self.deleteAction.triggered.connect(self.delete_musics) self.clearListWidgetAction.triggered.connect(self.clear_musics) self.songSpecAction.triggered.connect(self.show_song_spec) self.artistSpecAction.triggered.connect(self.show_artist_info) self.downloadAction.triggered.connect(self.download_signal.emit) self.doubleClicked.connect(self.double_click_to_play) self.songOperator.wheel_event_triggered_signal.connect(self.wheelEvent) self.songOperator.double_clicked_signal.connect( self.double_click_to_play_with_row) self.songOperator.right_mouse_button_clicked_signal.connect( self.music_table_menu) self.songOperator.left_mouse_button_clicked_signal.connect( self.selectRow) self.songOperator.left_mouse_button_dragged_signal.connect( self.select_multi_rows) def cell_entered(self, row, column): if self.songOperator.isHidden(): self.songOperator.set_contents(row, self.item(row, column).text()) self.songOperator.show() oldRow = self.songOperator.get_row() if self.item(oldRow, column): self.item(oldRow, column).setText(self.playlist.get_music_title_at(oldRow)) self.songOperator.set_contents(row, self.playlist.get_music_title_at(row)) self.item(row, column).setText('') scrollBar = self.verticalScrollBar() scrolledValue = scrollBar.value() # if scrolledValue and scrolledValue == scrollBar.maximum(): # scrolledValue -= 1 self.songOperator.setGeometry(0, (row - scrolledValue) * self.rowHeight(row), 270, 31) def leaveEvent(self, event=None): self.hide_song_operator() def select_multi_rows(self, pos): exactPos = pos + self.songOperator.pos() item = self.itemAt(exactPos) if item: self.cell_entered(item.row(), 0) if not item.isSelected(): item.setSelected(True) def hide_song_operator(self): if not self.songOperator.isHidden(): oldRow = self.songOperator.get_row() item = self.item(oldRow, 0) if item: item.setText(self.playlist.get_music_title_at(oldRow)) self.songOperator.hide() def initial_params(self): self.files = [] self.lock = None self.downloadDir = '' self.deleteFlag = False self.isPlaying = False self.playingList = Playlist() self.allPlaylistNames = [] self.mode = 0 def set_playlist_names(self, listNames): self.allPlaylistNames = listNames def set_lock(self, lock): self.lock = lock def set_download_dir(self, dir): self.downloadDir = dir def set_playing_status(self, playlist): self.playingList = playlist def set_playlist_use_name(self, listName): if self.listName != listName: self.listName = listName self.playlist_changed_signal.emit() self.isPlaying = False if self.playingList.get_name() == listName: self.isPlaying = True if self.get_playing_used_state(): self.playlist = self.playingList.copy() else: self.playlist.fill_list(listName) self.fill_playlist_widget(self.playlist) self.select_row() self.pick_actions_into_menu() def get_playing_used_state(self): return self.isPlaying def get_playlist_length(self): return self.playlist.length() def get_playing_list_name(self): return self.playingList.get_name() def set_attritutes(self): self.setMouseTracking(True) self.setContextMenuPolicy(Qt.CustomContextMenu) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.horizontalHeader().setDefaultAlignment(Qt.AlignLeft) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.horizontalHeader().setVisible(False) self.verticalHeader().setVisible(False) self.setShowGrid(False) self.setRowCount(0) self.setColumnCount(1) self.setColumnWidth(0, 270) self.setColumnWidth(1, 80) def pick_actions_into_menu(self): self.listMenu.clear() if self.listName == Configures.PlaylistOnline: self.create_online_playlist_menu() elif self.listName == Configures.PlaylistFavorite: self.create_favor_playlist_menu() else: self.create_other_playlist_menu() def create_menu_items(self): self.listMenu = QMenu() self.addMusicAction = QAction("添加歌曲", self) self.selectAllAction = QAction("全选", self) self.selectInvertAction = QAction("反选", self) self.selectNoneAction = QAction("取消选择", self) self.markSelectedAsFavoriteAction = QAction("添加到“我的收藏”", self) self.copytoMenu = QMenu('复制到...') self.movetoMenu = QMenu('移动到...') self.downloadAction = QAction("下载", self) self.removeAction = QAction("移除歌曲", self) self.deleteAction = QAction("移除歌曲并删除本地文件", self) self.clearListWidgetAction = QAction("清空列表", self) self.songSpecAction = QAction("歌曲信息", self) self.artistSpecAction = QAction("歌手信息", self) def create_online_playlist_menu(self): self.listMenu.addAction(self.downloadAction) self.listMenu.addSeparator() self.listMenu.addAction(self.selectAllAction) self.listMenu.addAction(self.selectInvertAction) self.listMenu.addAction(self.selectNoneAction) self.listMenu.addSeparator() self.listMenu.addAction(self.removeAction) self.listMenu.addSeparator() self.listMenu.addAction(self.clearListWidgetAction) self.listMenu.addSeparator() self.listMenu.addAction(self.songSpecAction) self.listMenu.addAction(self.artistSpecAction) def create_favor_playlist_menu(self): self.listMenu.addAction(self.addMusicAction) self.listMenu.addSeparator() self.listMenu.addAction(self.selectAllAction) self.listMenu.addAction(self.selectInvertAction) self.listMenu.addAction(self.selectNoneAction) self.listMenu.addSeparator() self.listMenu.addAction(self.removeAction) self.listMenu.addAction(self.deleteAction) self.listMenu.addSeparator() self.listMenu.addAction(self.clearListWidgetAction) self.listMenu.addSeparator() self.listMenu.addAction(self.songSpecAction) self.listMenu.addAction(self.artistSpecAction) def fill_copyto_and_moveto_menu(self): self.copytoMenu.clear() self.movetoMenu.clear() if self.listName == Configures.PlaylistDefault: if len(self.allPlaylistNames) > 4: for i, name in enumerate(self.allPlaylistNames): if i >= 4: self.add_action(name) return True elif self.listName == Configures.PlaylistDownloaded: if len(self.allPlaylistNames) > 3: for i, name in enumerate(self.allPlaylistNames): if i >= 4 or i == 1: self.add_action(name) return True else: for i, name in enumerate(self.allPlaylistNames): if i == 1 or i >= 4 and name != self.listName: self.add_action(name) return True return False def add_action(self, name): action1 = QAction(name, self) self.copytoMenu.addAction(action1) action2 = QAction(name, self) self.movetoMenu.addAction(action2) def create_other_playlist_menu(self): self.listMenu.addAction(self.addMusicAction) self.listMenu.addSeparator() self.listMenu.addAction(self.selectAllAction) self.listMenu.addAction(self.selectInvertAction) self.listMenu.addAction(self.selectNoneAction) self.listMenu.addSeparator() self.listMenu.addAction(self.markSelectedAsFavoriteAction) self.listMenu.addSeparator() if self.fill_copyto_and_moveto_menu(): self.listMenu.addMenu(self.copytoMenu) self.listMenu.addMenu(self.movetoMenu) self.listMenu.addSeparator() self.listMenu.addAction(self.removeAction) self.listMenu.addAction(self.deleteAction) self.listMenu.addSeparator() self.listMenu.addAction(self.clearListWidgetAction) self.listMenu.addSeparator() self.listMenu.addAction(self.songSpecAction) self.listMenu.addAction(self.artistSpecAction) def music_table_menu(self, pos): pos += QPoint(10, 0) self.listMenu.exec_(self.mapToGlobal(pos)) def select_row(self): row = self.playingList.get_current_row() if self.get_playing_used_state() and row >= 0: self.selectRow(row) def add_musics(self): self.files = QFileDialog.getOpenFileNames(self, "选择音乐文件", self.downloadDir, self.tr("*.mp3"))[0] if not self.files: return self.exec_add_operation(self.files) self.musics_added_signal.emit(True) for item in self.files: row = self.playlist.get_item_index(item) self.setRangeSelected( QTableWidgetSelectionRange(row, 0, row, self.columnCount() - 1), True) @operate_after_check_thread_locked_state @trace_to_keep_time def exec_add_operation(self, files): self.addedIndexes = [] for item in sorted( list(set(files) - set(self.playlist.get_items_queue()))): self.add_a_music(item) self.addedIndexes.append(self.playlist.get_item_index(item)) if self.addedIndexes: self.playlist.commit_records() def remove_musics(self): self.removedIndexes = [] selecteds = self.selectedIndexes() currentRow = self.playingList.get_current_row( ) % self.playingList.length() if selecteds: for index in selecteds: row = index.row() if index.column() == 0: self.removedIndexes.append(row) self.removedIndexes.sort(reverse=True) if self.deleteFlag: text_tmp1 = "移除并删除本地文件" text_tmp2 = "有%s首歌曲将被移出列表,并被彻底删除,请确认!" % len( self.removedIndexes) else: text_tmp1 = "移除选中项" text_tmp2 = "有%s首歌曲将被移出列表,请确认!" % len(self.removedIndexes) ok = QMessageBox.warning(self, text_tmp1, text_tmp2, QMessageBox.No | QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.hide_song_operator() item = self.playingList.get_item_from_queue(currentRow) if not (self.get_playing_used_state() and currentRow in self.removedIndexes): self.exec_remove_operation(self.removedIndexes) if self.get_playing_used_state(): currentRow = self.playlist.get_item_index(item) else: currentMusic = self.playingList.get_music_title_at( currentRow) if self.deleteFlag: text_tmp3 = "移除并删除当前歌曲" text_tmp4 = "当前播放的歌曲: %s 将会被移除并被删除,请确认!" % currentMusic else: text_tmp3 = "移除当前歌曲" text_tmp4 = "当前播放的歌曲: %s 将会被移除,请确认!" % currentMusic ok = QMessageBox.warning(self, text_tmp3, text_tmp4, QMessageBox.No | QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.exec_remove_operation(self.removedIndexes) currentRow = -1 else: self.removedIndexes.remove(currentRow) self.exec_remove_operation(self.removedIndexes) currentRow = self.playlist.get_item_index(item) self.playlist.set_current_row(currentRow) self.musics_removed_signal.emit() def remove_without_check(self, selecteds): self.hide_song_operator() self.removedIndexes = [] currentRow = self.playingList.get_current_row( ) % self.playingList.length() if len(selecteds): for index in selecteds: row = index.row() if index.column() == 0: self.removedIndexes.append(row) self.removedIndexes.sort(reverse=True) item = self.playingList.get_item_from_queue(currentRow) if not (self.get_playing_used_state() and currentRow in self.removedIndexes): self.exec_remove_operation(self.removedIndexes) if self.get_playing_used_state(): currentRow = self.playlist.get_item_index(item) else: self.exec_remove_operation(self.removedIndexes) currentRow = -1 self.playlist.set_current_row(currentRow) self.musics_removed_signal.emit() @operate_after_check_thread_locked_state def exec_remove_operation(self, rows): if len(rows): for row in rows: self.removeRow(row) self.playlist.remove_item_at(row, self.deleteFlag) self.playlist.commit_records() def delete_musics(self): self.deleteFlag = True self.remove_musics() self.deleteFlag = False def clear_musics(self): if not self.rowCount(): return ok = QMessageBox.warning(self, "清空列表", "当前列表的所有歌曲(包括当前播放歌曲)都将被移除,请确认!", QMessageBox.No | QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.hide_song_operator() self.exec_clear_operation() self.musics_cleared_signal.emit() @operate_after_check_thread_locked_state def exec_clear_operation(self): self.clear_all_items() self.playlist.clear_list() self.playlist.commit_records() #标记选中项为喜欢 def mark_selected_as_favorite(self): selecteds = self.selectedIndexes() self.markedIndexes = [] playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) existsTitles = playlistTemp.get_titles() for index in selecteds: row = index.row() path = self.playlist.get_music_path_at(row) title = self.playlist.get_music_title_at(row) if index.column( ) == 0 and title not in existsTitles and os.path.exists(path): playlistTemp.add_item(self.playlist.get_item_from_queue(row), self.playlist.get_record_at(row)) self.markedIndexes.append(row) if len(self.markedIndexes): playlistTemp.commit_records() self.musics_marked_signal.emit() def copy_to_other_playlist(self, action): selecteds = self.selectedIndexes() self.add_items_to_new_playlist(action.text(), selecteds) self.select_range_rows(selecteds) def move_to_other_playlist(self, action): selecteds = self.selectedIndexes() self.add_items_to_new_playlist(action.text(), selecteds) self.remove_without_check(selecteds) def add_items_to_new_playlist(self, name, selecteds): currentListName = self.listName if not selecteds: return playlistTemp = Playlist() for index in selecteds: row = index.row() if index.column() == 0: playlistTemp.add_item(self.playlist.get_item_from_queue(row), self.playlist.get_infos_at(row)) self.set_playlist_use_name(name) self.add_musics_from_other_playlist(playlistTemp) self.set_playlist_use_name(currentListName) def add_musics_from_other_playlist(self, playlistTemp): self.addedIndexes = [] for item in sorted( list(playlistTemp.get_ids() - self.playlist.get_ids())): self.playlist.add_item(item, playlistTemp.get_info_use_id(item)) self.addedIndexes.append(self.playlist.get_item_index(item)) if self.addedIndexes: self.playlist.commit_records() self.musics_added_signal.emit(False) def select_range_rows(self, selecteds, flag=True): for index in selecteds: if index.column() == 0: self.select_a_row(index.row(), flag) def select_a_row(self, row, flag=True): self.setRangeSelected( QTableWidgetSelectionRange(row, 0, row, self.columnCount() - 1), flag) def select_invert_rows(self): selecteds = self.selectedIndexes() self.select_all_rows() self.select_range_rows(selecteds, False) def select_all_rows(self): self.setRangeSelected( QTableWidgetSelectionRange(0, 0, self.rowCount() - 1, self.columnCount() - 1), True) def select_none_rows(self): self.setRangeSelected( QTableWidgetSelectionRange(0, 0, self.rowCount() - 1, self.columnCount() - 1), False) def show_song_spec(self): row = self.currentRow() self.show_song_info_signal.emit(row) def show_artist_info(self): row = self.currentRow() artist, musicName = get_artist_and_musicname_from_title( self.playlist.get_music_title_at(row)) self.show_artist_info_signal.emit(artist) def change_tag_value(self, row, title, album, modifiedTime): oldTitle = self.playlist.get_music_title_at(row) self.playlist.set_music_title_at(row, title, False) self.playlist.set_music_album_at(row, album, False) self.playlist.set_modified_time_at(row, modifiedTime, False) self.playlist.commit_records() if oldTitle != title: widgetItem = self.item(row, 0) widgetItem.setText(title) rename_lyric_file_use_title(oldTitle, title) self.tag_values_changed_signal.emit(row, oldTitle, title, album) def double_click_to_play(self, index): row = index.row() self.double_click_to_play_with_row(row) def double_click_to_play_with_row(self, row): self.selectRow(row) self.playlist.set_current_row(row) if self.get_playing_used_state(): self.play_or_pause_signal.emit(row) else: self.isPlaying = True self.playing_list_changed_signal.emit(self.playingList.get_name(), self.listName)
def __init__(self, listName, parent=None): super(PlaylistWidgetBasic, self).__init__(parent) self.listName = '' self.playlist = Playlist()
def mark_as_favorite(self): if self.playlist.get_name( ) == Configures.PlaylistFavorite or not self.playlist.length( ) or self.currentSourceRow < 0: return path = self.playlist.get_music_path_at(self.currentSourceRow) title = self.playlist.get_music_title_at(self.currentSourceRow) if self.playlist.get_name() == Configures.PlaylistOnline: musicName = get_full_music_name_from_title(title) musicPath = os.path.join(self.downloadDir, musicName) musicPathO = os.path.join(Configures.MusicsDir, musicName) if not os.path.exists(musicPath) and not os.path.exists( musicPathO): QMessageBox.information(self, '提示', '请先下载该歌曲再添加喜欢!') return if os.path.exists(musicPath): path = musicPath else: path = musicPathO elif not os.path.exists(path): QMessageBox.information(self, "提示", "路径'" + "%s" % path + "'无效,无法标记喜欢!") return playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) if title in self.lovedSongs: playlistTemp.remove_item_at(self.lovedSongs.index(title)) playlistTemp.commit_records() self.lovedSongs.remove(title) self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo)) self.favoriteButton.setToolTip("收藏") else: playlistTemp.add_item_from_path(path) playlistTemp.commit_records() self.lovedSongs.append(title) self.favoriteButton.setIcon(QIcon(IconsHub.Favorites)) self.favoriteButton.setToolTip("取消收藏") self.mark_favorite_completed_signal.emit()
def run(self): if self.songLink == Configures.NoLink: self.songLink = SearchOnline.get_song_link(self.musicId) if not self.songLink: self.errorHappend('歌曲的网络链接为空') return self.downloadStatus = Configures.Downloading self.print_info('开始下载') self.download_lrc_and_artistinfo(self.title, self.musicId) if self.length == 0: res = self.try_to_open_url(self.songLink) if not res: self.errorHappend('无法打开歌曲链接') else: if res.status == 200 and res.reason == 'OK' and res.getheader('Content-Type') == 'audio/mpeg': try: self.length = int(res.getheader('Content-Length')) except ValueError: self.errorHappend('无法获取歌曲的大小') else: self.errorHappend('不是音乐资源类型') if not self.length or self.downloadStatus == Configures.DownloadError: return self.currentLength = self.check_temp_downloaded(self.tempfileName) req = request.Request(self.songLink) req.headers['Range'] = 'bytes= %s-%s'%(self.currentLength, self.length) res = self.try_to_open_url(req) if not res or res.getheader('Content-Type') != 'audio/mpeg': self.errorHappend('无法定位到开始下载处的节点位置') return contentsList = [] while self.currentLength<self.length and self.runPermit and self.noPause: trytimes = 5 while(trytimes): try: contentCache = res.read(BufferBlock) contentsList.append(contentCache) self.currentLength += BufferBlock if self.currentLength>self.length: self.currentLength = self.length break except: time.sleep(0.05) trytimes -= 1 continue if trytimes == 0: self.print_info('下载超时') self.pause() res.close() if self.currentLength == self.length: self.downloadStatus = Configures.DownloadCompleted if self.downloadStatus != Configures.DownloadCancelled: contentsStr = b''.join(contentsList) with open(self.tempfileName, 'ab+') as f: f.write(contentsStr) if self.downloadStatus == Configures.DownloadCompleted: if os.path.exists(self.musicPath): os.remove(self.musicPath) os.rename(self.tempfileName, self.musicPath) write_tags(self.musicPath, self.title, self.album) self.print_info('准备添加到“%s”'%Configures.PlaylistDownloaded) playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistDownloaded) title, album, totalTime = read_music_info(self.musicPath) if self.lock.acquire(): if self.musicPath not in playlistTemp.get_items_queue(): playlistTemp.add_record(self.musicPath, title, totalTime, album, self.musicPath, self.length, self.musicId) playlistTemp.commit_records() self.print_info("已完成下载") self.lock.release()
def mark_as_favorite(self): if ( self.playlist.get_name() == Configures.PlaylistFavorite or not self.playlist.length() or self.currentSourceRow < 0 ): return path = self.playlist.get_music_path_at(self.currentSourceRow) title = self.playlist.get_music_title_at(self.currentSourceRow) if self.playlist.get_name() == Configures.PlaylistOnline: musicName = get_full_music_name_from_title(title) musicPath = os.path.join(self.downloadDir, musicName) musicPathO = os.path.join(Configures.MusicsDir, musicName) if not os.path.exists(musicPath) and not os.path.exists(musicPathO): QMessageBox.information(self, "提示", "请先下载该歌曲再添加喜欢!") return if os.path.exists(musicPath): path = musicPath else: path = musicPathO elif not os.path.exists(path): QMessageBox.information(self, "提示", "路径'" + "%s" % path + "'无效,无法标记喜欢!") return playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) if title in self.lovedSongs: playlistTemp.remove_item_at(self.lovedSongs.index(title)) playlistTemp.commit_records() self.lovedSongs.remove(title) self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo)) self.favoriteButton.setToolTip("收藏") else: playlistTemp.add_item_from_path(path) playlistTemp.commit_records() self.lovedSongs.append(title) self.favoriteButton.setIcon(QIcon(IconsHub.Favorites)) self.favoriteButton.setToolTip("取消收藏") self.mark_favorite_completed_signal.emit()
def run(self): if self.songLink == Configures.NoLink: self.songLink = SearchOnline.get_song_link(self.musicId) if not self.songLink: self.errorHappend('歌曲的网络链接为空') return self.downloadStatus = Configures.Downloading self.print_info('开始下载') self.download_lrc_and_artistinfo(self.title, self.musicId) if self.length == 0: res = self.try_to_open_url(self.songLink) if not res: self.errorHappend('无法打开歌曲链接') else: if res.status == 200 and res.reason == 'OK' and res.getheader( 'Content-Type') == 'audio/mpeg': try: self.length = int(res.getheader('Content-Length')) except ValueError: self.errorHappend('无法获取歌曲的大小') else: self.errorHappend('不是音乐资源类型') if not self.length or self.downloadStatus == Configures.DownloadError: return self.currentLength = self.check_temp_downloaded(self.tempfileName) req = request.Request(self.songLink) req.headers['Range'] = 'bytes= %s-%s' % (self.currentLength, self.length) res = self.try_to_open_url(req) if not res or res.getheader('Content-Type') != 'audio/mpeg': self.errorHappend('无法定位到开始下载处的节点位置') return contentsList = [] while self.currentLength < self.length and self.runPermit and self.noPause: trytimes = 5 while (trytimes): try: contentCache = res.read(BufferBlock) contentsList.append(contentCache) self.currentLength += BufferBlock if self.currentLength > self.length: self.currentLength = self.length break except: time.sleep(0.05) trytimes -= 1 continue if trytimes == 0: self.print_info('下载超时') self.pause() res.close() if self.currentLength == self.length: self.downloadStatus = Configures.DownloadCompleted if self.downloadStatus != Configures.DownloadCancelled: contentsStr = b''.join(contentsList) with open(self.tempfileName, 'ab+') as f: f.write(contentsStr) if self.downloadStatus == Configures.DownloadCompleted: if os.path.exists(self.musicPath): os.remove(self.musicPath) os.rename(self.tempfileName, self.musicPath) write_tags(self.musicPath, self.title, self.album) self.print_info('准备添加到“%s”' % Configures.PlaylistDownloaded) playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistDownloaded) title, album, totalTime = read_music_info(self.musicPath) if self.lock.acquire(): if self.musicPath not in playlistTemp.get_items_queue(): playlistTemp.add_record(self.musicPath, title, totalTime, album, self.musicPath, self.length, self.musicId) playlistTemp.commit_records() self.print_info("已完成下载") self.lock.release()
class PlaylistWidget(PlaylistWidgetBasic): play_music_at_row_signal = pyqtSignal(int) play_or_pause_signal = pyqtSignal(int) playing_list_changed_signal = pyqtSignal(str, str) musics_added_signal = pyqtSignal(bool) musics_removed_signal = pyqtSignal() musics_cleared_signal = pyqtSignal() musics_marked_signal = pyqtSignal() download_signal = pyqtSignal() show_artist_info_signal = pyqtSignal(str) show_song_info_signal = pyqtSignal(int) tag_values_changed_signal = pyqtSignal(int, str, str, str) playlist_changed_signal = pyqtSignal() def __init__(self, parent=None): super(PlaylistWidget, self).__init__(parent) self.songOperator = SongOperator(self) self.initial_params() self.set_attritutes() self.create_menu_items() self.create_connections() def create_connections(self): self.cellEntered.connect(self.cell_entered) self.customContextMenuRequested.connect(self.music_table_menu) self.selectAllAction.triggered.connect(self.select_all_rows) self.selectInvertAction.triggered.connect(self.select_invert_rows) self.selectNoneAction.triggered.connect(self.select_none_rows) self.copytoMenu.triggered.connect(self.copy_to_other_playlist) self.movetoMenu.triggered.connect(self.move_to_other_playlist) self.addMusicAction.triggered.connect(self.add_musics) self.markSelectedAsFavoriteAction.triggered.connect(self.mark_selected_as_favorite) self.removeAction.triggered.connect(self.remove_musics) self.deleteAction.triggered.connect(self.delete_musics) self.clearListWidgetAction.triggered.connect(self.clear_musics) self.songSpecAction.triggered.connect(self.show_song_spec) self.artistSpecAction.triggered.connect(self.show_artist_info) self.downloadAction.triggered.connect(self.download_signal.emit) self.doubleClicked.connect(self.double_click_to_play) self.songOperator.wheel_event_triggered_signal.connect(self.wheelEvent) self.songOperator.double_clicked_signal.connect(self.double_click_to_play_with_row) self.songOperator.right_mouse_button_clicked_signal.connect(self.music_table_menu) self.songOperator.left_mouse_button_clicked_signal.connect(self.selectRow) self.songOperator.left_mouse_button_dragged_signal.connect(self.select_multi_rows) def cell_entered(self, row, column): if self.songOperator.isHidden(): self.songOperator.set_contents(row, self.item(row, column).text()) self.songOperator.show() oldRow = self.songOperator.get_row() if self.item(oldRow, column): self.item(oldRow, column).setText(self.playlist.get_music_title_at(oldRow)) self.songOperator.set_contents(row, self.item(row, column).text()) self.item(row, column).setText('') scrollBar = self.verticalScrollBar() scrolledValue = scrollBar.value() # if scrolledValue and scrolledValue == scrollBar.maximum(): # scrolledValue -= 1 self.songOperator.setGeometry(0, (row - scrolledValue)*self.rowHeight(row), 270, 31) def leaveEvent(self, event=None): self.hide_song_operator() def select_multi_rows(self, pos): exactPos = pos + self.songOperator.pos() item = self.itemAt(exactPos) if item: self.cell_entered(item.row(), 0) if not item.isSelected(): item.setSelected(True) def hide_song_operator(self): if not self.songOperator.isHidden(): oldRow = self.songOperator.get_row() item = self.item(oldRow, 0) if item: item.setText(self.playlist.get_music_title_at(oldRow)) self.songOperator.hide() def initial_params(self): self.files = [] self.lock = None self.downloadDir = '' self.deleteFlag = False self.isPlaying = False self.playingList = Playlist() self.allPlaylistNames = [] self.mode = 0 def set_playlist_names(self, listNames): self.allPlaylistNames = listNames def set_lock(self, lock): self.lock = lock def set_download_dir(self, dir): self.downloadDir = dir def set_playing_status(self, playlist): self.playingList = playlist def set_playlist_use_name(self, listName): if self.listName != listName: self.listName = listName self.playlist_changed_signal.emit() self.isPlaying = False if self.playingList.get_name() == listName: self.isPlaying = True if self.get_playing_used_state(): self.playlist = self.playingList.copy() else: self.playlist.fill_list(listName) self.fill_playlist_widget(self.playlist) self.select_row() self.pick_actions_into_menu() def get_playing_used_state(self): return self.isPlaying def get_playlist_length(self): return self.playlist.length() def get_playing_list_name(self): return self.playingList.get_name() def set_attritutes(self): self.setMouseTracking(True) self.setContextMenuPolicy(Qt.CustomContextMenu) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.horizontalHeader().setDefaultAlignment(Qt.AlignLeft) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.horizontalHeader().setVisible(False) self.verticalHeader().setVisible(False) self.setShowGrid(False) self.setRowCount(0) self.setColumnCount(1) self.setColumnWidth(0, 270) self.setColumnWidth(1, 80) def pick_actions_into_menu(self): self.listMenu.clear() if self.listName == Configures.PlaylistOnline: self.create_online_playlist_menu() elif self.listName == Configures.PlaylistFavorite: self.create_favor_playlist_menu() else: self.create_other_playlist_menu() def create_menu_items(self): self.listMenu = QMenu() self.addMusicAction = QAction("添加歌曲", self) self.selectAllAction = QAction("全选", self) self.selectInvertAction = QAction("反选", self) self.selectNoneAction = QAction("取消选择", self) self.markSelectedAsFavoriteAction = QAction("添加到“我的收藏”", self) self.copytoMenu = QMenu('复制到...') self.movetoMenu = QMenu('移动到...') self.downloadAction = QAction("下载", self) self.removeAction = QAction("移除歌曲", self) self.deleteAction = QAction("移除歌曲并删除本地文件", self) self.clearListWidgetAction = QAction("清空列表", self) self.songSpecAction = QAction("歌曲信息", self) self.artistSpecAction = QAction("歌手信息", self) def create_online_playlist_menu(self): self.listMenu.addAction(self.downloadAction) self.listMenu.addSeparator() self.listMenu.addAction(self.selectAllAction) self.listMenu.addAction(self.selectInvertAction) self.listMenu.addAction(self.selectNoneAction) self.listMenu.addSeparator() self.listMenu.addAction(self.removeAction) self.listMenu.addSeparator() self.listMenu.addAction(self.clearListWidgetAction) self.listMenu.addSeparator() self.listMenu.addAction(self.songSpecAction) self.listMenu.addAction(self.artistSpecAction) def create_favor_playlist_menu(self): self.listMenu.addAction(self.addMusicAction) self.listMenu.addSeparator() self.listMenu.addAction(self.selectAllAction) self.listMenu.addAction(self.selectInvertAction) self.listMenu.addAction(self.selectNoneAction) self.listMenu.addSeparator() self.listMenu.addAction(self.removeAction) self.listMenu.addAction(self.deleteAction) self.listMenu.addSeparator() self.listMenu.addAction(self.clearListWidgetAction) self.listMenu.addSeparator() self.listMenu.addAction(self.songSpecAction) self.listMenu.addAction(self.artistSpecAction) def fill_copyto_and_moveto_menu(self): self.copytoMenu.clear() self.movetoMenu.clear() if self.listName == Configures.PlaylistDefault: if len(self.allPlaylistNames) > 4: for i, name in enumerate(self.allPlaylistNames): if i >= 4: self.add_action(name) return True elif self.listName == Configures.PlaylistDownloaded: if len(self.allPlaylistNames) > 3: for i, name in enumerate(self.allPlaylistNames): if i >= 4 or i == 1: self.add_action(name) return True else: for i, name in enumerate(self.allPlaylistNames): if i == 1 or i >= 4 and name!=self.listName: self.add_action(name) return True return False def add_action(self, name): action1 = QAction(name, self) self.copytoMenu.addAction(action1) action2 = QAction(name, self) self.movetoMenu.addAction(action2) def create_other_playlist_menu(self): self.listMenu.addAction(self.addMusicAction) self.listMenu.addSeparator() self.listMenu.addAction(self.selectAllAction) self.listMenu.addAction(self.selectInvertAction) self.listMenu.addAction(self.selectNoneAction) self.listMenu.addSeparator() self.listMenu.addAction(self.markSelectedAsFavoriteAction) self.listMenu.addSeparator() if self.fill_copyto_and_moveto_menu(): self.listMenu.addMenu(self.copytoMenu) self.listMenu.addMenu(self.movetoMenu) self.listMenu.addSeparator() self.listMenu.addAction(self.removeAction) self.listMenu.addAction(self.deleteAction) self.listMenu.addSeparator() self.listMenu.addAction(self.clearListWidgetAction) self.listMenu.addSeparator() self.listMenu.addAction(self.songSpecAction) self.listMenu.addAction(self.artistSpecAction) def music_table_menu(self, pos): pos += QPoint(10, 0) self.listMenu.exec_(self.mapToGlobal(pos)) def select_row(self): row = self.playingList.get_current_row() if self.get_playing_used_state() and row>=0: self.selectRow(row) def add_musics(self): self.files = QFileDialog.getOpenFileNames(self, "选择音乐文件", self.downloadDir, self.tr("*.mp3"))[0] if not self.files: return self.exec_add_operation(self.files) self.musics_added_signal.emit(True) for item in self.files: row = self.playlist.get_item_index(item) self.setRangeSelected(QTableWidgetSelectionRange(row, 0, row, self.columnCount()-1), True) @operate_after_check_thread_locked_state @trace_to_keep_time def exec_add_operation(self, files): self.addedIndexes = [] for item in sorted(list(set(files)-set(self.playlist.get_items_queue()))): self.add_a_music(item) self.addedIndexes.append(self.playlist.get_item_index(item)) if self.addedIndexes: self.playlist.commit_records() def remove_musics(self): self.removedIndexes = [] selecteds = self.selectedIndexes() currentRow = self.playingList.get_current_row() % self.playingList.length() if selecteds: for index in selecteds: row = index.row() if index.column() == 0: self.removedIndexes.append(row) self.removedIndexes.sort(reverse=True) if self.deleteFlag: text_tmp1 = "移除并删除本地文件" text_tmp2 = "有%s首歌曲将被移出列表,并被彻底删除,请确认!"%len(self.removedIndexes) else: text_tmp1 = "移除选中项" text_tmp2 = "有%s首歌曲将被移出列表,请确认!"%len(self.removedIndexes) ok = QMessageBox.warning(self, text_tmp1, text_tmp2, QMessageBox.No|QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.hide_song_operator() item = self.playingList.get_item_from_queue(currentRow) if not (self.get_playing_used_state() and currentRow in self.removedIndexes): self.exec_remove_operation(self.removedIndexes) if self.get_playing_used_state(): currentRow = self.playlist.get_item_index(item) else: currentMusic = self.playingList.get_music_title_at(currentRow) if self.deleteFlag: text_tmp3 = "移除并删除当前歌曲" text_tmp4 = "当前播放的歌曲: %s 将会被移除并被删除,请确认!"%currentMusic else: text_tmp3 = "移除当前歌曲" text_tmp4 = "当前播放的歌曲: %s 将会被移除,请确认!"%currentMusic ok = QMessageBox.warning(self, text_tmp3, text_tmp4, QMessageBox.No|QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.exec_remove_operation(self.removedIndexes) currentRow = -1 else: self.removedIndexes.remove(currentRow) self.exec_remove_operation(self.removedIndexes) currentRow = self.playlist.get_item_index(item) self.playlist.set_current_row(currentRow) self.musics_removed_signal.emit() def remove_without_check(self, selecteds): self.hide_song_operator() self.removedIndexes = [] currentRow = self.playingList.get_current_row() % self.playingList.length() if len(selecteds): for index in selecteds: row = index.row() if index.column() == 0: self.removedIndexes.append(row) self.removedIndexes.sort(reverse=True) item = self.playingList.get_item_from_queue(currentRow) if not (self.get_playing_used_state() and currentRow in self.removedIndexes): self.exec_remove_operation(self.removedIndexes) if self.get_playing_used_state(): currentRow = self.playlist.get_item_index(item) else: self.exec_remove_operation(self.removedIndexes) currentRow = -1 self.playlist.set_current_row(currentRow) self.musics_removed_signal.emit() @operate_after_check_thread_locked_state def exec_remove_operation(self, rows): if len(rows): for row in rows: self.removeRow(row) self.playlist.remove_item_at(row, self.deleteFlag) self.playlist.commit_records() def delete_musics(self): self.deleteFlag = True self.remove_musics() self.deleteFlag = False def clear_musics(self): if not self.rowCount(): return ok = QMessageBox.warning(self, "清空列表", "当前列表的所有歌曲(包括当前播放歌曲)都将被移除,请确认!", QMessageBox.No|QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.hide_song_operator() self.exec_clear_operation() self.musics_cleared_signal.emit() @operate_after_check_thread_locked_state def exec_clear_operation(self): self.clear_all_items() self.playlist.clear_list() self.playlist.commit_records() #标记选中项为喜欢 def mark_selected_as_favorite(self): selecteds = self.selectedIndexes() self.markedIndexes = [] playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) existsTitles = playlistTemp.get_titles() for index in selecteds: row = index.row() path = self.playlist.get_music_path_at(row) title = self.playlist.get_music_title_at(row) if index.column() == 0 and title not in existsTitles and os.path.exists(path): playlistTemp.add_item(self.playlist.get_item_from_queue(row), self.playlist.get_record_at(row)) self.markedIndexes.append(row) if len(self.markedIndexes): playlistTemp.commit_records() self.musics_marked_signal.emit() def copy_to_other_playlist(self, action): selecteds = self.selectedIndexes() self.add_items_to_new_playlist(action.text(), selecteds) self.select_range_rows(selecteds) def move_to_other_playlist(self, action): selecteds = self.selectedIndexes() self.add_items_to_new_playlist(action.text(), selecteds) self.remove_without_check(selecteds) def add_items_to_new_playlist(self, name, selecteds): currentListName = self.listName if not selecteds: return playlistTemp = Playlist() for index in selecteds: row = index.row() if index.column() == 0: playlistTemp.add_item(self.playlist.get_item_from_queue(row), self.playlist.get_infos_at(row)) self.set_playlist_use_name(name) self.add_musics_from_other_playlist(playlistTemp) self.set_playlist_use_name(currentListName) def add_musics_from_other_playlist(self, playlistTemp): self.addedIndexes = [] for item in sorted(list(playlistTemp.get_ids()-self.playlist.get_ids())): self.playlist.add_item(item, playlistTemp.get_info_use_id(item)) self.addedIndexes.append(self.playlist.get_item_index(item)) if self.addedIndexes: self.playlist.commit_records() self.musics_added_signal.emit(False) def select_range_rows(self, selecteds, flag=True): for index in selecteds: if index.column() == 0: self.select_a_row(index.row(), flag) def select_a_row(self, row, flag=True): self.setRangeSelected(QTableWidgetSelectionRange(row, 0, row, self.columnCount() - 1), flag) def select_invert_rows(self): selecteds = self.selectedIndexes() self.select_all_rows() self.select_range_rows(selecteds, False) def select_all_rows(self): self.setRangeSelected(QTableWidgetSelectionRange(0, 0, self.rowCount()-1, self.columnCount()-1), True) def select_none_rows(self): self.setRangeSelected(QTableWidgetSelectionRange(0, 0, self.rowCount()-1, self.columnCount()-1), False) def show_song_spec(self): row = self.currentRow() self.show_song_info_signal.emit(row) def show_artist_info(self): row = self.currentRow() artist, musicName = get_artist_and_musicname_from_title(self.playlist.get_music_title_at(row)) self.show_artist_info_signal.emit(artist) def change_tag_value(self, row, title, album, modifiedTime): oldTitle = self.playlist.get_music_title_at(row) self.playlist.set_music_title_at(row, title, False) self.playlist.set_music_album_at(row, album, False) self.playlist.set_modified_time_at(row, modifiedTime, False) self.playlist.commit_records() if oldTitle != title: widgetItem = self.item(row, 0) widgetItem.setText(title) rename_lyric_file_use_title(oldTitle, title) self.tag_values_changed_signal.emit(row, oldTitle, title, album) def double_click_to_play(self, index): row = index.row() self.double_click_to_play_with_row(row) def double_click_to_play_with_row(self, row): self.selectRow(row) self.playlist.set_current_row(row) if self.get_playing_used_state(): self.play_or_pause_signal.emit(row) else: self.isPlaying = True self.playing_list_changed_signal.emit(self.playingList.get_name(), self.listName)