예제 #1
0
    def __init__(self, app=None, options=None, args=None):
        """Initialize the GUI and many variables and load the configuration."""
        
        
        super(Gui, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.playlistWidget.hide()
        
        self.app = app
        
        # Load settings
        self.settings = Settings()
        
        self.download_urls = {}
        self.download_folder = c.HOME_FOLDER
        self.convert_thread = None
        self.active_download_items = []
        self.downloads_trash = []
        self.match_url = None
        self.action = ""
        self.namelabel = None
        self.menu_active = None
        self.show_confirm_dialog = True
        self.active_tree_widget = None
        self.ignoreMovement = 0
        self.quality_options = ["custom", "ask", "low", "high"]
        #the user can use different temporary quality
        self.global_quality = self.settings.global_quality 
        self.clipboard = QtGui.QApplication.clipboard()
        self.visited_urls = []
        self.searchIconSize = QSize(0, 0)
        
        #create actions for downloads, search and player's right click menu
        self.start = QAction(QIcon(c.PATH_MEDIA + "start.png"), self.tr("Start"), self)
        self.stop = QAction(QIcon(c.PATH_MEDIA + "stop.png"), self.tr("Stop"), self)
        self.remove = QAction(QIcon(c.ICON_REMOVE), self.tr("Remove"), self)
        self.remove_delete = QAction(QIcon(c.ICON_DELETE), self.tr("Remove and delete file"), self)
        self.opendir = QAction(QIcon(c.ICON_OPEN_FOLDER), self.tr("Open Folder"), self)
        self.copyurl = QAction(QIcon(c.ICON_COPY), self.tr("Copy original URL"), self)
        self.a_play_local = QAction(self.tr("Play local file"), self)
        self.a_download = QAction(QIcon(c.ICON_DOWNLOAD), self.tr("Download"), self)
        
        
        if HAS_PLAYER and c.HAS_FFMPEG:
          self.player = Player(self)
          #self.ui.horizontalLayout.addWidget(self.player.slider)
          self.ui.videoWidget.installEventFilter(self)
          self.ui.playlistWidget.installEventFilter(self)
          self.videoWidgetParent = self.ui.videoWidget.parentWidget()
          

          #player's right click menu
          self.ui.videoWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
          self.menu_player = QMenu(self)
          self.menu_player.addAction(self.copyurl)
          self.menu_player.addAction(self.a_download)
          self.ui.videoWidget.customContextMenuRequested.connect(self.showPlayerRightClickMenu)
          
          
          self.ui.nameLabel.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
          #repeat button
          self.disabled_replay_icon = gui_utils.getGreyedIcon(c.ICON_REPEAT)
          self.enabled_replay_icon = QIcon(c.ICON_REPEAT)
          self.ui.btn_replay.setFlat(True)
          self.onReplayClicked(next=False)#update button's icon
        else:
          self.ui.tab_widget.removeTab(0)
          self.player = None
        
        #cancel button
        self.b_cancelSearch = QPushButton("Cancel", self.ui.statusbar)
        self.b_cancelSearch.clicked.connect(self.cancelSearch)
        self.b_cancelSearch.hide()
        
        #quality button
        self.btn_quality = QPushButton(self.ui.statusbar)
        self.btn_quality.setFlat(True)
        self.ui.statusbar.addPermanentWidget(self.btn_quality)
        self.switchQuality(next=False)
        
        #create tray icon
        self.trayicon = QSystemTrayIcon(QIcon(c.ICON_WATCHVIDEO), self.app)
        self.trayicon.show()
        
        self.notification = Notification(self.trayicon, self.settings)
        

        self.dialogs = {
            'about': None,        # The instance of the "About..." window will be stored here
            'preferences': None,        # The instance of the "Preferences" window will be stored here
            'add_videos': None,
            }

        
        if c.FIREFOX_SESSION is None:
            self.ui.a_searchBrowser.setDisabled(True)
        
        
        self.ui.tree_downloads.setColumnCount(5)
        self.ui.tree_downloads.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.menu = QMenu(self)
        
        #Timers
        self.timer_check_downloads = QTimer(self)
        self.timer_check_downloads.timeout.connect(self.updateDownloads)
        self.convert_timer = QTimer(self)
        self.convert_timer.timeout.connect(self.isConversionDone)
        self.timer_match_urls = QTimer(self)
        self.timer_match_urls.timeout.connect(self.isCheckingDone)
        self.close_timer = QTimer(self)
        self.close_timer.timeout.connect(self.close_window)
        self.close_timer.setSingleShot(True)
        
        #stuff related to the search
        self.search = None
        self.ui.searchLine.addResultsWidget(self.ui.resultsWidget)
        self.ui.resultsWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.ui.searchLine.setFocus(QtCore.Qt.MouseFocusReason)
        self.ui.dockWidget.addAction(self.ui.a_viewSearch)
        self.abort_search_timer = QTimer(self)
        self.abort_search_timer.timeout.connect(self.searchYoutube)
        self.abort_search_timer.setSingleShot(True)
        
        #add actions to the search's right click menu
        self.search_menu = QMenu(self)
        self.search_menu.addAction(self.copyurl)
        self.search_menu.addAction(self.a_download)
        
        #add actions to the download's right click menu
        self.menu.addAction(self.start)
        self.menu.addAction(self.stop)
        self.menu.addSeparator()
        self.menu.addAction(self.remove)
        self.menu.addAction(self.remove_delete)
        self.menu.addSeparator()
        self.menu.addAction(self.opendir)
        self.menu.addAction(self.copyurl)
        self.menu.addAction(self.a_play_local)

        
        # connect signals with slots
        self.ui.a_addVideos.triggered.connect(self.showAddVideos)
        self.ui.a_searchBrowser.triggered.connect(self.searchBrowser)
        self.ui.a_clearCompleted.triggered.connect(self.clearCompleted)
        self.ui.a_preferences.triggered.connect(self.showPreferences)
        self.ui.a_about.triggered.connect(self.showAbout)
        self.ui.a_quit.triggered.connect(self.close)
        self.ui.a_clipboard.triggered.connect(self.addFromClipboard)
        self.ui.a_clipboard.hovered.connect(self.showStatusMessage)
        self.ui.a_play.triggered.connect(self.addFromClipboard)
        self.ui.a_play.hovered.connect(self.showStatusMessage)
        self.ui.a_download.triggered.connect(self.addFromClipboard)
        self.ui.a_download.hovered.connect(self.showStatusMessage)
        self.copyurl.triggered.connect(self.copyOriginalUrl)
        self.ui.tree_downloads.customContextMenuRequested.connect(self.showRightClickMenu)
        self.ui.tree_downloads.itemDoubleClicked.connect(self.onDownloadDoubleClick)
        self.start.triggered.connect(self.startDownloads)
        self.stop.triggered.connect(self.stopDownloads)
        self.remove.triggered.connect(self.removeTriggered)
        self.remove_delete.triggered.connect(self.removeAndDelete)
        self.opendir.triggered.connect(self.openDir)
        self.trayicon.activated.connect(self.openWindow)
        self.a_play_local.triggered.connect(self.play)
        self.clipboard.dataChanged.connect(self.clipboardDataChanged)
       
        self.ui.btn_replay.clicked.connect(self.onReplayClicked)
        self.btn_quality.clicked.connect(self.switchQuality)

        #search related signals
        self.ui.searchLine.returnPressed.connect(self.searchYoutube)
        self.ui.b_search.pressed.connect(self.searchYoutube)
        self.ui.resultsWidget.itemDoubleClicked.connect(self.onSearchDoubleClick)
        self.a_download.triggered.connect(self.onDownloadActionPressed)
        self.ui.resultsWidget.customContextMenuRequested.connect(self.showResultsRightClickMenu)
        self.ui.a_viewSearch.toggled.connect(lambda state: self.ui.dockWidget.setVisible(state))
        
        self.loadWindow() #loads window geometry, widgets' size, etc
        
        if len(args) > 0:
            if options.down:
                self.action = "download"
                self.getFilesUrl(args)
            elif options.more:
                self.action = "clipboard"
                self.getFilesUrl(args)
            else:
                self.action = "play"
                self.getFilesUrl(args)
예제 #2
0
class Gui(QtGui.QMainWindow):
    """WatchVideo's main class."""
    #gotVideo = Signal(tuple)  
    
    def __init__(self, app=None, options=None, args=None):
        """Initialize the GUI and many variables and load the configuration."""
        
        
        super(Gui, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.playlistWidget.hide()
        
        self.app = app
        
        # Load settings
        self.settings = Settings()
        
        self.download_urls = {}
        self.download_folder = c.HOME_FOLDER
        self.convert_thread = None
        self.active_download_items = []
        self.downloads_trash = []
        self.match_url = None
        self.action = ""
        self.namelabel = None
        self.menu_active = None
        self.show_confirm_dialog = True
        self.active_tree_widget = None
        self.ignoreMovement = 0
        self.quality_options = ["custom", "ask", "low", "high"]
        #the user can use different temporary quality
        self.global_quality = self.settings.global_quality 
        self.clipboard = QtGui.QApplication.clipboard()
        self.visited_urls = []
        self.searchIconSize = QSize(0, 0)
        
        #create actions for downloads, search and player's right click menu
        self.start = QAction(QIcon(c.PATH_MEDIA + "start.png"), self.tr("Start"), self)
        self.stop = QAction(QIcon(c.PATH_MEDIA + "stop.png"), self.tr("Stop"), self)
        self.remove = QAction(QIcon(c.ICON_REMOVE), self.tr("Remove"), self)
        self.remove_delete = QAction(QIcon(c.ICON_DELETE), self.tr("Remove and delete file"), self)
        self.opendir = QAction(QIcon(c.ICON_OPEN_FOLDER), self.tr("Open Folder"), self)
        self.copyurl = QAction(QIcon(c.ICON_COPY), self.tr("Copy original URL"), self)
        self.a_play_local = QAction(self.tr("Play local file"), self)
        self.a_download = QAction(QIcon(c.ICON_DOWNLOAD), self.tr("Download"), self)
        
        
        if HAS_PLAYER and c.HAS_FFMPEG:
          self.player = Player(self)
          #self.ui.horizontalLayout.addWidget(self.player.slider)
          self.ui.videoWidget.installEventFilter(self)
          self.ui.playlistWidget.installEventFilter(self)
          self.videoWidgetParent = self.ui.videoWidget.parentWidget()
          

          #player's right click menu
          self.ui.videoWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
          self.menu_player = QMenu(self)
          self.menu_player.addAction(self.copyurl)
          self.menu_player.addAction(self.a_download)
          self.ui.videoWidget.customContextMenuRequested.connect(self.showPlayerRightClickMenu)
          
          
          self.ui.nameLabel.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
          #repeat button
          self.disabled_replay_icon = gui_utils.getGreyedIcon(c.ICON_REPEAT)
          self.enabled_replay_icon = QIcon(c.ICON_REPEAT)
          self.ui.btn_replay.setFlat(True)
          self.onReplayClicked(next=False)#update button's icon
        else:
          self.ui.tab_widget.removeTab(0)
          self.player = None
        
        #cancel button
        self.b_cancelSearch = QPushButton("Cancel", self.ui.statusbar)
        self.b_cancelSearch.clicked.connect(self.cancelSearch)
        self.b_cancelSearch.hide()
        
        #quality button
        self.btn_quality = QPushButton(self.ui.statusbar)
        self.btn_quality.setFlat(True)
        self.ui.statusbar.addPermanentWidget(self.btn_quality)
        self.switchQuality(next=False)
        
        #create tray icon
        self.trayicon = QSystemTrayIcon(QIcon(c.ICON_WATCHVIDEO), self.app)
        self.trayicon.show()
        
        self.notification = Notification(self.trayicon, self.settings)
        

        self.dialogs = {
            'about': None,        # The instance of the "About..." window will be stored here
            'preferences': None,        # The instance of the "Preferences" window will be stored here
            'add_videos': None,
            }

        
        if c.FIREFOX_SESSION is None:
            self.ui.a_searchBrowser.setDisabled(True)
        
        
        self.ui.tree_downloads.setColumnCount(5)
        self.ui.tree_downloads.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.menu = QMenu(self)
        
        #Timers
        self.timer_check_downloads = QTimer(self)
        self.timer_check_downloads.timeout.connect(self.updateDownloads)
        self.convert_timer = QTimer(self)
        self.convert_timer.timeout.connect(self.isConversionDone)
        self.timer_match_urls = QTimer(self)
        self.timer_match_urls.timeout.connect(self.isCheckingDone)
        self.close_timer = QTimer(self)
        self.close_timer.timeout.connect(self.close_window)
        self.close_timer.setSingleShot(True)
        
        #stuff related to the search
        self.search = None
        self.ui.searchLine.addResultsWidget(self.ui.resultsWidget)
        self.ui.resultsWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.ui.searchLine.setFocus(QtCore.Qt.MouseFocusReason)
        self.ui.dockWidget.addAction(self.ui.a_viewSearch)
        self.abort_search_timer = QTimer(self)
        self.abort_search_timer.timeout.connect(self.searchYoutube)
        self.abort_search_timer.setSingleShot(True)
        
        #add actions to the search's right click menu
        self.search_menu = QMenu(self)
        self.search_menu.addAction(self.copyurl)
        self.search_menu.addAction(self.a_download)
        
        #add actions to the download's right click menu
        self.menu.addAction(self.start)
        self.menu.addAction(self.stop)
        self.menu.addSeparator()
        self.menu.addAction(self.remove)
        self.menu.addAction(self.remove_delete)
        self.menu.addSeparator()
        self.menu.addAction(self.opendir)
        self.menu.addAction(self.copyurl)
        self.menu.addAction(self.a_play_local)

        
        # connect signals with slots
        self.ui.a_addVideos.triggered.connect(self.showAddVideos)
        self.ui.a_searchBrowser.triggered.connect(self.searchBrowser)
        self.ui.a_clearCompleted.triggered.connect(self.clearCompleted)
        self.ui.a_preferences.triggered.connect(self.showPreferences)
        self.ui.a_about.triggered.connect(self.showAbout)
        self.ui.a_quit.triggered.connect(self.close)
        self.ui.a_clipboard.triggered.connect(self.addFromClipboard)
        self.ui.a_clipboard.hovered.connect(self.showStatusMessage)
        self.ui.a_play.triggered.connect(self.addFromClipboard)
        self.ui.a_play.hovered.connect(self.showStatusMessage)
        self.ui.a_download.triggered.connect(self.addFromClipboard)
        self.ui.a_download.hovered.connect(self.showStatusMessage)
        self.copyurl.triggered.connect(self.copyOriginalUrl)
        self.ui.tree_downloads.customContextMenuRequested.connect(self.showRightClickMenu)
        self.ui.tree_downloads.itemDoubleClicked.connect(self.onDownloadDoubleClick)
        self.start.triggered.connect(self.startDownloads)
        self.stop.triggered.connect(self.stopDownloads)
        self.remove.triggered.connect(self.removeTriggered)
        self.remove_delete.triggered.connect(self.removeAndDelete)
        self.opendir.triggered.connect(self.openDir)
        self.trayicon.activated.connect(self.openWindow)
        self.a_play_local.triggered.connect(self.play)
        self.clipboard.dataChanged.connect(self.clipboardDataChanged)
       
        self.ui.btn_replay.clicked.connect(self.onReplayClicked)
        self.btn_quality.clicked.connect(self.switchQuality)

        #search related signals
        self.ui.searchLine.returnPressed.connect(self.searchYoutube)
        self.ui.b_search.pressed.connect(self.searchYoutube)
        self.ui.resultsWidget.itemDoubleClicked.connect(self.onSearchDoubleClick)
        self.a_download.triggered.connect(self.onDownloadActionPressed)
        self.ui.resultsWidget.customContextMenuRequested.connect(self.showResultsRightClickMenu)
        self.ui.a_viewSearch.toggled.connect(lambda state: self.ui.dockWidget.setVisible(state))
        
        self.loadWindow() #loads window geometry, widgets' size, etc
        
        if len(args) > 0:
            if options.down:
                self.action = "download"
                self.getFilesUrl(args)
            elif options.more:
                self.action = "clipboard"
                self.getFilesUrl(args)
            else:
                self.action = "play"
                self.getFilesUrl(args)
                
        

    def clipboardDataChanged(self):
        if not self.settings.check_links_auto: return
        
        if "http" in self.clipboard.text():
            text = self.clipboard.text().split()
            text = [ url for url in text if url not in self.visited_urls and "http://" in url ]
            
            if text:
                self.action = "clipboard-auto"
                self.getFilesUrl(text)
            
      
    def showPlayerRightClickMenu(self):
        if self.player and self.player.download:
            self.menu_active = "player"
            point = QtGui.QCursor.pos() 
            self.menu_player.exec_(point)
    
    
    def onDownloadActionPressed(self):
        """Used by the player and search"""
        if self.menu_active == "player":
            download_item = self.player.getDownloadItem()
            name = os.path.split(download_item.dest_file)[1]
            download_item.copyAfterComplete(self.settings.download_folder, name)
            tree_item = TreeWidgetItem([name, "-", "", "0", "00:00:00"], 
                                        download_item)
                                        
            #insert QProgressBar
            self.ui.tree_downloads.addTopLevelItem(tree_item)
            self.ui.tree_downloads.setItemWidget(tree_item, 2, QProgressBar(self.ui.tree_downloads))
            
            self.active_download_items.append(tree_item)
            if not self.timer_check_downloads.isActive():
                self.timer_check_downloads.start(1000)

                
        else:
            urls = [ item.getOriginalUrl() for item in self.ui.resultsWidget.selectedItems()]
            self.action = "download"
            self.getFilesUrl(urls)
            
            
    def onSearchDoubleClick(self, item, pos):
        """On double click play the video - ToDo: Add option in preferences"""
        last_index = self.ui.resultsWidget.topLevelItemCount() - 1
        if not self.search.isRunning() and self.ui.resultsWidget.indexOfTopLevelItem(item) == last_index:
            self.ui.resultsWidget.takeTopLevelItem(last_index)
            self.searchYoutube(False)
            return
        
        self.action = "play"
        self.getFilesUrl([item.getOriginalUrl()])
        
    
    def searchYoutube(self, clear_previous_search=True):
        if self.ui.searchLine.isEmpty():
            return
    
        if self.search and self.search.isRunning():
            self.search.abort()
            self.abort_search_timer.start(1000)
            return
        
        if clear_previous_search:
            for i in xrange(self.ui.resultsWidget.topLevelItemCount()-1, -1, -1):
                self.ui.resultsWidget.takeTopLevelItem(i)
            
        start_pos = self.ui.resultsWidget.topLevelItemCount() + 1
        
        self.search = Search(self, start_pos)
        self.search.start()
    
    
    def addResult(self, item):
        image = item[0]
        if image:
            if image != QImage(c.ICON_ADD) and (image.width() > self.searchIconSize.width() and 
            image.height() > self.searchIconSize.height()):
                self.searchIconSize = QSize(image.width(), image.height())
                self.ui.resultsWidget.setIconSize(QSize(image.width(),image.height()))
                
                #image = gui_utils.setTextOnImage(image, "")
                
            item[1].setIcon(0, QIcon(QPixmap.fromImage(image)))
        self.ui.resultsWidget.addTopLevelItem(item[1])
    
    def onReplayClicked(self, checked=False, next=True):
        
        if next:
            i = self.player.repeat_modes.index(self.player.repeat)
            if i == len(self.player.repeat_modes) - 1:
                i = 0
            else:
                i += 1
                
            self.player.repeat = self.player.repeat_modes[i]
      
        if self.player.repeat == "none":
            self.ui.btn_replay.setIcon(self.disabled_replay_icon)
            self.ui.btn_replay.setToolTip(self.tr("Don't repeat"))
        elif self.player.repeat == "one":
            self.ui.btn_replay.setIcon(self.enabled_replay_icon)
            self.ui.btn_replay.setToolTip(self.tr("Repeat track"))
        else:
            self.ui.btn_replay.setIcon(QIcon(c.ICON_PLAYLIST_REPEAT))
            self.ui.btn_replay.setToolTip(self.tr("Repeat playlist"))
        

    def switchQuality(self, checked=False, next=True):
    
        if next: #when clicking in the button
            quality_options = self.quality_options
            if self.settings.global_video_quality: #remove the "custom" key
                quality_options = quality_options[1:]
            
            try:
                i = quality_options.index(self.global_quality)
                if i == len(quality_options) - 1:  i = 0
                else: i += 1
            except ValueError:
                i = 0
                
            option = quality_options[i]
        else:
            option = self.global_quality = self.settings.global_quality
        
        if option == "ask":
            icon = QIcon(c.ICON_ASK_QUALITY)
            msg = self.tr("A dialog to choose the format will appear for all videos with more than one format available.")
            img = "<img src='%s'><br></br>" % c.ICON_ASK_QUALITY
        elif option == "low":
            icon = QIcon(c.ICON_LOW_QUALITY)
            msg = self.tr("All videos are played/downloaded in the lowest quality available.")
            img = "<img src='%s'><br></br>" % c.ICON_LOW_QUALITY
        elif option == "high":
            icon = QIcon(c.ICON_HIGH_QUALITY)
            msg = self.tr("All videos are played/downloaded in the highest quality available.")
            img = "<img src='%s'><br></br>" % c.ICON_HIGH_QUALITY
        else:
            icon = QIcon(c.ICON_CUSTOM_QUALITY)
            msg = self.tr("The videos are played/downloaded according to what " + \
            "was defined in preferences. If it's the first time accessing a particular " + \
            "website through WatchVideo, the default action will be to ask for the quality.")
            img = "<img src='%s'><br></br>" % c.ICON_CUSTOM_QUALITY
        
        self.global_quality = img.split(":/media/")[1].split("-")[0]
        self.btn_quality.setToolTip(img+msg)
        self.btn_quality.setIcon(icon)
   
    def onDownloadDoubleClick(self, item, pos):
        #Open the folder containing the video or play it.
        download = item.getDownload()
        if not self.settings.play_downloaded:
            self.playDownload(download)
        else:
            self.openDir(os.path.split(download.dest_file)[0])
    
    def playDownload(self, download):
        if os.path.exists(download.dest_file):
            filename = os.path.split(download.dest_file)[1]
            Thread(target=main.play, args=(download.dest_file, filename,
            self.settings.media_player)).start()
                
                
    def startDownloads(self):
        if self.active_tree_widget is None: return
        for item in self.active_tree_widget.selectedItems():
            download = item.getDownload().resume()

    def stopDownloads(self):
        if self.active_tree_widget is None: return
        for item in self.active_tree_widget.selectedItems():
            download = item.getDownload()
            download.stop()
            item.setText(3, "Paused")
            item.setText(4, "Paused")

                    
    def removeTriggered(self):
        downloads_removed = []
        if self.active_tree_widget is None: return
        
        answer = None
 
        for item in self.active_tree_widget.selectedItems():
            download = item.getDownload()
            
            if answer is None:
                if not download.isActive():
                    answer = QtGui.QMessageBox.Yes
                else:
                    answer = gui_utils.confirm(self, "Abort Download(s)", self.tr("This will abort the download(s) too, are you sure?"))
            
            if answer == QtGui.QMessageBox.No: return
            
            if "playlist" in self.active_tree_widget.objectName():
                if download == self.player.download:
                    self.player.stop()
                
                if item in self.player.treeWidgetItems:
                    self.player.treeWidgetItems.remove(item)
                    
            
            if download.isActive():
                download.abort()
                self.downloads_trash.append(download)
            
            #remove the item
            self.removeDownloadItem(item)
            
            downloads_removed.append(download)
        
        if ( "downloads" in self.active_tree_widget.objectName()
        and self.active_tree_widget.topLevelItemCount() == 0 ):
            self.ui.a_clearCompleted.setDisabled(True)
                    
        return downloads_removed
                        
            
    
    def removeAndDelete(self):
        downloads_removed = self.removeTriggered()
        
        for download in downloads_removed:
            os.remove(download.dest_file)


    def showResultsRightClickMenu(self, point):
        if self.ui.resultsWidget.selectedItems():
            self.menu_active = "search"
            point = QtGui.QCursor.pos() 
            self.search_menu.exec_(point) 
     
    def showRightClickMenu(self, point):
        if self.ui.tree_downloads.selectedItems():
            self.active_tree_widget = self.ui.tree_downloads
            paused_found = False
            active_found = False
            completed_found = False
            self.menu_active = "download"
            
            for item in self.ui.tree_downloads.selectedItems():
                download = item.getDownload()
                
                if download.isStopped():
                    paused_found = True
                elif download.completed:
                    completed_found = True
                else:
                    active_found = True
                    
                    
            if completed_found:
                self.a_play_local.setEnabled(True)
            else:
                self.a_play_local.setEnabled(False)
            
            if active_found: #if an active download is found
                if not self.stop.isEnabled(): self.stop.setEnabled(True)
            else:
                if self.stop.isEnabled(): self.stop.setEnabled(False)
            
            if paused_found: #if a paused download is found
                if not self.start.isEnabled(): self.start.setEnabled(True)
            else:
                if self.start.isEnabled(): self.start.setEnabled(False)
                        
            point = QtGui.QCursor.pos() 
            self.menu.exec_(point)
        
        
    def addNewDownloads(self, videos):
        self.action = ""
        if not videos: return
        
        if videos[0].down: #download
            self.ui.tab_widget.setCurrentIndex(1)
            for video in videos:
                if len(video.name) * 7 > self.ui.tree_downloads.header().sectionSize(0):
                    self.ui.tree_downloads.header().resizeSection(0, len(video.name)*7)
                
                download_item = DownloadItem(video.url, video.dl_url, video.filepath, video.after_complete, self)
                
                item = TreeWidgetItem([video.name, "-", "", "0", "00:00:00"], download_item)
                #insert QProgressBar
                self.ui.tree_downloads.addTopLevelItem(item)
                self.ui.tree_downloads.setItemWidget(item, 2, QProgressBar(self.ui.tree_downloads))
                
                download_item.start()
                self.active_download_items.append(item)
                
                if not self.timer_check_downloads.isActive():
                    self.timer_check_downloads.start(750)
        else: #Play
            self.ui.tab_widget.setCurrentIndex(0)
            if self.settings.use_builtin_player:
                for video in videos:
                    item = DownloadItem(video.url, video.dl_url, video.filepath, video.after_complete, self)
                    self.player.loadfile(video.filepath, item)
            else:
                #names = [video.name for video in videos]
                #urls = [video.dl_url for video in videos]
                for video in videos:
                    Thread(target=main.play, args=(video.dl_url, video.name,
                        self.settings.media_player)).start()
                    time.sleep(2)
                
        
        

    def afterComplete(self, download_item):
        start_thread = False
        if download_item.after_complete == 1: #play option
            Thread(target=main.play, args=(download_item.dest_file, os.path.split(download_item.dest_file)[1],
            self.settings.media_player)).start()
        elif download_item.after_complete == 2: #convert to Ogg Vorbis
            self.convert_thread = Convert(main.convert, download_item.dest_file)
            start_thread = True
        elif download_item.after_complete == 3: #convert to Ogg Theora
            self.convert_thread = Convert(main.convert, download_item.dest_file, audio_only=False)
            start_thread = True
        elif download_item.after_complete == 4: #rip audio option
            self.convert_thread = Convert(main.rip, download_item.dest_file)
            start_thread = True
            
        if start_thread:
            self.convert_thread.start()
            self.convert_timer.start(750)
            
            
    def isConversionDone(self):
        if self.convert_thread.type == "rip":
            message_waiting = self.tr("Ripping audio of") + " " + self.convert_thread.filename
            title_done = self.tr("Audio Ripped")
            title_error = self.tr("Error ripping audio")
        else:
            message_waiting = self.tr("Converting video:") + " " + self.convert_thread.filename
            title_done = self.tr("Video Converted")
            title_error = self.tr("Error converting video")

        if self.convert_thread.isDone():
            self.convert_timer.stop()

            if self.convert_thread.successful:
                if self.settings.notify_done:
                    self.notification.show(title_done, self.convert_thread.filename)
                self.ui.statusbar.showMessage(title_done + ": " + self.convert_thread.filename)
            else:
                self.notification.show(title_error, self.convert_thread.filename)
                self.ui.statusbar.showMessage(title_error + ": " + self.convert_thread.filename)
                if self.settings.notify_error:
                    self.notification.show(title_error, self.convert_thread.filename)
            
            self.convert_thread = None
        else:
            self.ui.statusbar.showMessage(message_waiting)

    def searchBrowser(self):
        session = json.loads(open(c.FIREFOX_SESSION).read().strip("()"))
        urls = []

        #search windows and tabs open in firefox
        for window in session["windows"]:
            for tab in window["tabs"]:
                for entry in tab["entries"]:
                    try:
                        urls.append(entry["url"])
                    except IndexError:
                        pass
        
        self.getFilesUrl(urls, fast=True)
                        

    def getFilesUrl(self, urls, fast=False):
        if self.match_url: return
        urls = [url for url in urls if "http" in url and len(url) > len("http")] 

        if urls:
            print urls
            #add cancel button
            self.b_cancelSearch.show()
            self.ui.statusbar.insertPermanentWidget(0, self.b_cancelSearch)
            self.cleanStatusTip()
            
            
            if "clipboard" in self.action: 
                quality = "ask"
            else:
                quality = self.global_quality
            
            self.match_url = main.Match(urls, quality, fast=False) #start a check thread       
            Thread(target=self.match_url.match, args=()).start()
            
            self.timer_match_urls.start(750)
        else:
            self.ui.statusbar.showMessage(self.tr("No valid URLs found."))
    

    
    def isCheckingDone(self):
        """Called in intervals of 750ms to see if the url thread is ready"""
        if self.match_url.done:
            self.timer_match_urls.stop()
            mediums = self.match_url.mediums
            ready_mediums = self.match_url.ready_mediums
            #a new website might have been added to the settings file
            #through ConfigParser, so we need to sync the QSettings instance with
            #the settings' file
            if self.match_url.update_settings: self.settings.sync()
            self.match_url = None
            self.resetStatusBar()
            
            if not mediums and not ready_mediums:
                self.ui.statusbar.showMessage(self.tr("No supported services were found"))
                self.b_cancelSearch.setText(self.tr("Close"))
                return
            
            #append mediums' urls to the visited urls
            for medium in mediums.keys() + ready_mediums.keys():
                self.visited_urls.append(medium.url)
            
            if self.action == "clipboard-auto":
                for medium in mediums: 
                    self.notification.show("WatchVideo", medium.title)
                self.action = "clipboard"
                
            if "clipboard" in self.action:
                for medium in ready_mediums:
                    mediums[medium] = [ready_mediums[medium]]
                ready_mediums = None
            
            if mediums:
                if "clipboard" in self.action:
                    self.showAddVideos(mediums)
                else:
                    self.showAddVideos(mediums, format_mode=True)
                
            if ready_mediums: 
                self.processVideos(ready_mediums)
                
                
        elif self.match_url.url: #if the url is valid, show it
            self.ui.statusbar.showMessage(self.tr("Currently checking: ") + self.match_url.url)
    
    
    def clearCompleted(self):
        for i in xrange(self.ui.tree_downloads.topLevelItemCount()-1, -1, -1):
            item = self.ui.tree_downloads.topLevelItem(i)
            download = item.getDownload()
            
            if download.completed:
                self.ui.tree_downloads.takeTopLevelItem(i)
                
        self.ui.a_clearCompleted.setDisabled(True)
        
    def updateDownloads(self):
        if not self.active_download_items:
            if self.timer_check_downloads.isActive():
                self.timer_check_downloads.stop()
            return
        
        for download in self.downloads_trash:
            if download.aborted: self.downloads_trash.remove(download)
        
        for download_item in self.active_download_items:
            download = download_item.getDownload()
            if download.isStopped(): continue
            
            progressBar = self.ui.tree_downloads.itemWidget(download_item, 2)
            total_size = download.size
            unit = download.size_unit
            downloaded = download.downloaded
            speed = round(download.speed, 2)
            speed_unit = download.speed_unit
            time_left_str = download.time_left_str
            
            if download.completed:
                progressBar.setMaximum(download.size_kib)
                progressBar.setValue(download.size_kib)
                download_item.setText(3, "Completed") #Cleans the 'speed' column
                download_item.setText(4, "Completed") #Cleans the 'time left' column
                self.active_download_items.remove(download_item)
                
                if not self.ui.a_clearCompleted.isEnabled():
                    self.ui.a_clearCompleted.setEnabled(True)
                
                if self.settings.notify_done:
                    self.notification.show(self.tr("Download Finished"), 
                    os.path.split(download.dest_file)[1])
                
                self.afterComplete(download)
                
            else:
                download_item.setText(1, str(total_size) + " " + unit)
                progressBar.setMaximum(download.size_kib)
                progressBar.setValue(downloaded)
                
                download_item.setText(3, str(speed) + " " + speed_unit)
                download_item.setText(4, time_left_str)

    def openDir(self, dir=None):
        
        if not dir:
            directories = set()
            for item in self.active_tree_widget.selectedItems():
                download = item.getDownload()
                directories.add(os.path.split(download.dest_file)[0])
            
            filemanager = None
        else:
            directories = (dir,)
        
        for manager in c.FILEMANAGERS:
            if is_command(manager):
                filemanager = manager
                break

        if filemanager:
            for directory in directories:
                subprocess.Popen((filemanager, directory))
            
            self.ui.statusbar.showMessage(self.tr("Opening download directory %s with %s") % (" ".join(directories), filemanager), 5000)

    def processVideos(self, mediums=None):
        
        if mediums is None: return
        
        videos = []
        
        for medium in mediums:
            format = mediums[medium]
            videos.append(VideoInfo(medium.title, medium.url, format.url))
        
        if self.action == "download":
            for video in videos: 
                video.folder = self.settings.download_folder
                video.after_complete = self.settings.after_download
        elif self.action == "play":
            for video in videos: video.toPlay()
        
        self.addNewDownloads(videos)

    #dialogs
    def showAddVideos(self, urls=None, format_mode=False):
        if self.dialogs["add_videos"] is None:
            from watchvideo.add_videos import AddVideosDialog
            self.dialogs["add_videos"] = AddVideosDialog(self, self.settings)
        
        self.dialogs["add_videos"].load(urls, format_mode)
        if self.isVisible():
            self.dialogs["add_videos"].show()
            self.dialogs["add_videos"].activateWindow()
        
        

    def showPreferences(self):
        """Displays the Preferences dialog."""
        self.dialogs['preferences'] = Preferences(self, self.settings)
        self.dialogs['preferences'].show()
        self.dialogs['preferences'].activateWindow()
        
    def showAbout(self):
        """Displays the About dialog."""
        if self.dialogs['about'] is None:
            from watchvideo.about import AboutDialog
            self.dialogs['about'] = AboutDialog(self)
        
        self.dialogs['about'].show()
        self.dialogs['about'].activateWindow()
        
    def addFromClipboard(self):
        urls = self.getClipboardText().split()
        objname = self.sender().objectName()
        if "a_" in objname:
            objname = objname.split("a_")[1]
        self.action = objname
        self.getFilesUrl(urls)
        
    def getClipboardText(self):
        return self.clipboard.text()
        
    def copyOriginalUrl(self):
        """Copies the original url to the Clipboard"""
        if self.menu_active == "download":
            urls = [item.getOriginalUrl() for item in self.ui.tree_downloads.selectedItems()]
        elif self.menu_active == "search":
            urls = [item.getOriginalUrl() for item in self.ui.resultsWidget.selectedItems()]
        elif self.menu_active == "playlist":
            urls = [item.getOriginalUrl() for item in self.ui.playlistWidget.selectedItems()]
        else:
            urls = [self.player.getOriginalUrl()]
        self.clipboard.setText("\n".join(urls))
        
    def showStatusMessage(self):
        if not self.match_url:
            self.sender().setStatusTip(self.getClipboardText())
            self.sender().showStatusText()
            
    def cleanStatusTip(self):
        self.ui.a_clipboard.setStatusTip("")
        self.ui.a_download.setStatusTip("")
        self.ui.a_play.setStatusTip("")
    
    def cancelSearch(self):
        self.stopChecking()
        self.resetStatusBar()
        
    def stopChecking(self):
        if self.match_url:
            self.match_url.stop = True
            self.timer_match_urls.stop()
            self.match_url = None
            
    def resetStatusBar(self):
        self.ui.statusbar.showMessage("")
        self.ui.statusbar.removeWidget(self.b_cancelSearch)
        
    def play(self, video):
        if self.settings.use_builtin_player:
            item = DownloadItem(video.url, video.dl_url, video.filepath, video.after_complete, self)
            self.player.loadfile(video.filepath, item)
        else:
            Thread(target=main.play, args=(video.dl_url, video.name,
            self.settings.media_player)).start()
            
    def removeDownloadItem(self, item, rmFromGui=True):
        """item: is a TreeWidgetItem
           rmFromGui: if true, removes the item from the QTreeWidget """
            
        if item in self.active_download_items:
            self.active_download_items.remove(item)
            
        if rmFromGui:
            i = self.active_tree_widget.indexOfTopLevelItem(item)
            if i != -1:
                if "playlist" in self.active_tree_widget.objectName():
                    del self.player.counters[i]
                self.active_tree_widget.takeTopLevelItem(i)
        
    
    def openWindow(self, activation):
        if activation in (3, 2): #show/hide window
            if self.isVisible():
                self.hide()
                for dialog in self.dialogs:
                    if self.dialogs[dialog] and self.dialogs[dialog].isVisible():
                        self.dialogs[dialog].hide()

            else:
                self.show()
                for dialog in self.dialogs:
                    if self.dialogs[dialog] and self.dialogs[dialog].visible:
                        self.dialogs[dialog].show()
                
                if self.dialogs['add_videos'] and self.dialogs['add_videos'].mediums:
                    self.dialogs['add_videos'].show()
                
    def eventFilter(self, obj, event):
        if obj == self.ui.videoWidget:

            if self.ignoreMovement:
                self.ignoreMovement -= 1
                return False
                
            if  event.type() == QEvent.MouseMove:
                if self.ui.videoWidget.width() - 50 < event.x() < self.ui.videoWidget.width():
                    self.ui.playlistWidget.show()
                    self.ignoreMovement = 8
                    self.player.startTextMoveTimer()
                else:
                    self.ui.playlistWidget.hide()
                    self.player.stopTextMoveTimer()

                return True
            elif event.type() == QEvent.MouseButtonDblClick:
                self.player.setFullscreen()
                return True
            else:
                return False
        elif obj == self.ui.playlistWidget:
            
            if self.ignoreMovement:
                self.ignoreMovement -= 1
                return False
                
            if  event.type() == QEvent.MouseMove:
                if event.x() < 0 or event.x() > self.ui.playlistWidget.width() or\
                event.y() < 0 or event.y() > self.ui.playlistWidget.height():
                    self.ui.playlistWidget.hide()
                    self.player.stopTextMoveTimer()
                    self.ignoreMovement = 10
                return True
            else:
                return False
    
        return QtGui.QMainWindow.eventFilter(obj, event)
    
    def isEverythingAborted(self):
        abortCompleted = True 
        for download_item in self.active_download_items:
            if not download_item.getDownload().aborted:
                download_item.getDownload().abort()
                return False
                     
        if self.player and self.player.areDownloadsActive():
            return False
           
        #just a measure for extra security when closing the app
        for download in self.downloads_trash:
            if not download.aborted:
                return False
                
        if self.dialogs["add_videos"] and not self.dialogs["add_videos"].isFinished():
            return False
            
        return True
    
    def abortDownloads(self):
        for download_item in self.active_download_items:
            download = download_item.getDownload()
            if download.isActive(): download.abort()
                
        if self.player: 
            self.player.reset(downloads=True)
            
        if self.dialogs["add_videos"] and not self.dialogs["add_videos"].isFinished():
            self.dialogs["add_videos"].close()
    
    def saveWindow(self):
        self.settings.window_state = self.saveState()
        self.settings.window_geometry = self.saveGeometry()
        self.settings.show_search = self.ui.a_viewSearch.isChecked()

        
    def loadWindow(self):
        if self.settings.window_geometry:
            self.restoreGeometry(self.settings.window_geometry)
        if self.settings.window_state:
            self.restoreState(self.settings.window_state)

        self.ui.a_viewSearch.setChecked(self.settings.show_search)
        
    
    def close_window(self):
        """called by self.close_timer"""
        self.show_confirm_dialog = False
        self.close()
    
    def closeEvent(self, event):
        if self.active_download_items or (self.player and self.player.isActive()) or (
        self.dialogs["add_videos"] and not self.dialogs["add_videos"].isFinished()):
            if self.show_confirm_dialog:
                answer = gui_utils.confirm(self, title="Quit?",
                msg=self.tr("There are still some tasks active, do you really want to quit?" + 
                "\n(you won't be able to continue them after quitting)"))
            else:
                answer = QtGui.QMessageBox.Yes
            
            if answer == QtGui.QMessageBox.Yes:
                self.abortDownloads()
                if not self.isEverythingAborted():
                    #hide GUI so it gets out of the user's way while the app is closing
                    self.hide() 
                    self.close_timer.start(750)
                    event.ignore()
                    return
            else:
                event.ignore()
                return
           

        self.saveWindow()