Пример #1
0
    def __init__(self, master, config, *args, **kwargs):
        super().__init__(master, *args, **kwargs)
        self.config = init_section(config, section_name='translate_external_files')
        config = self.config

        tk.Label(self, text='Dwarf Fortress root path:').grid()

        self.fileentry_df_root_path = FileEntry(
            self,
            dialogtype='askdirectory',
            default_path=config.get('df_root_path', ''),
            on_change=lambda text: check_and_save_path(self.config, 'df_root_path', text),
        )
        self.fileentry_df_root_path.grid(row=0, column=1, sticky='WE')

        tk.Label(self, text="Translation files' directory:").grid()

        self.fileentry_translation_files = FileEntry(
            self,
            dialogtype='askdirectory',
            default_path=config.get('translation_files_path', ''),
            on_change=lambda text: self.on_change_translation_files_path(self.config, 'translation_files_path', text),
        )
        self.fileentry_translation_files.grid(row=1, column=1, sticky='WE')

        tk.Label(self, text="Language:").grid()
        self.combo_language = ComboboxCustom(self)
        self.combo_language.grid(row=2, column=1, sticky='WE')

        directory = self.fileentry_translation_files.text
        if path.exists(directory):
            languages = self.get_languages(directory)
            self.combo_language.values = languages
            if languages:
                self.combo_language.current(0)

        self.combo_language.bind('<<ComboboxSelected>>', self.update_listbox_translation_files)

        tk.Label(self, text="Encoding:").grid()
        self.combo_encoding = ComboboxCustom(self)
        self.combo_encoding.grid(row=3, column=1, sticky='WE')

        self.update_combo_encoding()

        self.listbox_translation_files = ListboxCustom(self)
        self.listbox_translation_files.grid(columnspan=2, sticky='NSWE')
        self.update_listbox_translation_files(language=self.combo_language.text)

        ttk.Button(self, text='Search', command=self.bt_search).grid()
        ttk.Button(self, text='Translate', command=lambda: self.bt_search(translate=True)).grid(row=5, column=1)

        self.listbox_found_directories = ListboxCustom(self)
        self.listbox_found_directories.grid(columnspan=2, sticky='NSWE')

        self.grid_columnconfigure(1, weight=1)
class PatchExecutableFrame(tk.Frame):
    def update_log(self, message_queue):
        try:
            while message_queue.poll():
                self.log_field.write(message_queue.recv())

            if not self.dfrus_process.is_alive():
                self.log_field.write('\n[PROCESS FINISHED]')
                self.button_patch.reset_state()
            else:
                self.after(100, self.update_log, message_queue)
        except (EOFError, BrokenPipeError):
            self.log_field.write('\n[MESSAGE QUEUE/PIPE BROKEN]')
            self.button_patch.reset_state()

    def load_dictionary(self, translation_file):
        with open(translation_file, 'r', encoding='utf-8') as fn:
            pofile = po.PoReader(fn)
            meta = pofile.meta
            dictionary = OrderedDict(
                cleanup_spaces(((entry['msgid'], cleanup_special_symbols(entry['msgstr'])) for entry in pofile),
                               self.exclusions.get(meta['Language'], self.exclusions))
            )
        return dictionary

    @property
    def dictionary(self):
        if not self._dictionary:
            translation_file = self.fileentry_translation_file.text
            if self.fileentry_translation_file.path_is_valid():
                self._dictionary = self.load_dictionary(translation_file)
        return self._dictionary

    def bt_patch(self):
        if self.dfrus_process is not None and self.dfrus_process.is_alive():
            return False

        executable_file = self.fileentry_executable_file.text

        if not executable_file or not path.exists(executable_file):
            messagebox.showerror('Error', 'Valid path to an executable file must be specified')
        elif not self.dictionary:
            messagebox.showerror('Error', "Dictionary wasn't loaded")
        else:
            if not self.debug_frame:
                dictionary = self.dictionary
            else:
                dictionary = OrderedDict(self.debug_frame.bisect.filtered_strings)

            self.config['last_encoding'] = self.combo_encoding.text

            parent_conn, child_conn = mp.Pipe()

            self.after(100, self.update_log, parent_conn)
            self.log_field.clear()
            self.dfrus_process = mp.Process(
                target=dfrus.run,
                kwargs=dict(
                    path=executable_file,
                    dest='',
                    trans_table=dictionary,
                    codepage=self.combo_encoding.text,
                    debug=self.chk_debug_output.is_checked,
                    stdout=ProcessMessageWrapper(child_conn)
                )
            )
            self.dfrus_process.start()
            return True

        return False

    def bt_stop(self):
        r = messagebox.showwarning('Are you sure?', 'Stop the patching process?', type=messagebox.OKCANCEL)
        if r == 'cancel':
            return False
        else:
            self.dfrus_process.terminate()
            return True

    def kill_processes(self, _):
        if self.dfrus_process and self.dfrus_process.is_alive():
            self.dfrus_process.terminate()

    def bt_exclusions(self):
        translation_file = self.fileentry_translation_file.text
        language = None
        dictionary = None
        if translation_file and path.exists(translation_file):
            with open(translation_file, 'r', encoding='utf-8') as fn:
                pofile = po.PoReader(fn)
                meta = pofile.meta
                language = meta['Language']
                dictionary = {entry['msgid']: entry['msgstr'] for entry in pofile}

        dialog = DialogDontFixSpaces(self, self.config['fix_space_exclusions'], language, dictionary)
        self.config['fix_space_exclusions'] = dialog.exclusions or self.config['fix_space_exclusions']
        self.exclusions = self.config['fix_space_exclusions']

    def setup_checkbutton(self, text, config_key, default_state):
        config = self.config

        def save_checkbox_state(event, option_name):
            config[option_name] = not event.widget.is_checked  # Event occurs before the widget changes state

        check = CheckbuttonVar(self, text=text)
        check.bind('<1>', lambda event: save_checkbox_state(event, config_key))
        check.is_checked = config[config_key] = config.get(config_key, default_state)
        return check

    def update_combo_encoding(self, text):
        check_and_save_path(self.config, 'df_exe_translation_file', text)

        # Update codepage combobox
        # TODO: Cache supported codepages' list
        codepages = get_codepages().keys()
        if self.fileentry_translation_file.path_is_valid():
            translation_file = self.fileentry_translation_file.text
            with open(translation_file, 'r', encoding='utf-8') as fn:
                pofile = po.PoReader(fn)
                self.translation_file_language = pofile.meta['Language']
                strings = [cleanup_special_symbols(entry['msgstr']) for entry in pofile]
            codepages = filter_codepages(codepages, strings)
        self.combo_encoding.values = sorted(codepages,
                                            key=lambda x: int(x.strip(string.ascii_letters)))

        
        if self.translation_file_language not in self.config['language_codepages']:
            if self.combo_encoding.values:
                self.combo_encoding.current(0)
            else:
                self.combo_encoding.text = 'cp437'
        else:
            self.combo_encoding.text = self.config['language_codepages'][self.translation_file_language]

    def __init__(self, master, config, debug=False):
        super().__init__(master)

        self.config = init_section(
            config, section_name='patch_executable',
            defaults=dict(
                fix_space_exclusions=dict(ru=['Histories of ']),
                language_codepages=dict(),
            )
        )
        config = self.config
        self.exclusions = config['fix_space_exclusions']

        self.dfrus_process = None

        self._dictionary = None

        tk.Label(self, text='DF executable file:').grid()

        self.fileentry_executable_file = FileEntry(
            self,
            dialogtype='askopenfilename',
            filetypes=[('Executable files', '*.exe')],
            default_path=config.get('df_executable', ''),
            on_change=lambda text: check_and_save_path(self.config, 'df_executable', text),
        )
        self.fileentry_executable_file.grid(column=1, row=0, columnspan=2, sticky='EW')

        tk.Label(self, text='DF executable translation file:').grid()

        self.fileentry_translation_file = FileEntry(
            self,
            dialogtype='askopenfilename',
            filetypes=[
                ("Hardcoded strings' translation", '*hardcoded*.po'),
                ('Translation files', '*.po'),
                # ('csv file', '*.csv'), # @TODO: Currently not supported
            ],
            default_path=config.get('df_exe_translation_file', ''),
            on_change=self.update_combo_encoding,
            change_color=True
        )
        self.fileentry_translation_file.grid(column=1, row=1, columnspan=2, sticky='EW')

        tk.Label(self, text='Encoding:').grid()

        self.combo_encoding = ComboboxCustom(self)
        self.combo_encoding.grid(column=1, row=2, sticky=tk.E + tk.W)

        codepages = get_codepages().keys()

        if not self.fileentry_translation_file.path_is_valid():
            self.translation_file_language = None
        else:
            translation_file = self.fileentry_translation_file.text
            with open(translation_file, 'r', encoding='utf-8') as fn:
                pofile = po.PoReader(fn)
                self.translation_file_language = pofile.meta['Language']
                strings = [cleanup_special_symbols(entry['msgstr']) for entry in pofile]
            codepages = filter_codepages(codepages, strings)

        self.combo_encoding.values = sorted(codepages,
                                            key=lambda x: int(x.strip(string.ascii_letters)))

        if 'last_encoding' in config:
            self.combo_encoding.text = config['last_encoding']
        else:
            self.combo_encoding.current(0)

        def save_encoding_into_config(event):
            config['last_encoding'] = event.widget.text
            if self.translation_file_language:
                config['language_codepages'][self.translation_file_language] = event.widget.text

        self.combo_encoding.bind('<<ComboboxSelected>>', func=save_encoding_into_config)

        # FIXME: chk_dont_patch_charmap does nothing
        self.chk_dont_patch_charmap = self.setup_checkbutton(
            text="Don't patch charmap table",
            config_key='dont_patch_charmap',
            default_state=False)

        self.chk_dont_patch_charmap.grid(column=1, sticky=tk.W)

        self.chk_add_leading_trailing_spaces = self.setup_checkbutton(
            text='Add necessary leading/trailing spaces',
            config_key='add_leading_trailing_spaces',
            default_state=True)

        self.chk_add_leading_trailing_spaces.grid(columnspan=2, sticky=tk.W)

        button_exclusions = ttk.Button(self, text='Exclusions...', command=self.bt_exclusions)
        button_exclusions.grid(row=4, column=2)

        self.debug_frame = None if not debug else DebugFrame(self, dictionary=self.dictionary)
        if self.debug_frame:
            self.debug_frame.grid(columnspan=3, sticky='NSWE')
            self.grid_rowconfigure(5, weight=1)

        self.chk_debug_output = self.setup_checkbutton(
            text='Enable debugging output',
            config_key='debug_output',
            default_state=False)

        self.chk_debug_output.grid(columnspan=2, sticky=tk.W)

        self.button_patch = TwoStateButton(self,
                                           text='Patch!', command=self.bt_patch,
                                           text2='Stop!', command2=self.bt_stop)
        self.button_patch.grid(row=6, column=2)

        self.log_field = CustomText(self, width=48, height=8, enabled=False)
        self.log_field.grid(columnspan=3, sticky='NSWE')
        self.grid_rowconfigure(self.log_field.grid_info()['row'], weight=1)

        self.grid_columnconfigure(1, weight=1)
        
        self.bind('<Destroy>', self.kill_processes)
    def __init__(self, master, config, debug=False):
        super().__init__(master)

        self.config = init_section(
            config, section_name='patch_executable',
            defaults=dict(
                fix_space_exclusions=dict(ru=['Histories of ']),
                language_codepages=dict(),
            )
        )
        config = self.config
        self.exclusions = config['fix_space_exclusions']

        self.dfrus_process = None

        self._dictionary = None

        tk.Label(self, text='DF executable file:').grid()

        self.fileentry_executable_file = FileEntry(
            self,
            dialogtype='askopenfilename',
            filetypes=[('Executable files', '*.exe')],
            default_path=config.get('df_executable', ''),
            on_change=lambda text: check_and_save_path(self.config, 'df_executable', text),
        )
        self.fileentry_executable_file.grid(column=1, row=0, columnspan=2, sticky='EW')

        tk.Label(self, text='DF executable translation file:').grid()

        self.fileentry_translation_file = FileEntry(
            self,
            dialogtype='askopenfilename',
            filetypes=[
                ("Hardcoded strings' translation", '*hardcoded*.po'),
                ('Translation files', '*.po'),
                # ('csv file', '*.csv'), # @TODO: Currently not supported
            ],
            default_path=config.get('df_exe_translation_file', ''),
            on_change=self.update_combo_encoding,
            change_color=True
        )
        self.fileentry_translation_file.grid(column=1, row=1, columnspan=2, sticky='EW')

        tk.Label(self, text='Encoding:').grid()

        self.combo_encoding = ComboboxCustom(self)
        self.combo_encoding.grid(column=1, row=2, sticky=tk.E + tk.W)

        codepages = get_codepages().keys()

        if not self.fileentry_translation_file.path_is_valid():
            self.translation_file_language = None
        else:
            translation_file = self.fileentry_translation_file.text
            with open(translation_file, 'r', encoding='utf-8') as fn:
                pofile = po.PoReader(fn)
                self.translation_file_language = pofile.meta['Language']
                strings = [cleanup_special_symbols(entry['msgstr']) for entry in pofile]
            codepages = filter_codepages(codepages, strings)

        self.combo_encoding.values = sorted(codepages,
                                            key=lambda x: int(x.strip(string.ascii_letters)))

        if 'last_encoding' in config:
            self.combo_encoding.text = config['last_encoding']
        else:
            self.combo_encoding.current(0)

        def save_encoding_into_config(event):
            config['last_encoding'] = event.widget.text
            if self.translation_file_language:
                config['language_codepages'][self.translation_file_language] = event.widget.text

        self.combo_encoding.bind('<<ComboboxSelected>>', func=save_encoding_into_config)

        # FIXME: chk_dont_patch_charmap does nothing
        self.chk_dont_patch_charmap = self.setup_checkbutton(
            text="Don't patch charmap table",
            config_key='dont_patch_charmap',
            default_state=False)

        self.chk_dont_patch_charmap.grid(column=1, sticky=tk.W)

        self.chk_add_leading_trailing_spaces = self.setup_checkbutton(
            text='Add necessary leading/trailing spaces',
            config_key='add_leading_trailing_spaces',
            default_state=True)

        self.chk_add_leading_trailing_spaces.grid(columnspan=2, sticky=tk.W)

        button_exclusions = ttk.Button(self, text='Exclusions...', command=self.bt_exclusions)
        button_exclusions.grid(row=4, column=2)

        self.debug_frame = None if not debug else DebugFrame(self, dictionary=self.dictionary)
        if self.debug_frame:
            self.debug_frame.grid(columnspan=3, sticky='NSWE')
            self.grid_rowconfigure(5, weight=1)

        self.chk_debug_output = self.setup_checkbutton(
            text='Enable debugging output',
            config_key='debug_output',
            default_state=False)

        self.chk_debug_output.grid(columnspan=2, sticky=tk.W)

        self.button_patch = TwoStateButton(self,
                                           text='Patch!', command=self.bt_patch,
                                           text2='Stop!', command2=self.bt_stop)
        self.button_patch.grid(row=6, column=2)

        self.log_field = CustomText(self, width=48, height=8, enabled=False)
        self.log_field.grid(columnspan=3, sticky='NSWE')
        self.grid_rowconfigure(self.log_field.grid_info()['row'], weight=1)

        self.grid_columnconfigure(1, weight=1)
        
        self.bind('<Destroy>', self.kill_processes)
Пример #4
0
    def __init__(self, parent, exclusions: dict, language: str,
                 dictionary: dict, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.grab_set()

        self.exclusions = exclusions

        self.title("Choose exclusions")

        language_list = list(self.exclusions)
        if language:
            if language in language_list:
                language_list.remove(language)
            language_list.insert(0, language)
        self.language = language

        self.dictionary = dictionary or dict()
        self.strings = sorted((key for key in dictionary.keys()
                               if key.startswith(' ') or key.endswith(' ')),
                              key=lambda x: x.lower().strip())
        self.restore_strings = {show_spaces(s): s for s in self.strings}

        parent_frame = tk.Frame(self)
        tk.Label(parent_frame, text='Language:').pack(side=tk.LEFT)

        self.combo_language = ComboboxCustom(parent_frame,
                                             values=language_list)

        self.combo_language.pack(fill='both', expand=1)
        parent_frame.grid(sticky=tk.W + tk.E)

        self.combo_language.current(0)
        self.combo_language.bind('<<ComboboxSelected>>',
                                 self.combo_language_change_selection)
        self.combo_language.bind('<Any-KeyRelease>',
                                 self.combo_language_change_selection)

        bt = ttk.Button(self,
                        text='-- Remove selected --',
                        command=self.bt_remove_selected)
        bt.grid(column=0, row=1, sticky=tk.W + tk.E)

        self.listbox_exclusions = ListboxCustom(self, width=40, height=20)
        self.listbox_exclusions.grid(sticky='NSWE')

        self.update_listbox_exclusions()

        parent_frame = tk.Frame(self)
        tk.Label(parent_frame, text='Filter:').pack(side=tk.LEFT)

        self.entry_search = EntryCustom(parent_frame)
        self.entry_search.bind('<Any-KeyRelease>', self.entry_search_key_up)
        self.entry_search.pack(fill='both', expand=1)

        parent_frame.grid(column=1, row=0, sticky=tk.W + tk.E)

        bt = ttk.Button(self,
                        text='<< Add selected <<',
                        command=self.bt_add_selected)
        bt.grid(column=1, row=1, sticky=tk.W + tk.E)

        self.listbox_exclusions_hints = ListboxCustom(self,
                                                      width=40,
                                                      height=20)
        self.listbox_exclusions_hints.grid(column=1, row=2, sticky='NSWE')
        self.update_listbox_exclusions_hints()

        button = ttk.Button(self, text="OK", command=self.destroy)
        button.grid(row=3, column=0)

        def cancel():
            self.exclusions = None
            self.destroy()

        button = ttk.Button(self, text="Cancel", command=cancel)
        button.grid(row=3, column=1)

        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=1)
        self.grid_rowconfigure(2, weight=1)
Пример #5
0
class DownloadTranslationsFrame(tk.Frame):
    def bt_connect(self):
        username = self.entry_username.text
        password = self.entry_password.text  # DO NOT remember password (not safe)
        project = self.combo_projects.text
        try:
            # Todo: make connection in separate thread
            self.tx = TransifexAPI(username, password, 'https://www.transifex.com')
            assert self.tx.ping(), 'No connection to the server'
            assert self.tx.project_exists(project), "Project %r does not exist" % project
            self.resources = self.tx.list_resources(project)
            languages = self.tx.list_languages(project, resource_slug=self.resources[0]['slug'])
        except (TransifexAPIException, requests.exceptions.ConnectionError, AssertionError) as err:
            messagebox.showerror('Error', err)
        except:
            messagebox.showerror('Unexpected error', traceback.format_exc())
        else:
            self.combo_languages.values = sorted(languages)
            last_language = self.config.get('language', None)
            if last_language and last_language in languages:
                self.combo_languages.text = last_language
            else:
                self.combo_languages.current(0)
            
            self.listbox_resources.clear()
            self.listbox_resources.values = tuple(res['name'] for res in self.resources)
            
            self.config['username'] = username

            recent_projects = self.config['recent_projects']
            if recent_projects or project != recent_projects[0]:
                if project in recent_projects:
                    recent_projects.remove(project)
                recent_projects.insert(0, project)
            self.combo_projects.values = recent_projects

    def download_waiter(self, resources, language, project, download_dir, parent_conn=None,
                        initial_names=None, resource_names=None, i=0):
        if initial_names is None:
            initial_names = [res['name'] for res in self.resources]
            resource_names = initial_names.copy()

        if self.download_process is None:
            parent_conn, child_conn = mp.Pipe()

            self.download_process = mp.Process(
                target=downloader,
                kwargs=dict(
                    conn=child_conn,
                    tx=self.tx,
                    project=project,
                    language=language,
                    resources=resources,
                    file_path_pattern=path.join(download_dir, '%s_' + language + '.po')
                )
            )
            self.download_process.start()

        while parent_conn.poll() or not self.download_process.is_alive():
            if parent_conn.poll():
                i, message = parent_conn.recv()
            else:
                i, message = i, 'stopped'

            if message == 'completed':
                # Everything is downloaded
                self.download_process.join()
                self.download_process = None
                self.button_download.reset_state()
                self.download_started = False

                self.config['language'] = language

                if sys.platform == 'win32':
                    subprocess.Popen('explorer "%s"' % (download_dir.replace('/', '\\')))
                else:
                    pass  # Todo: open the directory in a file manager on linux

                return

            resource_names[i] = '{} - {}'.format(initial_names[i], message)
            self.listbox_resources.values = resource_names
            self.update()

            if message == 'ok!':
                self.progressbar.step()
                break
            elif message == 'failed':
                error = parent_conn.recv()
                self.download_process.join()
                self.download_process = None
                self.button_download.reset_state()
                self.download_started = False
                messagebox.showerror('Downloading error', error)
                return
            elif message == 'stopped':
                self.download_process = None
                self.button_download.reset_state()
                self.download_started = False
                return

        self.after(100, self.download_waiter,
                   resources, language, project, download_dir,
                   parent_conn, initial_names, resource_names, i)
    
    def bt_download(self):
        if self.tx and self.resources and not self.download_started:
            self.progressbar['maximum'] = len(self.resources) * 1.001
            self.progressbar['value'] = 0
            
            download_dir = self.fileentry_download_to.text
            if not download_dir:
                messagebox.showwarning('Directory not specified', 'Specify download directory first')
                return
            else:
                self.config['download_to'] = download_dir
            
            if not path.exists(download_dir):
                messagebox.showerror('Directory does not exist', 'Specify existing directory first')
                return
            
            project = self.combo_projects.get()
            language = self.combo_languages.get()
            
            initial_names = [res['name'] for res in self.resources]
            resource_names = list(initial_names)
            
            self.listbox_resources.values = resource_names
            self.download_started = True
            self.download_waiter(self.resources, language, project, download_dir)
            return True

    def bt_stop_downloading(self):
        r = messagebox.showwarning('Are you sure?', 'Stop downloading?', type=messagebox.OKCANCEL)
        if r == 'cancel':
            return False
        else:
            self.download_process.terminate()
            return True

    def kill_processes(self, _):
        if self.download_process and self.download_process.is_alive():
            self.download_process.terminate()

    def __init__(self, master, config):
        super().__init__(master)
        
        self.config = init_section(
            config, section_name='download_translations',
            defaults=dict(recent_projects=['dwarf-fortress'])
        )

        tk.Label(self, text='Transifex project:').grid()

        self.combo_projects = ComboboxCustom(self, values=self.config['recent_projects'])
        self.combo_projects.current(0)
        self.combo_projects.grid(column=1, row=0, sticky=tk.W + tk.E)
        
        tk.Label(self, text='Username:'******'username', '')
        self.entry_username.grid(column=1, row=1, sticky=tk.W + tk.E)
        
        tk.Label(self, text='Password:'******'\u2022')  # 'bullet' symbol
        self.entry_password.grid(column=1, row=2, sticky=tk.W + tk.E)
        
        button_connect = ttk.Button(self, text='Connect...', command=self.bt_connect)
        button_connect.grid(row=0, column=2, rowspan=3, sticky=tk.N + tk.S + tk.W + tk.E)
        
        ttk.Separator(self, orient=tk.HORIZONTAL).grid(columnspan=3, sticky=tk.W + tk.E, pady=5)
        
        tk.Label(self, text='Choose language:').grid(column=0)
        
        self.combo_languages = ComboboxCustom(self)
        self.combo_languages.grid(column=1, row=4, sticky=tk.W + tk.E)
        
        # self.chk_all_languages = CheckbuttonVar(self, text='All languages (backup)')
        # self.chk_all_languages.grid(column=1)
        
        ttk.Separator(self, orient=tk.HORIZONTAL).grid(columnspan=3, sticky=tk.W + tk.E, pady=5)
        
        tk.Label(self, text='Download to:').grid()
        
        self.fileentry_download_to = FileEntry(
            self,
            dialogtype='askdirectory',
            default_path=self.config.get('download_to', ''),
            on_change=lambda text: check_and_save_path(self.config, 'download_to', text),
        )
        
        self.fileentry_download_to.grid(column=1, row=6, columnspan=2, sticky='WE')
        
        self.button_download = TwoStateButton(self, text='Download translations', command=self.bt_download,
                                              text2='Stop', command2=self.bt_stop_downloading)
        self.button_download.grid(sticky=tk.W + tk.E)
        
        self.progressbar = ttk.Progressbar(self)
        self.progressbar.grid(column=1, row=7, columnspan=2, sticky=tk.W + tk.E)
        
        tk.Label(self, text='Resources:').grid(columnspan=3)

        self.listbox_resources = ListboxCustom(self)
        self.listbox_resources.grid(column=0, columnspan=3, sticky=tk.E + tk.W + tk.N + tk.S)

        self.grid_columnconfigure(1, weight=1)
        self.grid_rowconfigure(9, weight=1)

        self.resources = None
        self.tx = None
        self.download_started = False
        self.download_process = None

        self.bind('<Destroy>', self.kill_processes)
Пример #6
0
    def __init__(self, master, config):
        super().__init__(master)
        
        self.config = init_section(
            config, section_name='download_translations',
            defaults=dict(recent_projects=['dwarf-fortress'])
        )

        tk.Label(self, text='Transifex project:').grid()

        self.combo_projects = ComboboxCustom(self, values=self.config['recent_projects'])
        self.combo_projects.current(0)
        self.combo_projects.grid(column=1, row=0, sticky=tk.W + tk.E)
        
        tk.Label(self, text='Username:'******'username', '')
        self.entry_username.grid(column=1, row=1, sticky=tk.W + tk.E)
        
        tk.Label(self, text='Password:'******'\u2022')  # 'bullet' symbol
        self.entry_password.grid(column=1, row=2, sticky=tk.W + tk.E)
        
        button_connect = ttk.Button(self, text='Connect...', command=self.bt_connect)
        button_connect.grid(row=0, column=2, rowspan=3, sticky=tk.N + tk.S + tk.W + tk.E)
        
        ttk.Separator(self, orient=tk.HORIZONTAL).grid(columnspan=3, sticky=tk.W + tk.E, pady=5)
        
        tk.Label(self, text='Choose language:').grid(column=0)
        
        self.combo_languages = ComboboxCustom(self)
        self.combo_languages.grid(column=1, row=4, sticky=tk.W + tk.E)
        
        # self.chk_all_languages = CheckbuttonVar(self, text='All languages (backup)')
        # self.chk_all_languages.grid(column=1)
        
        ttk.Separator(self, orient=tk.HORIZONTAL).grid(columnspan=3, sticky=tk.W + tk.E, pady=5)
        
        tk.Label(self, text='Download to:').grid()
        
        self.fileentry_download_to = FileEntry(
            self,
            dialogtype='askdirectory',
            default_path=self.config.get('download_to', ''),
            on_change=lambda text: check_and_save_path(self.config, 'download_to', text),
        )
        
        self.fileentry_download_to.grid(column=1, row=6, columnspan=2, sticky='WE')
        
        self.button_download = TwoStateButton(self, text='Download translations', command=self.bt_download,
                                              text2='Stop', command2=self.bt_stop_downloading)
        self.button_download.grid(sticky=tk.W + tk.E)
        
        self.progressbar = ttk.Progressbar(self)
        self.progressbar.grid(column=1, row=7, columnspan=2, sticky=tk.W + tk.E)
        
        tk.Label(self, text='Resources:').grid(columnspan=3)

        self.listbox_resources = ListboxCustom(self)
        self.listbox_resources.grid(column=0, columnspan=3, sticky=tk.E + tk.W + tk.N + tk.S)

        self.grid_columnconfigure(1, weight=1)
        self.grid_rowconfigure(9, weight=1)

        self.resources = None
        self.tx = None
        self.download_started = False
        self.download_process = None

        self.bind('<Destroy>', self.kill_processes)
Пример #7
0
class TranslateExternalFiles(tk.Frame):
    @staticmethod
    def get_languages(directory):
        languages = set()
        for filename in os.listdir(directory):
            if filename.endswith('.po'):
                with open(path.join(directory, filename), encoding='utf-8') as file:
                    languages.add(po.PoReader(file).meta['Language'])

        return sorted(languages)

    def on_change_translation_files_path(self, config, key, directory):
        check_and_save_path(config, key, directory)
        if path.exists(directory):
            languages = self.get_languages(directory)
            self.combo_language.values = languages

            if languages:
                self.combo_language.current(0)
            else:
                self.combo_language.text = ''

            self.update_listbox_translation_files(language=self.combo_language.text)
        else:
            self.combo_language.values = tuple()
            self.combo_language.text = ''

    @staticmethod
    def filter_files_by_language(directory, language):
        for filename in os.listdir(directory):
            if filename.endswith('.po'):
                with open(path.join(directory, filename), encoding='utf-8') as file:
                    if po.PoReader(file).meta['Language'] == language:
                        yield filename

    def update_listbox_translation_files(self, _=None, language=None):
        language = self.combo_language.text if not language else language
        directory = self.fileentry_translation_files.text
        files = self.filter_files_by_language(directory, language) if path.exists(directory) else tuple()
        self.listbox_translation_files.values = files

    def update_combo_encoding(self, _=None):
        language = self.combo_language.text
        directory = self.fileentry_translation_files.text
        # TODO: Unify with PatchExecutableFrame.update_combo_encoding()
        if path.exists(directory):
            files = self.filter_files_by_language(directory, language)
            codepages = get_codepages().keys()
            for file in files:
                with open(path.join(directory, file), 'r', encoding='utf-8') as fn:
                    pofile = po.PoReader(fn)
                    strings = [cleanup_special_symbols(entry['msgstr']) for entry in pofile]
                codepages = filter_codepages(codepages, strings)
            self.combo_encoding.values = sorted(codepages,
                                                key=lambda x: int(x.strip(string.ascii_letters)))

            self.combo_encoding.current(0)

    def bt_search(self, translate=False):
        patterns = {
            r'raw\objects': dict(
                po_filename='raw-objects',
                func=translate_raws,
            ),
            # Swithched off for now
            # r'data_src': dict(
            #     po_filename='uncompressed',
            #     func=lambda *args: translate_plain_text(*args, join_paragraphs=True),
            # ),
            r'data\speech': dict(
                po_filename='speech',
                func=lambda *args: translate_plain_text(*args, join_paragraphs=False),
            ),
            r'raw\objects\text': dict(
                po_filename='text',
                func=lambda *args: translate_plain_text(*args, join_paragraphs=False),
            ),
        }

        # TODO: add progressbar
        self.listbox_found_directories.clear()
        for cur_dir, _, files in os.walk(self.fileentry_df_root_path.text):
            for pattern in patterns:
                if cur_dir.endswith(pattern):
                    self.listbox_found_directories.append(cur_dir + ' (%s files)' % len(files))
                    postfix = '_{}.po'.format(self.combo_language.text)
                    po_filename = os.path.join(self.fileentry_translation_files.text,
                                               patterns[pattern]['po_filename'] + postfix)

                    if translate:
                        func = patterns[pattern]['func']
                        for filename in func(po_filename, cur_dir, self.combo_encoding.get()):
                            # print(filename, file=sys.stderr)
                            self.listbox_found_directories.append(filename)

        if translate:
            self.listbox_found_directories.append("Completed.")

    def __init__(self, master, config, *args, **kwargs):
        super().__init__(master, *args, **kwargs)
        self.config = init_section(config, section_name='translate_external_files')
        config = self.config

        tk.Label(self, text='Dwarf Fortress root path:').grid()

        self.fileentry_df_root_path = FileEntry(
            self,
            dialogtype='askdirectory',
            default_path=config.get('df_root_path', ''),
            on_change=lambda text: check_and_save_path(self.config, 'df_root_path', text),
        )
        self.fileentry_df_root_path.grid(row=0, column=1, sticky='WE')

        tk.Label(self, text="Translation files' directory:").grid()

        self.fileentry_translation_files = FileEntry(
            self,
            dialogtype='askdirectory',
            default_path=config.get('translation_files_path', ''),
            on_change=lambda text: self.on_change_translation_files_path(self.config, 'translation_files_path', text),
        )
        self.fileentry_translation_files.grid(row=1, column=1, sticky='WE')

        tk.Label(self, text="Language:").grid()
        self.combo_language = ComboboxCustom(self)
        self.combo_language.grid(row=2, column=1, sticky='WE')

        directory = self.fileentry_translation_files.text
        if path.exists(directory):
            languages = self.get_languages(directory)
            self.combo_language.values = languages
            if languages:
                self.combo_language.current(0)

        self.combo_language.bind('<<ComboboxSelected>>', self.update_listbox_translation_files)

        tk.Label(self, text="Encoding:").grid()
        self.combo_encoding = ComboboxCustom(self)
        self.combo_encoding.grid(row=3, column=1, sticky='WE')

        self.update_combo_encoding()

        self.listbox_translation_files = ListboxCustom(self)
        self.listbox_translation_files.grid(columnspan=2, sticky='NSWE')
        self.update_listbox_translation_files(language=self.combo_language.text)

        ttk.Button(self, text='Search', command=self.bt_search).grid()
        ttk.Button(self, text='Translate', command=lambda: self.bt_search(translate=True)).grid(row=5, column=1)

        self.listbox_found_directories = ListboxCustom(self)
        self.listbox_found_directories.grid(columnspan=2, sticky='NSWE')

        self.grid_columnconfigure(1, weight=1)