From 9c4558c8c2cebe6fd70cfca56712275b3fa484e4 Mon Sep 17 00:00:00 2001 From: "St.Huang" Date: Wed, 15 Aug 2018 00:46:46 +0800 Subject: [PATCH] Add dictionary manager dialog --- addons/fastwq/context.py | 4 + addons/fastwq/gui/common.py | 27 ++++- addons/fastwq/gui/dictmanager.py | 173 +++++++++++++++++++++++++++++ addons/fastwq/gui/options.py | 55 +++++---- addons/fastwq/lang.py | 2 + addons/fastwq/res/add.png | Bin 0 -> 378 bytes addons/fastwq/res/setting.png | Bin 0 -> 1429 bytes addons/fastwq/res/wqicon.png | Bin 2712 -> 577 bytes addons/fastwq/service/manager.py | 1 + addons21/fastwq/context.py | 4 + addons21/fastwq/gui/common.py | 27 ++++- addons21/fastwq/gui/dictmanager.py | 173 +++++++++++++++++++++++++++++ addons21/fastwq/gui/options.py | 55 +++++---- addons21/fastwq/lang.py | 2 + addons21/fastwq/res/add.png | Bin 0 -> 378 bytes addons21/fastwq/res/setting.png | Bin 0 -> 1429 bytes addons21/fastwq/res/wqicon.png | Bin 2712 -> 577 bytes addons21/fastwq/service/manager.py | 1 + 18 files changed, 478 insertions(+), 46 deletions(-) create mode 100644 addons/fastwq/gui/dictmanager.py create mode 100644 addons/fastwq/res/add.png create mode 100644 addons/fastwq/res/setting.png create mode 100644 addons21/fastwq/gui/dictmanager.py create mode 100644 addons21/fastwq/res/add.png create mode 100644 addons21/fastwq/res/setting.png diff --git a/addons/fastwq/context.py b/addons/fastwq/context.py index cb40c2b..206505d 100644 --- a/addons/fastwq/context.py +++ b/addons/fastwq/context.py @@ -90,6 +90,10 @@ class Config(object): def dirs(self): return self.data.get('dirs', list()) + @property + def dicts(self): + return self.data.get('dicts', dict()) + @property def use_filename(self): return self.data.get('use_filename', True) diff --git a/addons/fastwq/gui/common.py b/addons/fastwq/gui/common.py index f4acdd5..239946f 100644 --- a/addons/fastwq/gui/common.py +++ b/addons/fastwq/gui/common.py @@ -23,11 +23,12 @@ from aqt.qt import * from aqt.utils import showInfo from .options import OptionsDialog from .foldermanager import FoldersManageDialog +from .dictmanager import DictManageDialog from ..libs import ankihub from ..context import config from ..lang import _ from ..constants import Endpoint, Template -from ..service import service_manager +from ..service import service_manager, service_pool __all__ = ['show_options', 'check_updates', 'show_fm_dialog', 'show_about_dialog'] @@ -55,12 +56,27 @@ def show_fm_dialog(browser = None): fm_dialog.raise_() if fm_dialog.exec_() == QDialog.Accepted: # update local services + service_pool.clean() service_manager.update_services() fm_dialog.destroy() # reshow options window show_options(browser) +def show_dm_dialog(browser = None): + parent = mw if browser is None else browser + dm_dialog = DictManageDialog(parent, u'Dictionary Manager') + dm_dialog.activateWindow() + dm_dialog.raise_() + if dm_dialog.exec_() == QDialog.Accepted: + # update local services + service_pool.clean() + service_manager.update_services() + dm_dialog.destroy() + # reshow options window + show_options(browser) + + def show_options(browser = None, model_id = -1, callback = None, *args, **kwargs): '''open options window''' parent = mw if browser is None else browser @@ -68,10 +84,15 @@ def show_options(browser = None, model_id = -1, callback = None, *args, **kwargs opt_dialog = OptionsDialog(parent, u'Options', model_id) opt_dialog.activateWindow() opt_dialog.raise_() - if opt_dialog.exec_() == QDialog.Accepted: + result = opt_dialog.exec_() + opt_dialog.destroy() + if result == QDialog.Accepted: if isinstance(callback, types.FunctionType): callback(*args, **kwargs) - opt_dialog.destroy() + elif result == 1001: + show_fm_dialog(parent) + elif result == 1002: + show_dm_dialog(parent) def show_about_dialog(parent): diff --git a/addons/fastwq/gui/dictmanager.py b/addons/fastwq/gui/dictmanager.py new file mode 100644 index 0000000..d1412ef --- /dev/null +++ b/addons/fastwq/gui/dictmanager.py @@ -0,0 +1,173 @@ +#-*- coding:utf-8 -*- +# +# Copyright (C) 2018 sthoo +# +# Support: Report an issue at https://github.com/sth2018/FastWordQuery/issues +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version; http://www.gnu.org/copyleft/gpl.html. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import sys +from aqt.qt import * +from aqt.forms.editaddon import Ui_Dialog +from .base import Dialog, WIDGET_SIZE +from ..service import service_manager, service_pool +from ..context import config +from ..lang import _, _sl +from ..utils import get_icon + +# 2x3 compatible +if sys.hexversion >= 0x03000000: + unicode = str + + +__all__ = ['DictManageDialog'] + + +class DictManageDialog(Dialog): + ''' + Dictionary manager window. enabled or disabled dictionary, and setting params of dictionary. + ''' + + def __init__(self, parent, title=u'Dictionary Manager'): + super(DictManageDialog, self).__init__(parent, title) + self.main_layout = QVBoxLayout() + self.setLayout(self.main_layout) + self._options = list() + btnbox = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal , self) + btnbox.accepted.connect(self.accept) + # add dicts mapping + self.dicts_layout = QGridLayout() + self.main_layout.addLayout(self.dicts_layout) + self.main_layout.addWidget(btnbox) + self.build() + + def build(self): + ''' ''' + # labels + f = QFont() + f.setBold(True) + labels = ['', ''] + for i, s in enumerate(labels): + if s: + label = QLabel(_(s)) + label.setFont(f) + label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + self.dicts_layout.addWidget(label, 0, i) + # enabled all + self.enabled_all_check_btn = QCheckBox(_('DICTS_NAME')) + self.enabled_all_check_btn.setFont(f) + self.enabled_all_check_btn.setEnabled(True) + self.enabled_all_check_btn.setChecked(True) + # signal + self.enabled_all_check_btn.clicked.connect(self.enabled_all_changed) + # add widgets + self.dicts_layout.addWidget(self.enabled_all_check_btn, 0, 0) + # dict service list + confs = config.dicts + dicts = list() + for clazz in service_manager.web_services: + service = service_pool.get(clazz.__unique__) + if service and service.support: + dicts.append({ + 'title': service.title, + 'unique': service.unique, + 'path': clazz.__path__, + 'enabled': confs.get(service.unique, dict()).get('enabled', True) + }) + service_pool.put(service) + # add dict + for i, d in enumerate(dicts): + self.add_dict_layout(i, **d) + # update + self.enabled_all_update() + self.adjustSize() + + def add_dict_layout(self, i, **kwargs): + # args + title, unique, enabled, path = ( + kwargs.get('title', u''), + kwargs.get('unique', u''), + kwargs.get('enabled', False), + kwargs.get('path', u''), + ) + # button + check_btn = QCheckBox(title) + check_btn.setMinimumSize(WIDGET_SIZE.map_dict_width*1.5, 0) + check_btn.setEnabled(True) + check_btn.setChecked(enabled) + edit_btn = QToolButton(self) + edit_btn.setText(_('EDIT')) + # signal + check_btn.stateChanged.connect(self.enabled_all_update) + edit_btn.clicked.connect(lambda: self.on_edit(path)) + # add + self.dicts_layout.addWidget(check_btn, i + 1, 0) + self.dicts_layout.addWidget(edit_btn, i + 1, 1) + self._options.append({ + 'unique': unique, + 'check_btn': check_btn, + 'edit_btn': edit_btn, + }) + + def enabled_all_update(self): + b = True + for row in self._options: + if not row['check_btn'].isChecked(): + b = False + break + self.enabled_all_check_btn.setChecked(b) + + def enabled_all_changed(self): + b = self.enabled_all_check_btn.isChecked() + for row in self._options: + row['check_btn'].setChecked(b) + + def on_edit(self, path): + '''edit dictionary file''' + d = QDialog(self) + frm = Ui_Dialog() + frm.setupUi(d) + d.setWindowTitle(os.path.basename(path)) + # 2x3 compatible + if sys.hexversion >= 0x03000000: + frm.text.setPlainText(open(path, 'r', encoding="utf-8").read()) + else: + frm.text.setPlainText(unicode(open(path).read(), "utf8")) + d.accepted.connect(lambda: self.on_accept_edit(path, frm)) + d.exec_() + + def on_accept_edit(self, path, frm): + '''save dictionary file''' + # 2x3 compatible + if sys.hexversion >= 0x03000000: + open(path, "w", encoding='utf-8').write(frm.text.toPlainText()) + else: + open(path, "w").write(frm.text.toPlainText().encode("utf8")) + + def accept(self): + '''ok button clicked''' + self.save() + super(DictManageDialog, self).accept() + + def save(self): + '''save config to file''' + data = dict() + dicts = {} + for row in self._options: + dicts[row['unique']] = { + 'enabled': row['check_btn'].isChecked(), + } + data['dicts'] = dicts + config.update(data) diff --git a/addons/fastwq/gui/options.py b/addons/fastwq/gui/options.py index 325268a..586edef 100644 --- a/addons/fastwq/gui/options.py +++ b/addons/fastwq/gui/options.py @@ -74,6 +74,7 @@ class OptionsDialog(Dialog): if s != 'before_build': return # dict service list + dicts = config.dicts self.dict_services = { 'local': [], #本地词典 'web': [] #网络词典 @@ -87,13 +88,14 @@ class OptionsDialog(Dialog): }) service_pool.put(service) for clazz in service_manager.web_services: - service = service_pool.get(clazz.__unique__) - if service and service.support: - self.dict_services['web'].append({ - 'title': service.title, - 'unique': service.unique - }) - service_pool.put(service) + if dicts.get(clazz.__unique__, dict()).get('enabled', True): + service = service_pool.get(clazz.__unique__) + if service and service.support: + self.dict_services['web'].append({ + 'title': service.title, + 'unique': service.unique + }) + service_pool.put(service) # emit finished self._signal.emit('after_build') @@ -117,6 +119,7 @@ class OptionsDialog(Dialog): self.tab_widget = QTabWidget() self.tab_widget.setTabsClosable(True) self.tab_widget.setMovable(False) + self.tab_widget.tabBar().setExpanding(False) self.tab_widget.setStyleSheet( """ QTabWidget::pane { /* The tab widget frame */ @@ -124,10 +127,21 @@ class OptionsDialog(Dialog): } """ ) + tab_corner = QWidget() + tab_corner_layout = QHBoxLayout() + tab_corner_layout.setSpacing(1) + tab_corner_layout.setSizeConstraint(QLayout.SetMinAndMaxSize) + tab_corner_layout.setContentsMargins(0, 0, 0, 0) + tab_corner.setLayout(tab_corner_layout) tab_add_button = QToolButton(self) - tab_add_button.setText(' + ') - self.tab_widget.setCornerWidget(tab_add_button) + tab_add_button.setIcon(get_icon('add.png')) + tab_set_button = QToolButton(self) + tab_set_button.setIcon(get_icon('setting.png')) + tab_corner_layout.addWidget(tab_set_button) + tab_corner_layout.addWidget(tab_add_button) + self.tab_widget.setCornerWidget(tab_corner) # signals + tab_set_button.clicked.connect(self.show_dm_dialog) tab_add_button.clicked.connect(self.addTab) self.tab_widget.tabCloseRequested.connect(self.removeTab) # layout @@ -178,11 +192,13 @@ class OptionsDialog(Dialog): def show_fm_dialog(self): '''open folder manager dialog''' - from .common import show_fm_dialog - self.save() - self.close() - self.destroy() - show_fm_dialog(self._parent) + self.accept() + self.setResult(1001) + + def show_dm_dialog(self): + '''open dictionary manager dialog''' + self.accept() + self.setResult(1002) def show_about(self): '''open about dialog''' @@ -398,9 +414,9 @@ class TabContent(QWidget): dict_combo.setFocusPolicy( Qt.TabFocus | Qt.ClickFocus | Qt.StrongFocus | Qt.WheelFocus ) - dict_combo.setEnabled(not word_checked and not ignore) - self.fill_dict_combo_options(dict_combo, dict_unique, self._services) + ignore = not self.fill_dict_combo_options(dict_combo, dict_unique, self._services) or ignore dict_unique = dict_combo.itemData(dict_combo.currentIndex()) + dict_combo.setEnabled(not word_checked and not ignore) # field combox field_combo = QComboBox() field_combo.setMinimumSize(WIDGET_SIZE.map_field_width, 0) @@ -500,15 +516,14 @@ class TabContent(QWidget): dict_combo.addItem(service['title'], userData=service['unique']) def set_dict_combo_index(): - #dict_combo.setCurrentIndex(-1) dict_combo.setCurrentIndex(0) if current_unique: for i in range(dict_combo.count()): if dict_combo.itemData(i) == current_unique: dict_combo.setCurrentIndex(i) - break - - set_dict_combo_index() + return True + return False + return set_dict_combo_index() def fill_field_combo_options(self, field_combo, dict_combo_text, dict_combo_itemdata, dict_fld_name, dict_fld_ord): '''setup field combobox''' diff --git a/addons/fastwq/lang.py b/addons/fastwq/lang.py index 9a0bb52..54afdd0 100644 --- a/addons/fastwq/lang.py +++ b/addons/fastwq/lang.py @@ -69,6 +69,8 @@ _arr = [ ['PLS_SET_DICTIONARY_FIELDS', u'请设置字典和字段', u'Please set the dictionary and fields.'], ['CONFIG_INDEX', u'配置 %s', u'Config %s'], ['SELECT_ALL', u'全选', u'All'], + ['DICTS_NAME', u'字典名称', u'Dictionary Name'], + ['EDIT', u'编辑', u'Edit'], ['BRE_PRON', u'英式发音', u'British Pronunciation'], ['AME_PRON', u'美式发音', u'American Pronunciation'], diff --git a/addons/fastwq/res/add.png b/addons/fastwq/res/add.png new file mode 100644 index 0000000000000000000000000000000000000000..6a3b981dbf8f880db111e0e9766c667f5dd10fce GIT binary patch literal 378 zcmV-=0fqjFP)F?ja*d0J3$OPgRDEliA_mX1>BXS}nAp`_~_&u7K6c9fr zH3Y~_1HxFur0AIl|6mdOHJS}a9Y9Y9yu~8+p5l@a3Ge~2ARc|vSj4oTr6Mly5r{uv zh=K|t7-nK(;sD|dApQl!|EY}s0&xit3n1Hx?to?*Sd5PQQ0znt5LS9ufaoE>1H?r% z^nE=Liz3^Jt1=P?Vlh0vkObnLXkx)Ye49Ydd4^sYky{&b0P%M$j(S0_+E5&enCNIx zJn8^?IsjW8!bVRAV5|9F(9;3$fVdQi-vGo_xlwo)cE*#MO9TLT(sD;)B_*8z z(5HBv9O5a2zJLm%=~s6n7VjdSiwWTk_5%1Wu{$u{o}8R))a&(A2?+_?oclL6HVh9R zKFoK!-6q0+9lj>SYXEeE=)BJJR>+y?Dagsm3GR}+_4V~HQBr`1R)pXCyF|3}@{Vy; zr_*UT*TCasxAI#K20sRX9Wt-2t-V@RRduYOpy0~p=4NaWh+H>s-hBV)(WBoIZaZH4 z!oV;ryXy6NwHOKz6)%Pr-h;&_Yj$?l(AwI1@9Nd7Z}B=Ga}7iSs;#Z{wr!z@@6FwnoB7TYpcYSm=G}vrTZGs@H8qu0T3YJr?d`o*Utj+xIoFPijMR5`cfaOxxs>AK;s*eW zL$ASZw=a^0X4J0kR|85!b??P+AvZTSaQN_HOL=*@H6M+XVTKrmWkX?MDvZkWFD&l7*As88bTitcBizE6xQN*#Cs6DI%wqb0ZN z=g*&Cks6`rgCm#XQ^>VKdKB`#hKxI$9*k-rAB8F%8NSl!ejjp~d>;dl3FEgrD&=g$|m?$jESD&0kMQ) z0bnJ^7RIp51qWV_LgO+ch>R11CgBlYWSlK6Ek8uj|9BC0b#*Dz)6>er!h({YpYN6e z!a%s^RlHSsze5BPNz;pnYy;vR=N`_q;aLJ8kJ)TCG&D5CI~)!lX;el>M-TQjWPMJ> ze?w@^07;<>bcA+8CL(J`Hgxd_&>8VtTU&YndXRa5Oci7NGg!{W{52dN9uDplk}^I% zzS_~zAvc*4=>Q_KJTo(sCpIy#EJlS_dLA#0QZJ2-jkAl3i~6~_xiV_ObNTY+X}Ut; zcO|Aa+(l|%U*9=~579Ks1Z*7~9Q-=e9rJ*Y@hq*jK)xp?Cnvvx=M{{9c>46|U-$rZ zMyr8n0EDuj8YnK}?4_ET8WV=aEk|{AwJF3C{#|NDE-}f`^v7~5UV;9Q`)TA=;rQ|6 z1MGUCwzjq(Lpja3lf`)R0li*;*U_a9GMP~ zL1Moksc3{2B8QO@k_Z_N_zuo4aAj54wyrt<)uh^E66Pe1kp-0TOuu&L(`W{ zNl93WW|%7h%MGB_GkOITM@enC3(c^_Kx_%b>`-}TsDH(i2-K2slvKytuowu+W>0YV zm?%e(;s6lHgO&;ZDa3K)IsjInBm(g=Xi@zH+5lM%#K}Oc0mSEsa6}Bb4j=}AS~C}j zaD*|f8~_7^95EYTWkd}C${82&$g|-qim3_C;|Kv~T1NqLn%IqIc^N6KVrl?MAWnsL qYEA?30wHXzV#d+V=|DRGAix0Jz9z94%>y_90000qx delta 2704 zcmZ`*c{tR27ymN0Y}t3RYi_v1a7EmPMwUX9%2*=1i7-a?-`p^aOC)3`yBIJH5aIyXV^V}=0PqL^R$Kuv$Ob?>Fu&c_kXhikdBF_LL}u)s>wuVWEYREm z2LO-of0G5|=1VY1&JYVLQ_fjVetrp6$&OuaW?O;<+W5-#-o9%PHqic)=+W4h{rtQ< zs$qa!8s{;E+U#A3afUkX@TYHYu5`;?aRce}@Swh;WxSG~`H0=b0iTl)a8_u=wE19mkO#Z^^O zLVcdiqF7wzlYyJ*HY*&d9J)vvpxr^x^Kxvtxt-C9Z~-h~xzfolS9N zBLWg$L~g243?)(NJZ0lSzigzWas^T_Mfaq1wL|06e$2eL8krdz3k{!t?ftLJK=`rl zlYkHXlphrr39@<7=^x?*S^Vkc{H0UCl(`sag9h~EuH1hozclJi)>iiCH1jWtg z9UaeTIBt#qrSJ*^CMtY26-&qcmcM zAt{EUs7vr>*Pgq(j$J!*WzW%ZO6qDJ9m76doN0YTMDoI6eIF- zytU~QM7N{!T!K;n#il0J42iLv{1HYe2Yl~z8`ZHY1l97FH=}O8CSa zCw{4Tj6AhW8Ys{Q&(WvTv$EP}yY|-t>Z`*Uf{Gh!V`S;$-^Uvqd7n{F)z{wP?Ok?V z9DV!t8$;>*yx%|&$KqUtZ@?$a(7U0bGev1L`nb7QZ~pKqBlH>;qE6>{M=MV#lMXm&CSm9^BzT)-(FWOPgYjjPvSdQuoXs$ zEXzn0vVB@gqw^f8JRK`#31bP#tyq!)p)zVb#fd`?CCqKMaiLoXBZQb{6sqGcZFKZX z!2_g|x2LBMSvMHhg!f+3`*x4!B+N_vi)b>tt$2Sq02)jpyDbLUB^8fJ>9FZrz^@@U zwZSy{S60p52Z~`~;!%8zxJ(iT7A1?cBl)E6YX;ZznwIOu*}+E; z6(G@Hid%XgQ{UWd1%}Uk^Zd2n5wgy{N5;<-NIdiA;EPr*K?wGh*wWd(G?hxGiEb2Y zn{8<5HHEU%FhFZdN&JgNg1L+rrdkehw_IHA5j#-b&QJb?!-G6+Y}S42KRX6YZH>f0 zlOMx37o(=X9Qjip*NC4UshDoa&8g4*`*3k3IXR>=g7IJ@Jsm5K!08LF+E`e)?0j#6 ze5lRX)L@wuiwCM90ppkUJ#n}i*Tu+ETZq0SD_ihFNm0xs5m~qE(SNhy{%qhWNunQY zoGU@8twq*MeprR0|9!#wN0b;_tntd)+M|i4b*oX#S8iaJgvWmF8h;kP8CqKZr}=DP zHox3~xzWzdVP}PJE&Fh3b79O*pmY1zqW+hN(PN)K2+@Knzwa(#(OzEXPoWB0{2?24 zxFqg=!i^mt2@ZoZFc-om_yzZj>VkgvT(G{*bfBV^)*_+1p^KC@ImJB`HhM5i2uiAiNu)o}Pq^;teI-iRD_1Wa)I~o?Nm%6YZ z@5(Duqqm){Ps?b+(#+6mheuCu=jP^;9zPDyU7@F{=;^f{W#-g48HGU4zGbh*lul3U z&Q9I*VD;eu3a|3)-fsI(9htp&RDHw#YSwzbE`2LZ-D`v-tmb>TXLVU)5W`c9wshzW zUigTQ++Gt7(3k6_kNH1W5R+CP@XoZmkXSX;vML@gkY^}|6Gvt^CO>AG@90Y`7kN}$ zOUWVCN(8bWh0XNI5cmXUo56@MrLPM?Oq@>`c#$e3LT8Gw1 z-rg{Ct`BN)uJDDJ`p=P_ZW6~W;oE9VbLK>{BYDb4N9^8eAicjVhA$QPYa@|L*Wirg zp@%xga7LU!i33-UcnU#a?!xvLJ4>Uy%*>pMy}p6OzMB$fp%`j^saa~J5BZ_ird5__ zr)J#sp(1rKOXTJ)Yjy(h?fP_*Bl1j7@yv*8BD6{@z`zQ)j#; zPF-(&-G;V0b?4&K+VS4C<0C|mE8X}@3*5Tc*G}1qTc^rh-42k)CpJiFt7Nt&*WFb@+umk;%gAsjT&3Fg(1i{RyHd`tK7!UMi)e zp#jQa9{j4-R-1#f@8E~StGf`8ElG7Rq}mNLKR1;S)9WD~ZXuoq?!lf+0NMyGJq?7O zhL+A1Egb`G9RuX)QwVJX1VYv}=F0yF{BL{sdWHXg!7bi?=35Dl0Si-Wbe)Oo-TwfV Ci3O +# +# Support: Report an issue at https://github.com/sth2018/FastWordQuery/issues +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version; http://www.gnu.org/copyleft/gpl.html. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import sys +from aqt.qt import * +from aqt.forms.editaddon import Ui_Dialog +from .base import Dialog, WIDGET_SIZE +from ..service import service_manager, service_pool +from ..context import config +from ..lang import _, _sl +from ..utils import get_icon + +# 2x3 compatible +if sys.hexversion >= 0x03000000: + unicode = str + + +__all__ = ['DictManageDialog'] + + +class DictManageDialog(Dialog): + ''' + Dictionary manager window. enabled or disabled dictionary, and setting params of dictionary. + ''' + + def __init__(self, parent, title=u'Dictionary Manager'): + super(DictManageDialog, self).__init__(parent, title) + self.main_layout = QVBoxLayout() + self.setLayout(self.main_layout) + self._options = list() + btnbox = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal , self) + btnbox.accepted.connect(self.accept) + # add dicts mapping + self.dicts_layout = QGridLayout() + self.main_layout.addLayout(self.dicts_layout) + self.main_layout.addWidget(btnbox) + self.build() + + def build(self): + ''' ''' + # labels + f = QFont() + f.setBold(True) + labels = ['', ''] + for i, s in enumerate(labels): + if s: + label = QLabel(_(s)) + label.setFont(f) + label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + self.dicts_layout.addWidget(label, 0, i) + # enabled all + self.enabled_all_check_btn = QCheckBox(_('DICTS_NAME')) + self.enabled_all_check_btn.setFont(f) + self.enabled_all_check_btn.setEnabled(True) + self.enabled_all_check_btn.setChecked(True) + # signal + self.enabled_all_check_btn.clicked.connect(self.enabled_all_changed) + # add widgets + self.dicts_layout.addWidget(self.enabled_all_check_btn, 0, 0) + # dict service list + confs = config.dicts + dicts = list() + for clazz in service_manager.web_services: + service = service_pool.get(clazz.__unique__) + if service and service.support: + dicts.append({ + 'title': service.title, + 'unique': service.unique, + 'path': clazz.__path__, + 'enabled': confs.get(service.unique, dict()).get('enabled', True) + }) + service_pool.put(service) + # add dict + for i, d in enumerate(dicts): + self.add_dict_layout(i, **d) + # update + self.enabled_all_update() + self.adjustSize() + + def add_dict_layout(self, i, **kwargs): + # args + title, unique, enabled, path = ( + kwargs.get('title', u''), + kwargs.get('unique', u''), + kwargs.get('enabled', False), + kwargs.get('path', u''), + ) + # button + check_btn = QCheckBox(title) + check_btn.setMinimumSize(WIDGET_SIZE.map_dict_width*1.5, 0) + check_btn.setEnabled(True) + check_btn.setChecked(enabled) + edit_btn = QToolButton(self) + edit_btn.setText(_('EDIT')) + # signal + check_btn.stateChanged.connect(self.enabled_all_update) + edit_btn.clicked.connect(lambda: self.on_edit(path)) + # add + self.dicts_layout.addWidget(check_btn, i + 1, 0) + self.dicts_layout.addWidget(edit_btn, i + 1, 1) + self._options.append({ + 'unique': unique, + 'check_btn': check_btn, + 'edit_btn': edit_btn, + }) + + def enabled_all_update(self): + b = True + for row in self._options: + if not row['check_btn'].isChecked(): + b = False + break + self.enabled_all_check_btn.setChecked(b) + + def enabled_all_changed(self): + b = self.enabled_all_check_btn.isChecked() + for row in self._options: + row['check_btn'].setChecked(b) + + def on_edit(self, path): + '''edit dictionary file''' + d = QDialog(self) + frm = Ui_Dialog() + frm.setupUi(d) + d.setWindowTitle(os.path.basename(path)) + # 2x3 compatible + if sys.hexversion >= 0x03000000: + frm.text.setPlainText(open(path, 'r', encoding="utf-8").read()) + else: + frm.text.setPlainText(unicode(open(path).read(), "utf8")) + d.accepted.connect(lambda: self.on_accept_edit(path, frm)) + d.exec_() + + def on_accept_edit(self, path, frm): + '''save dictionary file''' + # 2x3 compatible + if sys.hexversion >= 0x03000000: + open(path, "w", encoding='utf-8').write(frm.text.toPlainText()) + else: + open(path, "w").write(frm.text.toPlainText().encode("utf8")) + + def accept(self): + '''ok button clicked''' + self.save() + super(DictManageDialog, self).accept() + + def save(self): + '''save config to file''' + data = dict() + dicts = {} + for row in self._options: + dicts[row['unique']] = { + 'enabled': row['check_btn'].isChecked(), + } + data['dicts'] = dicts + config.update(data) diff --git a/addons21/fastwq/gui/options.py b/addons21/fastwq/gui/options.py index 325268a..586edef 100644 --- a/addons21/fastwq/gui/options.py +++ b/addons21/fastwq/gui/options.py @@ -74,6 +74,7 @@ class OptionsDialog(Dialog): if s != 'before_build': return # dict service list + dicts = config.dicts self.dict_services = { 'local': [], #本地词典 'web': [] #网络词典 @@ -87,13 +88,14 @@ class OptionsDialog(Dialog): }) service_pool.put(service) for clazz in service_manager.web_services: - service = service_pool.get(clazz.__unique__) - if service and service.support: - self.dict_services['web'].append({ - 'title': service.title, - 'unique': service.unique - }) - service_pool.put(service) + if dicts.get(clazz.__unique__, dict()).get('enabled', True): + service = service_pool.get(clazz.__unique__) + if service and service.support: + self.dict_services['web'].append({ + 'title': service.title, + 'unique': service.unique + }) + service_pool.put(service) # emit finished self._signal.emit('after_build') @@ -117,6 +119,7 @@ class OptionsDialog(Dialog): self.tab_widget = QTabWidget() self.tab_widget.setTabsClosable(True) self.tab_widget.setMovable(False) + self.tab_widget.tabBar().setExpanding(False) self.tab_widget.setStyleSheet( """ QTabWidget::pane { /* The tab widget frame */ @@ -124,10 +127,21 @@ class OptionsDialog(Dialog): } """ ) + tab_corner = QWidget() + tab_corner_layout = QHBoxLayout() + tab_corner_layout.setSpacing(1) + tab_corner_layout.setSizeConstraint(QLayout.SetMinAndMaxSize) + tab_corner_layout.setContentsMargins(0, 0, 0, 0) + tab_corner.setLayout(tab_corner_layout) tab_add_button = QToolButton(self) - tab_add_button.setText(' + ') - self.tab_widget.setCornerWidget(tab_add_button) + tab_add_button.setIcon(get_icon('add.png')) + tab_set_button = QToolButton(self) + tab_set_button.setIcon(get_icon('setting.png')) + tab_corner_layout.addWidget(tab_set_button) + tab_corner_layout.addWidget(tab_add_button) + self.tab_widget.setCornerWidget(tab_corner) # signals + tab_set_button.clicked.connect(self.show_dm_dialog) tab_add_button.clicked.connect(self.addTab) self.tab_widget.tabCloseRequested.connect(self.removeTab) # layout @@ -178,11 +192,13 @@ class OptionsDialog(Dialog): def show_fm_dialog(self): '''open folder manager dialog''' - from .common import show_fm_dialog - self.save() - self.close() - self.destroy() - show_fm_dialog(self._parent) + self.accept() + self.setResult(1001) + + def show_dm_dialog(self): + '''open dictionary manager dialog''' + self.accept() + self.setResult(1002) def show_about(self): '''open about dialog''' @@ -398,9 +414,9 @@ class TabContent(QWidget): dict_combo.setFocusPolicy( Qt.TabFocus | Qt.ClickFocus | Qt.StrongFocus | Qt.WheelFocus ) - dict_combo.setEnabled(not word_checked and not ignore) - self.fill_dict_combo_options(dict_combo, dict_unique, self._services) + ignore = not self.fill_dict_combo_options(dict_combo, dict_unique, self._services) or ignore dict_unique = dict_combo.itemData(dict_combo.currentIndex()) + dict_combo.setEnabled(not word_checked and not ignore) # field combox field_combo = QComboBox() field_combo.setMinimumSize(WIDGET_SIZE.map_field_width, 0) @@ -500,15 +516,14 @@ class TabContent(QWidget): dict_combo.addItem(service['title'], userData=service['unique']) def set_dict_combo_index(): - #dict_combo.setCurrentIndex(-1) dict_combo.setCurrentIndex(0) if current_unique: for i in range(dict_combo.count()): if dict_combo.itemData(i) == current_unique: dict_combo.setCurrentIndex(i) - break - - set_dict_combo_index() + return True + return False + return set_dict_combo_index() def fill_field_combo_options(self, field_combo, dict_combo_text, dict_combo_itemdata, dict_fld_name, dict_fld_ord): '''setup field combobox''' diff --git a/addons21/fastwq/lang.py b/addons21/fastwq/lang.py index 9a0bb52..54afdd0 100644 --- a/addons21/fastwq/lang.py +++ b/addons21/fastwq/lang.py @@ -69,6 +69,8 @@ _arr = [ ['PLS_SET_DICTIONARY_FIELDS', u'请设置字典和字段', u'Please set the dictionary and fields.'], ['CONFIG_INDEX', u'配置 %s', u'Config %s'], ['SELECT_ALL', u'全选', u'All'], + ['DICTS_NAME', u'字典名称', u'Dictionary Name'], + ['EDIT', u'编辑', u'Edit'], ['BRE_PRON', u'英式发音', u'British Pronunciation'], ['AME_PRON', u'美式发音', u'American Pronunciation'], diff --git a/addons21/fastwq/res/add.png b/addons21/fastwq/res/add.png new file mode 100644 index 0000000000000000000000000000000000000000..6a3b981dbf8f880db111e0e9766c667f5dd10fce GIT binary patch literal 378 zcmV-=0fqjFP)F?ja*d0J3$OPgRDEliA_mX1>BXS}nAp`_~_&u7K6c9fr zH3Y~_1HxFur0AIl|6mdOHJS}a9Y9Y9yu~8+p5l@a3Ge~2ARc|vSj4oTr6Mly5r{uv zh=K|t7-nK(;sD|dApQl!|EY}s0&xit3n1Hx?to?*Sd5PQQ0znt5LS9ufaoE>1H?r% z^nE=Liz3^Jt1=P?Vlh0vkObnLXkx)Ye49Ydd4^sYky{&b0P%M$j(S0_+E5&enCNIx zJn8^?IsjW8!bVRAV5|9F(9;3$fVdQi-vGo_xlwo)cE*#MO9TLT(sD;)B_*8z z(5HBv9O5a2zJLm%=~s6n7VjdSiwWTk_5%1Wu{$u{o}8R))a&(A2?+_?oclL6HVh9R zKFoK!-6q0+9lj>SYXEeE=)BJJR>+y?Dagsm3GR}+_4V~HQBr`1R)pXCyF|3}@{Vy; zr_*UT*TCasxAI#K20sRX9Wt-2t-V@RRduYOpy0~p=4NaWh+H>s-hBV)(WBoIZaZH4 z!oV;ryXy6NwHOKz6)%Pr-h;&_Yj$?l(AwI1@9Nd7Z}B=Ga}7iSs;#Z{wr!z@@6FwnoB7TYpcYSm=G}vrTZGs@H8qu0T3YJr?d`o*Utj+xIoFPijMR5`cfaOxxs>AK;s*eW zL$ASZw=a^0X4J0kR|85!b??P+AvZTSaQN_HOL=*@H6M+XVTKrmWkX?MDvZkWFD&l7*As88bTitcBizE6xQN*#Cs6DI%wqb0ZN z=g*&Cks6`rgCm#XQ^>VKdKB`#hKxI$9*k-rAB8F%8NSl!ejjp~d>;dl3FEgrD&=g$|m?$jESD&0kMQ) z0bnJ^7RIp51qWV_LgO+ch>R11CgBlYWSlK6Ek8uj|9BC0b#*Dz)6>er!h({YpYN6e z!a%s^RlHSsze5BPNz;pnYy;vR=N`_q;aLJ8kJ)TCG&D5CI~)!lX;el>M-TQjWPMJ> ze?w@^07;<>bcA+8CL(J`Hgxd_&>8VtTU&YndXRa5Oci7NGg!{W{52dN9uDplk}^I% zzS_~zAvc*4=>Q_KJTo(sCpIy#EJlS_dLA#0QZJ2-jkAl3i~6~_xiV_ObNTY+X}Ut; zcO|Aa+(l|%U*9=~579Ks1Z*7~9Q-=e9rJ*Y@hq*jK)xp?Cnvvx=M{{9c>46|U-$rZ zMyr8n0EDuj8YnK}?4_ET8WV=aEk|{AwJF3C{#|NDE-}f`^v7~5UV;9Q`)TA=;rQ|6 z1MGUCwzjq(Lpja3lf`)R0li*;*U_a9GMP~ zL1Moksc3{2B8QO@k_Z_N_zuo4aAj54wyrt<)uh^E66Pe1kp-0TOuu&L(`W{ zNl93WW|%7h%MGB_GkOITM@enC3(c^_Kx_%b>`-}TsDH(i2-K2slvKytuowu+W>0YV zm?%e(;s6lHgO&;ZDa3K)IsjInBm(g=Xi@zH+5lM%#K}Oc0mSEsa6}Bb4j=}AS~C}j zaD*|f8~_7^95EYTWkd}C${82&$g|-qim3_C;|Kv~T1NqLn%IqIc^N6KVrl?MAWnsL qYEA?30wHXzV#d+V=|DRGAix0Jz9z94%>y_90000qx delta 2704 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 Ci3O