diff --git a/src/fastwq/context.py b/src/fastwq/context.py index e130cf5..4f7f56f 100644 --- a/src/fastwq/context.py +++ b/src/fastwq/context.py @@ -51,7 +51,7 @@ class Config(object): data['%s_last' % self.pmname] = data.get('last_model', self.last_model_id) self.data.update(data) with open(self.path, 'wb') as f: - json.dump(self.data, f) + json.dump(self.data, f, indent=4, sort_keys=True) f.close() def read(self): diff --git a/src/fastwq/lang.py b/src/fastwq/lang.py index ba736a3..0495250 100644 --- a/src/fastwq/lang.py +++ b/src/fastwq/lang.py @@ -18,54 +18,80 @@ # along with this program. If not, see . from anki.lang import currentLang -trans = { - 'CHECK_FILENAME_LABEL': {'zh_CN': u'使用文件名作为标签', 'en': u'Use filename as dict label', 'fr': r"Utiliser le nom de fichier en tant qu'étiquette de dico"}, - 'EXPORT_MEDIA': {'zh_CN': u'导出媒体文件', 'en': u'Export media files', 'fr': u'Exporter les fichiers multimédias'}, - 'DICTS_FOLDERS': {'zh_CN': u'字典文件夹', 'en': u'Dict folders', 'fr': u'Dossiers dico'}, - 'CHOOSE_NOTE_TYPES': {'zh_CN': u'选择笔记类型', 'en': u'Choose note types', 'fr': u'Choisir le type de note '}, - 'CURRENT_NOTE_TYPE': {'zh_CN': u'当前类型', 'en': u'Current type', 'fr': u'Type utilisé en cours'}, - 'MDX_SERVER': {'zh_CN': u'MDX服务器', 'en': u'MDX server', 'fr': u'serveur MDX'}, - 'USE_DICTIONARY': {'zh_CN': u'使用字典', 'en': u'Use dict', 'fr': u'Utilisé un dico'}, - 'UPDATED': {'zh_CN': u'更新', 'en': u'Updated', 'fr': u'Mettre à jour'}, - 'CARDS': {'zh_CN': u'卡片', 'en': u'Cards', 'fr': u'Cartes'}, - 'FAILURE': {'zh_CN': u'失败', 'en': u'Failure', 'fr': u'Échec'}, - 'SUCCESS': {'zh_CN': u'成功', 'en': u'Success', 'fr': u'Succès'}, - 'QUERIED': {'zh_CN': u'查询', 'en': u'Queried', 'fr': u'Quêté'}, - 'FIELDS': {'zh_CN': u'字段', 'en': u'Fields', 'fr': u'Champs'}, - 'WORDS': {'zh_CN': u'单词', 'en': u'Words', 'fr': u'Mots'}, - 'NOT_DICT_FIELD': {'zh_CN': u'不是字典字段', 'en': u'Not dict field', 'fr': u'Pas un champ de dico'}, - 'NOTE_TYPE_FIELDS': {'zh_CN': u'笔记字段', 'en': u'Note fields', 'fr': u'Champ de note'}, - 'DICTS': {'zh_CN': u'字典', 'en': u'Dict', 'fr': u'Dico'}, - 'DICT_FIELDS': {'zh_CN': u'字典字段', 'en': u'Dict fields', 'fr': u'Champ de dico'}, - 'RADIOS_DESC': {'zh_CN': u'单选框选中为待查询单词字段', 'en': u'Word field needs to be selected.', 'fr': u'Champ de mot doit d\'être sélectionné. '}, - 'NO_QUERY_WORD': {'zh_CN': u'查询字段无单词', 'en': u'No word is found in the query field', 'fr': u'Aucun est trouvé dans le champ'}, - 'CSS_NOT_FOUND': {'zh_CN': u'没有找到CSS文件,请手动选择', 'en': u'No valid css stylesheets found, please choose the file', 'fr': u'Aucun fichier de style CSS est valide, veuillez choisir le fichier'}, - 'ABOUT': {'zh_CN': u'关于', 'en': u'About', 'fr': u'À propos'}, - 'REPOSITORY': {'zh_CN': u'项目地址', 'en': u'Project homepage', 'fr': u'Accueil du projet'}, - 'FEEDBACK': {'zh_CN': u'反馈', 'en': u'Feedback', 'fr': u'Retourner de l\'information'}, - 'VERSION': {'zh_CN': u'版本', 'en': u'Version', 'fr': u'Version'}, - 'LATEST_VERSION': {'zh_CN': u'无更新版本.', 'en': u'No update version.', 'fr': u'Pas de mise à jour.'}, - 'ABNORMAL_VERSION': {'zh_CN': u'当前版本异常.', 'en': u'The current version is abnormal.', 'fr': u'La version actuelle est anormale.'}, - 'CHECK_FAILURE': {'zh_CN': u'版本检查失败.', 'en': u'Version check failure.', 'fr': u'Erreur de vérifier la version.'}, - 'NEW_VERSION': {'zh_CN': u'检查到新版本:', 'en': u'New version:', 'fr': u'Nouvelle version:'}, - 'UPDATE': {'zh_CN': u'更新', 'en': u'Update', 'fr': u'Mise à jour'}, - 'FORCE_UPDATE': {'zh_CN': u'强制更新字段', 'en': u'Force update'}, - 'SETTINGS': {'zh_CN': u'参数', 'en': u'Settings'}, - 'THREAD_NUMBER': {'zh_CN': u'线程数', 'en': u'Thread'}, -} +__all__ = ['_', '_cl', '_sl'] + + +#Language Define, [Key, zh_CN, en] +arr = [ + ['CHECK_FILENAME_LABEL', u'使用文件名作为标签', u'Use filename as dict label'], + ['EXPORT_MEDIA', u'导出媒体文件', u'Export media files'], + ['DICTS_FOLDERS', u'字典文件夹', u'Dict folders'], + ['CHOOSE_NOTE_TYPES', u'选择笔记类型', u'Choose note types'], + ['CURRENT_NOTE_TYPE', u'当前类型', u'Current type'], + ['MDX_SERVER', u'MDX服务器', u'MDX server'], + ['USE_DICTIONARY', u'使用字典', u'Use dict'], + ['UPDATED', u'更新', u'Updated'], + ['CARDS', u'卡片', u'Cards'], + ['FAILURE', u'失败', u'Failure'], + ['SUCCESS', u'成功', u'Success'], + ['QUERIED', u'查询', u'Queried'], + ['FIELDS', u'字段', u'Fields'], + ['WORDS', u'单词', u'Words'], + ['NOT_DICT_FIELD', u'忽略', u'Ignore'], #不是字典字段 + ['NOTE_TYPE_FIELDS', u'笔记字段', u'Note fields'], + ['DICTS', u'字典', u'Dict'], + ['DICT_FIELDS', u'字典字段', u'Dict fields'], + ['RADIOS_DESC', u'单选框选中为待查询单词字段', u'Word field needs to be selected.'], + ['NO_QUERY_WORD', u'查询字段无单词', u'No word is found in the query field'], + ['CSS_NOT_FOUND', u'没有找到CSS文件,请手动选择', u'No valid css stylesheets found, please choose the file'], + ['ABOUT', u'关于', u'About'], + ['REPOSITORY', u'项目地址', u'Project homepage'], + ['FEEDBACK', u'反馈', u'Feedback'], + ['VERSION', u'版本', u'Version'], + ['LATEST_VERSION', u'已经是最新版本.', u'It\'s the lastest version.'], + ['ABNORMAL_VERSION', u'当前版本异常.', u'The current version is abnormal.'], + ['CHECK_FAILURE', u'版本检查失败.', u'Version check failure.'], + ['NEW_VERSION', u'检查到新版本:', u'New version:'], + ['UPDATE', u'更新', u'Update'], + ['FORCE_UPDATE', u'强制更新字段', u'Force update'], + ['SETTINGS', u'参数', u'Settings'], + ['THREAD_NUMBER', u'线程数', u'Thread'], + + ['BRE_PRON', u'英式发音', u'British Pronunciation'], + ['AME_PRON', u'美式发音', u'American Pronunciation'], + ['PRON', u'发音', u'Pronunciation'], + ['EXAMPLE', u'例句', u'Example'], + ['TRANS', u'翻译', u'Translation'], + ['DEF', u'释义', u'Definition'], + ['PHON', u'音标', u'Phonetic'], + ['BRE_PHON', u'英式音标', u'British Phonetic'], + ['AME_PHON', u'美式音标', u'American Phonetic'], + ['IMAGE', u'图片', u'Image'], +] + +trans = {item[0]: {'zh_CN': item[1], 'en': item[2]} for item in arr} + def _(key, lang=currentLang): - if lang != 'zh_CN' and lang != 'en' and lang != 'fr': - lang = 'en' # fallback + if lang != 'zh_CN' and lang != 'en': + lang = 'en' def disp(s): return s.lower().capitalize() - + if key not in trans or lang not in trans[key]: return disp(key) return trans[key][lang] +def _cl(labels, lang=currentLang): + if isinstance(labels, basestring): + return _(labels) + if lang != 'zh_CN' and lang != 'en': + lang = 'en' + return labels[0] if lang == 'zh_CN' else labels[1] + + def _sl(key): return trans[key].values() diff --git a/src/fastwq/progress.py b/src/fastwq/progress.py index d320aaa..c2f4541 100644 --- a/src/fastwq/progress.py +++ b/src/fastwq/progress.py @@ -52,12 +52,12 @@ class ProgressWindow(object): self._msg_count['fails_number'] ) if words_number or fields_number: - number_info += _('QUERIED') + '
' + 45 * '-' - number_info += u'
{0}: {1}{2}'.format( + number_info += _('QUERIED') + u'
' + 45 * u'-' + number_info += u'
{0}: {1} {2}'.format( _('SUCCESS'), words_number, _('WORDS')) - number_info += u'
{0}: {1}{2}'.format( + number_info += u'
{0}: {1} {2}'.format( _('UPDATE'), fields_number, _('FIELDS')) - number_info += u'
{0}: {1}{2}'.format( + number_info += u'
{0}: {1} {2}'.format( _('FAILURE'), fails_number, _('WORDS')) self._update(label=number_info, value=words_number) diff --git a/src/fastwq/service/LDOCE6.py b/src/fastwq/service/LDOCE6.py index c6302bd..499e5e6 100644 --- a/src/fastwq/service/LDOCE6.py +++ b/src/fastwq/service/LDOCE6.py @@ -12,7 +12,7 @@ MAPPINGS = [ LANG_TO_REGEXPS = {lang: regexps for lang, regexps in MAPPINGS} -@register(u'本地词典-LDOCE6') +@register([u'本地词典-LDOCE6', u'MDX-LDOCE6']) class Ldoce6(MdxService): def __init__(self): @@ -26,7 +26,7 @@ class Ldoce6(MdxService): def title(self): return self.__register_label__ - @export(u'音标', 1) + @export('PHON', 1) def fld_phonetic(self): html = self.get_html() m = re.search(r'(.*?)', html) @@ -59,15 +59,15 @@ class Ldoce6(MdxService): return self.get_anki_label(name, 'audio') return '' - @export(u'英式发音', 2) + @export('BRE_PRON', 2) def fld_voicebre(self): return self._fld_voice(self.get_html(), 'br') - @export(u'美式发音', 3) + @export('AME_PRON', 3) def fld_voiceame(self): return self._fld_voice(self.get_html(), 'us') - @export(u'例句', 4) + @export('EXAMPLE', 4) def fld_sentence(self): m = re.findall(r'\s*.*<\/span>', self.get_html()) if m: @@ -84,7 +84,7 @@ class Ldoce6(MdxService): return self._css(my_str) return '' - @export(u'释义', 5) + @export('DEF', 5) def fld_definate(self): m = m = re.findall(r'\s*.*<\/span>', self.get_html()) if m: diff --git a/src/fastwq/service/baicizhan.py b/src/fastwq/service/baicizhan.py index beaaacc..556d26e 100644 --- a/src/fastwq/service/baicizhan.py +++ b/src/fastwq/service/baicizhan.py @@ -1,24 +1,16 @@ #-*- coding:utf-8 -*- import json import os -import re -import urllib -import urllib2 -import xml.etree.ElementTree from collections import defaultdict - -from aqt.utils import showInfo - from .base import WebService, export, register -from ..utils import ignore_exception - -bcz_download_mp3 = True -bcz_download_img = True -@register(u'百词斩') +@register([u'百词斩', u'Baicizhan']) class Baicizhan(WebService): + bcz_download_mp3 = True + bcz_download_img = True + def __init__(self): super(Baicizhan, self).__init__() @@ -26,18 +18,17 @@ class Baicizhan(WebService): word = self.word.replace(' ', '_') url = u"http://mall.baicizhan.com/ws/search?w={}".format(word) try: - html = urllib2.urlopen(url, timeout=5).read() + html = self.get_response(url, timeout=5)#urllib2.urlopen(url, timeout=5).read() return self.cache_this(json.loads(html)) except: return defaultdict(str) - # @ignore_exception - @export(u'发音', 0) + @export('PRON', 0) def fld_phonetic(self): word = self.word.replace(' ', '_') url = u'http://baicizhan.qiniucdn.com/word_audios/{}.mp3'.format(word) audio_name = 'bcz_%s.mp3' % self.word - if bcz_download_mp3: + if self.bcz_download_mp3: if self.download(url, audio_name): # urllib.urlretrieve(url, audio_name) with open(audio_name, 'rb') as f: @@ -56,43 +47,43 @@ class Baicizhan(WebService): def _get_field(self, key, default=u''): return self.cache_result(key) if self.cached(key) else self._get_from_api().get(key, default) - @export(u'音标', 1) + @export('PHON', 1) def fld_explains(self): return self._get_field('accent') - @export(u'图片', 2) + @export('IMAGE', 2) def fld_img(self): url = self._get_field('img') - if url and bcz_download_img: + if url and self.bcz_download_img: filename = url[url.rindex('/') + 1:] if self.download(url, filename): return self.get_anki_label(filename, 'img') #return self.get_anki_label(url, 'img') return '' - @export(u'象形', 3) + @export([u'象形', u'Pictogram'], 3) def fld_df(self): url = self._get_field('df') - if url and bcz_download_img: + if url and self.bcz_download_img: filename = url[url.rindex('/') + 1:] if self.download(url, filename): return self.get_anki_label(filename, 'img') #return self.get_anki_label(url, 'img') return '' - @export(u'中文释义', 6) + @export(u'DEF', 6) def fld_mean(self): return self._get_field('mean_cn') - @export(u'英文例句', 4) + @export(u'EXAMPLE', 4) def fld_st(self): return self._get_field('st') - @export(u'例句翻译', 5) + @export('TRANS', 5) def fld_sttr(self): return self._get_field('sttr') - @export(u'单词tv', 7) + @export([u'单词tv', u'TV'], 7) def fld_tv_url(self): video = self._get_field('tv') if video: diff --git a/src/fastwq/service/base.py b/src/fastwq/service/base.py index 589b515..e741be7 100644 --- a/src/fastwq/service/base.py +++ b/src/fastwq/service/base.py @@ -38,6 +38,7 @@ from ..context import config from ..libs import MdxBuilder, StardictBuilder from ..utils import MapDict, wrap_css from ..libs.bs4 import BeautifulSoup +from ..lang import _cl try: import threading as _threading @@ -45,22 +46,26 @@ except ImportError: import dummy_threading as _threading -def register(label): - """register the dict service with a label, which will be shown in the dicts list.""" +def register(labels): + """ + register the dict service with a labels, which will be shown in the dicts list. + """ def _deco(cls): - cls.__register_label__ = label + cls.__register_label__ = _cl(labels) return cls return _deco -def export(label, index): - """export dict field function with a label, which will be shown in the fields list.""" +def export(labels, index): + """ + export dict field function with a labels, which will be shown in the fields list. + """ def _with(fld_func): @wraps(fld_func) def _deco(cls, *args, **kwargs): res = fld_func(cls, *args, **kwargs) return QueryResult(result=res) if not isinstance(res, QueryResult) else res - _deco.__export_attrs__ = (label, index) + _deco.__export_attrs__ = (_cl(labels), index) return _deco return _with @@ -123,12 +128,12 @@ def with_styles(**styles): return _deco return _with -# BS4资源锁,防止程序卡死 +# bs4 threading lock, overload protection BS_LOCKS = [_threading.Lock(), _threading.Lock()] def parseHtml(html): ''' - 使用BS4解析html + use bs4 lib parse HTML, run only 2 BS at the same time ''' lock = BS_LOCKS[random.randrange(0, len(BS_LOCKS) - 1, 1)] lock.acquire() @@ -138,7 +143,9 @@ def parseHtml(html): class Service(object): - '''service base class''' + ''' + Dictionary Service Abstract Class + ''' def __init__(self): self.cache = defaultdict(defaultdict) @@ -207,7 +214,9 @@ class Service(object): class WebService(Service): - '''web service class''' + """ + Web Dictionary Service + """ def __init__(self): super(WebService, self).__init__() @@ -250,7 +259,7 @@ class WebService(Service): class LocalService(Service): """ - 本地词典 + Local Dictionary Service """ def __init__(self, dict_path): @@ -275,12 +284,12 @@ class LocalService(Service): def _filename(self): return os.path.splitext(os.path.basename(self.dict_path))[0] -# mdx字典实例集 +# MdxBuilder instances map mdx_builders = defaultdict(dict) class MdxService(LocalService): """ - Mdx本地词典 + MDX Local Dictionary Service """ def __init__(self, dict_path): @@ -304,14 +313,14 @@ class MdxService(LocalService): else: return self.builder['_title'] - @export(u"default", 0) + @export([u'默认', u'Default'], 0) def fld_whole(self): html = self.get_html() js = re.findall(r'.*?', html, re.DOTALL) return QueryResult(result=html, js=u'\n'.join(js)) def _get_definition_mdx(self): - """根据关键字得到MDX词典的解释""" + """according to the word return mdx dictionary page""" content = self.builder.mdx_lookup(self.word) str_content = "" if len(content) > 0: @@ -321,7 +330,7 @@ class MdxService(LocalService): return str_content def _get_definition_mdd(self, word): - """根据关键字得到MDX词典的媒体""" + """according to the keyword(param word) return the media file contents""" word = word.replace('/', '\\') content = self.builder.mdd_lookup(word) if len(content) > 0: @@ -330,7 +339,7 @@ class MdxService(LocalService): return [] def get_html(self): - """取得self.word对应的html页面""" + """get self.word's html page from MDX""" if not self.html_cache[self.word]: html = self._get_definition_mdx() if html: @@ -338,7 +347,7 @@ class MdxService(LocalService): return self.html_cache[self.word] def save_file(self, filepath_in_mdx, savepath): - """从mmd中取出filepath_in_mdx媒体文件并保存到savepath""" + """according to filepath_in_mdx to get media file and save it to savepath""" try: bytes_list = self._get_definition_mdd(filepath_in_mdx) if bytes_list: @@ -372,7 +381,7 @@ class StardictService(LocalService): else: return self.builder.ifo.bookname.decode('utf-8') - @export(u"default", 0) + @export([u'默认', u'Default'], 0) def fld_whole(self): #self.builder.check_build() try: diff --git a/src/fastwq/service/bing.py b/src/fastwq/service/bing.py index 66500d6..b8ef0ea 100644 --- a/src/fastwq/service/bing.py +++ b/src/fastwq/service/bing.py @@ -5,7 +5,7 @@ from aqt.utils import showInfo, showText from .base import WebService, export, register, with_styles, parseHtml -@register(u'Bing') +@register([u'必应', u'Bing']) class Bing(WebService): def __init__(self): @@ -40,15 +40,15 @@ class Bing(WebService): def _get_field(self, key, default=u''): return self.cache_result(key) if self.cached(key) else self._get_content().get(key, default) - @export(u'美式音标', 1) + @export('AME_PHON', 1) def fld_phonetic_us(self): return self._get_field('phonitic_us') - @export(u'英式音标', 2) + @export('BRE_PHON', 2) def fld_phonetic_uk(self): return self._get_field('phonitic_uk') - @export(u'词语时态', 3) + @export([u'词语时态', u'Participle'], 3) def fld_participle(self): return self._get_field('participle') @@ -56,7 +56,7 @@ class Bing(WebService): def _css(self, val): return val - @export(u'释义', 4) + @export('DEF', 4) def fld_definition(self): val = self._get_field('def') if val == None or val == '': diff --git a/src/fastwq/service/bing3tp.py b/src/fastwq/service/bing3tp.py index 2a95fd1..3a4c035 100644 --- a/src/fastwq/service/bing3tp.py +++ b/src/fastwq/service/bing3tp.py @@ -1,9 +1,5 @@ #-*- coding:utf-8 -*- import json -import re -import urllib2 - -from aqt.utils import showInfo, showText from .base import WebService, export, register, with_styles bing_download_mp3 = True @@ -21,13 +17,15 @@ class BingXtk(WebService): 'Accept-Language': 'en-US,zh-CN;q=0.8,zh;q=0.6,en;q=0.4', 'User-Agent': 'WordQuery Addon (Anki)', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'} + word = self.word.replace(' ', '_') + url = u'http://xtk.azurewebsites.net/BingDictService.aspx?Word={}'.format(word.encode('utf-8')) try: - word = self.word.replace(' ', '_') - request = urllib2.Request(u'http://xtk.azurewebsites.net/BingDictService.aspx?Word=' +\ - word.encode('utf-8'), headers=headers) - resp = json.loads(urllib2.urlopen(request).read()) + #request = urllib2.Request(u'http://xtk.azurewebsites.net/BingDictService.aspx?Word=' +\ + # word.encode('utf-8'), headers=headers) + #resp = json.loads(urllib2.urlopen(request).read()) + resp = json.loads(self.get_response(url, headers=headers, timeout=10)) return self.cache_this(resp) - except Exception as e: + except: return resp def _get_field(self, key, default=u''): @@ -41,17 +39,17 @@ class BingXtk(WebService): subfield = default return subfield - @export(u'美式音标', 1) + @export('AME_PHON', 1) def fld_phonetic_us(self): seg = self._get_field('pronunciation') return self._get_subfield(seg, 'AmE') - @export(u'英式音标', 2) + @export('BRE_PHON', 2) def fld_phonetic_uk(self): seg = self._get_field('pronunciation') return self._get_subfield(seg, 'BrE') - @export(u'美式发音', 3) + @export('AME_PRON', 3) def fld_mp3_us(self): seg = audio_url = self._get_field('pronunciation') audio_url = self._get_subfield(seg, 'AmEmp3') @@ -61,7 +59,7 @@ class BingXtk(WebService): return self.get_anki_label(filename, 'audio') return audio_url - @export(u'英式发音', 4) + @export('BRE_PRON', 4) def fld_mp3_uk(self): seg = self._get_field('pronunciation') audio_url = self._get_subfield(seg, 'BrEmp3') @@ -75,15 +73,16 @@ class BingXtk(WebService): def _css(self, val): return val - @export(u'释义', 5) + @export('DEF', 5) def fld_definition(self): segs = self._get_field('defs') if isinstance(segs, list) and len(segs) > 0: - val = u'
'.join([u'{0} {1}'.format(seg['pos'], seg['def']) for seg in segs]) + val = u'
'.join([u'''{0} + {1}'''.format(seg['pos'], seg['def']) for seg in segs]) return self._css(val) return '' - @export(u'例句', 6) + @export('EXAMPLE', 6) # @with_styles(cssfile='_bing2.css', need_wrap_css=True, wrap_class=u'bing') def fld_samples(self): max_numbers = 10 @@ -92,11 +91,9 @@ class BingXtk(WebService): for i, seg in enumerate(segs): sentences = sentences +\ u"""
  • -
    {0}
    {1}
    -
    -
  • """.format(seg['eng'], seg['chn'], i + 1) + """.format(seg['eng'], seg['chn'])#, i + 1) if i == 9: break return u"""
    diff --git a/src/fastwq/service/pool.py b/src/fastwq/service/pool.py index 2446c10..39b88c1 100644 --- a/src/fastwq/service/pool.py +++ b/src/fastwq/service/pool.py @@ -39,6 +39,8 @@ class ServicePool(object): return self.manager.get_service(unique) def put(self, service): + if service is None: + return unique = service.unique queue = self.pools.get(unique, None) if queue == None: diff --git a/src/fastwq/ui.py b/src/fastwq/ui.py index 3b0cd9b..5df1494 100644 --- a/src/fastwq/ui.py +++ b/src/fastwq/ui.py @@ -309,6 +309,7 @@ class OptionsDialog(QDialog): self.setLayout(self.main_layout) self.resize(widget_size.dialog_width, (i + 1) * widget_size.map_max_height + widget_size.dialog_height_margin) + self.save() def show_models(self): edit = QPushButton(anki.lang._("Manage"), @@ -384,13 +385,13 @@ class OptionsDialog(QDialog): unique = dict_combo_itemdata service = service_pool.get(unique) # problem + field_combo.setEditText(u'') if service and service.support and service.fields: for each in service.fields: field_combo.addItem(each) if each == field_text: field_combo.setEditText(field_text) - - field_combo.setEnabled(service.support) + field_combo.setEnabled(service != None and service.support) service_pool.put(service) def radio_btn_checked(self):