def initAttributes(self):
        self.showMaximized()

        # Initialize the play list.
        self.playlist = []  # A list of links to the file to play.
        self.playlistTmp = [
        ]  # A temporary play list, use to shuffle play list.
        self.repeat = False

        # A timer showing the playing time.
        self.tmrTimer = QtCore.QTimer(self)
        self.tmrTimer.setInterval(
            250)  # This will emit a signal every 1/4 second
        self.tmrTimer.timeout.connect(self.on_tmrTimer_timeout)
        self.tmrTimer.start()

        #Volume control.
        self.sldVolumeSlider.setAudioOutput(self.vdpVideo.audioOutput())
        self.sldSeekSlider.setMediaObject(self.vdpVideo.mediaObject())

        # initialize the current mouse position and time.
        self.mousePos0 = QtGui.QCursor.pos()
        self.mouseT0 = QtCore.QTime.currentTime()

        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()

        # A list of uploading video.
        self.uploadingList = {}
        self.uploadDialog = UploadDialog(self)
        self.downloadingList = []

        self.feed = None  # The current feed, displayed on the search result page.
        self.entry = None  # The current entry, playing.
        self.currentDirectLink = ""  # Direct link to the current video.
        self.currentVideo = None

        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()

        # Search thread.
        self.threadPool = []
        self.threadType = [
        ]  # Store the function names that run as threads in self.threadPool.

        # Search box: Enter pressed.
        self.lineEditSearch.returnPressed.connect(
            self.on_btnSearchVideo_clicked)

        # The page showing search result.
        # Enable the flash plugin
        QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled,
                                                   True)
        self.videoList.page().setLinkDelegationPolicy(
            QWebPage.DelegateAllLinks)
        self.videoList.connect(self.videoList,
                               QtCore.SIGNAL('linkClicked(const QUrl&)'),
                               self.linkClicked)

        # A seperate frame for login.
        self.logged_in = False
        self.yt_service = None

        # Advance search options
        self.advancedSearchDialog = SearchOptionDialog(parent=self)
        self.connect(self.advancedSearchDialog.optionDialogSearchTerm,
                     QtCore.SIGNAL("returnPressed()"), self.advancedSearch)
        self.connect(self.advancedSearchDialog.lineeditUserFeed,
                     QtCore.SIGNAL("returnPressed()"),
                     self.on_lineeditUserFeed_returnPressed)

        self.connect(self.advancedSearchDialog.btnTrending,
                     QtCore.SIGNAL("clicked()"), self.on_btnTrending_clicked)
        self.connect(self.advancedSearchDialog.btnTopRated,
                     QtCore.SIGNAL("clicked()"), self.on_btnTopRated_clicked)
        self.connect(self.advancedSearchDialog.btnRecentlyFeatured,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnRecentlyFeatured_clicked)
        self.connect(self.advancedSearchDialog.btnTopFavorites,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnTopFavorites_clicked)
        self.connect(self.advancedSearchDialog.btnMostShared,
                     QtCore.SIGNAL("clicked()"), self.on_btnMostShared_clicked)
        self.connect(self.advancedSearchDialog.btnMostResponded,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnMostResponded_clicked)
        self.connect(self.advancedSearchDialog.btnMostDiscussed,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnMostDiscussed_clicked)
        self.connect(self.advancedSearchDialog.btnMostRecent,
                     QtCore.SIGNAL("clicked()"), self.on_btnMostRecent_clicked)
        self.connect(self.advancedSearchDialog.btnMostPopular,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnMostPopular_clicked)

        # Menu bar actions.
        self.action_Save_playlist.triggered.connect(
            self.on_action_Save_playlist)
        self.action_Load_playlist.triggered.connect(
            self.on_action_Load_playlist)
        self.action_Open_download_folder.triggered.connect(
            self.on_action_Open_download_folder)
        self.action_Quit.triggered.connect(self.on_action_Quit)
        self.action_Guide.triggered.connect(self.on_action_Guide)
        self.action_About.triggered.connect(self.on_action_About)
        self.actionS_earch_option.triggered.connect(
            self.on_actionS_earch_option)

        self.vdpVideo.finished.connect(self.on_btnNext_clicked)

        self.btnLogout.setEnabled(False)

        self.connect(self, QtCore.SIGNAL("IWantToBeNoticed(QString)"),
                     self.showMessage)
    def initAttributes(self):
        self.showMaximized()

        # Initialize the play list.
        self.playlist = []  # A list of links to the file to play.
        self.playlistTmp = []  # A temporary play list, use to shuffle play list.
        self.repeat = False
        
        # A timer showing the playing time.
        self.tmrTimer = QtCore.QTimer(self)
        self.tmrTimer.setInterval(250) # This will emit a signal every 1/4 second
        self.tmrTimer.timeout.connect(self.on_tmrTimer_timeout)
        self.tmrTimer.start()
        
        #Volume control.
        self.sldVolumeSlider.setAudioOutput(self.vdpVideo.audioOutput())
        self.sldSeekSlider.setMediaObject(self.vdpVideo.mediaObject())        
        
        
        # initialize the current mouse position and time.
        self.mousePos0 = QtGui.QCursor.pos()
        self.mouseT0 = QtCore.QTime.currentTime()
        
        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()   
        
        
        # A list of uploading video.
        self.uploadingList = {}
        self.uploadDialog = UploadDialog(self)
        self.downloadingList = []

        self.feed = None  # The current feed, displayed on the search result page.
        self.entry = None  # The current entry, playing.
        self.currentDirectLink = "" # Direct link to the current video.
        self.currentVideo = None
        
        
        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()   
        
        # Search thread.
        self.threadPool = []
        self.threadType = []  # Store the function names that run as threads in self.threadPool.
        
        # Search box: Enter pressed.
        self.lineEditSearch.returnPressed.connect(self.on_btnSearchVideo_clicked)
        
        # The page showing search result.
        # Enable the flash plugin
        QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled, True)
        self.videoList.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.videoList.connect(self.videoList, QtCore.SIGNAL('linkClicked(const QUrl&)'), self.linkClicked)

        # A seperate frame for login.
        self.logged_in = False
        self.yt_service = None
        
        # Advance search options
        self.advancedSearchDialog = SearchOptionDialog(parent=self)
        self.connect(self.advancedSearchDialog.optionDialogSearchTerm, QtCore.SIGNAL("returnPressed()"), self.advancedSearch)
        self.connect(self.advancedSearchDialog.lineeditUserFeed, QtCore.SIGNAL("returnPressed()"), self.on_lineeditUserFeed_returnPressed)
        
        self.connect(self.advancedSearchDialog.btnTrending , QtCore.SIGNAL("clicked()"), self.on_btnTrending_clicked)
        self.connect(self.advancedSearchDialog.btnTopRated , QtCore.SIGNAL("clicked()"), self.on_btnTopRated_clicked)
        self.connect(self.advancedSearchDialog.btnRecentlyFeatured , QtCore.SIGNAL("clicked()"), self.on_btnRecentlyFeatured_clicked)
        self.connect(self.advancedSearchDialog.btnTopFavorites , QtCore.SIGNAL("clicked()"), self.on_btnTopFavorites_clicked)
        self.connect(self.advancedSearchDialog.btnMostShared , QtCore.SIGNAL("clicked()"), self.on_btnMostShared_clicked)
        self.connect(self.advancedSearchDialog.btnMostResponded , QtCore.SIGNAL("clicked()"), self.on_btnMostResponded_clicked)
        self.connect(self.advancedSearchDialog.btnMostDiscussed , QtCore.SIGNAL("clicked()"), self.on_btnMostDiscussed_clicked)
        self.connect(self.advancedSearchDialog.btnMostRecent , QtCore.SIGNAL("clicked()"), self.on_btnMostRecent_clicked)
        self.connect(self.advancedSearchDialog.btnMostPopular , QtCore.SIGNAL("clicked()"), self.on_btnMostPopular_clicked)        
    
        # Menu bar actions.
        self.action_Save_playlist.triggered.connect(self.on_action_Save_playlist)
        self.action_Load_playlist.triggered.connect(self.on_action_Load_playlist)
        self.action_Open_download_folder.triggered.connect(self.on_action_Open_download_folder)
        self.action_Quit.triggered.connect(self.on_action_Quit)
        self.action_Guide.triggered.connect(self.on_action_Guide)
        self.action_About.triggered.connect(self.on_action_About)
        self.actionS_earch_option.triggered.connect(self.on_actionS_earch_option)
        
        self.vdpVideo.finished.connect(self.on_btnNext_clicked)
        
        self.btnLogout.setEnabled(False)
        
        self.connect(self, QtCore.SIGNAL("IWantToBeNoticed(QString)"), self.showMessage) 
class VideoPlayer(QtGui.QMainWindow):
    def __init__(self):
        # Initialize: calling the inherited __init__ function.
        super(VideoPlayer, self).__init__()

        # Load the defined UI.
        uic.loadUi('../share/ui/new_ui.ui', self)
        self.initAttributes()

################################################################################################
# Initialize class attributes.
################################################################################################

    def initAttributes(self):
        self.showMaximized()

        # Initialize the play list.
        self.playlist = []  # A list of links to the file to play.
        self.playlistTmp = [
        ]  # A temporary play list, use to shuffle play list.
        self.repeat = False

        # A timer showing the playing time.
        self.tmrTimer = QtCore.QTimer(self)
        self.tmrTimer.setInterval(
            250)  # This will emit a signal every 1/4 second
        self.tmrTimer.timeout.connect(self.on_tmrTimer_timeout)
        self.tmrTimer.start()

        #Volume control.
        self.sldVolumeSlider.setAudioOutput(self.vdpVideo.audioOutput())
        self.sldSeekSlider.setMediaObject(self.vdpVideo.mediaObject())

        # initialize the current mouse position and time.
        self.mousePos0 = QtGui.QCursor.pos()
        self.mouseT0 = QtCore.QTime.currentTime()

        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()

        # A list of uploading video.
        self.uploadingList = {}
        self.uploadDialog = UploadDialog(self)
        self.downloadingList = []

        self.feed = None  # The current feed, displayed on the search result page.
        self.entry = None  # The current entry, playing.
        self.currentDirectLink = ""  # Direct link to the current video.
        self.currentVideo = None

        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()

        # Search thread.
        self.threadPool = []
        self.threadType = [
        ]  # Store the function names that run as threads in self.threadPool.

        # Search box: Enter pressed.
        self.lineEditSearch.returnPressed.connect(
            self.on_btnSearchVideo_clicked)

        # The page showing search result.
        # Enable the flash plugin
        QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled,
                                                   True)
        self.videoList.page().setLinkDelegationPolicy(
            QWebPage.DelegateAllLinks)
        self.videoList.connect(self.videoList,
                               QtCore.SIGNAL('linkClicked(const QUrl&)'),
                               self.linkClicked)

        # A seperate frame for login.
        self.logged_in = False
        self.yt_service = None

        # Advance search options
        self.advancedSearchDialog = SearchOptionDialog(parent=self)
        self.connect(self.advancedSearchDialog.optionDialogSearchTerm,
                     QtCore.SIGNAL("returnPressed()"), self.advancedSearch)
        self.connect(self.advancedSearchDialog.lineeditUserFeed,
                     QtCore.SIGNAL("returnPressed()"),
                     self.on_lineeditUserFeed_returnPressed)

        self.connect(self.advancedSearchDialog.btnTrending,
                     QtCore.SIGNAL("clicked()"), self.on_btnTrending_clicked)
        self.connect(self.advancedSearchDialog.btnTopRated,
                     QtCore.SIGNAL("clicked()"), self.on_btnTopRated_clicked)
        self.connect(self.advancedSearchDialog.btnRecentlyFeatured,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnRecentlyFeatured_clicked)
        self.connect(self.advancedSearchDialog.btnTopFavorites,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnTopFavorites_clicked)
        self.connect(self.advancedSearchDialog.btnMostShared,
                     QtCore.SIGNAL("clicked()"), self.on_btnMostShared_clicked)
        self.connect(self.advancedSearchDialog.btnMostResponded,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnMostResponded_clicked)
        self.connect(self.advancedSearchDialog.btnMostDiscussed,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnMostDiscussed_clicked)
        self.connect(self.advancedSearchDialog.btnMostRecent,
                     QtCore.SIGNAL("clicked()"), self.on_btnMostRecent_clicked)
        self.connect(self.advancedSearchDialog.btnMostPopular,
                     QtCore.SIGNAL("clicked()"),
                     self.on_btnMostPopular_clicked)

        # Menu bar actions.
        self.action_Save_playlist.triggered.connect(
            self.on_action_Save_playlist)
        self.action_Load_playlist.triggered.connect(
            self.on_action_Load_playlist)
        self.action_Open_download_folder.triggered.connect(
            self.on_action_Open_download_folder)
        self.action_Quit.triggered.connect(self.on_action_Quit)
        self.action_Guide.triggered.connect(self.on_action_Guide)
        self.action_About.triggered.connect(self.on_action_About)
        self.actionS_earch_option.triggered.connect(
            self.on_actionS_earch_option)

        self.vdpVideo.finished.connect(self.on_btnNext_clicked)

        self.btnLogout.setEnabled(False)

        self.connect(self, QtCore.SIGNAL("IWantToBeNoticed(QString)"),
                     self.showMessage)

################################################################################################
# Actions related to playlist
################################################################################################
# Some menu action.

    def on_action_Save_playlist(self):
        if self.playlist is None or len(self.playlist) == 0:
            warning = WarningDialog.WarningDialog("There is nothing to save!",
                                                  self)
            warning.show()
        else:
            # Create a dialog showing the place to save the playlist.
            file_types = "Playlist (*.playlist);; All file (*.*)"
            filename, _ = QtGui.QFileDialog.getSaveFileNameAndFilter(
                self, QtCore.QString("Save play list"), '', file_types)
            filename = unicode(filename.__str__())
            try:
                # save the playlist.
                playlist_file = open(filename, 'wb')
                pickle.dump(self.playlist, playlist_file)
                playlist_file.close()
                print "The play list is saved."
            except:
                warning = WarningDialog.WarningDialog(
                    "Sorry, the play list cannot be saved!", self)
                warning.show()

    def on_action_Load_playlist(self):
        # Create a file dialog to load the playlist.
        file_types = "Playlist (*.playlist);; All file (*.*)"
        filename, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(
            self, QtCore.QString("Load play list"), '', file_types)
        filename = unicode(filename.__str__())

        playlist_file = open(filename, 'rb')
        temp_playlist = pickle.load(playlist_file)
        if temp_playlist is None or not isinstance(temp_playlist, list):
            raise ValueError
        self.playlist = []
        for entry in temp_playlist:
            # Check the validity of the entry.
            if isinstance(entry, gdata.youtube.YouTubeVideoEntry):
                self.playlist.append(entry)
            # update the playlist.
        self.updatePlayList()
        # except:
        #    warning = WarningDialog.WarningDialog("Sorry, the play list cannot be loaded!", self)
        #    warning.show()
        # finally:
        playlist_file.close()

    # Event: The next button is pressed.
    @QtCore.pyqtSlot()
    def on_btnNext_clicked(self):
        print "The next button is clicked."
        if self.playlist == []:
            # Nothing to do.
            return
        # Get the reference to the current selected media.
        curIndex = self.lswPlaylist.currentRow()
        if curIndex + 1 < len(self.playlist):
            # Not the last video
            index = curIndex + 1
        else:
            # This is the last video.
            if not self.repeat:
                # No repeat: just return.
                return
            else:
                index = 0

        # Select the next media in the play list, and play it.
        self.lswPlaylist.setCurrentRow(index,
                                       QtGui.QItemSelectionModel.SelectCurrent)
        self.on_lswPlaylist_doubleClicked()

    # Action: click on the 'previous' button.
    @QtCore.pyqtSlot()
    def on_btnPrevious_clicked(self):
        if self.playlist == []:
            return

        # Get a reference of the current selected media.
        curIndex = self.lswPlaylist.currentRow()

        # If the current selected media index is greater or equal to the first
        # index of the play list...
        if curIndex > 0:
            # decrease the index of the current media.
            index = curIndex - 1
        else:
            # This is the first item in the list.
            # If the repeat mode isn't selected then do nothing.
            if not self.repeat:
                return

            # otherwise, the next media to play will be the last in the list.
            index = len(self.playlist) - 1

        # Select the previous media in the play list and play it.
        self.lswPlaylist.setCurrentRow(index,
                                       QtGui.QItemSelectionModel.SelectCurrent)
        self.on_lswPlaylist_doubleClicked()

    # Action: Click on the 'Remove media' button.
    @QtCore.pyqtSlot()
    def on_btnRemoveMedia_clicked(self):
        # For each selected media...
        for media in self.lswPlaylist.selectedItems():
            try:
                # get it's index and remove it from the play list.
                del self.playlist[self.lswPlaylist.row(media)]
            except:
                pass

        self.updatePlayList()

    # Action: click on the 'Repeat' button.
    @QtCore.pyqtSlot()
    def on_btnRepeatPlayList_clicked(self):
        self.repeat = not self.repeat

    # Action: Click on the 'Show Play list' button.
    @QtCore.pyqtSlot()
    def on_btnShowPlayList_clicked(self):
        if self.dckShown:
            self.dckPlayList.hide()
        else:
            self.dckPlayList.show()
        self.dckShown = not self.dckShown

    # Action: Click on the 'Shuffle Play list' button.
    @QtCore.pyqtSlot()
    def on_btnShufflePlayList_clicked(self):
        if self.playlistTmp == []:
            # this mean the play list is not shuffled.
            self.playlistTmp = self.playlist[:]

            # Now shuffle it.
            item = len(self.playlist) - 1
            while item > 0:
                index = random.randint(0, item)
                tmp = self.playlist[index]
                self.playlist[index] = self.playlist[item]
                self.playlist[item] = tmp
                item -= 1
        else:
            # Return the list to the original state.
            self.playlist = self.playlistTmp[:]
            self.playlistTmp = []

        # Update the play list.
        self.updatePlayList()

    def updatePlayList(self):
        currentRow = self.lswPlaylist.currentRow()
        # Remove all items in QListWidget
        self.lswPlaylist.clear()
        # add the new play list.
        for item in self.playlist:
            self.lswPlaylist.addItem(
                QtCore.QString(unicode(item.media.title.text)))
        self.lswPlaylist.setCurrentRow(currentRow)

    # Action: Double an item in the play list to play it.
    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def on_lswPlaylist_doubleClicked(self):
        # If the play list is empty, do nothing.
        if self.playlist == []:
            return

        # Get the index of model_index, use it to obtain corresponding link
        self.entry = self.playlist[self.lswPlaylist.currentRow()]

        # Switch to the playerPage
        # Play the selected video.
        print "Processing the link,", self.entry.media.player.url
        self.startThread(self.getYoutubeLinkToPlay,
                         QtCore.SIGNAL("doneGetDirectLinks(QString)"),
                         QtCore.SIGNAL("failedGetDirectLinks(QString)"),
                         self.playVideo, self.dummy,
                         self.entry.media.player.url)

################################################################################################
# Action related tp main menu.
################################################################################################

    def on_action_Open_download_folder(self):
        print "Open download folder here."

    def on_action_Quit(self):
        self.close()

    def on_actionS_earch_option(self):
        print "Setting search option here!"

    def on_action_Guide(self):
        webbrowser.open(
            r'https://code.google.com/p/simple-media-player/w/list')

    def on_action_About(self):
        aboutDialog = about.About(parent=self)
        aboutDialog.show()

################################################################################################
# Search
################################################################################################

    def getAdvancedSearchOptions(self):
        vq = str(self.advancedSearchDialog.optionDialogSearchTerm.text())
        author = str(self.advancedSearchDialog.lineeditUserFeed.text())
        results_number = self.advancedSearchDialog.spbMaxResults.value()
        sort_by = str(self.advancedSearchDialog.optionDialogSortby.currentText(
        )).lower()

        # Change to standard name.
        if sort_by == 'published date':
            sort_by = 'published'
        elif sort_by == 'view count':
            sort_by = 'viewCount'

        racy = str(self.advancedSearchDialog.optionDialogSafeSearch.
                   currentText()).lower()
        startIndex = self.advancedSearchDialog.spbStartIndex.value()
        time = str(self.advancedSearchDialog.cbTime.currentText()).lower()

        return [vq, author, results_number, sort_by, racy, startIndex, time]

    # User's feed.
    @QtCore.pyqtSlot()
    def on_lineeditUserFeed_returnPressed(self):
        # Start a thread for searching.
        self.advancedSearchDialog.lineeditUserFeed
        self.startThread(self.ytUserFeedSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("searchFailed()"), self.setHtml,
                         self.dummy)

    # Return an instance that helps us to use youtube's services.
    def getYouTubeService(self, username='', password=''):
        if (username != '' and password != ''):  # new instance.
            self.yt_service = YouTubeService(username, password)
            return self.yt_service
        elif self.yt_service != None:
            return self.yt_service
        else:
            self.yt_service = YouTubeService()
            return self.yt_service

    def ytUserFeedSearch(self):
        try:
            [vq, author, results_number, sort_by, racy, startIndex,
             time] = self.getAdvancedSearchOptions()
            print[vq, author, results_number, sort_by, racy, startIndex, time]
            yt_service = self.getYouTubeService()
            query = gdata.youtube.service.YouTubeVideoQuery()
            query.author = author
            query.max_results = results_number
            query.orderby = sort_by
            query.racy = racy
            query.start_index = startIndex
            feed = yt_service.client.YouTubeQuery(query)

            html = getHtmlFeedDescription(feed)
        except:
            html = "Sorry, no such user."
            feed = None

        self.feed = feed
        self.emit(QtCore.SIGNAL('doneSearching(QString)'),
                  QtCore.QString(html))

    # Click on the Search options button.
    @QtCore.pyqtSlot()
    def on_btnSearchOption_clicked(self):
        self.advancedSearchDialog.show()
        self.advancedSearchDialog.setFocus()

    # Click on the 'search' button in the search tab.
    @QtCore.pyqtSlot()
    def on_btnSearchVideo_clicked(self):
        # Get the order option.
        if self.lineEditSearch.text() == '':
            return

        # get the search term.
        vq = str(self.lineEditSearch.text())

        # searching not done: Print the defaul message.
        self.videoList.setHtml(
            "<html><body><h1>Searching ...</h1></body></html>")
        # Create a thread to do the search.
        self.startThread(self.ytSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("searchFailed()"), self.setHtml,
                         self.dummy, vq, 'relevance', 'include', 1, 40,
                         'all_time')

    # Set the content of the playlist page.
    def setHtml(self, html):
        self.videoList.setHtml(html)
        self.twgWebpage.setCurrentIndex(1)

    # Do the search.
    # TODO Re-implement using YoutubeService.
    def ytSearch(self, vq, orderby, racy, start_index, max_results, time):
        print "Calling ytSearch with ", [
            vq, orderby, racy, start_index, max_results, time
        ]
        try:
            # Init service.
            yt_service = self.getYouTubeService()
            # vq must be converted to str.
            feed = yt_service.SearchWithVideoQuery(vq, orderby, racy,
                                                   start_index, max_results,
                                                   time)
        except:
            print "Something weird has occurred!"
            feed = None
        self.feed = feed
        html = getHtmlFeedDescription(feed)
        self.emit(QtCore.SIGNAL('doneSearching(QString)'), html)

    def advancedSearch(self):
        [vq, author, results_number, sort_by, racy, startIndex,
         time] = self.getAdvancedSearchOptions()
        # print  [vq, author, results_number, sort_by, racy,startIndex, time]
        # Create a thread to do the search.
        self.startThread(self.ytSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("searchFailed()"), self.setHtml,
                         self.dummy, vq, sort_by, racy, startIndex,
                         results_number, time)

################################################################################################
#
################################################################################################
# Click a link in the list of videos.

    def linkClicked(self, url):
        print url
        tmp = None
        # Find the entry that has that url.
        if (self.feed == None):
            pass
        else:
            for entry in self.feed.entry:
                # print  entry.GetSwfUrl()
                if entry.GetSwfUrl() == str(url.toString()):
                    tmp = entry
                    break
        self.addMedia(tmp)

################################################################################################
# Functions related to threads.
################################################################################################

    def startThread(self, function, signal_ok, signal_fail, function_if_ok,
                    function_if_fail, *args):
        # Connect signals and slots.
        self.disconnect(self, signal_ok, function_if_ok)
        self.connect(self, signal_ok, function_if_ok)
        self.disconnect(self, signal_fail, function_if_fail)
        self.connect(self, signal_fail, function_if_fail)

        # Start this thread.
        # Stop all the thread of the same type as this thread first.
        name = function.__name__.lower()

        # there should be only on 'search' thread.
        if name.find('search') != -1 or name == 'getyoutubelinktoplay':
            count = len(self.threadPool) - 1
            while count >= 0:
                if self.threadType[count].find('search'):
                    # Stop this thread first.
                    if self.threadPool[count].stopped():
                        print "This thread (%s) is stopped already" % count
                    else:
                        try:
                            print "Stopping thread number", count
                            self.threadPool[count].stop()
                        except:
                            pass
                    break
                count -= 1

        elif name.find('setplayerpage') != -1:
            # Thread of this type should not run concurrently.
            # Stop all previous thread of this type.
            count = len(self.threadPool) - 1
            while count >= 0:
                if self.threadType[count] == name:
                    # Stop this thread first.
                    if self.threadPool[count].stopped():
                        print "This thread (%s) is stopped already" % count
                    else:
                        try:
                            print "Stopping thread number", count
                            self.threadPool[count].stop()
                        except:
                            pass
                    break
                count -= 1

        # Update the thread pool
        self.threadPool.append(GenericThread(function, *args))
        self.threadType.append(name)
        self.threadPool[len(self.threadPool) - 1].start()
        self.setFocus()

    def dummy(self):
        print 'This function do nothing'

    # Event: The 'About' button is clicked
    # Show the about dialog.
    def on_btnAbout_clicked(self):
        ab = about.About(self)
        ab.show()

    # Event: The button 'Clear Play list' is pressed.
    @QtCore.pyqtSlot()
    def on_btnClearPlayList_clicked(self):
        # Clear the original and temporal play list.
        self.playlist = []
        self.playlistTmp = []
        self.updatePlayList()


###################################################################################
# Video playback controls.
###################################################################################
# Event: The 'play/pause' is pressed.

    @QtCore.pyqtSlot()
    def on_btnPlayPause_clicked(self):
        # If there is some selected item, and it is either 'playing' or
        # 'paused', then switch between the two states.
        if self.vdpVideo.isPlaying():
            print "Change to pause"
            self.vdpVideo.pause()
        elif self.vdpVideo.isPaused():
            print "Change to play"
            self.vdpVideo.play()
        else:
            # There is no media being played/paused. The state is 'stop'.
            # Select one video and play it.
            if self.lswPlaylist.currentRow() < 0:
                # Nothing has been played.
                # Select the first item
                self.lswPlaylist.setCurrentRow(
                    0, QtGui.QItemSelectionModel.SelectCurrent)

            # Now play the video.
            self.on_lswPlaylist_doubleClicked()

    # Response to timer event.
    @QtCore.pyqtSlot()
    def on_tmrTimer_timeout(self):
        # Update the playing time and the label.
        currentTime = self.vdpVideo.currentTime()

        if currentTime == 0:
            # This is the first time the label is changed.
            self.lblTime.setText('')
        else:
            # Get the total play time
            totalTime = self.vdpVideo.totalTime()
            # If the total playing time is less than 1 hour, just show minutes
            # and seconds.
            tFormat = 'mm:ss' if totalTime < 3600000 else 'hh:mm:ss'

            # We use Qtime for time conversions.
            currentTimeH = QtCore.QTime()

            # Convert times to a human readable strings.
            ct = currentTimeH.addMSecs(currentTime).toString(tFormat)

            totalTimeH = QtCore.QTime()
            tt = totalTimeH.addMSecs(totalTime).toString(tFormat)

            # Set time to label.
            self.lblTime.setText(ct + '/' + tt)

        # Now update the mouse status.
        # The window is in full-screen mode...
        if self.isFullScreen():
            # Update the current mouse time and position.
            mousePos = QtGui.QCursor.pos()
            mouseT = QtCore.QTime.currentTime()

            # Normally, when the program is in full-screen mode, the mouse must
            # be hidden until user move it.
            if (mousePos != self.mousePos0
                    and self.cursor().shape() == QtCore.Qt.BlankCursor
                ) or self.wdgVideoControls.isVisible():
                self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

                # Reset the time count for calculating the mouse moving time.
                self.mouseT0 = QtCore.QTime.currentTime()
            # If user stops moving the mouse, it must stay visible at least some
            # seconds.
            elif self.cursor().shape(
            ) == QtCore.Qt.ArrowCursor and self.mouseT0.secsTo(mouseT) > 1:
                self.setCursor(QtGui.QCursor(QtCore.Qt.BlankCursor))

            # Update the current mouse position.
            self.mousePos0 = mousePos

            # Convert the global mouse position in the screen to the window
            # local coordinates. And get the coordinate for Y axis.
            mouseY = self.mapFromGlobal(mousePos).y()

            # If the mouse approaches to the position in which must be the
            # controls bar, it must be visible.
            if mouseY < self.height() and \
                mouseY > self.height() - self.wdgVideoControls.height():
                if self.wdgVideoControls.isHidden():
                    self.wdgVideoControls.show()
            # otherwise it must stay hidden.
            elif self.wdgVideoControls.isVisible():
                self.wdgVideoControls.hide()
        # The window is in normal mode...
        else:
            # If the mouse cursor is hidden, show it.
            if self.cursor().shape() == QtCore.Qt.BlankCursor:
                self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

            # Show play list.
            if self.wdgVideoControls.isHidden():
                self.wdgVideoControls.show()

    # mouseDoubleClickEvent is a protected method which called when user
    # double clicks in the GUI and this event isn't caught by any other widget.
    def mouseDoubleClickEvent(self, event):
        # Always, before process the event, we must send a copy of it to the
        # ancestor class.
        QtGui.QMainWindow.mouseDoubleClickEvent(self, event)

        # Go to full-screen mode or exit from it.
        self.on_btnFullscreen_clicked()

    # Event: The 'Full screen' button is clicked.
    # Switch between 'normal' mode and 'full screen' mode.
    @QtCore.pyqtSlot()
    def on_btnFullscreen_clicked(self):
        if self.isFullScreen():
            # switch to normal mode.
            self.showNormal()
            # show the play list.
            self.dckPlayList.show()
        else:
            # Switch to full screen mode.
            self.showFullScreen()
            # Hide the play list.
            self.dckPlayList.hide()
            # Hide the mouse cursor.
            self.setCursor(QtGui.QCursor(QtCore.Qt.BlankCursor))

    # Get direct link for one video.
    def getYoutubeLinkToPlay(self, link):
        try:
            # In this version, we will just get any link.
            print "Decoding the link", str(link)
            # Get the video quality.
            desired_resolution = str(self.cbQuality.currentText())
            print "Desired resolution:", desired_resolution

            # Find the resolution nearest to the desired resolution.
            direct_link = YouTubeDl().getDirectLink(link, desired_resolution)
            self.emit(QtCore.SIGNAL("doneGetDirectLinks(QString)"),
                      QtCore.QString(direct_link))
        except:
            self.emit(
                QtCore.SIGNAL("IWantToBeNoticed(QString)"),
                QtCore.QString(
                    "Sorry, it seems that you have to watch this video on YouTube."
                ))

    def playVideo(self, link):
        print "link:", link
        match = re.search(r'(.*)\n\"(.*)\"', link)
        if match:
            link = match.group(1)

        # Play the video.
        if link.startsWith(QtCore.QString(r'http://')) or link.startsWith(
                QtCore.QString(r'https://')) or link.startsWith(
                    QtCore.QString(r'mms://')):
            print "Link: via web"
            print "Asking the phonon player to play."
            self.vdpVideo.play(phonon.Phonon.MediaSource(QtCore.QUrl(link)))
            self.currentDirectLink = str(link)
        else:
            print "Link: local file"
            self.vdpVideo.play(phonon.Phonon.MediaSource(link))
            print "Asking the player to play."

    @QtCore.pyqtSlot()
    def on_btnDownloadPlaying_clicked(self):
        try:
            # In this version, we will just get any link.
            link = self.entry.media.player.url
            # Get the video quality.
            desired_resolution = str(self.cbQuality.currentText())

            # Find the resolution nearest to the desired resolution.
            direct_link = YouTubeDl().getDirectLink(link, desired_resolution)
            match = re.search(r'(.*)\n\"(.*)\"', direct_link)
            if match:
                media = [match.group(1), match.group(2)]
            command = 'aria2c "%s" -o %s' % (media[0], media[1])
            command = command.replace("\n", "")
            print command.find("\n")
            Popen(command, shell=True, close_fds=True)
        except:
            self.emit(
                QtCore.SIGNAL("IWantToBeNoticed(QString)"),
                QtCore.QString(
                    "Sorry, it seems that you have to watch this video on YouTube."
                ))

    # Add to the play a link
    # Url must be a string.
    def addMedia(self, entry):
        print "Adding media to playlist."
        self.playlist.append(entry)

        # update the play list.
        self.updatePlayList()

        # If the play list has been loaded and there isn't a media playing,
        # play it.
        if len(self.playlist) == 1:
            self.entry = entry
            # Start a thread getting the direct link play.
            self.lswPlaylist.setCurrentRow(0)
            self.startThread(self.getYoutubeLinkToPlay,
                             QtCore.SIGNAL("doneGetDirectLinks(QString)"),
                             QtCore.SIGNAL("failedGetDirectLinks(QString)"),
                             self.playVideo, self.dummy,
                             self.entry.media.player.url)

    @QtCore.pyqtSlot()
    def on_btnUpload_clicked(self):
        if not self.logged_in:
            messageBox = WarningDialog.WarningDialog(
                warning="You have to log in first", parent=self)
            messageBox.show()
        else:
            print "Calling the function upload"
            # Get the video information.
            self.uploadDialog.show()
            self.connect(self.uploadDialog, QtCore.SIGNAL("accepted()"),
                         self.doUpload)

    # Managing the upload queue.
    def doUpload(self):
        print "Inside the function doUpload"
        # upload the file.

        # Get the video's info.
        video_location = str(self.uploadDialog.lineEditFilePath.text())
        video_title = str(self.uploadDialog.lineEditVideoName.text())
        tags = str(self.uploadDialog.lineEditTags.text())
        description = str(
            self.uploadDialog.plainTextEditDescription.toPlainText())

        # This will work on Windows only.
        video_location = video_location.replace('/', '\\')
        print video_location, type(video_location)
        print video_title, type(video_title)
        print tags, type(tags)
        print description, type(description)
        print "trying..."

        # Show an upload dialog.
        uploadDialog = UploadStatusDialog('Uploading', video_title,
                                          video_location, self)
        uploadDialog.show()
        self.startThread(self.doRealUpload,
                         QtCore.SIGNAL("doneUpload(QString)"),
                         QtCore.SIGNAL('uploadFailed(QString)'),
                         self.doneUpload, self.uploadFailed, video_title,
                         description, tags, video_location, uploadDialog)

    # Do the upload.
    def doRealUpload(self, video_title, description, tags, video_location,
                     uploadDialog):
        print "doRealUPload"
        try:
            self.getYouTubeService()
            new_entry = self.yt_service.DirectVideoUpload(
                video_title, description, tags, video_location)
            self.emit(QtCore.SIGNAL('doneUpload(QString)'),
                      QtCore.QString(video_location))
            # Setting the upload dialog.
            uploadDialog.lbStatus.setText(
                QtCore.QString(
                    'Video uploaded. Waiting for YouTube\'s acceptance.'))

            # Wait and check for Youtube Status.
            for i in range(10):  # wait for at most 10 * 30 seconds.
                time.sleep(30)
                uploadStatus = self.yt_service.client.CheckUploadStatus(
                    new_entry)
                if uploadStatus is not None:
                    status = str(uploadStatus[0])
                    print status
                    uploadDialog.lbStatus.setText(QtCore.QString(status))
                else:
                    uploadDialog.lbStatus.setText(QtCore.QString("Done."))
                    break
        except:
            self.emit(QtCore.SIGNAL('uploadFailed(QString)'),
                      QtCore.QString(video_location))
            uploadDialog.lbStatus.setText(QtCore.QString('Failed.'))

    # A message notifying upload sucessfully event.
    def doneUpload(self, message):
        pass
        # self.uploadingList[str(message)].lbStatus.setText(QtCore.QString('Done.'))

    def uploadFailed(self, message):
        pass
        # self.uploadingList[str(message)].lbStatus.setText(QtCore.QString('Failed.'))

    # Search for popular feeds.
    def on_btnTopRated_clicked(self):
        self.searchFeed("topRated")

    def on_btnTopFavorites_clicked(self):
        self.searchFeed("topFavorites")

    def on_btnMostShared_clicked(self):
        self.searchFeed("mostShared")

    def on_btnMostPopular_clicked(self):
        self.searchFeed("mostPopular")

    def on_btnMostRecent_clicked(self):
        self.searchFeed("mostRecent")

    def on_btnMostDiscussed_clicked(self):
        self.searchFeed("mostDiscussed")

    def on_btnMostResponded_clicked(self):
        self.searchFeed("mostResponded")

    def on_btnRecentlyFeatured_clicked(self):
        self.searchFeed("recentlyFeatured")

    def on_btnTrending_clicked(self):
        self.searchFeed("trending")

    # Search a feed of given name.
    def searchFeed(self, feedName):
        print "Searching", feedName
        # Create a thread to do the search.
        self.startThread(self.ytFeedSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("failedSearching(QString)"),
                         self.setHtml, self.dummy, feedName)

    def ytFeedSearch(self, feedName):
        yt_service = self.getYouTubeService()
        if feedName == 'topRated':
            feed = yt_service.RetrieveTopRatedVideoFeed()
        elif feedName == "topFavorites":
            feed = yt_service.RetrieveTopFavoritesVideoFeed()
        elif feedName == "mostShared":
            feed = yt_service.client.GetYouTubeVideoFeed(
                "https://gdata.youtube.com/feeds/api/standardfeeds/most_shared"
            )
        elif feedName == "mostPopular":
            feed = yt_service.client.GetYouTubeVideoFeed(
                "https://gdata.youtube.com/feeds/api/standardfeeds/most_popular"
            )
        elif feedName == "mostRecent":
            feed = yt_service.RetrieveMostRecentVideoFeed()
        elif feedName == "mostDiscussed":
            feed = yt_service.RetrieveMostDiscussedVideoFeed()
        elif feedName == "mostResponded":
            feed = yt_service.RetrieveMostRespondedVideoFeed()
        elif feedName == 'recentlyFeatured':
            feed = yt_service.RetrieveRecentlyFeaturedVideoFeed()
        elif feedName == "trending":
            feed = yt_service.client.GetYouTubeVideoFeed(
                "https://gdata.youtube.com/feeds/api/standardfeeds/on_the_web")
        else:
            feed = None
            print 'Invalid feed'

        self.feed = feed
        html = getHtmlFromFeed.getHtmlFeedDescription(feed)
        self.emit(QtCore.SIGNAL('doneSearching(QString)'), html)

    def login(self, email, password):
        '''
        Log in to YouTube, using an email and password. 
        '''
        print "Inside the login function"
        print email, type(email)
        try:
            self.yt_service = YouTubeService(email, password)
            self.logged_in = self.yt_service.loggedIn
            if (self.logged_in):
                self.emit(QtCore.SIGNAL("doneLogin(QString)"), email)
            else:
                self.emit(QtCore.SIGNAL("failedLogin()"))
        except:
            self.emit(QtCore.SIGNAL("failedLogin()"))

    @QtCore.pyqtSlot()
    def on_btnPost_clicked(self):
        '''
        Post a comment to the current video.
        If the user has logged in, post a comment, otherwise display a warning message.
        '''
        if self.yt_service == None or self.yt_service.loggedIn == False:
            messageBox = WarningDialog.WarningDialog(
                "Sorry, you have to log in first.", self)
            messageBox.show()
        else:
            # Get the in the textEditComment
            text = str(self.textEditComment.toPlainText())
            print "You want to post a comment:", text
            self.startThread(self.postComment,
                             QtCore.SIGNAL("donePostComment()"),
                             QtCore.SIGNAL("failedPostComment()"), self.dummy,
                             self.dummy, text)

    def postComment(self, comment):
        '''
        Post a comment to the playing video.
        '''
        print "You want to post a comment."
        try:
            self.yt_service.AddComment(getVideoId(self.entry), comment)
            self.emit(QtCore.SIGNAL("donePostComment()"))
        except:
            self.emit("failedPostComment()")

    @QtCore.pyqtSlot()
    def on_btnRate_clicked(self):
        '''
        Handle the event that the user click on the 'Rate' button.
        '''
        print "You want to rate the video."
        if self.logged_in:
            self.startThread(self.addRating, QtCore.SIGNAL("doneAddRating()"),
                             QtCore.SIGNAL("failedAddRating()"), self.dummy,
                             self.dummy)
        else:
            message = WarningDialog.WarningDialog(
                "Sorry, you have to log in first.", self)
            message.showNormal()

    def addRating(self):
        '''
        Rate the current (playing) video.
        '''
        number = self.value()
        try:
            self.yt_service.AddRating(getVideoId(self.entry), number)
            self.emit(QtCore.SIGNAL("doneAddRating()"))
        except:
            self.emit(QtCore.SIGNAL("failedAddRating()"))

    # User clicked on the 'login' button.
    @QtCore.pyqtSlot()
    def on_btnLogin_clicked(self):
        # Start a login thread.
        username = str(self.ledUsername.text())
        password = str(self.ledPassword.text())

        self.startThread(self.login, QtCore.SIGNAL("doneLogin(QString)"),
                         QtCore.SIGNAL("failedLogin()"), self.setUsernameView,
                         self.failedLoginWarning, username, password)

    @QtCore.pyqtSlot()
    def on_btnLogout_clicked(self):
        self.yt_service = YouTubeService()
        self.logged_in = False
        self.labelGreeting.setText('Hello')

    # Show the username.
    def setUsernameView(self, username):
        self.labelGreeting.setText("Hello, %s" % username)
        self.ledUsername.setText('')
        self.ledPassword.setText('')
        self.btnLogout.setEnabled(True)

    def failedLoginWarning(self):
        print "Sorry, login failed!"
        self.yt_service = YouTubeService()
        self.btnLogout.setEnabled(False)
        warningDialog = WarningDialog.WarningDialog(
            warning="Sorry, logging in failed", parent=self)
        warningDialog.show()

    def _htmlForFlash(self, url):
        html = ''''<embed src="%s" type="application/x-shockwave-flash" allowfullscreen="true" width="640" height="480"></embed>
        ''' % url

        return html

    def showMessage(self, message):
        wd = WarningDialog.WarningDialog(message, self)
        wd.show()
class VideoPlayer(QtGui.QMainWindow):

    def __init__(self):
        # Initialize: calling the inherited __init__ function.
        super(VideoPlayer, self).__init__()
        
        # Load the defined UI.
        uic.loadUi('../share/ui/new_ui.ui', self)
        self.initAttributes()           

################################################################################################
# Initialize class attributes.
################################################################################################
    def initAttributes(self):
        self.showMaximized()

        # Initialize the play list.
        self.playlist = []  # A list of links to the file to play.
        self.playlistTmp = []  # A temporary play list, use to shuffle play list.
        self.repeat = False
        
        # A timer showing the playing time.
        self.tmrTimer = QtCore.QTimer(self)
        self.tmrTimer.setInterval(250) # This will emit a signal every 1/4 second
        self.tmrTimer.timeout.connect(self.on_tmrTimer_timeout)
        self.tmrTimer.start()
        
        #Volume control.
        self.sldVolumeSlider.setAudioOutput(self.vdpVideo.audioOutput())
        self.sldSeekSlider.setMediaObject(self.vdpVideo.mediaObject())        
        
        
        # initialize the current mouse position and time.
        self.mousePos0 = QtGui.QCursor.pos()
        self.mouseT0 = QtCore.QTime.currentTime()
        
        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()   
        
        
        # A list of uploading video.
        self.uploadingList = {}
        self.uploadDialog = UploadDialog(self)
        self.downloadingList = []

        self.feed = None  # The current feed, displayed on the search result page.
        self.entry = None  # The current entry, playing.
        self.currentDirectLink = "" # Direct link to the current video.
        self.currentVideo = None
        
        
        # The dock widget: show or hide?
        self.dckShown = True
        self.lineEditSearch.setFocus()   
        
        # Search thread.
        self.threadPool = []
        self.threadType = []  # Store the function names that run as threads in self.threadPool.
        
        # Search box: Enter pressed.
        self.lineEditSearch.returnPressed.connect(self.on_btnSearchVideo_clicked)
        
        # The page showing search result.
        # Enable the flash plugin
        QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled, True)
        self.videoList.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.videoList.connect(self.videoList, QtCore.SIGNAL('linkClicked(const QUrl&)'), self.linkClicked)

        # A seperate frame for login.
        self.logged_in = False
        self.yt_service = None
        
        # Advance search options
        self.advancedSearchDialog = SearchOptionDialog(parent=self)
        self.connect(self.advancedSearchDialog.optionDialogSearchTerm, QtCore.SIGNAL("returnPressed()"), self.advancedSearch)
        self.connect(self.advancedSearchDialog.lineeditUserFeed, QtCore.SIGNAL("returnPressed()"), self.on_lineeditUserFeed_returnPressed)
        
        self.connect(self.advancedSearchDialog.btnTrending , QtCore.SIGNAL("clicked()"), self.on_btnTrending_clicked)
        self.connect(self.advancedSearchDialog.btnTopRated , QtCore.SIGNAL("clicked()"), self.on_btnTopRated_clicked)
        self.connect(self.advancedSearchDialog.btnRecentlyFeatured , QtCore.SIGNAL("clicked()"), self.on_btnRecentlyFeatured_clicked)
        self.connect(self.advancedSearchDialog.btnTopFavorites , QtCore.SIGNAL("clicked()"), self.on_btnTopFavorites_clicked)
        self.connect(self.advancedSearchDialog.btnMostShared , QtCore.SIGNAL("clicked()"), self.on_btnMostShared_clicked)
        self.connect(self.advancedSearchDialog.btnMostResponded , QtCore.SIGNAL("clicked()"), self.on_btnMostResponded_clicked)
        self.connect(self.advancedSearchDialog.btnMostDiscussed , QtCore.SIGNAL("clicked()"), self.on_btnMostDiscussed_clicked)
        self.connect(self.advancedSearchDialog.btnMostRecent , QtCore.SIGNAL("clicked()"), self.on_btnMostRecent_clicked)
        self.connect(self.advancedSearchDialog.btnMostPopular , QtCore.SIGNAL("clicked()"), self.on_btnMostPopular_clicked)        
    
        # Menu bar actions.
        self.action_Save_playlist.triggered.connect(self.on_action_Save_playlist)
        self.action_Load_playlist.triggered.connect(self.on_action_Load_playlist)
        self.action_Open_download_folder.triggered.connect(self.on_action_Open_download_folder)
        self.action_Quit.triggered.connect(self.on_action_Quit)
        self.action_Guide.triggered.connect(self.on_action_Guide)
        self.action_About.triggered.connect(self.on_action_About)
        self.actionS_earch_option.triggered.connect(self.on_actionS_earch_option)
        
        self.vdpVideo.finished.connect(self.on_btnNext_clicked)
        
        self.btnLogout.setEnabled(False)
        
        self.connect(self, QtCore.SIGNAL("IWantToBeNoticed(QString)"), self.showMessage) 

################################################################################################
# Actions related to playlist
################################################################################################     
    # Some menu action.
    def on_action_Save_playlist(self):
        if self.playlist is None or len(self.playlist) == 0:
            warning = WarningDialog.WarningDialog("There is nothing to save!", self)
            warning.show()
        else:
            # Create a dialog showing the place to save the playlist.
            file_types = "Playlist (*.playlist);; All file (*.*)"
            filename, _ = QtGui.QFileDialog.getSaveFileNameAndFilter(self, QtCore.QString("Save play list"), '', file_types)
            filename = unicode(filename.__str__())
            try:
                # save the playlist.
                playlist_file = open(filename, 'wb')
                pickle.dump(self.playlist, playlist_file)
                playlist_file.close()
                print "The play list is saved."
            except:
                warning = WarningDialog.WarningDialog("Sorry, the play list cannot be saved!", self)
                warning.show()
    
    def on_action_Load_playlist(self):
        # Create a file dialog to load the playlist.
        file_types = "Playlist (*.playlist);; All file (*.*)"
        filename, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(self, QtCore.QString("Load play list"), '', file_types)
        filename = unicode(filename.__str__())
        
        playlist_file = open(filename, 'rb')
        temp_playlist = pickle.load(playlist_file)
        if temp_playlist is None or not isinstance(temp_playlist, list):
            raise ValueError
        self.playlist = []
        for entry in temp_playlist:
            # Check the validity of the entry.
            if isinstance(entry, gdata.youtube.YouTubeVideoEntry):
                self.playlist.append(entry)
            # update the playlist.
        self.updatePlayList()
        # except:
        #    warning = WarningDialog.WarningDialog("Sorry, the play list cannot be loaded!", self)
        #    warning.show()
        # finally:
        playlist_file.close()
        
    # Event: The next button is pressed.
    @QtCore.pyqtSlot()
    def on_btnNext_clicked(self):
        print "The next button is clicked."
        if self.playlist == []:
            # Nothing to do.
            return
        # Get the reference to the current selected media.
        curIndex = self.lswPlaylist.currentRow()
        if curIndex + 1 < len(self.playlist):
            # Not the last video
            index = curIndex + 1
        else:
            # This is the last video.
            if not self.repeat:
                # No repeat: just return.
                return
            else:
                index = 0

        # Select the next media in the play list, and play it.
        self.lswPlaylist.setCurrentRow(index, QtGui.QItemSelectionModel.SelectCurrent)
        self.on_lswPlaylist_doubleClicked()

    # Action: click on the 'previous' button.
    @QtCore.pyqtSlot()
    def on_btnPrevious_clicked(self):
        if self.playlist == []:
            return

        # Get a reference of the current selected media.
        curIndex = self.lswPlaylist.currentRow()

        # If the current selected media index is greater or equal to the first
        # index of the play list...
        if curIndex > 0:
            # decrease the index of the current media.
            index = curIndex - 1
        else:
            # This is the first item in the list.
            # If the repeat mode isn't selected then do nothing.
            if not self.repeat:
                return

            # otherwise, the next media to play will be the last in the list.
            index = len(self.playlist) - 1

        # Select the previous media in the play list and play it.
        self.lswPlaylist.setCurrentRow(index, QtGui.QItemSelectionModel.SelectCurrent)
        self.on_lswPlaylist_doubleClicked()

    # Action: Click on the 'Remove media' button.
    @QtCore.pyqtSlot()
    def on_btnRemoveMedia_clicked(self):
        # For each selected media...
        for media in self.lswPlaylist.selectedItems():
            try:
                # get it's index and remove it from the play list.
                del self.playlist[self.lswPlaylist.row(media)]
            except:
                pass

        self.updatePlayList()


    # Action: click on the 'Repeat' button.
    @QtCore.pyqtSlot()
    def on_btnRepeatPlayList_clicked(self):
        self.repeat = not self.repeat

    # Action: Click on the 'Show Play list' button.
    @QtCore.pyqtSlot()
    def on_btnShowPlayList_clicked(self):
        if self.dckShown:
            self.dckPlayList.hide()
        else:
            self.dckPlayList.show()
        self.dckShown = not self.dckShown
            
    # Action: Click on the 'Shuffle Play list' button.
    @QtCore.pyqtSlot()
    def on_btnShufflePlayList_clicked(self):
        if self.playlistTmp == []:
            # this mean the play list is not shuffled.
            self.playlistTmp = self.playlist[:]

            # Now shuffle it.
            item = len(self.playlist) - 1
            while item > 0:
                index = random.randint(0, item)
                tmp = self.playlist[index]
                self.playlist[index] = self.playlist[item]
                self.playlist[item] = tmp
                item -= 1
        else:
            # Return the list to the original state.
            self.playlist = self.playlistTmp[:]
            self.playlistTmp = []

        # Update the play list.
        self.updatePlayList()
        
    def updatePlayList(self):
        currentRow = self.lswPlaylist.currentRow()
        # Remove all items in QListWidget
        self.lswPlaylist.clear()
        # add the new play list.
        for item in self.playlist:
            self.lswPlaylist.addItem(QtCore.QString(unicode(item.media.title.text)))
        self.lswPlaylist.setCurrentRow(currentRow)
    
    

    # Action: Double an item in the play list to play it.
    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def on_lswPlaylist_doubleClicked(self):
        # If the play list is empty, do nothing.
        if self.playlist == []:
            return
        
        # Get the index of model_index, use it to obtain corresponding link
        self.entry = self.playlist[self.lswPlaylist.currentRow()]
        
        # Switch to the playerPage
        # Play the selected video.
        print "Processing the link,", self.entry.media.player.url
        self.startThread(self.getYoutubeLinkToPlay, QtCore.SIGNAL("doneGetDirectLinks(QString)"), QtCore.SIGNAL("failedGetDirectLinks(QString)"), self.playVideo, self.dummy, self.entry.media.player.url)

################################################################################################
# Action related tp main menu.
################################################################################################
    def on_action_Open_download_folder(self):
        print "Open download folder here."
    
    def on_action_Quit(self):
        self.close()
        
    def on_actionS_earch_option(self):
        print "Setting search option here!"
        
    def on_action_Guide(self):
        webbrowser.open(r'https://code.google.com/p/simple-media-player/w/list')
        
    def on_action_About(self):
        aboutDialog = about.About(parent=self)
        aboutDialog.show()

################################################################################################
# Search
################################################################################################        
    def getAdvancedSearchOptions(self):
        vq = str(self.advancedSearchDialog.optionDialogSearchTerm.text())
        author = str(self.advancedSearchDialog.lineeditUserFeed.text())
        results_number = self.advancedSearchDialog.spbMaxResults.value()
        sort_by = str(self.advancedSearchDialog.optionDialogSortby.currentText()).lower()
        
        # Change to standard name.
        if sort_by == 'published date':
            sort_by = 'published'
        elif sort_by == 'view count':
            sort_by = 'viewCount'
            
        racy = str(self.advancedSearchDialog.optionDialogSafeSearch.currentText()).lower()
        startIndex = self.advancedSearchDialog.spbStartIndex.value()
        time = str(self.advancedSearchDialog.cbTime.currentText()).lower()
        
        return [vq, author, results_number, sort_by, racy, startIndex, time]
    
    
    # User's feed.
    @QtCore.pyqtSlot()
    def on_lineeditUserFeed_returnPressed(self):
        # Start a thread for searching.
        self.advancedSearchDialog.lineeditUserFeed
        self.startThread(self.ytUserFeedSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("searchFailed()"),
                         self.setHtml,
                         self.dummy)        
    
    # Return an instance that helps us to use youtube's services.
    def getYouTubeService(self, username='', password=''):
        if (username != '' and password != ''):  # new instance.
                self.yt_service = YouTubeService(username, password)
                return self.yt_service
        elif self.yt_service != None:
            return self.yt_service
        else:
            self.yt_service = YouTubeService()
            return self.yt_service
    
    def ytUserFeedSearch(self):
        try:
            [vq, author, results_number, sort_by, racy, startIndex, time] = self.getAdvancedSearchOptions()
            print [vq, author, results_number, sort_by, racy, startIndex, time]
            yt_service = self.getYouTubeService()
            query = gdata.youtube.service.YouTubeVideoQuery()
            query.author = author
            query.max_results = results_number
            query.orderby = sort_by
            query.racy = racy
            query.start_index = startIndex
            feed = yt_service.client.YouTubeQuery(query)
      
            html = getHtmlFeedDescription(feed)
        except:
            html = "Sorry, no such user."
            feed = None
        
        self.feed = feed        
        self.emit(QtCore.SIGNAL('doneSearching(QString)'), QtCore.QString(html))
            
    # Click on the Search options button.
    @QtCore.pyqtSlot()
    def on_btnSearchOption_clicked(self):
        self.advancedSearchDialog.show()
        self.advancedSearchDialog.setFocus()
    
    # Click on the 'search' button in the search tab.
    @QtCore.pyqtSlot()
    def on_btnSearchVideo_clicked(self):
        # Get the order option.
        if self.lineEditSearch.text() == '':
            return    
        
        # get the search term.
        vq = str(self.lineEditSearch.text())
        
        # searching not done: Print the defaul message.
        self.videoList.setHtml("<html><body><h1>Searching ...</h1></body></html>")        
        # Create a thread to do the search.
        self.startThread(self.ytSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("searchFailed()"),
                         self.setHtml,
                         self.dummy,
                         vq, 'relevance', 'include', 1, 40, 'all_time')        
    
        
    # Set the content of the playlist page.
    def setHtml(self, html):
        self.videoList.setHtml(html)
        self.twgWebpage.setCurrentIndex(1)
    
    # Do the search.
    # TODO Re-implement using YoutubeService.
    def ytSearch(self, vq, orderby, racy, start_index, max_results, time):
        print "Calling ytSearch with ", [vq, orderby, racy, start_index, max_results, time]
        try:
            # Init service.
            yt_service = self.getYouTubeService()
            # vq must be converted to str.
            feed = yt_service.SearchWithVideoQuery(vq, orderby, racy, start_index, max_results, time)
        except:
            print "Something weird has occurred!"
            feed = None
        self.feed = feed
        html = getHtmlFeedDescription(feed)
        self.emit(QtCore.SIGNAL('doneSearching(QString)'), html)


    def advancedSearch(self):
        [vq, author, results_number, sort_by, racy, startIndex, time] = self.getAdvancedSearchOptions()
        # print  [vq, author, results_number, sort_by, racy,startIndex, time]
        # Create a thread to do the search.
        self.startThread(self.ytSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("searchFailed()"),
                         self.setHtml,
                         self.dummy,
                         vq, sort_by, racy, startIndex, results_number, time)  
        
################################################################################################
#
################################################################################################        
    # Click a link in the list of videos.
    def linkClicked(self, url):
        print url
        tmp = None
        # Find the entry that has that url.
        if (self.feed == None):
            pass
        else:
            for  entry in self.feed.entry:
                # print  entry.GetSwfUrl()
                if entry.GetSwfUrl() == str(url.toString()):
                    tmp = entry
                    break
        self.addMedia(tmp)

################################################################################################
# Functions related to threads.
################################################################################################    
    def startThread(self, function, signal_ok, signal_fail, function_if_ok, function_if_fail, *args):        
        # Connect signals and slots.
        self.disconnect(self, signal_ok, function_if_ok)
        self.connect(self, signal_ok, function_if_ok)
        self.disconnect(self, signal_fail, function_if_fail)
        self.connect(self, signal_fail, function_if_fail)
        
        # Start this thread.
        # Stop all the thread of the same type as this thread first.
        name = function.__name__.lower()
        
        # there should be only on 'search' thread.
        if name.find('search') != -1 or name == 'getyoutubelinktoplay':
            count = len(self.threadPool) - 1
            while count >= 0:
                if self.threadType[count].find('search'):
                    # Stop this thread first.
                    if self.threadPool[count].stopped():
                        print "This thread (%s) is stopped already" % count
                    else:
                        try:
                            print "Stopping thread number", count
                            self.threadPool[count].stop()
                        except:
                            pass
                    break
                count -= 1
        
        elif name.find('setplayerpage') != -1:
            # Thread of this type should not run concurrently.
            # Stop all previous thread of this type.
            count = len(self.threadPool) - 1
            while count >= 0:
                if self.threadType[count] == name:
                    # Stop this thread first.
                    if self.threadPool[count].stopped():
                        print "This thread (%s) is stopped already" % count
                    else:
                        try:
                            print "Stopping thread number", count
                            self.threadPool[count].stop()
                        except:
                            pass
                    break
                count -= 1
        
        # Update the thread pool
        self.threadPool.append(GenericThread(function, *args))
        self.threadType.append(name)
        self.threadPool[len(self.threadPool) - 1].start()
        self.setFocus()
    
    def dummy(self):
        print 'This function do nothing'


    # Event: The 'About' button is clicked
    # Show the about dialog.
    def on_btnAbout_clicked(self):
        ab = about.About(self)
        ab.show()

    # Event: The button 'Clear Play list' is pressed.
    @QtCore.pyqtSlot()
    def on_btnClearPlayList_clicked(self):
        # Clear the original and temporal play list.
        self.playlist = []
        self.playlistTmp = []
        self.updatePlayList()

###################################################################################
# Video playback controls.
###################################################################################
    # Event: The 'play/pause' is pressed.
    @QtCore.pyqtSlot()
    def on_btnPlayPause_clicked(self):
        # If there is some selected item, and it is either 'playing' or
        # 'paused', then switch between the two states.
        if self.vdpVideo.isPlaying():
            print "Change to pause"
            self.vdpVideo.pause()
        elif self.vdpVideo.isPaused(): 
            print "Change to play"
            self.vdpVideo.play()
        else:
            # There is no media being played/paused. The state is 'stop'.
            # Select one video and play it.
            if self.lswPlaylist.currentRow() < 0:
                # Nothing has been played.
                # Select the first item
                self.lswPlaylist.setCurrentRow(0, QtGui.QItemSelectionModel.SelectCurrent)
            
            # Now play the video.
            self.on_lswPlaylist_doubleClicked()
    # Response to timer event.
    @QtCore.pyqtSlot()
    def on_tmrTimer_timeout(self):
        # Update the playing time and the label.
        currentTime = self.vdpVideo.currentTime()

        if currentTime == 0:
            # This is the first time the label is changed.
            self.lblTime.setText('')
        else:
            # Get the total play time
            totalTime = self.vdpVideo.totalTime()
            # If the total playing time is less than 1 hour, just show minutes
            # and seconds.
            tFormat = 'mm:ss' if totalTime < 3600000 else 'hh:mm:ss'

            # We use Qtime for time conversions.
            currentTimeH = QtCore.QTime()

            # Convert times to a human readable strings.
            ct = currentTimeH.addMSecs(currentTime).toString(tFormat)

            totalTimeH = QtCore.QTime()
            tt = totalTimeH.addMSecs(totalTime).toString(tFormat)

            # Set time to label.
            self.lblTime.setText(ct + '/' + tt)

        # Now update the mouse status.
        # The window is in full-screen mode...
        if self.isFullScreen():
            # Update the current mouse time and position.
            mousePos = QtGui.QCursor.pos()
            mouseT = QtCore.QTime.currentTime()

            # Normally, when the program is in full-screen mode, the mouse must
            # be hidden until user move it.
            if (mousePos != self.mousePos0 and self.cursor().shape() == QtCore.Qt.BlankCursor) or self.wdgVideoControls.isVisible():
                self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

                # Reset the time count for calculating the mouse moving time.
                self.mouseT0 = QtCore.QTime.currentTime()
            # If user stops moving the mouse, it must stay visible at least some
            # seconds.
            elif self.cursor().shape() == QtCore.Qt.ArrowCursor and self.mouseT0.secsTo(mouseT) > 1:
                self.setCursor(QtGui.QCursor(QtCore.Qt.BlankCursor))

            # Update the current mouse position.
            self.mousePos0 = mousePos

            # Convert the global mouse position in the screen to the window
            # local coordinates. And get the coordinate for Y axis.
            mouseY = self.mapFromGlobal(mousePos).y()

            # If the mouse approaches to the position in which must be the
            # controls bar, it must be visible.
            if mouseY < self.height() and \
                mouseY > self.height() - self.wdgVideoControls.height():
                if self.wdgVideoControls.isHidden():
                    self.wdgVideoControls.show()
            # otherwise it must stay hidden.
            elif self.wdgVideoControls.isVisible():
                self.wdgVideoControls.hide()
        # The window is in normal mode...
        else:
            # If the mouse cursor is hidden, show it.
            if self.cursor().shape() == QtCore.Qt.BlankCursor:
                self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

            # Show play list.
            if self.wdgVideoControls.isHidden():
                self.wdgVideoControls.show()


    # mouseDoubleClickEvent is a protected method which called when user
    # double clicks in the GUI and this event isn't caught by any other widget.
    def mouseDoubleClickEvent(self, event):
        # Always, before process the event, we must send a copy of it to the
        # ancestor class.
        QtGui.QMainWindow.mouseDoubleClickEvent(self, event)

        # Go to full-screen mode or exit from it.
        self.on_btnFullscreen_clicked()
        
    
    # Event: The 'Full screen' button is clicked.
    # Switch between 'normal' mode and 'full screen' mode.
    @QtCore.pyqtSlot()
    def on_btnFullscreen_clicked(self):
        if self.isFullScreen():
            # switch to normal mode.
            self.showNormal()
            # show the play list.
            self.dckPlayList.show()
        else:
            # Switch to full screen mode.
            self.showFullScreen()
            # Hide the play list.
            self.dckPlayList.hide()
            # Hide the mouse cursor.
            self.setCursor(QtGui.QCursor(QtCore.Qt.BlankCursor))
            
    # Get direct link for one video.
    def getYoutubeLinkToPlay(self, link):
        try:
            # In this version, we will just get any link.
            print "Decoding the link", str(link)            
            # Get the video quality.
            desired_resolution = str(self.cbQuality.currentText())
            print "Desired resolution:", desired_resolution
            
            # Find the resolution nearest to the desired resolution.
            direct_link = YouTubeDl().getDirectLink(link, desired_resolution)
            self.emit(QtCore.SIGNAL("doneGetDirectLinks(QString)"), QtCore.QString(direct_link))
        except:
            self.emit(QtCore.SIGNAL("IWantToBeNoticed(QString)"), QtCore.QString("Sorry, it seems that you have to watch this video on YouTube."))
            
    def playVideo(self, link):
        print "link:", link
        match = re.search(r'(.*)\n\"(.*)\"', link)
        if match:
            link = match.group(1)
            
        # Play the video.
        if link.startsWith(QtCore.QString(r'http://')) or link.startsWith(QtCore.QString(r'https://')) or link.startsWith(QtCore.QString(r'mms://')):
            print "Link: via web"
            print "Asking the phonon player to play."
            self.vdpVideo.play(phonon.Phonon.MediaSource(QtCore.QUrl(link)))
            self.currentDirectLink = str(link);
        else:
            print "Link: local file"
            self.vdpVideo.play(phonon.Phonon.MediaSource(link))
            print "Asking the player to play."
            
    
    @QtCore.pyqtSlot()
    def on_btnDownloadPlaying_clicked(self):
        try:
            # In this version, we will just get any link.
            link = self.entry.media.player.url            
            # Get the video quality.
            desired_resolution = str(self.cbQuality.currentText())
            
            # Find the resolution nearest to the desired resolution.
            direct_link = YouTubeDl().getDirectLink(link, desired_resolution)
            match = re.search(r'(.*)\n\"(.*)\"', direct_link)
            if match:
                media = [match.group(1), match.group(2)]
            command = 'aria2c "%s" -o %s' %(media[0], media[1])
            command =  command.replace("\n", "")
            print command.find("\n")
            Popen(command, shell=True, close_fds=True)
        except:
            self.emit(QtCore.SIGNAL("IWantToBeNoticed(QString)"), QtCore.QString("Sorry, it seems that you have to watch this video on YouTube."))      
        
        
            
    # Add to the play a link
    # Url must be a string.
    def addMedia(self, entry):
        print "Adding media to playlist."
        self.playlist.append(entry)

        # update the play list.
        self.updatePlayList()
        
        # If the play list has been loaded and there isn't a media playing,
        # play it.
        if len(self.playlist) == 1:
            self.entry = entry
            # Start a thread getting the direct link play.
            self.lswPlaylist.setCurrentRow(0)
            self.startThread(self.getYoutubeLinkToPlay, QtCore.SIGNAL("doneGetDirectLinks(QString)"), QtCore.SIGNAL("failedGetDirectLinks(QString)"), self.playVideo, self.dummy, self.entry.media.player.url)
        
    @QtCore.pyqtSlot()
    def on_btnUpload_clicked(self):
        if not self.logged_in:
            messageBox = WarningDialog.WarningDialog(warning="You have to log in first", parent=self)
            messageBox.show()
        else:
            print "Calling the function upload"
            # Get the video information.            
            self.uploadDialog.show()
            self.connect(self.uploadDialog, QtCore.SIGNAL("accepted()"), self.doUpload)            
    
    # Managing the upload queue.
    def doUpload(self):
        print "Inside the function doUpload"
        # upload the file.
        
        # Get the video's info.
        video_location = str(self.uploadDialog.lineEditFilePath.text())
        video_title = str(self.uploadDialog.lineEditVideoName.text())
        tags = str(self.uploadDialog.lineEditTags.text())
        description = str(self.uploadDialog.plainTextEditDescription.toPlainText())
        
        # This will work on Windows only.
        video_location = video_location.replace('/', '\\')
        print video_location, type(video_location)
        print video_title, type(video_title)
        print tags, type(tags)
        print description, type(description)
        print "trying..."
        
        # Show an upload dialog.
        uploadDialog = UploadStatusDialog('Uploading', video_title, video_location, self)
        uploadDialog.show()
        self.startThread(self.doRealUpload,
                         QtCore.SIGNAL("doneUpload(QString)"),
                         QtCore.SIGNAL('uploadFailed(QString)'),
                         self.doneUpload,
                         self.uploadFailed, video_title, description, tags, video_location, uploadDialog)
    
    # Do the upload.
    def doRealUpload(self, video_title, description, tags, video_location, uploadDialog):
        print  "doRealUPload"     
        try:
            self.getYouTubeService()
            new_entry = self.yt_service.DirectVideoUpload(video_title, description, tags, video_location)
            self.emit(QtCore.SIGNAL('doneUpload(QString)'), QtCore.QString(video_location))
            # Setting the upload dialog.
            uploadDialog.lbStatus.setText(QtCore.QString('Video uploaded. Waiting for YouTube\'s acceptance.'))
            
            # Wait and check for Youtube Status.
            for i in range(10):  # wait for at most 10 * 30 seconds.
                time.sleep(30)
                uploadStatus = self.yt_service.client.CheckUploadStatus(new_entry)
                if uploadStatus is not None:
                    status = str(uploadStatus[0])
                    print status
                    uploadDialog.lbStatus.setText(QtCore.QString(status))
                else:
                    uploadDialog.lbStatus.setText(QtCore.QString("Done."))
                    break
        except:
            self.emit(QtCore.SIGNAL('uploadFailed(QString)'), QtCore.QString(video_location))
            uploadDialog.lbStatus.setText(QtCore.QString('Failed.'))
        
    # A message notifying upload sucessfully event.
    def doneUpload(self, message):
        pass
        # self.uploadingList[str(message)].lbStatus.setText(QtCore.QString('Done.'))
        
    def uploadFailed(self, message):
        pass
        # self.uploadingList[str(message)].lbStatus.setText(QtCore.QString('Failed.'))
        
    # Search for popular feeds.
    def on_btnTopRated_clicked(self):
        self.searchFeed("topRated")
    
    def on_btnTopFavorites_clicked(self):
        self.searchFeed("topFavorites")
        
    def on_btnMostShared_clicked(self):
        self.searchFeed("mostShared")
                
    def on_btnMostPopular_clicked(self):
        self.searchFeed("mostPopular")
    
    def on_btnMostRecent_clicked(self):
        self.searchFeed("mostRecent")
    
    def on_btnMostDiscussed_clicked(self):
        self.searchFeed("mostDiscussed")
    
    def on_btnMostResponded_clicked(self):
        self.searchFeed("mostResponded")
            
    def on_btnRecentlyFeatured_clicked(self):
        self.searchFeed("recentlyFeatured")
    
    def on_btnTrending_clicked(self):
        self.searchFeed("trending")
    
    # Search a feed of given name.
    def searchFeed(self, feedName):
        print "Searching", feedName
        # Create a thread to do the search.
        self.startThread(self.ytFeedSearch,
                         QtCore.SIGNAL("doneSearching(QString)"),
                         QtCore.SIGNAL("failedSearching(QString)"),
                         self.setHtml,
                         self.dummy,
                         feedName)
    
    def ytFeedSearch(self, feedName):
        yt_service = self.getYouTubeService()
        if feedName == 'topRated':
            feed = yt_service.RetrieveTopRatedVideoFeed()
        elif feedName == "topFavorites":
            feed = yt_service.RetrieveTopFavoritesVideoFeed()
        elif feedName == "mostShared":
            feed = yt_service.client.GetYouTubeVideoFeed("https://gdata.youtube.com/feeds/api/standardfeeds/most_shared")
        elif feedName == "mostPopular":
            feed = yt_service.client.GetYouTubeVideoFeed("https://gdata.youtube.com/feeds/api/standardfeeds/most_popular")
        elif feedName == "mostRecent":
            feed = yt_service.RetrieveMostRecentVideoFeed()
        elif feedName == "mostDiscussed":
            feed = yt_service.RetrieveMostDiscussedVideoFeed()
        elif feedName == "mostResponded":
            feed = yt_service.RetrieveMostRespondedVideoFeed()
        elif feedName == 'recentlyFeatured':
            feed = yt_service.RetrieveRecentlyFeaturedVideoFeed()      
        elif feedName == "trending":
            feed = yt_service.client.GetYouTubeVideoFeed("https://gdata.youtube.com/feeds/api/standardfeeds/on_the_web")
        else:
            feed = None
            print 'Invalid feed'            
        
        self.feed = feed
        html = getHtmlFromFeed.getHtmlFeedDescription(feed)
        self.emit(QtCore.SIGNAL('doneSearching(QString)'), html)
    
    def login(self, email, password):
        '''
        Log in to YouTube, using an email and password. 
        '''
        print "Inside the login function"
        print email, type(email)
        try:
            self.yt_service = YouTubeService(email, password)
            self.logged_in = self.yt_service.loggedIn
            if (self.logged_in):
                self.emit(QtCore.SIGNAL("doneLogin(QString)"), email)
            else:
                self.emit(QtCore.SIGNAL("failedLogin()"))
        except:
            self.emit(QtCore.SIGNAL("failedLogin()"))
            
    
    @QtCore.pyqtSlot()
    def on_btnPost_clicked(self):
        '''
        Post a comment to the current video.
        If the user has logged in, post a comment, otherwise display a warning message.
        '''
        if self.yt_service == None or self.yt_service.loggedIn == False:
            messageBox = WarningDialog.WarningDialog("Sorry, you have to log in first.", self)
            messageBox.show()            
        else:
            # Get the in the textEditComment
            text = str(self.textEditComment.toPlainText())
            print "You want to post a comment:", text
            self.startThread(self.postComment, QtCore.SIGNAL("donePostComment()"), QtCore.SIGNAL("failedPostComment()"), self.dummy, self.dummy, text)
            
    def postComment(self, comment):
        '''
        Post a comment to the playing video.
        '''
        print "You want to post a comment."
        try:
            self.yt_service.AddComment(getVideoId(self.entry), comment)
            self.emit(QtCore.SIGNAL("donePostComment()"))
        except:
            self.emit("failedPostComment()")
    
    @QtCore.pyqtSlot()
    def on_btnRate_clicked(self):
        '''
        Handle the event that the user click on the 'Rate' button.
        '''
        print "You want to rate the video."
        if self.logged_in:
            self.startThread(self.addRating, QtCore.SIGNAL("doneAddRating()"), QtCore.SIGNAL("failedAddRating()"), self.dummy, self.dummy)
        else:
            message = WarningDialog.WarningDialog("Sorry, you have to log in first.", self)
            message.showNormal()
            
    def addRating(self):
        '''
        Rate the current (playing) video.
        '''
        number = self.value()
        try:
            self.yt_service.AddRating(getVideoId(self.entry), number)
            self.emit(QtCore.SIGNAL("doneAddRating()"))
        except:
            self.emit(QtCore.SIGNAL("failedAddRating()"))
        
    # User clicked on the 'login' button.
    @QtCore.pyqtSlot()
    def on_btnLogin_clicked(self):
        # Start a login thread.
        username = str(self.ledUsername.text())
        password = str(self.ledPassword.text())
        
        self.startThread(self.login,
                         QtCore.SIGNAL("doneLogin(QString)"),
                         QtCore.SIGNAL("failedLogin()"),
                        self.setUsernameView,
                        self.failedLoginWarning,
                        username, password)
    
    @QtCore.pyqtSlot()
    def on_btnLogout_clicked(self):
        self.yt_service = YouTubeService()
        self.logged_in = False
        self.labelGreeting.setText('Hello')
        
    # Show the username.
    def setUsernameView(self, username):
        self.labelGreeting.setText("Hello, %s" % username)
        self.ledUsername.setText('')
        self.ledPassword.setText('')
        self.btnLogout.setEnabled(True)
        
    def failedLoginWarning(self):
        print "Sorry, login failed!"
        self.yt_service = YouTubeService()
        self.btnLogout.setEnabled(False) 
        warningDialog = WarningDialog.WarningDialog(warning="Sorry, logging in failed", parent=self)
        warningDialog.show()
    
    def _htmlForFlash(self, url):
        html = ''''<embed src="%s" type="application/x-shockwave-flash" allowfullscreen="true" width="640" height="480"></embed>
        ''' % url
        
        return html
    
    def showMessage(self, message):
        wd = WarningDialog.WarningDialog(message, self)
        wd.show()