def get_language(self): result_lang = UnknownLanguage.create_generic() for subtitle in self._subtitles: lang = subtitle.get_language() if isinstance(result_lang, UnknownLanguage): result_lang = lang elif isinstance(lang, UnknownLanguage): pass if result_lang != lang: return UnknownLanguage.create_generic() return result_lang
def setup_ui(self): self.ui.setupUi(self) self.ui.buttonSearchByName.clicked.connect(self.onButtonSearchByTitle) self.ui.movieNameText.returnPressed.connect(self.onButtonSearchByTitle) self.ui.buttonDownloadByTitle.clicked.connect(self.onButtonDownloadByTitle) self.ui.buttonIMDBByTitle.clicked.connect(self.onViewOnlineInfo) self.ui.buttonIMDBByTitle.setEnabled(False) self.moviesModel = VideoTreeModel(self) self.moviesModel.connect_treeview(self.ui.moviesView) self.moviesModel.node_clicked.connect(self.on_item_clicked) self.moviesModel.dataChanged.connect(self.subtitlesMovieCheckedChanged) # FIXME: load settings from general place upload_language = Language.from_xxx( QSettings().value('options/uploadLanguage', UnknownLanguage.create_generic())) self.ui.filterLanguage.selected_language_changed.connect(self.on_language_combobox_filter_change) self.language_filter_change.connect(self.moviesModel.on_filter_languages_change) self.ui.moviesView.setContextMenuPolicy(Qt.CustomContextMenu) self.ui.moviesView.customContextMenuRequested.connect(self.onContext) self.retranslate()
def get_system_language(): locale = i18n_system_locale() for lc_fallback in i18n_locale_fallbacks_calculate(locale): try: language = Language.from_unknown(lc_fallback, locale=True) return language except NotALanguageException: continue return UnknownLanguage.create_generic()
def __init__(self, parent=None): QComboBox.__init__(self, parent) self._model = LanguageModel( unknown_text=UnknownLanguage.create_generic().name(), unknown_visible=True, legal_languages=self.legal_languages()) self._current_language = None self.setup_ui()
def do_upload_filescan(self, arg): if arg: self.echo(_('Unknown arguments: {}').format(arg)) return self._upload_movie = LocalMovie() callback = self.get_callback() 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(self.state.get_video_paths(), callback, recursive=self.state.get_recursive()) except IllegalPathException as e: callback.finish() self.echo(_('The video path "{}" does not exist').format(e.path())) return callback.finish() local_videos.sort(key=lambda v : v.get_filename()) data = [] nb_subs = 0 langs = dict() for video in local_videos: try: subtitle = next(video.get_subtitles().iter_local_subtitles()) lang = subtitle.detect_language_contents() subtitle.set_language_if_unknown(lang) langs.setdefault(subtitle.get_language(), 0) langs[subtitle.get_language()] += 1 nb_subs += 1 except StopIteration: subtitle = None vid_sub = VideoSubtitle(video, subtitle) data.append(vid_sub) self._upload_movie.set_data(data) unk = UnknownLanguage.create_generic() if unk in langs: del langs[unk] if len(langs) == 1: lang = tuple(langs.keys())[0] else: lang = unk if self._upload_movie.get_language().is_generic(): self._upload_movie.set_language(lang) self.set_videos(local_videos) self.echo(_('{}/{} videos/subtitles have been found').format(len(data), nb_subs))
def __init__(self, parent, state): QDialog.__init__(self, parent) self._state = state self._uploadLanguage = UnknownLanguage.create_generic() self.ui = Ui_PreferencesDialog() self.setup_ui()
def __init__(self, unknown_text, unknown_visible, legal_languages, parent=None): QAbstractItemModel.__init__(self, parent) self._unknown_text = unknown_text self._unknown_visible = unknown_visible self._languages = [UnknownLanguage.create_generic() ] if unknown_visible else [] self._languages += sorted(legal_languages, key=lambda x: x.name())
def __init__(self, parent, state, settings): QDialog.__init__(self, parent) self._state = state self._settings = settings self._uploadLanguage = UnknownLanguage.create_generic() self.providers_ui = dict() self.ui = Ui_PreferencesDialog() self.setup_ui()
def __init__(self): self._movie_name = None self._imdb_id = None self._language = UnknownLanguage.create_generic() self._release_name = None self._comments = None self._author = None self._hearing_impaired = None self._high_definition = None self._foreign_only = None self._automatic_translation = None self._data = []
def do_upload_set_language(self, arg): args = self.shlex_parse_argstr(arg) if len(args) == 0: self._upload_movie.set_language(UnknownLanguage.create_generic()) return if len(args) != 1: self.echo('Need 1 argument') return try: lang = Language.from_unknown(args[0], xx=True, xxx=True, name=True, locale=True) self.echo(_('Upload language set to {}.').format(lang.name())) self._upload_movie.set_language(lang) except NotALanguageException: self.echo(_('Unknown language')) return
def __init__(self, callback=None): self._providersState = ProvidersState(callback) self._recursive = False self._video_paths = [] self._interface_language = UnknownLanguage.create_generic() self._upload_language = None self._download_languages = [] self._naming_strategy = SubtitleNamingStrategy.VIDEO self._download_path_strategy = SubtitlePathStrategy.SAME self._default_download_path = Path().resolve() self._videoplayer = None self._imdb_history = ImdbHistory()
def onButtonSearchByTitle(self): if not self.ui.movieNameText.text().strip(): QMessageBox.about( self, _("Info"), _("You must enter at least one character in movie name")) else: self.ui.buttonSearchByName.setEnabled(False) callback = ProgressCallbackWidget(self) callback.set_title_text(_('Search')) callback.set_label_text(_("Searching...")) callback.set_block(True) callback.show() callback.update(0) self.moviesModel.clearTree() # This was a solution found to refresh the treeView self.ui.moviesView.expandAll() s = SearchByName() selected_language = self.ui.filterLanguage.get_selected_language() selected_language_xxx = None if selected_language.is_generic( ) else selected_language.xxx() search_text = self.ui.movieNameText.text() # This should be in a thread to be able to Cancel movies = s.search_movie( languages=[UnknownLanguage.create_generic()], moviename=search_text) if movies is None: QMessageBox.about( self, _("Info"), _("The server is momentarily unavailable. Please try later." )) callback.finish() self.ui.buttonSearchByName.setEnabled(True) return self.moviesModel.setMovies(movies, selected_language_xxx) if len(movies) == 1: self.ui.moviesView.expandAll() else: self.ui.moviesView.collapseAll() callback.finish() self.ui.buttonSearchByName.setEnabled(True)
def detect_language_filename(cls, filename): """ Detect the language of a subtitle filename :param filename: filename of a subtitle :return: Language object, None if language could not be detected. """ log.debug('detect_language(filename="{}") ...'.format(filename)) root, _ = os.path.splitext(filename) fn_lang = cls.DETECT_LANGUAGE_REGEX.findall(root) if fn_lang: language_part = fn_lang[0] try: lang = Language.from_unknown(language_part, xx=True, xxx=True) log.debug('... SUCCESS: detected from filename: {lang}'.format( lang=lang)) return lang except NotALanguageException: pass else: log.debug('... FAIL: could not detect from filename') return UnknownLanguage.create_generic()
def get_default_argument_settings(video_path, client): return ArgumentSettings( program=ArgumentProgramSettings( log=ArgumentLogSettings( path=None, level=logging.ERROR, ), settings=ArgumentSettingsSettings(path=None, ), client=client, ), search=ArgumentSearchSettings( recursive=True, working_directory=video_path, ), filter=FilterSettings(languages=[UnknownLanguage.create_generic()], ), download=DownloadSettings( rename_strategy=SubtitleRenameStrategy.ONLINE, ), providers=None, proxy=None, test=False, )
def onExpandMovie(self, index): if index.internalPointer() is None: return movie = index.internalPointer().data if type(movie) == Movie and not movie.subtitles and movie.totalSubs: callback = ProgressCallbackWidget(self) callback.set_title_text(_('Search')) callback.set_label_text(_("Searching...")) callback.set_cancellable(False) callback.set_block(True) callback.show() s = SearchByName() selected_language = self.ui.filterLanguage.get_selected_language() selected_language_xxx = None if selected_language.is_generic( ) else selected_language.xxx() callback.update(0) temp_movie = s.search_movie( languages=[UnknownLanguage.create_generic()], MovieID_link=movie.MovieSiteLink) # The internal results are not filtered by language, so in case we change the filter, we don't need to request again. # print temp_movie try: movie.subtitles = temp_movie[0].subtitles except IndexError: QMessageBox.about( self, _("Info"), _("This is a TV series and it cannot be handled.")) callback.finish() return except AttributeError: # this means only one subtitle was returned movie.subtitles = [temp_movie[1]] # The treeview is filtered by language self.moviesModel.updateMovie(index, selected_language_xxx) self.ui.moviesView.collapse(index) self.ui.moviesView.expand(index) callback.finish()
def setup_ui(self): self.ui.setupUi(self) # 0. Dialog self.ui.buttonApplyChanges.clicked.connect(self.onApplyChanges) self.ui.buttonCancel.clicked.connect(self.onCancel) self.ui.tabsPreferences.setCurrentIndex(0) # 1. Search tab # - Filter languages self._filterLanguageComboBoxes = {} self._search_languages = {lang: False for lang in all_languages()} nb_columns_languages = 4 for lang_i, lang in enumerate(all_languages()): row = lang_i // nb_columns_languages column = lang_i % nb_columns_languages checkBox = QCheckBox(_(lang.generic_name()), self.ui.scrollAreaWidgetSearch) def createSearchLangSlot(lang): @pyqtSlot(bool) def onSearchLangCheckBoxToggled(toggled): self.searchLanguageChanged.emit(lang, toggled) return onSearchLangCheckBoxToggled checkBox.toggled.connect(createSearchLangSlot(lang)) checkBox.setChecked(self._search_languages[lang]) self._filterLanguageComboBoxes[lang] = checkBox self.ui.scrollAreaWidgetLayoutSearch.addWidget( checkBox, row, column) self.searchLanguageChanged.connect(self.onSearchLanguageChanged) fontSearchItem = self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].font() fontSearchItem.setItalic(True) self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].setFont(fontSearchItem) # 2. Download tab # - Download Destination self._dlDestinationType = self.DEFAULT_DLDESTINATIONTYPE def create_dlDestinationTypeChangedSlot(dlDestinationType): @pyqtSlot(bool) def dlDestinationTypeChanged(toggled): if toggled: self.dlDestinationTypeChanged.emit(dlDestinationType) return dlDestinationTypeChanged self.ui.optionDlDestinationAsk.toggled.connect( create_dlDestinationTypeChangedSlot(SubtitlePathStrategy.ASK)) self.ui.optionDlDestinationSame.toggled.connect( create_dlDestinationTypeChangedSlot(SubtitlePathStrategy.SAME)) self.ui.optionDlDestinationUser.toggled.connect( create_dlDestinationTypeChangedSlot( SubtitlePathStrategy.PREDEFINED)) self.dlDestinationTypeChanged.connect(self.onDlDestinationTypeChange) self.ui.optionDlDestinationUser.toggled.connect( self.ui.inputDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.connect( self.ui.buttonDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.emit(False) # Always contains a valid download destination folder self._dlDestinationPredefined = Path() dlDestinationCompleter = QCompleter() dlDestinationCompleter.setModel( QDirModel([], QDir.Dirs | QDir.NoDotAndDotDot, QDir.Name, dlDestinationCompleter)) self.ui.inputDlDestinationUser.setCompleter(dlDestinationCompleter) self.ui.inputDlDestinationUser.editingFinished.connect( self.onInputDlDestinationEditingFinished) self.ui.buttonDlDestinationUser.clicked.connect( self.onButtonDlDestinationClicked) # - Subtitle Filename self._subtitleFilename = self.DEFAULT_DLSUBFN def create_dlSubtitleFileNameChangedSlot(subtitleFilename): @pyqtSlot(bool) def subtitleFileNameChanged(toggled): if toggled: self.subtitleFilenameChanged.emit(subtitleFilename) return subtitleFileNameChanged self.ui.optionSubFnSame.toggled.connect( create_dlSubtitleFileNameChangedSlot(SubtitleNamingStrategy.VIDEO)) self.ui.optionSubFnSameLang.toggled.connect( create_dlSubtitleFileNameChangedSlot( SubtitleNamingStrategy.VIDEO_LANG)) self.ui.optionSubFnSameLangUploader.toggled.connect( create_dlSubtitleFileNameChangedSlot( SubtitleNamingStrategy.VIDEO_LANG_UPLOADER)) self.ui.optionSubFnOnline.toggled.connect( create_dlSubtitleFileNameChangedSlot( SubtitleNamingStrategy.ONLINE)) self.subtitleFilenameChanged.connect(self.onSubtitleFilenameChange) # 3. Upload tab # - Default Subtitle Language self._uploadLanguage = self.DEFAULT_UL_LANG self.ui.optionUlDefaultLanguage.set_unknown_text(_('Auto Detect')) self.ui.optionUlDefaultLanguage.set_selected_language( self._uploadLanguage) self.ui.optionUlDefaultLanguage.selected_language_changed.connect( self.onOptionUlDefaultLanguageChange) # 4. Providers tab for providerState in self._state.providers.all_states: provider = providerState.provider provider_name = provider.get_name() from PyQt5.QtWidgets import QVBoxLayout, QLabel ui_items = { '_enabled': QCheckBox(), '_textDisabled': QLabel( _('This provider is connected and cannot be configured')), } ui_items['_textDisabled'].setVisible( providerState.provider.connected()) ui_items['_textDisabled'].setEnabled(False) providerWidget = QWidget() providerLayout = QVBoxLayout() providerLayout.addWidget(ui_items['_textDisabled']) dataWidget = QWidget() providerLayout.addWidget(dataWidget) providerLayout.addStretch() dataLayout = QFormLayout() dataWidget.setLayout(dataLayout) dataLayout.addRow(_('enabled').capitalize(), ui_items['_enabled']) for key, key_type in provider.get_settings().key_types().items(): if key_type == ProviderSettingsType.String: widget = QLineEdit() elif key_type == ProviderSettingsType.Password: widget = QLineEdit() widget.setEchoMode(QLineEdit.Password) else: # FIXME: generalize this warning about possible warnings? log.error( 'Unknown provider settings type: {}: {} -> {}'.format( provider_name, key, key_type)) QMessageBox.warning( self, _('Unknown provider settings type'), '\n'.join( (_('An unknown settings type has been passed.'), _('Please open an issue')))) continue dataLayout.addRow(key.capitalize(), widget) ui_items[key] = widget providerWidget.setLayout(providerLayout) ui_items['_stack_index'] = self.ui.providerStack.addWidget( providerWidget) self.providers_ui[provider_name] = ui_items self.ui.providerComboBox.set_state(self._state) self.ui.providerComboBox.set_general_visible(False) self.ui.providerComboBox.set_filter_enable(False) self.ui.providerComboBox.selected_provider_state_changed.connect( self.on_selected_provider_state_changed) self.ui.providerComboBox.setCurrentIndex(0) # 5. Others tab # - Interface Language self._original_interface_language = UnknownLanguage.create_generic() self.ui.optionInterfaceLanguage.set_unknown_text(_('System Language')) self.ui.optionUlDefaultLanguage.set_selected_language( self._original_interface_language) # - Video Application Location self.ui.buttonVideoAppLocationChoose.clicked.connect( self.onButtonVideoAppLocationChoose) self.ui.buttonHelpTranslation.clicked.connect(self.onHelpTranslate) self.readSettings()
def search_videos(self, videos, callback, languages=None): log.debug('search_videos(#videos={})'.format(len(videos))) if not self.logged_in(): raise ProviderNotConnectedError() lang_str = self._languages_to_str(languages) window_size = 5 callback.set_range(0, (len(videos) + (window_size - 1)) // window_size) remote_subtitles = [] for window_i, video_window in enumerate( window_iterator(videos, window_size)): callback.update(window_i) if callback.canceled(): break queries = [] hash_video = {} for video in video_window: query = { 'sublanguageid': lang_str, 'moviehash': video.get_osdb_hash(), 'moviebytesize': str(video.get_size()), } queries.append(query) hash_video[video.get_osdb_hash()] = video def run_query(): return self._xmlrpc.SearchSubtitles( self._token, queries, {'limit': self.SEARCH_LIMIT}) result = self._safe_exec(run_query, None) self.check_result(result) if result is None: continue for rsub_raw in result['data']: try: remote_filename = rsub_raw['SubFileName'] remote_file_size = int(rsub_raw['SubSize']) remote_id = rsub_raw['IDSubtitleFile'] remote_md5_hash = rsub_raw['SubHash'] remote_download_link = rsub_raw['SubDownloadLink'] remote_link = rsub_raw['SubtitlesLink'] remote_uploader = rsub_raw['UserNickName'].strip() remote_language_raw = rsub_raw['SubLanguageID'] try: remote_language = Language.from_unknown( remote_language_raw, xx=True, xxx=True) except NotALanguageException: remote_language = UnknownLanguage(remote_language_raw) remote_rating = float(rsub_raw['SubRating']) remote_date = datetime.datetime.strptime( rsub_raw['SubAddDate'], '%Y-%m-%d %H:%M:%S') remote_subtitle = OpenSubtitlesSubtitleFile( filename=remote_filename, file_size=remote_file_size, md5_hash=remote_md5_hash, id_online=remote_id, download_link=remote_download_link, link=remote_link, uploader=remote_uploader, language=remote_language, rating=remote_rating, age=remote_date, ) movie_hash = '{:>016}'.format(rsub_raw['MovieHash']) video = hash_video[movie_hash] imdb_id = rsub_raw['IDMovieImdb'] imdb_identity = ImdbIdentity(imdb_id=imdb_id, imdb_rating=None) identity = ProviderIdentities(imdb_identity=imdb_identity, provider=self) video.add_subtitle(remote_subtitle) video.add_identity(identity) remote_subtitles.append(remote_subtitle) except (KeyError, ValueError): log.exception( 'Error parsing result of SearchSubtitles(...)') log.error('Offending query is: {queries}'.format( queries=queries)) log.error('Offending result is: {remote_sub}'.format( remote_sub=rsub_raw)) callback.finish() return remote_subtitles
def search_videos(self, videos, callback, languages=None): limit = 500 if languages: lang_str = ','.join([language.xxx() for language in languages]) else: lang_str = 'all' window_size = 5 callback.set_range(0, (len(videos) + (window_size - 1)) // window_size) remote_subtitles = [] for window_i, video_window in enumerate(window_iterator(videos, window_size)): callback.update(window_i) if callback.canceled(): break queries = [] hash_video = {} for video in video_window: query = { 'sublanguageid': lang_str, 'moviehash': video.get_osdb_hash(), 'moviebytesize': str(video.get_size()), } queries.append(query) hash_video[video.get_osdb_hash()] = video def run_query(): return self._xmlrpc_server.SearchSubtitles(self._token, queries, {'limit': limit}) result = self._safe_exec(run_query, None) if result is None: return remote_subtitles self.check_result(result) for rsub_raw in result['data']: try: remote_filename = rsub_raw['SubFileName'] remote_file_size = int(rsub_raw['SubSize']) remote_id = rsub_raw['IDSubtitleFile'] remote_md5_hash = rsub_raw['SubHash'] remote_download_link = rsub_raw['SubDownloadLink'] remote_link = rsub_raw['SubtitlesLink'] remote_uploader = rsub_raw['UserNickName'] remote_language_raw = rsub_raw['SubLanguageID'] try: remote_language = Language.from_unknown(remote_language_raw, locale=False, name=False) except NotALanguageException: remote_language = UnknownLanguage(remote_language_raw) remote_rating = float(rsub_raw['SubRating']) remote_subtitle = OpenSubtitles_SubtitleFile( filename=remote_filename, file_size=remote_file_size , md5_hash=remote_md5_hash, id_online=remote_id, download_link=remote_download_link, link=remote_link, uploader=remote_uploader, language=remote_language, rating=remote_rating, ) movie_hash = '{:>016}'.format(rsub_raw['MovieHash']) hash_video[movie_hash].add_subtitle(remote_subtitle) remote_subtitles.append(remote_subtitle) except (KeyError, ValueError): log.exception('Error parsing result of SearchSubtitles(...)') log.error('Offending query is: {queries}'.format(queries=queries)) log.error('Offending result is: {remote_sub}'.format(remote_sub=rsub_raw)) callback.finish() return remote_subtitles
def get_argument_parser(): """ Get a parser that is able to parse program arguments. :return: instance of arparse.ArgumentParser """ parser = argparse.ArgumentParser(description=project.get_description(), epilog=_('Visit us at {website}.').format( website=project.WEBSITE_MAIN)) parser.add_argument('--version', action='version', version='{project} {version}'.format( project=project.PROJECT_TITLE, version=project.PROJECT_VERSION_STR)) parser.add_argument('-T', '--test', dest='test', action='store_true', default=False, help=argparse.SUPPRESS) parser.add_argument('-V', '--video', dest='video_path', default=None, metavar='PATH', nargs=argparse.ONE_OR_MORE, action=PathsAction, help=_('Full path to your video(s).')) parser.add_argument('-s', '--settings', dest='settings_path', type=Path, default=None, metavar='FILE', help=_('Set the settings file.')) parser.add_argument( '-l', '--lang', dest='languages', metavar='LANGUAGE', default=[UnknownLanguage.create_generic()], nargs=argparse.ONE_OR_MORE, action=LanguagesAction, help=_( 'Set the preferred subtitle language(s) for download and upload.')) # interface options interface_group = parser.add_argument_group( _('interface'), _('Change settings of the interface')) guicli = interface_group.add_mutually_exclusive_group() guicli.add_argument( '-g', '--gui', dest='client_type', action='store_const', const=ClientType.GUI, help=_('Run application in GUI mode. This is the default.')) guicli.add_argument('-c', '--cli', dest='client_type', action='store_const', const=ClientType.CLI, help=_('Run application in CLI mode.')) parser.set_defaults(client_type=ClientType.GUI) # logger options loggroup = parser.add_argument_group( _('logging'), _('Change the amount of logging done.')) loglvlex = loggroup.add_mutually_exclusive_group() loglvlex.add_argument( '-d', '--debug', dest='loglevel', action='store_const', const=logging.DEBUG, help=_('Print log messages of debug severity and higher to stderr.')) loglvlex.add_argument( '-w', '--warning', dest='loglevel', action='store_const', const=logging.WARNING, help= _('Print log messages of warning severity and higher to stderr. This is the default.' )) loglvlex.add_argument( '-e', '--error', dest='loglevel', action='store_const', const=logging.ERROR, help=_('Print log messages of error severity and higher to stderr.')) loglvlex.add_argument('-q', '--quiet', dest='loglevel', action='store_const', const=LOGGING_LOGNOTHING, help=_('Don\'t log anything to stderr.')) loggroup.set_defaults(loglevel=logging.WARNING) loggroup.add_argument('--log', dest='logfile', metavar='FILE', type=Path, default=None, help=_('Path name of the log file.')) # cli options cli_group = parser.add_argument_group( _('cli'), _('Change the behavior of the command line interface.')) cli_group.add_argument( '-i', '--interactive', dest='interactive', action='store_true', default=False, help=_('Prompt user when decisions need to be done.')) cli_group.add_argument('-r', '--recursive', dest='recursive', action='store_true', default=False, help=_('Search for subtitles recursively.')) operation_group = cli_group.add_mutually_exclusive_group() operation_group.add_argument( '-D', '--download', dest='operation', action='store_const', const=CliAction.DOWNLOAD, help=_('Download subtitle(s). This is the default.')) operation_group.add_argument('-U', '--upload', dest='operation', action='store_const', const=CliAction.UPLOAD, help=_('Upload subtitle(s).')) # operation_group.add_argument('-L', '--list', dest='operation', action='store_const', const=CliAction.LIST, # help=_('List available subtitle(s) without downloading.')) parser.set_defaults(operation=CliAction.DOWNLOAD) rename_group = cli_group.add_mutually_exclusive_group() rename_group.add_argument( '--rename-online', dest='rename_strategy', action='store_const', const=SubtitleRenameStrategy.ONLINE, help=_( 'Use the on-line subtitle filename as name for the downloaded subtitles. ' 'This is the default.')) rename_group.add_argument( '--rename-video', dest='rename_strategy', action='store_const', const=SubtitleRenameStrategy.VIDEO, help=_( 'Use the local video filename as name for the downloaded subtitle.' )) rename_group.add_argument( '--rename-lang', dest='rename_strategy', action='store_const', const=SubtitleRenameStrategy.VIDEO_LANG, help= _('Use the local video filename + language as name for the downloaded subtitle.' )) rename_group.add_argument( '--rename-uploader', dest='rename_strategy', action='store_const', const=SubtitleRenameStrategy.VIDEO_LANG_UPLOADER, help=_('Use the local video filename + uploader + language ' 'as name for the downloaded subtitle.')) parser.set_defaults(rename_strategy=SubtitleRenameStrategy.ONLINE) # online options online_group = parser.add_argument_group( 'online', 'Change parameters related to the online provider.') online_group.add_argument('-P', '--proxy', dest='proxy', default=None, action=ProxyAction, help=_('Proxy to use on internet connections.')) online_group.add_argument('--provider', dest='providers', metavar='NAME [KEY1=VALUE1 [KEY2=VALUE2 [...]]]', nargs=argparse.ONE_OR_MORE, default=None, action=ProviderAction, help=_('Enable and configure a provider.')) return parser
class PreferencesDialog(QDialog): def __init__(self, parent, state, settings): QDialog.__init__(self, parent) self._state = state self._settings = settings self._uploadLanguage = UnknownLanguage.create_generic() self.providers_ui = dict() self.ui = Ui_PreferencesDialog() self.setup_ui() def setup_ui(self): self.ui.setupUi(self) # 0. Dialog self.ui.buttonApplyChanges.clicked.connect(self.onApplyChanges) self.ui.buttonCancel.clicked.connect(self.onCancel) self.ui.tabsPreferences.setCurrentIndex(0) # 1. Search tab # - Filter languages self._filterLanguageComboBoxes = {} self._search_languages = {lang: False for lang in all_languages()} nb_columns_languages = 4 for lang_i, lang in enumerate(all_languages()): row = lang_i // nb_columns_languages column = lang_i % nb_columns_languages checkBox = QCheckBox(_(lang.generic_name()), self.ui.scrollAreaWidgetSearch) def createSearchLangSlot(lang): @pyqtSlot(bool) def onSearchLangCheckBoxToggled(toggled): self.searchLanguageChanged.emit(lang, toggled) return onSearchLangCheckBoxToggled checkBox.toggled.connect(createSearchLangSlot(lang)) checkBox.setChecked(self._search_languages[lang]) self._filterLanguageComboBoxes[lang] = checkBox self.ui.scrollAreaWidgetLayoutSearch.addWidget( checkBox, row, column) self.searchLanguageChanged.connect(self.onSearchLanguageChanged) fontSearchItem = self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].font() fontSearchItem.setItalic(True) self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].setFont(fontSearchItem) # 2. Download tab # - Download Destination self._dlDestinationType = self.DEFAULT_DLDESTINATIONTYPE def create_dlDestinationTypeChangedSlot(dlDestinationType): @pyqtSlot(bool) def dlDestinationTypeChanged(toggled): if toggled: self.dlDestinationTypeChanged.emit(dlDestinationType) return dlDestinationTypeChanged self.ui.optionDlDestinationAsk.toggled.connect( create_dlDestinationTypeChangedSlot(SubtitlePathStrategy.ASK)) self.ui.optionDlDestinationSame.toggled.connect( create_dlDestinationTypeChangedSlot(SubtitlePathStrategy.SAME)) self.ui.optionDlDestinationUser.toggled.connect( create_dlDestinationTypeChangedSlot( SubtitlePathStrategy.PREDEFINED)) self.dlDestinationTypeChanged.connect(self.onDlDestinationTypeChange) self.ui.optionDlDestinationUser.toggled.connect( self.ui.inputDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.connect( self.ui.buttonDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.emit(False) # Always contains a valid download destination folder self._dlDestinationPredefined = Path() dlDestinationCompleter = QCompleter() dlDestinationCompleter.setModel( QDirModel([], QDir.Dirs | QDir.NoDotAndDotDot, QDir.Name, dlDestinationCompleter)) self.ui.inputDlDestinationUser.setCompleter(dlDestinationCompleter) self.ui.inputDlDestinationUser.editingFinished.connect( self.onInputDlDestinationEditingFinished) self.ui.buttonDlDestinationUser.clicked.connect( self.onButtonDlDestinationClicked) # - Subtitle Filename self._subtitleFilename = self.DEFAULT_DLSUBFN def create_dlSubtitleFileNameChangedSlot(subtitleFilename): @pyqtSlot(bool) def subtitleFileNameChanged(toggled): if toggled: self.subtitleFilenameChanged.emit(subtitleFilename) return subtitleFileNameChanged self.ui.optionSubFnSame.toggled.connect( create_dlSubtitleFileNameChangedSlot(SubtitleNamingStrategy.VIDEO)) self.ui.optionSubFnSameLang.toggled.connect( create_dlSubtitleFileNameChangedSlot( SubtitleNamingStrategy.VIDEO_LANG)) self.ui.optionSubFnSameLangUploader.toggled.connect( create_dlSubtitleFileNameChangedSlot( SubtitleNamingStrategy.VIDEO_LANG_UPLOADER)) self.ui.optionSubFnOnline.toggled.connect( create_dlSubtitleFileNameChangedSlot( SubtitleNamingStrategy.ONLINE)) self.subtitleFilenameChanged.connect(self.onSubtitleFilenameChange) # 3. Upload tab # - Default Subtitle Language self._uploadLanguage = self.DEFAULT_UL_LANG self.ui.optionUlDefaultLanguage.set_unknown_text(_('Auto Detect')) self.ui.optionUlDefaultLanguage.set_selected_language( self._uploadLanguage) self.ui.optionUlDefaultLanguage.selected_language_changed.connect( self.onOptionUlDefaultLanguageChange) # 4. Providers tab for providerState in self._state.providers.all_states: provider = providerState.provider provider_name = provider.get_name() from PyQt5.QtWidgets import QVBoxLayout, QLabel ui_items = { '_enabled': QCheckBox(), '_textDisabled': QLabel( _('This provider is connected and cannot be configured')), } ui_items['_textDisabled'].setVisible( providerState.provider.connected()) ui_items['_textDisabled'].setEnabled(False) providerWidget = QWidget() providerLayout = QVBoxLayout() providerLayout.addWidget(ui_items['_textDisabled']) dataWidget = QWidget() providerLayout.addWidget(dataWidget) providerLayout.addStretch() dataLayout = QFormLayout() dataWidget.setLayout(dataLayout) dataLayout.addRow(_('enabled').capitalize(), ui_items['_enabled']) for key, key_type in provider.get_settings().key_types().items(): if key_type == ProviderSettingsType.String: widget = QLineEdit() elif key_type == ProviderSettingsType.Password: widget = QLineEdit() widget.setEchoMode(QLineEdit.Password) else: # FIXME: generalize this warning about possible warnings? log.error( 'Unknown provider settings type: {}: {} -> {}'.format( provider_name, key, key_type)) QMessageBox.warning( self, _('Unknown provider settings type'), '\n'.join( (_('An unknown settings type has been passed.'), _('Please open an issue')))) continue dataLayout.addRow(key.capitalize(), widget) ui_items[key] = widget providerWidget.setLayout(providerLayout) ui_items['_stack_index'] = self.ui.providerStack.addWidget( providerWidget) self.providers_ui[provider_name] = ui_items self.ui.providerComboBox.set_state(self._state) self.ui.providerComboBox.set_general_visible(False) self.ui.providerComboBox.set_filter_enable(False) self.ui.providerComboBox.selected_provider_state_changed.connect( self.on_selected_provider_state_changed) self.ui.providerComboBox.setCurrentIndex(0) # 5. Others tab # - Interface Language self._original_interface_language = UnknownLanguage.create_generic() self.ui.optionInterfaceLanguage.set_unknown_text(_('System Language')) self.ui.optionUlDefaultLanguage.set_selected_language( self._original_interface_language) # - Video Application Location self.ui.buttonVideoAppLocationChoose.clicked.connect( self.onButtonVideoAppLocationChoose) self.ui.buttonHelpTranslation.clicked.connect(self.onHelpTranslate) self.readSettings() def readSettings(self): log.debug('readSettings: start') # 1. Search tab checked_languages = self._state.get_download_languages() for checked_language in checked_languages: self._filterLanguageComboBoxes[checked_language].setChecked(True) # 2. Download tab # - Download Destination optionWhereToDownload = self._state.get_subtitle_download_path_strategy( ) if optionWhereToDownload == SubtitlePathStrategy.ASK: self.ui.optionDlDestinationAsk.setChecked(True) elif optionWhereToDownload == SubtitlePathStrategy.SAME: self.ui.optionDlDestinationSame.setChecked(True) elif optionWhereToDownload == SubtitlePathStrategy.PREDEFINED: self.ui.optionDlDestinationUser.setChecked(True) dlDestination = self._state.get_default_download_path() self.ui.inputDlDestinationUser.setText(str(dlDestination)) self.ui.inputDlDestinationUser.editingFinished.emit() # - Subtitle Filename optionSubtitleName = self._state.get_subtitle_naming_strategy() if optionSubtitleName == SubtitleNamingStrategy.VIDEO: self.ui.optionSubFnSame.setChecked(True) elif optionSubtitleName == SubtitleNamingStrategy.VIDEO_LANG: self.ui.optionSubFnSameLang.setChecked(True) elif optionSubtitleName == SubtitleNamingStrategy.VIDEO_LANG_UPLOADER: self.ui.optionSubFnSameLangUploader.setChecked(True) elif optionSubtitleName == SubtitleNamingStrategy.ONLINE: self.ui.optionSubFnOnline.setChecked(True) # 3. Upload tab # - Default Subtitle Language self._uploadLanguage = self._state.get_upload_language() self.ui.optionUlDefaultLanguage.set_selected_language( self._uploadLanguage) # 4. Providers' tab for providerState in self._state.providers.all_states: provider = providerState.provider provider_name = provider.get_name() provider_ui = self.providers_ui[provider_name] provider_ui['_enabled'].setChecked(providerState.getEnabled()) if self._state.providers.connected(): provider_ui['_enabled'].setEnabled(False) dataDict = provider.get_settings().as_dict() for key, key_type in provider.get_settings().key_types().items(): if key_type == ProviderSettingsType.String: provider_ui[key].setText(dataDict[key]) elif key_type == ProviderSettingsType.Password: provider_ui[key].setText(dataDict[key]) else: continue if self._state.providers.connected(): provider_ui[key].setEnabled(False) # 5. Others tab # - Interface Language optionInterfaceLanguage = self._state.get_interface_language() self._original_interface_language = optionInterfaceLanguage self.ui.optionInterfaceLanguage.set_selected_language( optionInterfaceLanguage) playerPath = self._state.get_videoplayer().get_path() playerParams = self._state.get_videoplayer().get_command() self.ui.inputVideoAppLocation.setText(str(playerPath)) self.ui.inputVideoAppParams.setText(playerParams) log.debug('readSettings: finish') @pyqtSlot() def saveSettings(self): log.debug('saveSettings: start') # 1. Search tab checked_languages = [ lang[0] for lang in filter(lambda x: x[1], self._search_languages.items()) ] self._state.set_download_languages(checked_languages) # 2. Downloads tab # - Download Destination self._state.set_subtitle_download_path_strategy( self._dlDestinationType) self._state.set_default_download_path(self._dlDestinationPredefined) # - Subtitle Filename self._state.set_subtitle_naming_strategy(self._subtitleFilename) # 3. Upload tab # - Default Subtitle Language self._state.set_upload_language(self._uploadLanguage) # 4. Providers' tab for providerState in self._state.providers.all_states: provider = providerState.provider provider_name = provider.get_name() provider_ui = self.providers_ui[provider_name] providerState.setEnabled(provider_ui['_enabled'].isChecked()) dataDict = provider.get_settings().as_dict() for key, key_type in provider.get_settings().key_types().items(): if key_type == ProviderSettingsType.String: dataDict[key] = provider_ui[key].text() elif key_type == ProviderSettingsType.Password: dataDict[key] = provider_ui[key].text() else: continue if providerState.getEnabled( ) and not providerState.provider.connected(): new_settings = provider.get_settings().load(**dataDict) provider.set_settings(new_settings) # Emit signal to update number of providers self._state.signals.login_status_changed.emit() # 5. Others tab # - Interface Language new_interface_language = self.ui.optionInterfaceLanguage.get_selected_language( ) self._state.set_interface_language(new_interface_language) if self._original_interface_language != new_interface_language: self._state.signals.interface_language_changed.emit( new_interface_language) # - video player playerPath = Path(self.ui.inputVideoAppLocation.text()) playerParams = self.ui.inputVideoAppParams.text() videoPlayer = VideoPlayer(playerPath, playerParams) self._state.set_videoplayer(videoPlayer) # Finally, write to disk self._state.save_settings(self._settings) log.debug('saveSettings: finish') # 0. Interface def validate(self): # Download Destination Validation dlDestinationUser = self.ui.inputDlDestinationUser.text() if self._dlDestinationType == SubtitlePathStrategy.PREDEFINED and not os.path.isdir( dlDestinationUser): QMessageBox.about(self, _('Error'), _('Predefined Folder is invalid')) return False return True @pyqtSlot() def onApplyChanges(self): if self.validate(): self.saveSettings() self.close() @pyqtSlot() def onCancel(self): self.reject() # 1. Search tab searchLanguageChanged = pyqtSignal(Language, bool) @pyqtSlot(Language, bool) def onSearchLanguageChanged(self, lang, toggled): self._search_languages[lang] = toggled # 2. Downloads tab # - Download destination dlDestinationTypeChanged = pyqtSignal(SubtitlePathStrategy) dlDestinationPredefinedChanged = pyqtSignal(Path) DEFAULT_DLDESTINATIONTYPE = SubtitlePathStrategy.SAME @pyqtSlot(SubtitlePathStrategy) def onDlDestinationTypeChange(self, dlDestinationType): self._dlDestinationType = dlDestinationType @pyqtSlot() def onButtonDlDestinationClicked(self): directory = QFileDialog.getExistingDirectory( self, _('Select a directory'), str(self._dlDestinationPredefined)) if not directory: # Canceled return if os.path.isdir(directory): self.ui.inputDlDestinationUser.setText(directory) self._dlDestinationPredefined = Path(directory) self.dlDestinationPredefinedChanged.emit( self._dlDestinationPredefined) else: QMessageBox.warning( self, _('Not a directory'), _('"{path}" is not a directory').format(path=directory)) @pyqtSlot() def onInputDlDestinationEditingFinished(self): path = self.ui.inputDlDestinationUser.text() if os.path.isdir(path): self._dlDestinationPredefined = Path(path) def getDownloadDestinationPredefined(self): return self._dlDestinationPredefined # - Subtitle Filename subtitleFilenameChanged = pyqtSignal(SubtitleNamingStrategy) DEFAULT_DLSUBFN = SubtitleNamingStrategy.VIDEO def onSubtitleFilenameChange(self, subtitleFilename): self._subtitleFilename = subtitleFilename # 3. Upload tab # - Default Subtitle Language DEFAULT_UL_LANG = UnknownLanguage.create_generic() @pyqtSlot(Language) def onOptionUlDefaultLanguageChange(self, lang): self._uploadLanguage = lang # 4. Providers tab @pyqtSlot(ProviderState) def on_selected_provider_state_changed(self, provider_state): if provider_state.value is None: return provider = provider_state.value.provider self.ui.providerStack.setCurrentIndex( self.providers_ui[provider.get_name()]['_stack_index']) # 5. Others tab interfaceLanguageChange = pyqtSignal(Language) def actionContextMenu(self, action, os): pass @pyqtSlot() def onHelpTranslate(self): webbrowser.open(WEBSITE_TRANSLATE, new=2, autoraise=1) @pyqtSlot() def onButtonVideoAppLocationChoose(self): extensions = '' if platform.system == 'Windows': extensions = '*.exe' fileName, t = QFileDialog.getOpenFileName( self, _('Select the Video Player executable file'), '', extensions) if fileName: self.ui.inputVideoAppLocation.setText(fileName)
def language_at_index(self, index): if self._unknown_visible: if index == 0: return UnknownLanguage.create_generic() index -= 1 return self._languages[index]
def get_language(self, section, option): xxx = self.get_str(section, option, UnknownLanguage.create_generic()) return Language.from_xxx(xxx)
class PreferencesDialog(QDialog): def __init__(self, parent, state): QDialog.__init__(self, parent) self._state = state self._uploadLanguage = UnknownLanguage.create_generic() self.ui = Ui_PreferencesDialog() self.setup_ui() def setup_ui(self): self.ui.setupUi(self) # 0. Dialog self.ui.buttonApplyChanges.clicked.connect(self.onApplyChanges) self.ui.buttonCancel.clicked.connect(self.onCancel) self.ui.tabsPreferences.setCurrentIndex(0) # 1. Search tab # - Filter languages self._filterLanguageComboBoxes = {} self._search_languages = {lang: False for lang in all_languages()} nb_columns_languages = 4 for lang_i, lang in enumerate(all_languages()): row = lang_i // nb_columns_languages column = lang_i % nb_columns_languages checkBox = QCheckBox(_(lang.generic_name()), self.ui.scrollAreaWidgetSearch) def createSearchLangSlot(lang): @pyqtSlot(bool) def onSearchLangCheckBoxToggled(toggled): self.searchLanguageChanged.emit(lang, toggled) return onSearchLangCheckBoxToggled checkBox.toggled.connect(createSearchLangSlot(lang)) checkBox.setChecked(self._search_languages[lang]) self._filterLanguageComboBoxes[lang] = checkBox self.ui.scrollAreaWidgetLayoutSearch.addWidget( checkBox, row, column) self.searchLanguageChanged.connect(self.onSearchLanguageChanged) fontSearchItem = self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].font() fontSearchItem.setItalic(True) self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].setFont(fontSearchItem) # 2. Download tab # - Download Destination self._dlDestinationType = self.DEFAULT_DLDESTINATIONTYPE def create_dlDestinationTypeChangedSlot(dlDestinationType): @pyqtSlot(bool) def dlDestinationTypeChanged(toggled): if toggled: self.dlDestinationTypeChanged.emit(dlDestinationType) return dlDestinationTypeChanged self.ui.optionDlDestinationAsk.toggled.connect( create_dlDestinationTypeChangedSlot( self.DLDESTINATIONTYPE_ASKUSER)) self.ui.optionDlDestinationSame.toggled.connect( create_dlDestinationTypeChangedSlot( self.DLDESTINATIONTYPE_SAMEFOLDER)) self.ui.optionDlDestinationUser.toggled.connect( create_dlDestinationTypeChangedSlot( self.DLDESTINATIONTYPE_PREDEFINEDFOLDER)) self.dlDestinationTypeChanged.connect(self.onDlDestinationTypeChange) self.ui.optionDlDestinationUser.toggled.connect( self.ui.inputDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.connect( self.ui.buttonDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.emit(False) # Always contains a valid download destination folder self._dlDestinationPredefined = '' # FIXME: good default (USER HOME? USER DOWNLOADS?) dlDestinationCompleter = QCompleter() dlDestinationCompleter.setModel( QDirModel([], QDir.Dirs | QDir.NoDotAndDotDot, QDir.Name, dlDestinationCompleter)) self.ui.inputDlDestinationUser.setCompleter(dlDestinationCompleter) self.ui.inputDlDestinationUser.editingFinished.connect( self.onInputDlDestinationEditingFinished) self.ui.buttonDlDestinationUser.clicked.connect( self.onButtonDlDestinationClicked) # - Subtitle Filename self._subtitleFilename = self.DEFAULT_DLSUBFN def create_dlSubtitleFileNameChangedSlot(subtitleFilename): @pyqtSlot(bool) def subtitleFileNameChanged(toggled): if toggled: self.subtitleFilenameChanged.emit(subtitleFilename) return subtitleFileNameChanged self.ui.optionSubFnSame.toggled.connect( create_dlSubtitleFileNameChangedSlot(self.DLSUBFN_SAME)) self.ui.optionSubFnSameLang.toggled.connect( create_dlSubtitleFileNameChangedSlot(self.DLSUBFN_SAMELANG)) self.ui.optionSubFnSameLangUploader.toggled.connect( create_dlSubtitleFileNameChangedSlot( self.DLSUBFN_SAMELANGUPLOADER)) self.ui.optionSubFnOnline.toggled.connect( create_dlSubtitleFileNameChangedSlot(self.DLSUBFN_ONLINE)) self.subtitleFilenameChanged.connect(self.onSubtitleFilenameChange) # 3. Upload tab # - Default Subtitle Language self._uploadLanguage = self.DEFAULT_UL_LANG self.ui.optionUlDefaultLanguage.set_unknown_text(_('Auto Detect')) self.ui.optionUlDefaultLanguage.set_selected_language( self._uploadLanguage) self.ui.optionUlDefaultLanguage.selected_language_changed.connect( self.onOptionUlDefaultLanguageChange) # 4. Network tab self.ui.inputProxyPort.setRange(0, 65535) # 5. Others tab # - Interface Language self._original_interface_language = UnknownLanguage.create_generic() self.ui.optionInterfaceLanguage.set_unknown_text(_('System Language')) self.ui.optionUlDefaultLanguage.set_selected_language( self.DEFAULT_INTERFACE_LANG) # - Video Application Location self.ui.buttonVideoAppLocationChoose.clicked.connect( self.onButtonVideoAppLocationChoose) self.ui.buttonHelpTranslation.clicked.connect(self.onHelpTranslate) self.settings = QSettings() # FIXME: use config path self.readSettings() def readSettings(self): log.debug('readSettings: start') self.settings.sync() # 1. Search tab checked_languages_str = self.settings.value('options/filterSearchLang', []) if checked_languages_str: for lang_xxx in checked_languages_str.split(','): lang = Language.from_xxx(lang_xxx) if isinstance(lang, UnknownLanguage): continue self._filterLanguageComboBoxes[lang].setChecked(True) # 2. Download tab # - Download Destination optionWhereToDownload = self.settings.value( 'options/whereToDownload', self.DLDESTINATIONTYPE_SAMEFOLDER) if optionWhereToDownload == self.DLDESTINATIONTYPE_ASKUSER: self.ui.optionDlDestinationAsk.setChecked(True) elif optionWhereToDownload == self.DLDESTINATIONTYPE_SAMEFOLDER: self.ui.optionDlDestinationSame.setChecked(True) elif optionWhereToDownload == self.DLDESTINATIONTYPE_PREDEFINEDFOLDER: self.ui.optionDlDestinationUser.setChecked(True) dlDestination = self.settings.value('options/whereToDownloadFolder', '') #self._dlDestinationPredefined = dlDestination if os.path.isdir(dlDestination) else '' self.ui.inputDlDestinationUser.setText(dlDestination) self.ui.inputDlDestinationUser.editingFinished.emit() # - Subtitle Filename optionSubtitleName = self.settings.value('options/subtitleName', self.DLSUBFN_SAME) if optionSubtitleName == self.DLSUBFN_SAME: self.ui.optionSubFnSame.setChecked(True) elif optionSubtitleName == self.DLSUBFN_SAMELANG: self.ui.optionSubFnSameLang.setChecked(True) elif optionSubtitleName == self.DLSUBFN_SAMELANGUPLOADER: self.ui.optionSubFnSameLangUploader.setChecked(True) elif optionSubtitleName == self.DLSUBFN_ONLINE: self.ui.optionSubFnOnline.setChecked(True) # 3. Upload tab # - Default Subtitle Language optionUploadLanguage = self.settings.value('options/uploadLanguage', self.DEFAULT_UL_LANG.xxx()) self._uploadLanguage = Language.from_xxx(optionUploadLanguage) self.ui.optionUlDefaultLanguage.set_selected_language( self._uploadLanguage) # 4. Network tab self.ui.inputProxyHost.setText( self.settings.value("options/ProxyHost", "")) self.ui.inputProxyPort.setValue( int(self.settings.value("options/ProxyPort", 8080))) # 5. Others tab # - Interface Language optionInterfaceLanguage = self.settings.value( 'options/interfaceLang', self.DEFAULT_INTERFACE_LANG.locale()) self._original_interface_language = Language.from_locale( optionInterfaceLanguage) self.ui.optionInterfaceLanguage.set_selected_language( self._original_interface_language) optionIntegrationExplorer = self.settings.value( "options/IntegrationExplorer", False) self.ui.optionIntegrationExplorer.setChecked(optionIntegrationExplorer) programPath = self.settings.value("options/VideoPlayerPath", "") parameters = self.settings.value("options/VideoPlayerParameters", "") self.ui.inputVideoAppLocation.setText(programPath) self.ui.inputVideoAppParams.setText(parameters) # Context menu for Explorer if platform.system() == "Linux": self.ui.optionIntegrationExplorer.setText( _("Enable in your Konqueror/Dolphin/Nautilus")) self.ui.optionIntegrationExplorer.setEnabled(False) elif platform.system() == "Windows": self.ui.optionIntegrationExplorer.setText( _("Enable in your Windows Explorer")) self.ui.optionIntegrationExplorer.setEnabled(False) else: self.ui.optionIntegrationExplorer.setText( _("Enable in your File Manager")) self.ui.optionIntegrationExplorer.setEnabled(False) log.debug('readSettings: finish') @pyqtSlot() def saveSettings(self): log.debug('saveSettings: start') # 1. Search tab checked_languages = [ lang[0] for lang in filter(lambda x: x[1], self._search_languages.items()) ] checked_languages_str = ','.join( [lang.xxx() for lang in checked_languages]) self.settings.setValue("options/filterSearchLang", checked_languages_str) self.parent().permanent_language_filter_changed.emit(checked_languages) # 2. Downloads tab # - Download Destination self.settings.setValue('options/whereToDownload', self._dlDestinationType) self.settings.setValue('options/whereToDownloadFolder', self._dlDestinationPredefined) # - Subtitle Filename self.settings.setValue('options/subtitleName', self._subtitleFilename) # 3. Upload tab # - Default Subtitle Language self.settings.setValue('options/uploadLanguage', self._uploadLanguage.xxx()) self.defaultUploadLanguageChanged.emit(self._uploadLanguage) # 5. Others tab # - Interface Language new_interface_language = self.ui.optionInterfaceLanguage.get_selected_language( ) self.settings.setValue('options/interfaceLang', new_interface_language.locale()) if self._original_interface_language != new_interface_language: self._state.interface_language_changed.emit(new_interface_language) # Writing settings IEoldValue = self.settings.value("options/IntegrationExplorer", False) IEnewValue = self.ui.optionIntegrationExplorer.isChecked() if IEoldValue != IEnewValue: if IEnewValue: log.debug('Installing the Integration Explorer feature') ok = self.actionContextMenu("install", platform.system()) else: log.debug('Uninstalling the Integration Explorer feature') ok = self.actionContextMenu("uninstall", platform.system()) if ok: self.settings.setValue("options/IntegrationExplorer", IEnewValue) newProxyHost = self.ui.inputProxyHost.text() newProxyPort = self.ui.inputProxyPort.value() oldProxyHost = self.settings.value("options/ProxyHost", "") oldProxyPort = int(self.settings.value("options/ProxyPort", 8080)) if newProxyHost != oldProxyHost or newProxyPort != oldProxyPort: self.settings.setValue("options/ProxyHost", newProxyHost) self.settings.setValue("options/ProxyPort", newProxyPort) QMessageBox.about( self, _("Alert"), _("Modified proxy settings will take effect after restarting the program" )) programPath = self.ui.inputVideoAppLocation.text() parameters = self.ui.inputVideoAppParams.text() self.settings.setValue("options/VideoPlayerPath", programPath) self.settings.setValue("options/VideoPlayerParameters", parameters) self.settings.sync() log.debug('saveSettings: finish') # 0. Interface def validate(self): # Download Destination Validation dlDestinationUser = self.ui.inputDlDestinationUser.text() if self._dlDestinationType == self.DLDESTINATIONTYPE_PREDEFINEDFOLDER and not os.path.isdir( dlDestinationUser): QMessageBox.about(self, _("Error"), _("Predefined Folder is invalid")) return False return True @pyqtSlot() def onApplyChanges(self): if self.validate(): self.saveSettings() self.close() @pyqtSlot() def onCancel(self): self.reject() # 1. Search tab searchLanguageChanged = pyqtSignal(Language, bool) @pyqtSlot(Language, bool) def onSearchLanguageChanged(self, lang, toggled): self._search_languages[lang] = toggled # 2. Downloads tab # - Download destination dlDestinationTypeChanged = pyqtSignal(str) dlDestinationPredefinedChanged = pyqtSignal(str) DLDESTINATIONTYPE_ASKUSER = '******' DLDESTINATIONTYPE_SAMEFOLDER = 'SAME_FOLDER' DLDESTINATIONTYPE_PREDEFINEDFOLDER = 'PREDEFINED_FOLDER' DEFAULT_DLDESTINATIONTYPE = DLDESTINATIONTYPE_SAMEFOLDER @pyqtSlot(str) def onDlDestinationTypeChange(self, dlDestinationType): self._dlDestinationType = dlDestinationType @pyqtSlot() def onButtonDlDestinationClicked(self): directory = QFileDialog.getExistingDirectory( self, _("Select a directory"), self._dlDestinationPredefined) if not directory: # Cancelled return if os.path.isdir(directory): self.ui.inputDlDestinationUser.setText(directory) self._dlDestinationPredefined = directory self.dlDestinationPredefinedChanged.emit( self._dlDestinationPredefined) else: QMessageBox.warning( self, _('Not a directory'), _('"{path}" is not a directory').format(path=directory)) @pyqtSlot() def onInputDlDestinationEditingFinished(self): path = self.ui.inputDlDestinationUser.text() if os.path.isdir(path): self._dlDestinationPredefined = path def getDownloadDestinationPredefined(self): return self._dlDestinationPredefined # - Subtitle Filename subtitleFilenameChanged = pyqtSignal(str) DLSUBFN_SAME = 'SAME_VIDEO' DLSUBFN_SAMELANG = 'SAME_VIDEOPLUSLANG' DLSUBFN_SAMELANGUPLOADER = 'SAME_VIDEOPLUSLANGANDUPLOADER' DLSUBFN_ONLINE = 'SAME_ONLINE' DEFAULT_DLSUBFN = DLSUBFN_SAME def onSubtitleFilenameChange(self, subtitleFilename): self._subtitleFilename = subtitleFilename # 3. Upload tab # - Default Subtitle Language defaultUploadLanguageChanged = pyqtSignal(Language) DEFAULT_UL_LANG = UnknownLanguage.create_generic() @pyqtSlot(Language) def onOptionUlDefaultLanguageChange(self, lang): self._uploadLanguage = lang # 5. Others tab interfaceLanguageChange = pyqtSignal(Language) DEFAULT_INTERFACE_LANG = UnknownLanguage.create_generic() def actionContextMenu(self, action, os): pass @pyqtSlot() def onHelpTranslate(self): webbrowser.open(WEBSITE_TRANSLATE, new=2, autoraise=1) @pyqtSlot() def onButtonVideoAppLocationChoose(self): extensions = "" if platform.system == "Windows": extensions = "*.exe" fileName, t = QFileDialog.getOpenFileName( self, _("Select the Video Player executable file"), "", extensions) if fileName: self.ui.inputVideoAppLocation.setText(fileName)
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 setup_ui(self): self.ui.setupUi(self) # 0. Dialog self.ui.buttonApplyChanges.clicked.connect(self.onApplyChanges) self.ui.buttonCancel.clicked.connect(self.onCancel) self.ui.tabsPreferences.setCurrentIndex(0) # 1. Search tab # - Filter languages self._filterLanguageComboBoxes = {} self._search_languages = {lang: False for lang in all_languages()} nb_columns_languages = 4 for lang_i, lang in enumerate(all_languages()): row = lang_i // nb_columns_languages column = lang_i % nb_columns_languages checkBox = QCheckBox(_(lang.generic_name()), self.ui.scrollAreaWidgetSearch) def createSearchLangSlot(lang): @pyqtSlot(bool) def onSearchLangCheckBoxToggled(toggled): self.searchLanguageChanged.emit(lang, toggled) return onSearchLangCheckBoxToggled checkBox.toggled.connect(createSearchLangSlot(lang)) checkBox.setChecked(self._search_languages[lang]) self._filterLanguageComboBoxes[lang] = checkBox self.ui.scrollAreaWidgetLayoutSearch.addWidget( checkBox, row, column) self.searchLanguageChanged.connect(self.onSearchLanguageChanged) fontSearchItem = self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].font() fontSearchItem.setItalic(True) self._filterLanguageComboBoxes[ UnknownLanguage.create_generic()].setFont(fontSearchItem) # 2. Download tab # - Download Destination self._dlDestinationType = self.DEFAULT_DLDESTINATIONTYPE def create_dlDestinationTypeChangedSlot(dlDestinationType): @pyqtSlot(bool) def dlDestinationTypeChanged(toggled): if toggled: self.dlDestinationTypeChanged.emit(dlDestinationType) return dlDestinationTypeChanged self.ui.optionDlDestinationAsk.toggled.connect( create_dlDestinationTypeChangedSlot( self.DLDESTINATIONTYPE_ASKUSER)) self.ui.optionDlDestinationSame.toggled.connect( create_dlDestinationTypeChangedSlot( self.DLDESTINATIONTYPE_SAMEFOLDER)) self.ui.optionDlDestinationUser.toggled.connect( create_dlDestinationTypeChangedSlot( self.DLDESTINATIONTYPE_PREDEFINEDFOLDER)) self.dlDestinationTypeChanged.connect(self.onDlDestinationTypeChange) self.ui.optionDlDestinationUser.toggled.connect( self.ui.inputDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.connect( self.ui.buttonDlDestinationUser.setEnabled) self.ui.optionDlDestinationUser.toggled.emit(False) # Always contains a valid download destination folder self._dlDestinationPredefined = '' # FIXME: good default (USER HOME? USER DOWNLOADS?) dlDestinationCompleter = QCompleter() dlDestinationCompleter.setModel( QDirModel([], QDir.Dirs | QDir.NoDotAndDotDot, QDir.Name, dlDestinationCompleter)) self.ui.inputDlDestinationUser.setCompleter(dlDestinationCompleter) self.ui.inputDlDestinationUser.editingFinished.connect( self.onInputDlDestinationEditingFinished) self.ui.buttonDlDestinationUser.clicked.connect( self.onButtonDlDestinationClicked) # - Subtitle Filename self._subtitleFilename = self.DEFAULT_DLSUBFN def create_dlSubtitleFileNameChangedSlot(subtitleFilename): @pyqtSlot(bool) def subtitleFileNameChanged(toggled): if toggled: self.subtitleFilenameChanged.emit(subtitleFilename) return subtitleFileNameChanged self.ui.optionSubFnSame.toggled.connect( create_dlSubtitleFileNameChangedSlot(self.DLSUBFN_SAME)) self.ui.optionSubFnSameLang.toggled.connect( create_dlSubtitleFileNameChangedSlot(self.DLSUBFN_SAMELANG)) self.ui.optionSubFnSameLangUploader.toggled.connect( create_dlSubtitleFileNameChangedSlot( self.DLSUBFN_SAMELANGUPLOADER)) self.ui.optionSubFnOnline.toggled.connect( create_dlSubtitleFileNameChangedSlot(self.DLSUBFN_ONLINE)) self.subtitleFilenameChanged.connect(self.onSubtitleFilenameChange) # 3. Upload tab # - Default Subtitle Language self._uploadLanguage = self.DEFAULT_UL_LANG self.ui.optionUlDefaultLanguage.set_unknown_text(_('Auto Detect')) self.ui.optionUlDefaultLanguage.set_selected_language( self._uploadLanguage) self.ui.optionUlDefaultLanguage.selected_language_changed.connect( self.onOptionUlDefaultLanguageChange) # 4. Network tab self.ui.inputProxyPort.setRange(0, 65535) # 5. Others tab # - Interface Language self._original_interface_language = UnknownLanguage.create_generic() self.ui.optionInterfaceLanguage.set_unknown_text(_('System Language')) self.ui.optionUlDefaultLanguage.set_selected_language( self.DEFAULT_INTERFACE_LANG) # - Video Application Location self.ui.buttonVideoAppLocationChoose.clicked.connect( self.onButtonVideoAppLocationChoose) self.ui.buttonHelpTranslation.clicked.connect(self.onHelpTranslate) self.settings = QSettings() # FIXME: use config path self.readSettings()
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(str(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.set_selected_language( UnknownLanguage.create_generic()) self.ui.filterLanguageForVideo.selected_language_changed.connect( self.on_language_combobox_filter_change) self.videoModel = VideoModel(self) self.videoModel.connect_treeview(self.ui.videoView) self.ui.videoView.setHeaderHidden(True) 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()