Exemplo n.º 1
0
class SearchFrame(QWidget):
    switch_to_online_list = pyqtSignal()
    add_bunch_to_list_succeed = pyqtSignal()
    listen_online_signal = pyqtSignal(str, str, str)
    listen_local_signal = pyqtSignal(str)
    add_to_download_signal = pyqtSignal()
    def  __init__(self, parent = None):
        super(SearchFrame, self).__init__(parent)
        self.setup_ui()
        self.reset_search()
        self.create_connects()
    
    def setup_ui(self):
        self.searchTable = SearchTable()
        self.searchBox = SearchBox()      
        
        self.previousPageButton = QToolButton()
        self.previousPageButton.setFixedSize(40, 31)
        icon0  =  QIcon(":/iconSources/icons/previousPage.png")
        self.previousPageButton.setIcon(icon0)
        self.previousPageButton.setIconSize(QSize(25, 25))
        self.previousPageButton.setCursor(QCursor(Qt.PointingHandCursor))
        self.previousPageButton.setToolTip('上一页')
        
        self.nextPageButton = QToolButton()
        self.nextPageButton.setFixedSize(40, 31)
        icon1  =  QIcon(":/iconSources/icons/nextPage.png")
        self.nextPageButton.setIcon(icon1)
        self.nextPageButton.setIconSize(QSize(25, 25))
        self.nextPageButton.setCursor(QCursor(Qt.PointingHandCursor))
        self.nextPageButton.setToolTip('下一页')
        
        self.jumpNum = QLineEdit('0')
        self.jumpNum.setFixedWidth(39)
        self.jumpNum.setAlignment(Qt.AlignRight)
        
        self.pageNum = QLabel("/ 0")
        self.pageNum.setFixedHeight(35)
        self.pageNum.setFixedWidth(35)
        self.pageNum.setAlignment(Qt.AlignCenter )
        self.pageNum.setToolTip('当前页码/总页数')
        
        self.controlWidget = QWidget()
        controlLayout = QHBoxLayout(self.controlWidget)
        controlLayout.setMargin(0)
        controlLayout.setSpacing(4)
        spacerItem  =  QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        controlLayout.addItem(spacerItem)
        controlLayout.addWidget(self.previousPageButton)
        controlLayout.addWidget(self.jumpNum)
        controlLayout.addWidget(self.pageNum)
        controlLayout.addWidget(self.nextPageButton)
        controlLayout.addItem(spacerItem)
        
        self.controlSearch = QWidget()       
        controlSearchLayout = QVBoxLayout(self.controlSearch)
        controlSearchLayout.setMargin(0)
        controlSearchLayout.setSpacing(2)
        controlSearchLayout.addWidget(self.searchTable)
        controlSearchLayout.addWidget(self.controlWidget)
        
        mainLayout = QVBoxLayout(self)
        mainLayout.setMargin(2)
        mainLayout.setSpacing(2)
        mainLayout.addWidget(self.searchBox)
        mainLayout.addWidget(self.controlSearch)
                
        self.searchByType = 'all'
        self.searchBox.searchComboBox.setCurrentIndex(0)
    
    def create_connects(self):
        self.searchTable.installEventFilter(self)
        
        self.previousPageButton.clicked.connect(self.previous_page)
        self.nextPageButton.clicked.connect(self.next_page)
        self.jumpNum.returnPressed.connect(self.go_to_page)
        self.searchBox.searchButton.clicked.connect(self.search_musics)
        self.searchBox.lineEdit.returnPressed.connect(self.search_musics)
        self.searchBox.searchComboBox.currentIndexChanged.connect(self.searchtype_changed)
        self.searchBox.resetButton.clicked.connect(self.reset_search)
        self.searchTable.switchToOnlineListAction.triggered.connect(self.switch_to_online_list)
        self.searchTable.cellDoubleClicked.connect(self.searchtable_clicked)
        self.searchTable.cellClicked.connect(self.show_tooltip)
        self.searchTable.listenOnlineAction.triggered.connect(self.listen_online)
        self.searchTable.downloadAction.triggered.connect(self.download)
        self.searchTable.addBunchToListAction.triggered.connect(self.add_bunch_to_list)
    
    def eventFilter(self, target, event):
        if target == self.searchTable:
            if event.type() == QEvent.Resize:
                width = self.searchTable.width()
                widthTemp = (width-35)/3
                self.searchTable.setColumnWidth(0, 35)
                self.searchTable.setColumnWidth(1, widthTemp)
                self.searchTable.setColumnWidth(2, widthTemp)
                self.searchTable.setColumnWidth(3, widthTemp)
        return False
    
    def show_tooltip(self, row):
        mark = self.searchTable.item(row, 0).text()
        songName = self.searchTable.item(row, 1).text()
        artist = self.searchTable.item(row, 2).text()
        album = self.searchTable.item(row, 3).text()
        self.searchTable.setToolTip("评分:%s\n 歌曲:%s\n歌手:%s\n专辑:%s"%(mark, songName, artist, album))
    
    def switch_to_list(self):
        self.switchToOnlineList.emit()    
    
    def listen_online(self):
        if not self.searchTable.rowCount():
            return
        self.searchtable_clicked(self.searchTable.currentRow())
            
    def searchtable_clicked(self, row):
        musicName = self.searchTable.item(row, 1).text()
        artist = self.searchTable.item(row, 2).text()
        title = artist + '._.' + musicName
        album = self.searchTable.item(row, 3).text()
        musicId = self.searchTable.item(row, 4).text()
        songLink = SearchOnline.get_song_link(musicId)
        if not songLink:
            return
        songLinkWrap = songLink + '~' + musicId
        self.listen_online_signal.emit(title, album, songLinkWrap)
    
    def add_bunch_to_list(self):
        selections = self.searchTable.selectionModel()
        selecteds = selections.selectedIndexes()
        if not len(selecteds):
            return
        model = TableModel()
        model.initial_model("在线试听")
        songsInOnlineList = []
        added_items = []
        t1 = time.time()
        for i in range(model.rowCount()):
            songsInOnlineList.append(model.record(i).value("paths"))
        t2 = time.time()
        print(t2-t1)
        self.setCursor(QCursor(Qt.BusyCursor))
        for index in selecteds:
            if index.column() == 0:
                row = index.row()
                musicId = self.searchTable.item(row, 4).text()
                songLink = SearchOnline.get_song_link(musicId)
                if not songLink:
                    continue
                songLinkWrap = songLink + '~' + musicId
                if songLinkWrap  not in songsInOnlineList:
                    musicName = self.searchTable.item(row, 1).text()
                    artist = self.searchTable.item(row, 2).text()
                    title = artist + '._.' + musicName
                    album = self.searchTable.item(row, 3).text()
                    lrcName = title + '.lrc'
                    lrcPath = os.path.join(Configures.lrcsDir, lrcName)
                    if os.path.exists(lrcPath):
                        os.remove(lrcPath)
                    added_items.append([title, songLinkWrap])
#                    SearchOnline.get_lrc_path(title, musicId)
                    model.add_record(title, '未知', album, songLinkWrap)
        if len(added_items):
            thread = DownloadLrcThread(added_items)
            thread.setDaemon(True)
            thread.setName("downloadLrc")
            thread.start()
            self.add_bunch_to_list_succeed.emit()
        self.setCursor(QCursor(Qt.ArrowCursor))
        print(time.time()-t2)
        print("Success")
            
    def download(self):
        if not self.searchTable.rowCount():
            return
#        t1 = time.time()
        hasExisted = []
        linkError = []
        self.toBeEmited = []
        selections = self.searchTable.selectionModel()
        selecteds = selections.selectedIndexes()
        if  not len(selecteds):
            return
        with open(Configures.settingFile,  'r') as f:
            downloadDir = f.read()
        self.setCursor(QCursor(Qt.BusyCursor))
        for index in selecteds:
            if index.column() == 0:
                row = index.row()
                songName = self.searchTable.item(row, 1).text()
                artist = self.searchTable.item(row, 2).text()
                title = artist + '._.' + songName
                musicName = title + '.mp3'
                musicPath = os.path.join(downloadDir, musicName)
                if os.path.exists(musicPath):
                    hasExisted.append(title)
                    continue
                for t in threading.enumerate():
                    if t.name == musicPath:
                        continue
                album = self.searchTable.item(row, 3).text()
                musicId = self.searchTable.item(row, 4).text()
                songLink = SearchOnline.get_song_link(musicId)
                if not songLink:
                    linkError.append(title)
                    continue
        #            QMessageBox.critical(self, '错误','链接错误,无法下载该歌曲!')
        #            return
#                songInfo = '->'.join([songLink, musicPath, title , album, musicId])
                self.toBeEmited.append([songLink, musicPath, title , album, musicId])
#        songInfos = json.dumps(toBeEmited)
        self.add_to_download_signal.emit()
        self.setCursor(QCursor(Qt.ArrowCursor))
#        print('searchPageWidget.py searchFrame.download timecost = %s'%(time.time()-t1))
        if len(hasExisted):
            hasExistFiles = '\n'.join(hasExisted)
            self.show()
            QMessageBox.information(self, '提示','以下歌曲已在下载目录中,将不再进行下载!\n%s'%hasExistFiles)
        if len(linkError):
            linkErrorFiles = '\n'.join(linkError)
            self.show()
            QMessageBox.critical(self, '错误','以下歌曲链接出错,无法下载!\n%s'%linkErrorFiles)
    
    def reset_search(self):
        self.searchBox.lineEdit.clear()
        self.searchTable.clear_search_table()
        self.currentKeyword  =  None
        self.currentPage  =  0
        self.hit = 0
        self.pages = 0
        self.searchBox.searchButton.setText('搜索')
        self.pageNum.setText('/ 0')
        self.jumpNum.setText('0')
    
    def searchtype_changed(self, index):
        if index == 0:
            self.searchByType = 'all'
        elif index == 1:
            self.searchByType = 'artist'
        else:
            self.searchByType = 'album'
        self.search_musics()
        
    
    def go_to_page(self):
        if not self.currentKeyword:
            self.jumpNum.setText('%s'%self.currentPage)
            self.pageNum.setFocus()
            return
        page = self.jumpNum.text()
        try:
            page = int(page)
        except ValueError :
            self.jumpNum.setText('%s'%(self.currentPage + 1))
            QMessageBox.information(None, "提示", "请输入1~%s内的整数!"%self.pages)
            return
        if page == (self.currentPage + 1):
            self.pageNum.setFocus()
            return
        if page > self.pages or page < 1:
            self.jumpNum.setText('%s'%(self.currentPage + 1))
            QMessageBox.information(None, "提示", "页码范围1~%s"%self.pages)
            return
        self.show_musics(self.searchByType, self.currentKeyword, page - 1)    
        self.currentPage = page - 1
        self.searchBox.searchButton.setFocus()
    
    def search_musics(self):
        self.searchBox.searchButton.setFocus()
        keyword = self.searchBox.lineEdit.text()
        if not keyword:
            QMessageBox.information(self, '提示', '请输入搜索关键词!')
            return
#        if keyword == self.currentKeyword:
#            return
        self.currentKeyword = keyword
        self.hit  =  self.show_musics(self.searchByType, self.currentKeyword, 0)
        if self.hit == Configures.URLERROR:
            return
        self.currentPage = 0
        if self.hit:
            self.pages = self.hit//15 + 1
            self.jumpNum.setText('1')
            self.pageNum.setText('/ %s'%self.pages)
        else:
            self.jumpNum.setText('0')
            self.pageNum.setText('/ 0')
        self.searchBox.searchButton.setText('搜索(%s)'%self.hit)
        
    def previous_page(self):
        if not self.currentPage:
            return
        self.currentPage -= 1
        self.show_musics(self.searchByType, self.currentKeyword, self.currentPage)
        self.jumpNum.setText('%s'%(self.currentPage + 1))
        
    def next_page(self):
        if self.currentPage  +  1 >= self.pages:
            return
        self.currentPage  += 1
        self.show_musics(self.searchByType, self.currentKeyword, self.currentPage)
        self.jumpNum.setText('%s'%(self.currentPage + 1))
            
    def show_musics(self, searchByType, keyword, page):    
        self.searchTable.clear_search_table()
        t1 = time.time()
        songs, hit = SearchOnline.search_songs(searchByType, keyword, page)
        if hit == Configures.URLERROR:
            QMessageBox.critical(None, "错误", "联网出错!\n请检查网络连接是否正常!")     
            return Configures.URLERROR
        if not songs or hit == 0:
            return hit
        for song in songs:
            music = song[0]
            artist = song[1]
            album = song[2] 
            if not album:
                album = '未知专辑'
            music_id = song[3]
#            artistId = song['ARTISTID']
            score = song[4]
            self.searchTable.add_record(score, music, artist, album, music_id)
            self.searchTable.sortItems(0, Qt.DescendingOrder)
        t2 = time.time()
        print('searchPageWidget.py searchFrame.show_musics %s'%(t2 - t1))
        return hit