def directory(app):
    #app = QApplication(sys.argv)

    QCoreApplication.setApplicationVersion(QT_VERSION_STR)
    parser = QCommandLineParser()
    parser.setApplicationDescription("File Directory")
    parser.addHelpOption()
    parser.addVersionOption()

    dontUseCustomDirectoryIconsOption = QCommandLineOption(
        'C', "Set QFileIconProvider.DontUseCustomDirectoryIcons")
    parser.addOption(dontUseCustomDirectoryIconsOption)
    parser.addPositionalArgument('', "The directory to start in.")
    parser.process(app)
    try:
        rootPath = parser.positionalArguments().pop(0)
    except IndexError:
        rootPath = None

    model = QFileSystemModel()
    model.setRootPath('')
    filter = ['*.db']  #filtering out just by db
    model.setNameFilters(filter)
    model.setNameFilterDisables(0)  #Only show the filtered .db paths
    #filename = model.filePath()
    #print(filename)

    if parser.isSet(dontUseCustomDirectoryIconsOption):
        model.iconProvider().setOptions(
            QFileIconProvider.DontUseCustomDirectoryIcons)
    tree = QTreeView()
    tree.setModel(model)
    if rootPath is not None:
        rootIndex = model.index(QDir.cleanPath(rootPath))
        if rootIndex.isValid():
            tree.setRootIndex(rootIndex)

    # Demonstrating look and feel features.
    tree.setAnimated(False)
    tree.setIndentation(20)
    tree.setSortingEnabled(True)

    availableSize = QApplication.desktop().availableGeometry(tree).size()
    tree.resize(availableSize / 2)
    tree.setColumnWidth(0, tree.width() / 3)

    tree.setWindowTitle("Directory View")
    tree.show()

    sys.exit(app.exec_())
Exemplo n.º 2
0
parser.addVersionOption()

dontUseCustomDirectoryIconsOption = QCommandLineOption(
    "c", "Set QFileIconProvider.DontUseCustomDirectoryIcons")
parser.addOption(dontUseCustomDirectoryIconsOption)
parser.addPositionalArgument("directory", "The directory to start in.")
parser.process(app)
try:
    rootPath = parser.positionalArguments().pop(0)
except IndexError:
    rootPath = None

model = QFileSystemModel()
model.setRootPath("")
if parser.isSet(dontUseCustomDirectoryIconsOption):
    model.iconProvider().setOptions(
        QFileIconProvider.DontUseCustomDirectoryIcons)
tree = QTreeView()
tree.setModel(model)
if rootPath is not None:
    rootIndex = model.index(QDir.cleanPath(rootPath))
    if rootIndex.isValid():
        tree.setRootIndex(rootIndex)

# Demonstrating look and feel features.
tree.setAnimated(False)
tree.setIndentation(20)
tree.setSortingEnabled(True)

availableSize = QApplication.desktop().availableGeometry(tree).size()
tree.resize(availableSize / 2)
tree.setColumnWidth(0, tree.width() / 3)
Exemplo n.º 3
0
parser.addVersionOption()

dontUseCustomDirectoryIconsOption = QCommandLineOption('c',
        "Set QFileIconProvider.DontUseCustomDirectoryIcons")
parser.addOption(dontUseCustomDirectoryIconsOption)
parser.addPositionalArgument('directory', "The directory to start in.")
parser.process(app)
try:
    rootPath = parser.positionalArguments().pop(0)
except IndexError:
    rootPath = None

model = QFileSystemModel()
model.setRootPath('')
if parser.isSet(dontUseCustomDirectoryIconsOption):
    model.iconProvider().setOptions(
            QFileIconProvider.DontUseCustomDirectoryIcons)
tree = QTreeView()
tree.setModel(model)
if rootPath is not None:
    rootIndex = model.index(QDir.cleanPath(rootPath))
    if rootIndex.isValid():
        tree.setRootIndex(rootIndex)

# Demonstrating look and feel features.
tree.setAnimated(False)
tree.setIndentation(20)
tree.setSortingEnabled(True)

availableSize = QApplication.desktop().availableGeometry(tree).size()
tree.resize(availableSize / 2)
tree.setColumnWidth(0, tree.width() / 3)
Exemplo n.º 4
0
class SearchFileWidget(QWidget):

    language_filter_change = pyqtSignal(list)

    def __init__(self):
        QWidget.__init__(self)

        self._refreshing = False

        self.fileModel = None
        self.proxyFileModel = None
        self.videoModel = None

        self._state = None

        self.timeLastSearch = QTime.currentTime()

        self.ui = Ui_SearchFileWidget()
        self.setup_ui()

    def set_state(self, state):
        self._state = state
        self._state.login_status_changed.connect(self.on_login_state_changed)
        self._state.interface_language_changed.connect(
            self.on_interface_language_changed)

    def get_state(self):
        return self._state

    def setup_ui(self):
        self.ui.setupUi(self)
        settings = QSettings()

        self.ui.splitter.setSizes([600, 1000])
        self.ui.splitter.setChildrenCollapsible(False)

        # Set up folder view

        lastDir = settings.value("mainwindow/workingDirectory",
                                 QDir.homePath())
        log.debug('Current directory: {currentDir}'.format(currentDir=lastDir))

        self.fileModel = QFileSystemModel(self)
        self.fileModel.setFilter(QDir.AllDirs | QDir.Dirs | QDir.Drives
                                 | QDir.NoDotAndDotDot | QDir.Readable
                                 | QDir.Executable | QDir.Writable)
        self.fileModel.iconProvider().setOptions(
            QFileIconProvider.DontUseCustomDirectoryIcons)
        self.fileModel.setRootPath(QDir.rootPath())
        self.fileModel.directoryLoaded.connect(self.onFileModelDirectoryLoaded)

        self.proxyFileModel = QSortFilterProxyModel(self)
        self.proxyFileModel.setSortRole(Qt.DisplayRole)
        self.proxyFileModel.setSourceModel(self.fileModel)
        self.proxyFileModel.sort(0, Qt.AscendingOrder)
        self.proxyFileModel.setSortCaseSensitivity(Qt.CaseInsensitive)
        self.ui.folderView.setModel(self.proxyFileModel)

        self.ui.folderView.setHeaderHidden(True)
        self.ui.folderView.hideColumn(3)
        self.ui.folderView.hideColumn(2)
        self.ui.folderView.hideColumn(1)

        index = self.fileModel.index(lastDir)
        proxyIndex = self.proxyFileModel.mapFromSource(index)
        self.ui.folderView.scrollTo(proxyIndex)

        self.ui.folderView.expanded.connect(self.onFolderViewExpanded)
        self.ui.folderView.clicked.connect(self.onFolderTreeClicked)
        self.ui.buttonFind.clicked.connect(self.onButtonFind)
        self.ui.buttonRefresh.clicked.connect(self.onButtonRefresh)

        # Set up introduction
        self.showInstructions()

        # Set up video view
        self.ui.filterLanguageForVideo.set_unknown_text(_('All languages'))
        self.ui.filterLanguageForVideo.selected_language_changed.connect(
            self.on_language_combobox_filter_change)
        # self.ui.filterLanguageForVideo.selected_language_changed.connect(self.onFilterLanguageVideo)

        self.videoModel = VideoModel(self)
        self.ui.videoView.setHeaderHidden(True)
        self.ui.videoView.setModel(self.videoModel)
        self.ui.videoView.activated.connect(self.onClickVideoTreeView)
        self.ui.videoView.clicked.connect(self.onClickVideoTreeView)
        self.ui.videoView.customContextMenuRequested.connect(self.onContext)
        self.videoModel.dataChanged.connect(self.subtitlesCheckedChanged)
        self.language_filter_change.connect(
            self.videoModel.on_filter_languages_change)

        self.ui.buttonSearchSelectVideos.clicked.connect(
            self.onButtonSearchSelectVideos)
        self.ui.buttonSearchSelectFolder.clicked.connect(
            self.onButtonSearchSelectFolder)
        self.ui.buttonDownload.clicked.connect(self.onButtonDownload)
        self.ui.buttonPlay.clicked.connect(self.onButtonPlay)
        self.ui.buttonIMDB.clicked.connect(self.onViewOnlineInfo)
        self.ui.videoView.setContextMenuPolicy(Qt.CustomContextMenu)

        # Drag and Drop files to the videoView enabled
        self.ui.videoView.__class__.dragEnterEvent = self.dragEnterEvent
        self.ui.videoView.__class__.dragMoveEvent = self.dragEnterEvent
        self.ui.videoView.__class__.dropEvent = self.dropEvent
        self.ui.videoView.setAcceptDrops(1)

        # FIXME: ok to drop this connect?
        # self.ui.videoView.clicked.connect(self.onClickMovieTreeView)

        self.retranslate()

    def retranslate(self):
        introduction = '<p align="center"><h2>{title}</h2></p>' \
            '<p><b>{tab1header}</b><br/>{tab1content}</p>' \
            '<p><b>{tab2header}</b><br/>{tab2content}</p>'\
            '<p><b>{tab3header}</b><br/>{tab3content}</p>'.format(
                title=_('How To Use {title}').format(title=PROJECT_TITLE),
                tab1header=_('1st Tab:'),
                tab2header=_('2nd Tab:'),
                tab3header=_('3rd Tab:'),
                tab1content=_('Select, from the Folder Tree on the left, the folder which contains the videos '
                              'that need subtitles. {project} will then try to automatically find available '
                              'subtitles.').format(project=PROJECT_TITLE),
                tab2content=_('If you don\'t have the videos in your machine, you can search subtitles by '
                              'introducing the title/name of the video.').format(project=PROJECT_TITLE),
                tab3content=_('If you have found some subtitle somewhere else that is not in {project}\'s database, '
                              'please upload those subtitles so next users will be able to '
                              'find them more easily.').format(project=PROJECT_TITLE))
        self.ui.introductionHelp.setHtml(introduction)

    @pyqtSlot(Language)
    def on_interface_language_changed(self, language):
        self.ui.retranslateUi(self)
        self.retranslate()

    @pyqtSlot(str)
    def onFileModelDirectoryLoaded(self, path):
        settings = QSettings()
        lastDir = settings.value('mainwindow/workingDirectory',
                                 QDir.homePath())
        qDirLastDir = QDir(lastDir)
        qDirLastDir.cdUp()
        if qDirLastDir.path() == path:
            index = self.fileModel.index(lastDir)
            proxyIndex = self.proxyFileModel.mapFromSource(index)
            self.ui.folderView.scrollTo(proxyIndex)
            self.ui.folderView.setCurrentIndex(proxyIndex)

    @pyqtSlot(int, str)
    def on_login_state_changed(self, state, message):
        log.debug(
            'on_login_state_changed(state={state}, message={message}'.format(
                state=state, message=message))
        if state in (State.LOGIN_STATUS_LOGGED_OUT, State.LOGIN_STATUS_BUSY):
            self.ui.buttonSearchSelectFolder.setEnabled(False)
            self.ui.buttonSearchSelectVideos.setEnabled(False)
            self.ui.buttonFind.setEnabled(False)
        elif state == State.LOGIN_STATUS_LOGGED_IN:
            self.ui.buttonSearchSelectFolder.setEnabled(True)
            self.ui.buttonSearchSelectVideos.setEnabled(True)
            self.ui.buttonFind.setEnabled(
                self.get_current_selected_folder() is not None)
        else:
            log.warning('unknown state')

    @pyqtSlot(Language)
    def on_language_combobox_filter_change(self, language):
        if language.is_generic():
            self.language_filter_change.emit(
                self.get_state().get_permanent_language_filter())
        else:
            self.language_filter_change.emit([language])

    def on_permanent_language_filter_change(self, languages):
        selected_language = self.ui.filterLanguageForVideo.get_selected_language(
        )
        if selected_language.is_generic():
            self.language_filter_change.emit(languages)

    @pyqtSlot()
    def subtitlesCheckedChanged(self):
        subs = self.videoModel.get_checked_subtitles()
        if subs:
            self.ui.buttonDownload.setEnabled(True)
        else:
            self.ui.buttonDownload.setEnabled(False)

    def showInstructions(self):
        self.ui.stackedSearchResult.setCurrentWidget(self.ui.pageIntroduction)

    def hideInstructions(self):
        self.ui.stackedSearchResult.setCurrentWidget(self.ui.pageSearchResult)

    @pyqtSlot(QModelIndex)
    def onFolderTreeClicked(self, proxyIndex):
        """What to do when a Folder in the tree is clicked"""
        if not proxyIndex.isValid():
            return

        index = self.proxyFileModel.mapToSource(proxyIndex)
        settings = QSettings()
        folder_path = self.fileModel.filePath(index)
        settings.setValue('mainwindow/workingDirectory', folder_path)
        # self.ui.buttonFind.setEnabled(self.get_state().)

    def get_current_selected_folder(self):
        proxyIndex = self.ui.folderView.currentIndex()
        index = self.proxyFileModel.mapToSource(proxyIndex)
        folder_path = self.fileModel.filePath(index)
        if not folder_path:
            return None
        return folder_path

    def get_current_selected_item_videomodel(self):
        current_index = self.ui.videoView.currentIndex()
        return self.videoModel.getSelectedItem(current_index)

    @pyqtSlot()
    def onButtonFind(self):
        now = QTime.currentTime()
        if now < self.timeLastSearch.addMSecs(500):
            return
        folder_path = self.get_current_selected_folder()

        settings = QSettings()
        settings.setValue('mainwindow/workingDirectory', folder_path)
        self.search_videos([folder_path])

        self.timeLastSearch = QTime.currentTime()

    @pyqtSlot()
    def onButtonRefresh(self):
        currentPath = self.get_current_selected_folder()
        if not currentPath:
            settings = QSettings()
            currentPath = settings.value('mainwindow/workingDirectory',
                                         QDir.homePath())

        self._refreshing = True

        self.ui.folderView.collapseAll()

        currentPath = self.get_current_selected_folder()
        if not currentPath:
            settings = QSettings()
            currentPath = settings.value('mainwindow/workingDirectory',
                                         QDir.homePath())

        index = self.fileModel.index(currentPath)

        self.ui.folderView.scrollTo(self.proxyFileModel.mapFromSource(index))

    @pyqtSlot(QModelIndex)
    def onFolderViewExpanded(self, proxyIndex):
        if self._refreshing:
            expandedPath = self.fileModel.filePath(
                self.proxyFileModel.mapToSource(proxyIndex))
            if expandedPath == QDir.rootPath():
                currentPath = self.get_current_selected_folder()
                if not currentPath:
                    settings = QSettings()
                    currentPath = settings.value('mainwindow/workingDirectory',
                                                 QDir.homePath())

                index = self.fileModel.index(currentPath)

                self.ui.folderView.scrollTo(
                    self.proxyFileModel.mapFromSource(index))
                self._refreshing = False

    @pyqtSlot()
    def onButtonSearchSelectFolder(self):
        settings = QSettings()
        path = settings.value('mainwindow/workingDirectory', QDir.homePath())
        folder_path = QFileDialog.getExistingDirectory(
            self, _('Select the directory that contains your videos'), path)
        if folder_path:
            settings.setValue('mainwindow/workingDirectory', folder_path)
            self.search_videos([folder_path])

    @pyqtSlot()
    def onButtonSearchSelectVideos(self):
        settings = QSettings()
        currentDir = settings.value('mainwindow/workingDirectory',
                                    QDir.homePath())
        fileNames, t = QFileDialog.getOpenFileNames(
            self, _('Select the video(s) that need subtitles'), currentDir,
            SELECT_VIDEOS)
        if fileNames:
            settings.setValue('mainwindow/workingDirectory',
                              QFileInfo(fileNames[0]).absolutePath())
            self.search_videos(fileNames)

    def search_videos(self, paths):
        if not self.get_state().connected():
            QMessageBox.about(
                self, _("Error"),
                _('You are not connected to the server. Please reconnect first.'
                  ))
            return
        self.ui.buttonFind.setEnabled(False)
        self._search_videos_raw(paths)
        self.ui.buttonFind.setEnabled(True)

    def _search_videos_raw(self, paths):
        # FIXME: must pass mainwindow as argument to ProgressCallbackWidget
        callback = ProgressCallbackWidget(self)
        callback.set_title_text(_("Scanning..."))
        callback.set_label_text(_("Scanning files"))
        callback.set_finished_text(_("Scanning finished"))
        callback.set_block(True)

        try:
            local_videos, local_subs = scan_videopaths(paths,
                                                       callback=callback,
                                                       recursive=True)
        except OSError:
            callback.cancel()
            QMessageBox.warning(self, _('Error'),
                                _('Some directories are not accessible.'))

        if callback.canceled():
            return

        callback.finish()

        log.debug("Videos found: %s" % local_videos)
        log.debug("Subtitles found: %s" % local_subs)
        self.hideInstructions()

        QCoreApplication.processEvents()

        if not local_videos:
            QMessageBox.about(self, _("Scan Results"),
                              _("No video has been found!"))
            return

        total = len(local_videos)

        # FIXME: must pass mainwindow as argument to ProgressCallbackWidget
        # callback = ProgressCallbackWidget(self)
        # callback.set_title_text(_("Asking Server..."))
        # callback.set_label_text(_("Searching subtitles..."))
        # callback.set_updated_text(_("Searching subtitles ( %d / %d )"))
        # callback.set_finished_text(_("Search finished"))
        callback.set_block(True)
        callback.set_range(0, total)

        callback.show()

        callback.set_range(0, 2)

        download_callback = callback.get_child_progress(0, 1)
        # videoSearchResults = self.get_state().get_OSDBServer().SearchSubtitles("", videos_piece)
        remote_subs = self.get_state().get_OSDBServer().search_videos(
            videos=local_videos, callback=download_callback)

        self.videoModel.set_videos(local_videos)
        # self.onFilterLanguageVideo(self.ui.filterLanguageForVideo.get_selected_language())

        if remote_subs is None:
            QMessageBox.about(
                self, _("Error"),
                _("Error contacting the server. Please try again later"))
        callback.finish()

        # TODO: CHECK if our local subtitles are already in the server, otherwise suggest to upload
        # self.OSDBServer.CheckSubHash(sub_hashes)

    @pyqtSlot()
    def onButtonPlay(self):
        settings = QSettings()
        programPath = settings.value('options/VideoPlayerPath', '')
        parameters = settings.value('options/VideoPlayerParameters', '')
        if programPath == '':
            QMessageBox.about(
                self, _('Error'),
                _('No default video player has been defined in Settings.'))
            return

        selected_subtitle = self.get_current_selected_item_videomodel()
        if isinstance(selected_subtitle, SubtitleFileNetwork):
            selected_subtitle = selected_subtitle.get_subtitles()[0]

        if isinstance(selected_subtitle, LocalSubtitleFile):
            subtitle_file_path = selected_subtitle.get_filepath()
        elif isinstance(selected_subtitle, RemoteSubtitleFile):
            subtitle_file_path = QDir.temp().absoluteFilePath(
                'subdownloader.tmp.srt')
            log.debug(
                'Temporary subtitle will be downloaded into: {temp_path}'.
                format(temp_path=subtitle_file_path))
            # FIXME: must pass mainwindow as argument to ProgressCallbackWidget
            callback = ProgressCallbackWidget(self)
            callback.set_title_text(_('Playing video + sub'))
            callback.set_label_text(_('Downloading files...'))
            callback.set_finished_text(_('Downloading finished'))
            callback.set_block(True)
            callback.set_range(0, 100)
            callback.show()
            try:
                subtitle_stream = selected_subtitle.download(
                    self.get_state().get_OSDBServer(), callback=callback)
            except ProviderConnectionError:
                log.debug('Unable to download subtitle "{}"'.format(
                    selected_subtitle.get_filename()),
                          exc_info=True)
                QMessageBox.about(
                    self, _('Error'),
                    _('Unable to download subtitle "{subtitle}"').format(
                        subtitle=selected_subtitle.get_filename()))
                callback.finish()
                return
            callback.finish()
            write_stream(subtitle_stream, subtitle_file_path)

        video = selected_subtitle.get_parent().get_parent().get_parent()

        def windows_escape(text):
            return '"{text}"'.format(text=text.replace('"', '\\"'))

        params = [windows_escape(programPath)]

        for param in parameters.split(' '):
            param = param.format(video.get_filepath(), subtitle_file_path)
            if platform.system() in ('Windows', 'Microsoft'):
                param = windows_escape(param)
            params.append(param)

        pid = None
        log.info('Running this command: {params}'.format(params=params))
        try:
            log.debug('Trying os.spawnvpe ...')
            pid = os.spawnvpe(os.P_NOWAIT, programPath, params, os.environ)
            log.debug('... SUCCESS. pid={pid}'.format(pid=pid))
        except AttributeError:
            log.debug('... FAILED', exc_info=True)
        except Exception as e:
            log.debug('... FAILED', exc_info=True)
        if pid is None:
            try:
                log.debug('Trying os.fork ...')
                pid = os.fork()
                if not pid:
                    log.debug('... SUCCESS. pid={pid}'.format(pid=pid))
                    os.execvpe(os.P_NOWAIT, programPath, params, os.environ)
            except:
                log.debug('... FAIL', exc_info=True)
        if pid is None:
            QMessageBox.about(self, _('Error'),
                              _('Unable to launch videoplayer'))

    @pyqtSlot(QModelIndex)
    def onClickVideoTreeView(self, index):
        data_item = self.videoModel.getSelectedItem(index)

        if isinstance(data_item, SubtitleFile):
            self.ui.buttonPlay.setEnabled(True)
        else:
            self.ui.buttonPlay.setEnabled(False)

        if isinstance(data_item, VideoFile):
            video = data_item
            if True:  # video.getMovieInfo():
                self.ui.buttonIMDB.setEnabled(True)
                self.ui.buttonIMDB.setIcon(QIcon(':/images/info.png'))
                self.ui.buttonIMDB.setText(_('Movie Info'))
        elif isinstance(data_item, RemoteSubtitleFile):
            self.ui.buttonIMDB.setEnabled(True)
            self.ui.buttonIMDB.setIcon(
                QIcon(':/images/sites/opensubtitles.png'))
            self.ui.buttonIMDB.setText(_('Subtitle Info'))
        else:
            self.ui.buttonIMDB.setEnabled(False)

    def onContext(self, point):
        # FIXME: code duplication with Main.onContext and/or SearchNameWidget and/or SearchFileWidget
        menu = QMenu('Menu', self)

        listview = self.ui.videoView

        index = listview.currentIndex()
        data_item = listview.model().getSelectedItem(index)
        if data_item is not None:
            if isinstance(data_item, VideoFile):
                video = data_item
                movie_info = video.getMovieInfo()
                if movie_info:
                    subWebsiteAction = QAction(QIcon(":/images/info.png"),
                                               _("View IMDB info"), self)
                    subWebsiteAction.triggered.connect(self.onViewOnlineInfo)
                else:
                    subWebsiteAction = QAction(QIcon(":/images/info.png"),
                                               _("Set IMDB info..."), self)
                    subWebsiteAction.triggered.connect(self.onSetIMDBInfo)
                menu.addAction(subWebsiteAction)
            elif isinstance(data_item, SubtitleFile):
                downloadAction = QAction(QIcon(":/images/download.png"),
                                         _("Download"), self)
                # Video tab, TODO:Replace me with a enum

                downloadAction.triggered.connect(self.onButtonDownload)
                playAction = QAction(QIcon(":/images/play.png"),
                                     _("Play video + subtitle"), self)
                playAction.triggered.connect(self.onButtonPlay)
                menu.addAction(playAction)

                subWebsiteAction = QAction(
                    QIcon(":/images/sites/opensubtitles.png"),
                    _("View online info"), self)

                menu.addAction(downloadAction)
                subWebsiteAction.triggered.connect(self.onViewOnlineInfo)
                menu.addAction(subWebsiteAction)
            elif isinstance(data_item, Movie):
                subWebsiteAction = QAction(QIcon(":/images/info.png"),
                                           _("View IMDB info"), self)
                subWebsiteAction.triggered.connect(self.onViewOnlineInfo)
                menu.addAction(subWebsiteAction)

        # Show the context menu.
        menu.exec_(listview.mapToGlobal(point))

    def onButtonDownload(self):
        # We download the subtitle in the same folder than the video
        subs = self.videoModel.get_checked_subtitles()
        replace_all = False
        skip_all = False
        if not subs:
            QMessageBox.about(self, _("Error"),
                              _("No subtitles selected to be downloaded"))
            return
        total_subs = len(subs)
        answer = None
        success_downloaded = 0

        # FIXME: must pass mainwindow as argument to ProgressCallbackWidget
        callback = ProgressCallbackWidget(self)
        callback.set_title_text(_("Downloading..."))
        callback.set_label_text(_("Downloading files..."))
        callback.set_updated_text(_("Downloading subtitle {0} ({1}/{2})"))
        callback.set_finished_text(
            _("{0} from {1} subtitles downloaded successfully"))
        callback.set_block(True)
        callback.set_range(0, total_subs)

        callback.show()

        for i, sub in enumerate(subs):
            if callback.canceled():
                break
            destinationPath = self.get_state().getDownloadPath(self, sub)
            if not destinationPath:
                break
            log.debug("Trying to download subtitle '%s'" % destinationPath)
            callback.update(i,
                            QFileInfo(destinationPath).fileName(), i + 1,
                            total_subs)

            # Check if we have write permissions, otherwise show warning window
            while True:
                # If the file and the folder don't have write access.
                if not QFileInfo(
                        destinationPath).isWritable() and not QFileInfo(
                            QFileInfo(destinationPath).absoluteDir().path()
                        ).isWritable():
                    warningBox = QMessageBox(
                        _("Error write permission"),
                        _("%s cannot be saved.\nCheck that the folder exists and you have write-access permissions."
                          ) % destinationPath, QMessageBox.Warning,
                        QMessageBox.Retry | QMessageBox.Default,
                        QMessageBox.Discard | QMessageBox.Escape,
                        QMessageBox.NoButton, self)

                    saveAsButton = warningBox.addButton(
                        _("Save as..."), QMessageBox.ActionRole)
                    answer = warningBox.exec_()
                    if answer == QMessageBox.Retry:
                        continue
                    elif answer == QMessageBox.Discard:
                        break  # Let's get out from the While true
                    # If we choose the SAVE AS
                    elif answer == QMessageBox.NoButton:
                        fileName, t = QFileDialog.getSaveFileName(
                            self, _("Save subtitle as..."), destinationPath,
                            'All (*.*)')
                        if fileName:
                            destinationPath = fileName
                else:  # If we have write access we leave the while loop.
                    break

            # If we have chosen Discard subtitle button.
            if answer == QMessageBox.Discard:
                continue  # Continue the next subtitle

            optionWhereToDownload = QSettings().value(
                "options/whereToDownload", "SAME_FOLDER")
            # Check if doesn't exists already, otherwise show fileExistsBox
            # dialog
            if QFileInfo(destinationPath).exists(
            ) and not replace_all and not skip_all and optionWhereToDownload != "ASK_FOLDER":
                # The "remote filename" below is actually not the real filename. Real name could be confusing
                # since we always rename downloaded sub to match movie
                # filename.
                fileExistsBox = QMessageBox(
                    QMessageBox.Warning, _("File already exists"),
                    _("Local: {local}\n\nRemote: {remote}\n\nHow would you like to proceed?"
                      ).format(local=destinationPath,
                               remote=QFileInfo(destinationPath).fileName()),
                    QMessageBox.NoButton, self)
                skipButton = fileExistsBox.addButton(_("Skip"),
                                                     QMessageBox.ActionRole)
                #                    skipAllButton = fileExistsBox.addButton(_("Skip all"), QMessageBox.ActionRole)
                replaceButton = fileExistsBox.addButton(
                    _("Replace"), QMessageBox.ActionRole)
                replaceAllButton = fileExistsBox.addButton(
                    _("Replace all"), QMessageBox.ActionRole)
                saveAsButton = fileExistsBox.addButton(_("Save as..."),
                                                       QMessageBox.ActionRole)
                cancelButton = fileExistsBox.addButton(_("Cancel"),
                                                       QMessageBox.ActionRole)
                fileExistsBox.exec_()
                answer = fileExistsBox.clickedButton()
                if answer == replaceAllButton:
                    # Don't ask us again (for this batch of files)
                    replace_all = True
                elif answer == saveAsButton:
                    # We will find a uniqiue filename and suggest this to user.
                    # add .<lang> to (inside) the filename. If that is not enough, start adding numbers.
                    # There should also be a preferences setting "Autorename
                    # files" or similar ( =never ask) FIXME
                    suggBaseName, suggFileExt = os.path.splitext(
                        destinationPath)
                    fNameCtr = 0  # Counter used to generate a unique filename
                    suggestedFileName = suggBaseName + '.' + \
                        sub.get_language().xxx() + suggFileExt
                    while (os.path.exists(suggestedFileName)):
                        fNameCtr += 1
                        suggestedFileName = suggBaseName + '.' + \
                            sub.get_language().xxx() + '-' + \
                            str(fNameCtr) + suggFileExt
                    fileName, t = QFileDialog.getSaveFileName(
                        None, _("Save subtitle as..."), suggestedFileName,
                        'All (*.*)')
                    if fileName:
                        destinationPath = fileName
                    else:
                        # Skip this particular file if no filename chosen
                        continue
                elif answer == skipButton:
                    continue  # Skip this particular file
#                    elif answer == skipAllButton:
#                        count += percentage
#                        skip_all = True # Skip all files already downloaded
#                        continue
                elif answer == cancelButton:
                    break  # Break out of DL loop - cancel was pushed
            QCoreApplication.processEvents()
            # FIXME: redundant update?
            callback.update(i,
                            QFileInfo(destinationPath).fileName(), i + 1,
                            total_subs)
            try:
                if not skip_all:
                    log.debug("Downloading subtitle '%s'" % destinationPath)
                    download_callback = ProgressCallback()  # FIXME
                    data_stream = sub.download(
                        provider_instance=self.get_state().get_OSDBServer(),
                        callback=download_callback,
                    )
                    write_stream(data_stream, destinationPath)
            except Exception as e:
                log.exception('Unable to Download subtitle {}'.format(
                    sub.get_filename()))
                QMessageBox.about(
                    self, _("Error"),
                    _("Unable to download subtitle %s") % sub.get_filename())
        callback.finish(success_downloaded, total_subs)

    def onViewOnlineInfo(self):
        # FIXME: code duplication with Main.onContext and/or SearchNameWidget and/or SearchFileWidget
        # Tab for SearchByHash TODO:replace this 0 by an ENUM value
        listview = self.ui.videoView
        index = listview.currentIndex()
        data_item = self.videoModel.getSelectedItem(index)

        if isinstance(data_item, VideoFile):
            video = data_item
            movie_info = video.getMovieInfo()
            if movie_info:
                imdb = movie_info["IDMovieImdb"]
                if imdb:
                    webbrowser.open("http://www.imdb.com/title/tt%s" % imdb,
                                    new=2,
                                    autoraise=1)

        elif isinstance(data_item, RemoteSubtitleFile):
            sub = data_item
            webbrowser.open(sub.get_link(), new=2, autoraise=1)

        elif isinstance(data_item, Movie):
            movie = data_item
            imdb = movie.IMDBId
            if imdb:
                webbrowser.open("http://www.imdb.com/title/tt%s" % imdb,
                                new=2,
                                autoraise=1)

    @pyqtSlot()
    def onSetIMDBInfo(self):
        #FIXME: DUPLICATED WITH SEARCHNAMEWIDGET
        QMessageBox.about(self, _("Info"), "Not implemented yet. Sorry...")
Exemplo n.º 5
0
class SearchFileWidget(QWidget):

    language_filter_change = pyqtSignal(list)

    def __init__(self):
        QWidget.__init__(self)

        self._refreshing = False

        self.fileModel = None
        self.proxyFileModel = None
        self.videoModel = None

        self._state = None

        self.timeLastSearch = QTime.currentTime()

        self.ui = Ui_SearchFileWidget()
        self.setup_ui()
        QTimer.singleShot(0, self.on_event_loop_started)

    @pyqtSlot()
    def on_event_loop_started(self):
        lastDir = self._state.get_video_path()
        index = self.fileModel.index(str(lastDir))
        proxyIndex = self.proxyFileModel.mapFromSource(index)
        self.ui.folderView.scrollTo(proxyIndex)

    def set_state(self, state):
        self._state = state
        self._state.signals.interface_language_changed.connect(
            self.on_interface_language_changed)
        self._state.signals.login_status_changed.connect(
            self.on_login_state_changed)

    def setup_ui(self):
        self.ui.setupUi(self)

        self.ui.splitter.setSizes([600, 1000])
        self.ui.splitter.setChildrenCollapsible(False)

        # Set up folder view

        self.fileModel = QFileSystemModel(self)
        self.fileModel.setFilter(QDir.AllDirs | QDir.Dirs | QDir.Drives
                                 | QDir.NoDotAndDotDot | QDir.Readable
                                 | QDir.Executable | QDir.Writable)
        self.fileModel.iconProvider().setOptions(
            QFileIconProvider.DontUseCustomDirectoryIcons)
        self.fileModel.setRootPath(QDir.rootPath())
        self.fileModel.directoryLoaded.connect(self.onFileModelDirectoryLoaded)

        self.proxyFileModel = QSortFilterProxyModel(self)
        self.proxyFileModel.setSortRole(Qt.DisplayRole)
        self.proxyFileModel.setSourceModel(self.fileModel)
        self.proxyFileModel.sort(0, Qt.AscendingOrder)
        self.proxyFileModel.setSortCaseSensitivity(Qt.CaseInsensitive)
        self.ui.folderView.setModel(self.proxyFileModel)

        self.ui.folderView.setHeaderHidden(True)
        self.ui.folderView.hideColumn(3)
        self.ui.folderView.hideColumn(2)
        self.ui.folderView.hideColumn(1)

        self.ui.folderView.expanded.connect(self.onFolderViewExpanded)
        self.ui.folderView.clicked.connect(self.onFolderTreeClicked)
        self.ui.buttonFind.clicked.connect(self.onButtonFind)
        self.ui.buttonRefresh.clicked.connect(self.onButtonRefresh)

        # Setup and disable buttons
        self.ui.buttonFind.setEnabled(False)
        self.ui.buttonSearchSelectFolder.setEnabled(False)
        self.ui.buttonSearchSelectVideos.setEnabled(False)

        # Set up introduction
        self.showInstructions()

        # Set unknown  text here instead of `retranslate()` because widget translates itself
        self.ui.filterLanguageForVideo.set_unknown_text(_('All languages'))
        self.ui.filterLanguageForVideo.set_selected_language(
            UnknownLanguage.create_generic())
        self.ui.filterLanguageForVideo.selected_language_changed.connect(
            self.on_language_combobox_filter_change)

        # Set up video view
        self.videoModel = VideoModel(self)
        self.videoModel.connect_treeview(self.ui.videoView)
        self.ui.videoView.setHeaderHidden(True)
        self.ui.videoView.clicked.connect(self.onClickVideoTreeView)
        self.ui.videoView.selectionModel().currentChanged.connect(
            self.onSelectVideoTreeView)
        self.ui.videoView.customContextMenuRequested.connect(self.onContext)
        self.ui.videoView.setUniformRowHeights(True)
        self.videoModel.dataChanged.connect(self.subtitlesCheckedChanged)
        self.language_filter_change.connect(
            self.videoModel.on_filter_languages_change)

        self.ui.buttonSearchSelectVideos.clicked.connect(
            self.onButtonSearchSelectVideos)
        self.ui.buttonSearchSelectFolder.clicked.connect(
            self.onButtonSearchSelectFolder)
        self.ui.buttonDownload.clicked.connect(self.onButtonDownload)
        self.ui.buttonPlay.clicked.connect(self.onButtonPlay)
        self.ui.buttonIMDB.clicked.connect(self.onViewOnlineInfo)
        self.ui.videoView.setContextMenuPolicy(Qt.CustomContextMenu)

        self.ui.buttonPlay.setEnabled(False)

        # Drag and Drop files to the videoView enabled
        # FIXME: enable drag events for videoView (and instructions view)
        self.ui.videoView.__class__.dragEnterEvent = self.dragEnterEvent
        self.ui.videoView.__class__.dragMoveEvent = self.dragEnterEvent
        self.ui.videoView.__class__.dropEvent = self.dropEvent
        self.ui.videoView.setAcceptDrops(1)

        self.retranslate()

    def retranslate(self):
        introduction = '<p align="center"><h2>{title}</h2></p>' \
            '<p><b>{tab1header}</b><br/>{tab1content}</p>' \
            '<p><b>{tab2header}</b><br/>{tab2content}</p>'\
            '<p><b>{tab3header}</b><br/>{tab3content}</p>'.format(
                title=_('How To Use {title}').format(title=PROJECT_TITLE),
                tab1header=_('1st Tab:'),
                tab2header=_('2nd Tab:'),
                tab3header=_('3rd Tab:'),
                tab1content=_('Select, from the Folder Tree on the left, the folder which contains the videos '
                              'that need subtitles. {project} will then try to automatically find available '
                              'subtitles.').format(project=PROJECT_TITLE),
                tab2content=_('If you don\'t have the videos in your machine, you can search subtitles by '
                              'introducing the title/name of the video.').format(project=PROJECT_TITLE),
                tab3content=_('If you have found some subtitle somewhere else that is not in {project}\'s database, '
                              'please upload those subtitles so next users will be able to '
                              'find them more easily.').format(project=PROJECT_TITLE))
        self.ui.introductionHelp.setHtml(introduction)

    @pyqtSlot(Language)
    def on_interface_language_changed(self, language):
        self.ui.retranslateUi(self)
        self.retranslate()

    @pyqtSlot(str)
    def onFileModelDirectoryLoaded(self, path):
        lastDir = str(self._state.get_video_path())
        qDirLastDir = QDir(lastDir)
        qDirLastDir.cdUp()
        if qDirLastDir.path() == path:
            index = self.fileModel.index(lastDir)
            proxyIndex = self.proxyFileModel.mapFromSource(index)
            self.ui.folderView.scrollTo(proxyIndex)
            self.ui.folderView.setCurrentIndex(proxyIndex)

    @pyqtSlot()
    def on_login_state_changed(self):
        log.debug('on_login_state_changed()')
        nb_connected = self._state.providers.get_number_connected_providers()
        if nb_connected:
            self.ui.buttonSearchSelectFolder.setEnabled(True)
            self.ui.buttonSearchSelectVideos.setEnabled(True)
            self.ui.buttonFind.setEnabled(
                self.get_current_selected_folder() is not None)
        else:
            self.ui.buttonSearchSelectFolder.setEnabled(False)
            self.ui.buttonSearchSelectVideos.setEnabled(False)
            self.ui.buttonFind.setEnabled(False)

    @pyqtSlot(Language)
    def on_language_combobox_filter_change(self, language):
        if language.is_generic():
            self.language_filter_change.emit(
                self._state.get_download_languages())
        else:
            self.language_filter_change.emit([language])

    def on_permanent_language_filter_change(self, languages):
        selected_language = self.ui.filterLanguageForVideo.get_selected_language(
        )
        if selected_language.is_generic():
            self.language_filter_change.emit(languages)

    @pyqtSlot()
    def subtitlesCheckedChanged(self):
        subs = self.videoModel.get_checked_subtitles()
        if subs:
            self.ui.buttonDownload.setEnabled(True)
        else:
            self.ui.buttonDownload.setEnabled(False)

    def showInstructions(self):
        self.ui.stackedSearchResult.setCurrentWidget(self.ui.pageIntroduction)

    def hideInstructions(self):
        self.ui.stackedSearchResult.setCurrentWidget(self.ui.pageSearchResult)

    @pyqtSlot(QModelIndex)
    def onFolderTreeClicked(self, proxyIndex):
        """What to do when a Folder in the tree is clicked"""
        if not proxyIndex.isValid():
            return

        index = self.proxyFileModel.mapToSource(proxyIndex)
        folder_path = self.fileModel.filePath(index)
        self._state.set_video_paths([folder_path])

    def get_current_selected_folder(self):
        proxyIndex = self.ui.folderView.currentIndex()
        index = self.proxyFileModel.mapToSource(proxyIndex)
        folder_path = Path(self.fileModel.filePath(index))
        if not folder_path:
            return None
        return folder_path

    def get_current_selected_item_videomodel(self):
        current_index = self.ui.videoView.currentIndex()
        return self.videoModel.getSelectedItem(current_index)

    @pyqtSlot()
    def onButtonFind(self):
        now = QTime.currentTime()
        if now < self.timeLastSearch.addMSecs(500):
            return
        folder_path = self.get_current_selected_folder()

        self._state.set_video_paths([folder_path])
        self.search_videos([folder_path])

        self.timeLastSearch = QTime.currentTime()

    @pyqtSlot()
    def onButtonRefresh(self):
        currentPath = self.get_current_selected_folder()
        self._refreshing = True

        self.ui.folderView.collapseAll()

        currentPath = self.get_current_selected_folder()
        if not currentPath:
            self._state.set_video_paths([currentPath])

        index = self.fileModel.index(str(currentPath))

        self.ui.folderView.scrollTo(self.proxyFileModel.mapFromSource(index))

    @pyqtSlot(QModelIndex)
    def onFolderViewExpanded(self, proxyIndex):
        if self._refreshing:
            expandedPath = self.fileModel.filePath(
                self.proxyFileModel.mapToSource(proxyIndex))
            if expandedPath == QDir.rootPath():
                currentPath = self.get_current_selected_folder()
                if not currentPath:
                    currentPath = self._state.get_video_path()

                index = self.fileModel.index(str(currentPath))

                self.ui.folderView.scrollTo(
                    self.proxyFileModel.mapFromSource(index))
                self._refreshing = False

    @pyqtSlot()
    def onButtonSearchSelectFolder(self):
        paths = self._state.get_video_paths()
        path = paths[0] if paths else Path()
        selected_path = QFileDialog.getExistingDirectory(
            self, _('Select the directory that contains your videos'),
            str(path))
        if selected_path:
            selected_paths = [Path(selected_path)]
            self._state.set_video_paths(selected_paths)
            self.search_videos(selected_paths)

    @pyqtSlot()
    def onButtonSearchSelectVideos(self):
        paths = self._state.get_video_paths()
        path = paths[0] if paths else Path()
        selected_files, t = QFileDialog.getOpenFileNames(
            self, _('Select the video(s) that need subtitles'), str(path),
            get_select_videos())
        if selected_files:
            selected_files = list(Path(f) for f in selected_files)
            selected_dirs = list(set(p.parent for p in selected_files))
            self._state.set_video_paths(selected_dirs)
            self.search_videos(selected_files)

    def search_videos(self, paths):
        if not self._state.providers.get_number_connected_providers():
            QMessageBox.about(
                self, _('Error'),
                _('You are not connected to a server. Please connect first.'))
            return
        self.ui.buttonFind.setEnabled(False)
        self._search_videos_raw(paths)
        self.ui.buttonFind.setEnabled(True)

    def _search_videos_raw(self, paths):
        # FIXME: must pass mainwindow as argument to ProgressCallbackWidget
        callback = ProgressCallbackWidget(self)
        callback.set_title_text(_('Scanning...'))
        callback.set_label_text(_('Scanning files'))
        callback.set_finished_text(_('Scanning finished'))
        callback.set_block(True)
        callback.show()

        try:
            local_videos, local_subs = scan_videopaths(paths,
                                                       callback=callback,
                                                       recursive=True)
        except OSError:
            callback.cancel()
            QMessageBox.warning(self, _('Error'),
                                _('Some directories are not accessible.'))

        if callback.canceled():
            return

        callback.finish()

        log.debug('Videos found: {}'.format(local_videos))
        log.debug('Subtitles found: {}'.format(local_subs))

        self.hideInstructions()

        if not local_videos:
            QMessageBox.information(self, _('Scan Results'),
                                    _('No video has been found.'))
            return

        total = len(local_videos)

        # FIXME: must pass mainwindow as argument to ProgressCallbackWidget
        # callback = ProgressCallbackWidget(self)
        # callback.set_title_text(_('Asking Server...'))
        # callback.set_label_text(_('Searching subtitles...'))
        # callback.set_updated_text(_('Searching subtitles ( %d / %d )'))
        # callback.set_finished_text(_('Search finished'))
        callback.set_block(True)
        callback.set_range(0, total)

        callback.show()

        try:
            remote_subs = self._state.search_videos(local_videos, callback)
        except ProviderConnectionError:
            log.debug(
                'Unable to search for subtitles of videos: videos={}'.format(
                    list(v.get_filename() for v in local_videos)))
            QMessageBox.about(self, _('Error'),
                              _('Unable to search for subtitles'))
            callback.finish()
            return

        self.videoModel.set_videos(local_videos)

        if remote_subs is None:
            QMessageBox.about(
                self, _('Error'),
                _('Error contacting the server. Please try again later'))
        callback.finish()

        # TODO: CHECK if our local subtitles are already in the server, otherwise suggest to upload

    @pyqtSlot()
    def onButtonPlay(self):
        selected_item = self.get_current_selected_item_videomodel()
        log.debug('Trying to play selected item: {}'.format(selected_item))

        if selected_item is None:
            QMessageBox.warning(self, _('No subtitle selected'),
                                _('Select a subtitle and try again'))
            return

        if isinstance(selected_item, SubtitleFileNetwork):
            selected_item = selected_item.get_subtitles()[0]

        if isinstance(selected_item, VideoFile):
            subtitle_file_path = None
            video = selected_item
        elif isinstance(selected_item, LocalSubtitleFile):
            subtitle_file_path = selected_item.get_filepath()
            video = selected_item.get_super_parent(VideoFile)
        elif isinstance(selected_item, RemoteSubtitleFile):
            video = selected_item.get_super_parent(VideoFile)
            subtitle_file_path = Path(
                tempfile.gettempdir()) / 'subdownloader.tmp.srt'
            log.debug('tmp path is {}'.format(subtitle_file_path))
            log.debug(
                'Temporary subtitle will be downloaded into: {temp_path}'.
                format(temp_path=subtitle_file_path))
            # FIXME: must pass mainwindow as argument to ProgressCallbackWidget
            callback = ProgressCallbackWidget(self)
            callback.set_title_text(_('Playing video + sub'))
            callback.set_label_text(_('Downloading files...'))
            callback.set_finished_text(_('Downloading finished'))
            callback.set_block(True)
            callback.set_range(0, 100)
            callback.show()

            try:
                selected_item.download(
                    subtitle_file_path,
                    self._state.providers.get(selected_item.get_provider),
                    callback)
            except ProviderConnectionError:
                log.debug('Unable to download subtitle "{}"'.format(
                    selected_item.get_filename()),
                          exc_info=sys.exc_info())
                QMessageBox.about(
                    self, _('Error'),
                    _('Unable to download subtitle "{subtitle}"').format(
                        subtitle=selected_item.get_filename()))
                callback.finish()
                return
            callback.finish()
        else:
            QMessageBox.about(
                self, _('Error'),
                '{}\n{}'.format(_('Unknown Error'),
                                _('Please submit bug report')))
            return

        # video = selected_item.get_parent().get_parent().get_parent()
        # FIXME: download subtitle with provider + use returned localSubtitleFile instead of creating one here
        if subtitle_file_path:
            local_subtitle = LocalSubtitleFile(subtitle_file_path)
        else:
            local_subtitle = None
        try:
            player = self._state.get_videoplayer()
            player.play_video(video, local_subtitle)
        except RuntimeError as e:
            QMessageBox.about(self, _('Error'), e.args[0])

    @pyqtSlot(QModelIndex)
    def onClickVideoTreeView(self, index):
        data_item = self.videoModel.getSelectedItem(index)

        if isinstance(data_item, VideoFile):
            video = data_item
            if True:  # video.getMovieInfo():
                self.ui.buttonIMDB.setEnabled(True)
                self.ui.buttonIMDB.setIcon(QIcon(':/images/info.png'))
                self.ui.buttonIMDB.setText(_('Movie Info'))
        elif isinstance(data_item, RemoteSubtitleFile):
            self.ui.buttonIMDB.setEnabled(True)
            self.ui.buttonIMDB.setIcon(
                QIcon(':/images/sites/opensubtitles.png'))
            self.ui.buttonIMDB.setText(_('Subtitle Info'))
        else:
            self.ui.buttonIMDB.setEnabled(False)

    @pyqtSlot(QModelIndex)
    def onSelectVideoTreeView(self, index):
        data_item = self.videoModel.getSelectedItem(index)

        self.ui.buttonPlay.setEnabled(True)
        # if isinstance(data_item, SubtitleFile):
        #     self.ui.buttonPlay.setEnabled(True)
        # else:
        #     self.ui.buttonPlay.setEnabled(False)

    def onContext(self, point):
        # FIXME: code duplication with Main.onContext and/or SearchNameWidget and/or SearchFileWidget
        menu = QMenu('Menu', self)

        listview = self.ui.videoView

        index = listview.currentIndex()
        data_item = listview.model().getSelectedItem(index)
        if data_item is not None:
            if isinstance(data_item, VideoFile):
                video = data_item
                video_identities = video.get_identities()
                if any(video_identities.iter_imdb_identity()):
                    online_action = QAction(QIcon(":/images/info.png"),
                                            _("View IMDb info"), self)
                    online_action.triggered.connect(self.onViewOnlineInfo)
                else:
                    online_action = QAction(QIcon(":/images/info.png"),
                                            _("Set IMDb info..."), self)
                    online_action.triggered.connect(self.on_set_imdb_info)
                menu.addAction(online_action)
            elif isinstance(data_item, SubtitleFile):
                play_action = QAction(QIcon(":/images/play.png"),
                                      _("Play video + subtitle"), self)
                play_action.triggered.connect(self.onButtonPlay)
                menu.addAction(play_action)

                if isinstance(data_item, RemoteSubtitleFile):
                    download_action = QAction(QIcon(":/images/download.png"),
                                              _("Download"), self)
                    download_action.triggered.connect(self.onButtonDownload)
                    menu.addAction(download_action)

                    online_action = QAction(
                        QIcon(":/images/sites/opensubtitles.png"),
                        _("View online info"), self)
                    online_action.triggered.connect(self.onViewOnlineInfo)
                    menu.addAction(online_action)

        # Show the context menu.
        menu.exec_(listview.mapToGlobal(point))

    def _create_choose_target_subtitle_path_cb(self):
        def callback(path, filename):
            selected_path = QFileDialog.getSaveFileName(
                self, _('Choose the target filename'), str(path / filename))
            return selected_path

        return callback

    def onButtonDownload(self):
        # We download the subtitle in the same folder than the video
        rsubs = self.videoModel.get_checked_subtitles()

        sub_downloader = SubtitleDownloadProcess(parent=self.parent(),
                                                 rsubtitles=rsubs,
                                                 state=self._state,
                                                 parent_add=True)
        sub_downloader.download_all()
        new_subs = sub_downloader.downloaded_subtitles()
        self.videoModel.uncheck_subtitles(new_subs)

    def onViewOnlineInfo(self):
        # FIXME: code duplication with Main.onContext and/or SearchNameWidget and/or SearchFileWidget
        # Tab for SearchByHash TODO:replace this 0 by an ENUM value
        listview = self.ui.videoView
        index = listview.currentIndex()
        data_item = self.videoModel.getSelectedItem(index)

        if isinstance(data_item, VideoFile):
            video = data_item
            video_identities = video.get_identities()
            if any(video_identities.iter_imdb_identity()):
                imdb_identity = next(video_identities.iter_imdb_identity())
                webbrowser.open(imdb_identity.get_imdb_url(),
                                new=2,
                                autoraise=1)
            else:
                QMessageBox.information(self.parent(), _('imdb unknown'),
                                        _('imdb is unknown'))

        elif isinstance(data_item, RemoteSubtitleFile):
            sub = data_item
            webbrowser.open(sub.get_link(), new=2, autoraise=1)

    @pyqtSlot()
    def on_set_imdb_info(self):
        # FIXME: DUPLICATED WITH SEARCHNAMEWIDGET
        QMessageBox.about(self, _("Info"), "Not implemented yet. Sorry...")