#!/usr/bin/env python3
# -*- coding: utf8 -*-
import sys, os
import sqlite3
import urllib.request
#import requests
import subprocess
from urwid import *
import pdb
# 整體變數部份 #{
lPartOfSpeech = (
('冠詞', 0x0001, 'art.' ),
('名詞', 0x0002, 'n.' ),
('形容詞', 0x0004, 'adj.' ),
('動詞', 0x0008, 'v.' ),
('副詞', 0x0010, 'adv.' ),
('介係詞', 0x0020, 'prop.'),
('助動詞', 0x0040, 'aux.' ),
('代名詞', 0x0080, 'pron.'),
('連接詞', 0x0100, 'conj.'),
('感嘆詞', 0x0200, 'int.' )
)
dPStypes = {lPartOfSpeech[i][0]:(1<<i, i) for i in range(len(lPartOfSpeech))}
dPSnum = {1<<i:lPartOfSpeech[i][0] for i in range(len(lPartOfSpeech))}
C_coding = sys.getfilesystemencoding()
C_agent = {'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.165063 Safari/537.36 AppEngine-Google."}
#}-----------------------------------------------------------------------------
def playSound(filename): #{
if os.path.isfile(filename):
with open(os.devnull, 'w') as f:
subprocess.call(["mplayer", filename], stdout=f, stderr=f)
#}-----------------------------------------------------------------------------
def textToSound(source, filename='/tmp/out.wav'): #{
#sudo apt-get install libttspico-utils
try:
#cmd = 'pico2wave -w {0} "{1}"'.format(filename, source)
#subprocess.call(cmd, shell=True)
subprocess.call(['pico2wave', '-w', filename, '"{}"'.format(source)])
playSound(filename)
except Exception as e:
raise e
#}
def translate(source, to_l="zh-TW", from_l="en"): #{
flag = 'class="t0">'
urlstr = 'http://translate.google.com/m?hl=%s&sl=%s&q=%s \
' % (to_l, from_l, source.replace(" ", "%20"))
result = ''
try:
request = urllib.request.Request(urlstr, headers=C_agent)
#page = urllib.request.urlopen(request)
page = str(urllib.request.urlopen(request).read().decode(C_coding))
result = page[page.find(flag) + len(flag):]
result = result.split("<")[0]
except urllib.error.HTTPError as e:
pass
#with open('{}.html'.format(source), 'w') as f:
# f.write(page)
#soup = _soup(page.read())
#t = soup.p.findNext()
#result = ','.join([s for s in [str(x) for x in t.contents] if s[0] != '<'])
return result
#}-----------------------------------------------------------------------------
def downloadmp3(source, filename='/tmp/out.mp3', from_l="en"): #{
#urlstr = 'http://translate.google.com/translate_tts'
#with open(filename, 'wb') as f:
# payload = {
# 'ie' : 'UTF-8',
# 'tl' : from_l,
# 'q' : source }
# try:
# r = requests.get(urlstr, params=payload)
# for chunk in r.iter_content(chunk_size=1024):
# f.write(chunk)
# except Exception as e:
# raise
urlstr = "http://translate.google.com/translate_tts?ie=UTF-8&tl={0:s}&q={1:s}".format(from_l, source.replace(" ", "%20"))
request = urllib.request.Request(urlstr, headers=C_agent)
try:
response = urllib.request.urlopen(request)
with open(filename, 'wb') as f:
f.write(response.read())
#time.sleep(1)
except urllib.error.HTTPError as e:
pass
if os.path.exists(filename):
playSound(filename)
#}-----------------------------------------------------------------------------
class cEngDict: #{
# 類別私有變數 #{
__sPOSstr = ''
__db = None
__cur = None
__sqldbcreate = '''
CREATE TABLE IF NOT EXISTS DictWord(
SN INTEGER PRIMARY KEY NOT NULL,
WORD CHAR(64) NOT NULL,
PTWORD CHAR(64),
PPWORD CHAR(64),
VOICE BLOB,
UNIQUE(WORD)
);
CREATE TABLE IF NOT EXISTS DictState(
SN INTEGER PRIMARY KEY NOT NULL,
W_SN INTEGER NOT NULL,
TYPES INTEGER,
CHINA CHAR(64),
SENTENCE CHAR(255),
TRANSLATE CHAR(255)
);
'''
#}-------------------------------------------------------------------------
def __init__(self, dbname='./EnglishDict.db'): #{
for i in range(len(lPartOfSpeech)):
if (i > 0)and(i % 5 == 0):
self.__sPOSstr += '\n'
if len(lPartOfSpeech[i][0]) == 2:
self.__sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0])
else:
self.__sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0])
self.__sPOSstr += '\n詞性:'
self.dbname = dbname
self.db = sqlite3.connect(dbname)
try:
self.db.executescript(self.__sqldbcreate)
except Exception as e:
self.db.rollback()
raise e
#}-------------------------------------------------------------------------
def __del__(self): #{
self.db.commit()
#}-------------------------------------------------------------------------
def add(self, word, vptword='', vppword='', **data): #{
if type(word) is not str and word == '': return
if type(data) is not dict and len(data) == 0: return
WordSN = 1
sqlstr = '''SELECT SN FROM DictWord ORDER BY SN DESC LIMIT 1;'''
dbRec = self.db.execute(sqlstr).fetchone()
if type(dbRec) is not type(None):
WordSN += dbRec[0]
sqlstr = '''SELECT SN, WORD FROM DictWord WHERE WORD=="{0}";'''.format(word)
dbRec = self.db.execute(sqlstr).fetchone()
if type(dbRec) is not type(None):
WordSN = dbRec[0]
if type(dbRec) is type(None):
hVoice = None
try:
#if not os.path.isfile('/tmp/out.mp3'): return
#with open("/tmp/out.mp3", "rb") as f:
# hVoice = f.read()
if (data['types'] & dPStypes['動詞'][0] == 0) or (vptword == ''):
# self.db.execute('INSERT INTO DictWord(SN, WORD, VOICE) VALUES(?,?,?)',
# [
# WordSN,
# word,
# sqlite3.Binary(hVoice)
# ]);
sqlstr = '''INSERT INTO DictWord (SN, WORD) \
VALUES ({0}, "{1}")'''.format(WordSN, word)
else:
# self.db.execute('INSERT INTO DictWord(SN, WORD, PTWORD, PPWORD, VOICE) VALUES(?,?,?,?,?)',
# [
# WordSN,
# word,
# vptword,
# vppword,
# sqlite3.Binary(hVoice)
# ]);
sqlstr = '''INSERT INTO DictWord (SN, WORD, PTWORD, PPWORD) \
VALUES ({0}, "{1}", "{2}", "{3}")'''.format(WordSN, word,
vptword, vppword)
self.db.execute(sqlstr)
finally:
del hVoice
#os.remove('/tmp/out.mp3')
sqlstr = '''SELECT SENTENCE FROM DictState WHERE SENTENCE=="{0}";'''.format(
data['sentence'])
dbRec = self.db.execute(sqlstr).fetchone()
if type(dbRec) is not type(None): return
sqlstr = '''INSERT INTO DictState (W_SN, TYPES, CHINA, SENTENCE, TRANSLATE) \
VALUES ({0}, {1}, "{2}", "{3}", "{4}");'''.format(
WordSN,
data['types'],
data['china'],
data['sentence'],
data['translate']
)
self.db.execute(sqlstr)
self.db.commit()
#print('--------------===[ 資料添加成功 ]===--------------')
#}-------------------------------------------------------------------------
def NewWord(self): #{
sWord = input("\n單 字:").strip()
iTypes = 0
sPTsWord = ''
sPPsWord = ''
lType = [int(x) for x in input(self.__sPOSstr).split()]
if dPStypes['動詞'][1] in lType:
sIsIrregular = input("不規則動詞?").strip()
if (len(sIsIrregular) > 1) and (sIsIrregular[0] in ['y', 'Y']):
sPTsWord = input('過 去 式:')
sPPsWord = input('過去分詞:')
for i in lType:
iTypes = iTypes | lPartOfSpeech[i][1]
sChina = input('中文解釋:').strip()
sSentence = input('英文範例:').strip()
sTranslate = input('中文解釋:').strip()
print('\n{0}\n{1}\n{2}\n{3}\n{4}'.format(sWord, iTypes, sChina, sSentence, sTranslate))
sYesOrNo = input('\n資料是否正確?')
if (len(sYesOrNo) > 0) and (sYesOrNo[0] in ['y', 'Y']):
self.add(sWord, types=iTypes, china=sChina, sentence=sSentence, translate=sTranslate)
sYesOrNo = input("\n繼續輸入?")
if (len(sYesOrNo) > 0) and (sYesOrNo[0] in ['n', 'N']):
return False
else:
return True
#}-------------------------------------------------------------------------
#}
class DictInputListBox(ListBox): #{
# 類別私有變數 #{
__ltypekeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', 'backspace', 'enter'];
__yesorno = ['y', 'Y', 'n', 'N', ' ', 'backspace', 'enter'];
__steps = 0;
__word = '';
__ltypes = []
__types = 0;
__irreuglar = False;
__ptword = '';
__ppword = '';
__china = '';
__sentence = '';
__translate = '';
__current = False;
__qfunc = []
__stepsfunc = []
__db = None;
#}
def __init__(self): #{
body = SimpleFocusListWalker([self.__inputWord()]);
super(DictInputListBox, self).__init__(body);
self.__steps = 0;
sPOSstr = ''
for i in range(len(lPartOfSpeech)):
if (i >0) and (i % 5 == 0):
sPOSstr += '\n'
if len(lPartOfSpeech[i][0]) == 2:
sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0])
else:
sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0])
sPOSstr += '\n詞 性:'
self.__qfunc = [
self.__inputWord(), # 0
Pile([Edit(('Qcolor', sPOSstr))]), # 1
Pile([Edit(('Qcolor', '不 規 則?'))]), # 2
Pile([Edit(('Qcolor', '過 去 式:'))]), # 3
Pile([Edit(('Qcolor', '過去分詞:'))]), # 4
Pile([Edit(('Qcolor', '中文解釋:'))]), # 5
Pile([Edit(('Qcolor', '英文範例:'))]), # 6
Pile([Edit(('Qcolor', '中文翻譯:'))]), # 7
Pile([Edit(('Qcolor', '是否正確?'))]), # 8
Pile([Edit(('Qcolor', '是否繼續?'))]) # 9
];
self.__stepsfunc = [
self.step_00, # 檢查單字
self.step_01, # 檢查詞性
self.step_02, # 檢查規則動詞
self.step_03, # 檢查過去式動詞
self.step_04, # 檢查過去分詞
self.step_05, # 檢查中文解釋
self.step_06, # 檢查英文範例
self.step_07, # 檢查中文翻譯
self.step_08, # 檢查資料是否正
self.step_09 # 判斷是否離開
];
self.__db = cEngDict()
#}-------------------------------------------------------------------------
def __del__(self): #{
if self.__db is not None:
del self.__db;
self.__db = None;
#}-------------------------------------------------------------------------
def __inputWord(self): #{
return Pile([Edit(('Qcolor', "單 字:"))])
#}-------------------------------------------------------------------------
def __switchChina(self): #{
try:
import virtkey
v = virtkey.virtkey()
v.press_keysym(65505)
v.press_unicode(ord(' '))
v.release_unicode(ord(' '))
v.release_keysym(65505)
pass
except Exception as e:
raise e
#}-------------------------------------------------------------------------
def keypress(self, size, key): #{ overload
if key == 'up':
return None;
elif key == 'esc':
if self.__db is not None:
del self.__db;
self.__db = None;
raise ExitMainLoop()
elif self.__steps == 1:
if key not in self.__ltypekeys:
return None;
elif self.__steps in [2, 8, 9]:
if key not in self.__yesorno:
return None;
key = super(DictInputListBox, self).keypress(size, key);
if key != 'enter':
return key;
else:
data = self.focus[0].edit_text;
pos = self.focus_position
if not data:
if self.__steps == 2:
data = 'n'
self.focus[0].set_edit_text(data)
self.__stepsfunc[self.__steps](data, pos);
if self.__steps > 0:
self.focus_position = pos+1
elif self.__steps in [8, 9]:
data = 'y'
self.focus[0].set_edit_text(data)
self.__stepsfunc[self.__steps](data, pos);
if self.__steps > 0:
self.focus_position = pos+1
else:
self.body.clear()
self.body.insert(1, self.__qfunc[9])
self.__steps = 9
else:
self.__stepsfunc[self.__steps](data, pos);
if self.__steps > 0:
self.focus_position += 1
self.focus[0].set_edit_text('')
#}-------------------------------------------------------------------------
# 檢查單字
def step_00(self, data, pos): #{
self.__word = data.strip()
#textToSound(self.__word)
downloadmp3(self.__word)
self.body.insert(pos+1, self.__qfunc[1])
self.__steps = 1;
#}-------------------------------------------------------------------------
# 檢查詞性
def step_01(self, data, pos): #{
self.__types = 0
self.__ltypes = [int(x) for x in data.split() if x.isdigit()]
if dPStypes['動詞'][1] in self.__ltypes:
self.body.insert(pos+1, self.__qfunc[2])
self.__steps = 2
else:
self.body.insert(pos+1, self.__qfunc[5])
self.__steps = 5
self.__switchChina();
#}-------------------------------------------------------------------------
# 檢查規則動詞
def step_02(self, data, pos): #{
if data.strip()[0] in ['n', 'N']:
self.__irreuglar = False;
self.body.insert(pos+1, self.__qfunc[5])
self.__steps = 5;
self.__switchChina();
else:
self.__irreuglar = True
self.body.insert(pos+1, self.__qfunc[3])
self.__steps = 3;
#}-------------------------------------------------------------------------
# 檢查過去式動詞
def step_03(self, data, pos): #{
self.__ptword = data.strip()
textToSound(self.__ptword, filename='/tmp/ptout.wav')
#downloadmp3(self.__ptword, filename='/tmp/ptout.mp3')
self.body.insert(pos+1, self.__qfunc[4])
self.__steps = 4;
#}-------------------------------------------------------------------------
# 檢查過去分詞
def step_04(self, data, pos): #{
self.__ppword = data.strip()
testToSound(self.__ppword, filename='/tmp/ppout.wav')
#downloadmp3(self.__ppword, filename='/tmp/ppout.mp3')
self.body.insert(pos+1, self.__qfunc[5])
self.__steps = 5;
self.__switchChina();
#}-------------------------------------------------------------------------
# 檢查中文解釋
def step_05(self, data, pos): #{
if len(self.__ltypes) > 0:
for i in self.__ltypes:
self.__types |= lPartOfSpeech[i][1]
self.__china = data.strip()
self.body.insert(pos+1, self.__qfunc[6])
self.__steps = 6;
else:
self.body.insert(pos+1, self.__qfunc[1])
self.__steps = 1
self.__switchChina();
#}-------------------------------------------------------------------------
# 檢查英文範例
def step_06(self, data, pos): #{
self.__sentence = data.strip()
#textToSound(self.__sentence, filename='/tmp/sentence.wav')
downloadmp3(self.__sentence, filename='/tmp/sentence.mp3')
self.body.insert(pos+1, self.__qfunc[7])
self.__steps = 7;
self.__switchChina();
#}-------------------------------------------------------------------------
# 檢查中文翻譯
def step_07(self, data, pos): #{
self.__translate = data.strip();
if self.__irreuglar:
dataText = Pile([Text(('Acolor',
"\n單字: {0} (原型: {1} 過去式: {2} 過去分詞: {3})\n"
"詞性: {4}\n解釋: {5}\n範例: {6}\n翻譯: {7}\n".format(
self.__word,
self.__word,
self.__ptword,
self.__ppword,
self.__types,
self.__china,
self.__sentence,
self.__translate
)
))]);
else:
dataText = Pile([Text(('Acolor',
"\n單字: {0}\n詞性: {1}\n解釋: {2}\n範例: {3}\n翻譯: {4}\n".format(
self.__word,
self.__types,
self.__china,
self.__sentence,
self.__translate,
)
))]);
self.body.insert(pos+1, dataText)
self.focus_position = pos+1
self.body.insert(self.focus_position+1, self.__qfunc[8])
self.__steps = 8;
self.__switchChina();
#}-------------------------------------------------------------------------
# 檢查資料是否正
def step_08(self, data, pos): #{
if data.strip()[0] in ['n', 'N']:
self.body.clear()
self.body.insert(1, self.__qfunc[0])
self.__steps = 0
else:
# 保存資料 並重新設定參數
self.__db.add(
self.__word,
vptword = self.__ptword,
vppword = self.__ppword,
types = self.__types,
china = self.__china,
sentence = self.__sentence,
translate = self.__translate
);
self.__current = False;
self.body.insert(pos+1, self.__qfunc[9])
self.__steps = 9;
#}-------------------------------------------------------------------------
# 判斷是否離開
def step_09(self, data, pos): #{
if not data: return
if data.strip()[0] in ['n', 'N']:
if self.__db is not None:
del self.__db;
self.__db = None;
raise ExitMainLoop()
else:
self.body.clear()
self.body.insert(1, self.__qfunc[0])
self.__steps = 0
self.focus[0].set_edit_text('')
#}-------------------------------------------------------------------------
#}
def main(): #{
#try:
# eDict = cEngDict()
# bQuit = True
# while bQuit:
# bQuit = eDict.NewWord()
#finally:
# del eDict
#"""
# 'black', 'dark red', 'dark green', 'brown', 'dark blue',
# 'dark magenta', 'dark cyan', 'light gray', 'dark gray',
# 'light red', 'light green', 'yellow', 'light blue',
# 'light magenta', 'light cyan', 'white'
#"""
palette = [
('Qcolor', 'light magenta, bold', 'black'),
('Acolor', 'light green', 'black'),
];
loop = MainLoop(DictInputListBox(), palette);
loop.screen.set_terminal_properties(colors=256)
loop.run()
#}
if __name__ == "__main__":
main()