diff --git a/src/calibre/gui2/tweak_book/spell.py b/src/calibre/gui2/tweak_book/spell.py index c992b81035..7a8a52b4df 100644 --- a/src/calibre/gui2/tweak_book/spell.py +++ b/src/calibre/gui2/tweak_book/spell.py @@ -19,7 +19,7 @@ from calibre.gui2 import choose_files, error_dialog from calibre.gui2.tweak_book.widgets import Dialog from calibre.spell.dictionary import ( builtin_dictionaries, custom_dictionaries, best_locale_for_language, - get_dictionary, DictionaryLocale, dprefs, remove_dictionary) + get_dictionary, DictionaryLocale, dprefs, remove_dictionary, rename_dictionary) from calibre.spell.import_from import import_from_oxt from calibre.utils.localization import calibre_langcode_to_name from calibre.utils.icu import sort_key @@ -103,8 +103,10 @@ class AddDictionary(QDialog): # {{{ try: num = import_from_oxt(oxt, nick) except: + import traceback return error_dialog(self, _('Failed to import dictionaries'), _( - 'Failed to import dictionaries from %s. Click "Show Details" for more information') % oxt, show=True) + 'Failed to import dictionaries from %s. Click "Show Details" for more information') % oxt, + det_msg=traceback.format_exc(), show=True) if num == 0: return error_dialog(self, _('No dictionaries'), _( 'No dictionaries were found in %s') % oxt, show=True) @@ -146,6 +148,7 @@ class ManageDictionaries(Dialog): s.addWidget(w) self.dictionaries = d = QTreeWidget(self) + d.itemChanged.connect(self.data_changed, type=Qt.QueuedConnection) self.build_dictionaries() d.setCurrentIndex(d.model().index(0, 0)) d.header().close() @@ -161,6 +164,12 @@ class ManageDictionaries(Dialog): b.clicked.connect(self.add_dictionary) l.addWidget(self.bb, l.rowCount(), 0, 1, l.columnCount()) + def data_changed(self, item, column): + if column == 0 and item.type() == DICTIONARY: + d = item.data(0, Qt.UserRole).toPyObject() + if not d.builtin and unicode(item.text(0)) != d.name: + rename_dictionary(d, unicode(item.text(0))) + def build_dictionaries(self, reread=False): all_dictionaries = builtin_dictionaries() | custom_dictionaries(reread=reread) languages = defaultdict(lambda : defaultdict(set)) @@ -192,6 +201,8 @@ class ManageDictionaries(Dialog): pl += '-' + dictionary.primary_locale.countrycode.upper() k.setText(0, dictionary.name or (_('').format(pl))) k.setData(0, Qt.UserRole, dictionary) + if dictionary.name: + k.setFlags(k.flags() | Qt.ItemIsEditable) if pd == dictionary: k.setData(0, Qt.FontRole, itf) diff --git a/src/calibre/spell/dictionary.py b/src/calibre/spell/dictionary.py index 677f4cc186..fd5939c58e 100644 --- a/src/calibre/spell/dictionary.py +++ b/src/calibre/spell/dictionary.py @@ -70,7 +70,10 @@ def custom_dictionaries(reread=False): dics = [] for lc in glob.glob(os.path.join(config_dir, 'dictionaries', '*/locales')): locales = filter(None, open(lc, 'rb').read().decode('utf-8').splitlines()) - name, locale, locales = locales[0], locales[1], locales[1:] + try: + name, locale, locales = locales[0], locales[1], locales[1:] + except IndexError: + continue base = os.path.dirname(lc) dics.append(Dictionary( parse_lang_code(locale), frozenset(map(parse_lang_code, locales)), os.path.join(base, '%s.dic' % locale), @@ -95,6 +98,14 @@ def remove_dictionary(dictionary): shutil.rmtree(base) dprefs['preferred_dictionaries'] = {k:v for k, v in dprefs['preferred_dictionaries'].iteritems() if v != dictionary.id} +def rename_dictionary(dictionary, name): + lf = os.path.join(os.path.dirname(dictionary.dicpath), 'locales') + with open(lf, 'r+b') as f: + lines = f.read().splitlines() + lines[:1] = [name.encode('utf-8')] + f.seek(0), f.truncate(), f.write(b'\n'.join(lines)) + custom_dictionaries(reread=True) + def get_dictionary(locale, exact_match=False): preferred = preferred_dictionary(locale) # First find all dictionaries that match locale exactly diff --git a/src/calibre/spell/import_from.py b/src/calibre/spell/import_from.py index bda9155dd3..a83c92e345 100644 --- a/src/calibre/spell/import_from.py +++ b/src/calibre/spell/import_from.py @@ -63,6 +63,8 @@ def import_from_libreoffice_source_tree(source_path): def import_from_oxt(source_path, name, dest_dir=None, prefix='dic-'): dest_dir = dest_dir or os.path.join(config_dir, 'dictionaries') + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) num = 0 with ZipFile(source_path) as zf: root = etree.fromstring(zf.open('META-INF/manifest.xml').read())