def _updateCardFromPage(): # Update card/fact # get html newHtml = str(mw.bodyView.body.page().mainFrame().toHtml().toUtf8()) xml = libxml2.htmlParseDoc(newHtml, 'utf8') _updateAnchor(xml) context = xml.xpathNewContext() # find <div class="cardq" ...> tag to get only the main content res = context.xpathEval("//div[@class='cardq']") if len(res): # construct card content from serializations of children child = res[0].get_children() buf = u'' while child: # (strange behavior of libxml2: it replaces html entities by unicode chars) # replace our work-around that used res = child.serialize(encoding='utf-8').replace( '<span>\xc2\xa0</span>', '') buf += res.decode('utf-8', 'replace') child = child.get_next() fact = mw.currentCard.fact fact.fields[0].value = buf #utils.showText("New value: " + buf) fact.setModified(textChanged=True, deck=mw.deck) mw.deck.save() mw.deck.s.commit() else: utils.showInfo("xpath failure (2)") # free resources xml.freeDoc() context.xpathFreeContext() # update view mw.bodyView.redisplay()
def doAddURL(): # get URL from clipboard url = str(QApplication.clipboard().mimeData().text()) try: # download HTML file with urllib html = opener.open(url).read() except ValueError: utils.showInfo("Please copy a URL to clipboard first.") return # parse HTML and find images xml = libxml2.htmlParseDoc(html, 'utf-8') context = xml.xpathNewContext() # find correct nodes via XPath count = 0 for img in context.xpathEval('//img'): # get src attribute attr = img.get_properties() imgurl = None while attr: if attr.name == 'src': _replaceImageSrc(url, attr) count += 1 break attr = attr.get_next() # add new fact fact = Fact(mw.deck.currentModel) val = tidyHTML(xml.serialize(encoding='utf-8').decode('utf-8', 'replace')) fact.fields[0].value = val mw.deck.addFact(fact, reset=True) utils.showInfo( "URL successfully added as new fact (%d pictures downloaded)" % count)
def fetchData(self): self.parent.setProgressParent(None) self.parent.startProgress() self.parent.updateProgress() try: socket.setdefaulttimeout(30) try: sock = urllib2.urlopen( URL + "search?t=%d&c=1" % self.type) data = sock.read() try: data = gzip.GzipFile(fileobj=cStringIO.StringIO(data)).read() except: # the server is sending gzipped data, but a transparent # proxy or antivirus software may be decompressing it # before we get it pass self.allList = simplejson.loads(unicode(data)) except: showInfo(self.conErrMsg % cgi.escape(unicode( traceback.format_exc(), "utf-8", "replace"))) self.close() self.ok = False return finally: self.parent.finishProgress() socket.setdefaulttimeout(None) self.form.search.setFocus() self.typeChanged() self.limit()
def doAddURL(): # get URL from clipboard url = str(QApplication.clipboard().mimeData().text()) try: # download HTML file with urllib html = opener.open(url).read() except ValueError: utils.showInfo("Please copy a URL to clipboard first.") return # parse HTML and find images xml = libxml2.htmlParseDoc(html, 'utf-8') context = xml.xpathNewContext() # find correct nodes via XPath count = 0 for img in context.xpathEval('//img'): # get src attribute attr = img.get_properties() imgurl = None while attr: if attr.name == 'src': _replaceImageSrc(url, attr) count += 1 break attr = attr.get_next() # add new fact fact = Fact(mw.deck.currentModel) val = tidyHTML(xml.serialize(encoding='utf-8').decode('utf-8', 'replace')) fact.fields[0].value = val mw.deck.addFact(fact, reset = True) utils.showInfo("URL successfully added as new fact (%d pictures downloaded)" % count)
def accept(self): if self.type == 0: if not self.parent.saveAndClose(hideWelcome=True, parent=self): return QDialog.accept(self) (fd, tmpname) = tempfile.mkstemp(prefix="anki") tmpfile = os.fdopen(fd, "w+b") cnt = 0 try: self.parent.setProgressParent(self) self.parent.startProgress() try: sock = urllib2.urlopen( "http://anki.ichi2.net/file/get?id=%d" % self.curRow[R_ID]) while 1: data = sock.read(65536) if not data: break cnt += len(data) tmpfile.write(data) self.parent.updateProgress( label=_("Downloaded %dKB") % (cnt/1024.0)) except: showInfo(_("Unable to connect to server.\n\n") + traceback.format_exc()) self.close() return finally: self.parent.setProgressParent(None) self.parent.finishProgress() QDialog.accept(self) # file is fetched tmpfile.seek(0) self.handleFile(tmpfile) QDialog.accept(self)
def onReqFin(self, id, err): "List fetched." if id != self.conId: return self.parent.finishProgress() self.parent.setProgressParent(None) self.form.search.setFocus() if err: errorString = self.http.errorString() else: # double check ... make sure http status code was valid # this is to counter bugs in handling proxy responses respHeader = self.http.lastResponse() if respHeader.isValid(): statusCode = respHeader.statusCode() if statusCode < 200 or statusCode >= 300: err = True errorString = respHeader.reasonPhrase() else: err = True errorString = "Invalid HTTP header received!" if err: if self.parent.config['proxyHost']: errorString += "\n" + _("Please check the proxy settings.") showInfo(_("Unable to connect to server.") + "\n" + errorString, parent=self) self.close() return data = self.http.readAll() self.allList = simplejson.loads(unicode(data)) self.typeChanged() self.limit()
def accept(self): if self.type == 0: if not self.parent.saveAndClose(hideWelcome=True, parent=self): return QDialog.accept(self) (fd, tmpname) = tempfile.mkstemp(prefix="anki") tmpfile = os.fdopen(fd, "w+b") cnt = 0 try: socket.setdefaulttimeout(30) self.parent.setProgressParent(self) self.parent.startProgress() self.parent.updateProgress() try: sock = urllib2.urlopen("http://anki.ichi2.net/file/get?id=%d" % self.curRow[R_ID]) while 1: data = sock.read(32768) if not data: break cnt += len(data) tmpfile.write(data) self.parent.updateProgress(label=_("Downloaded %dKB") % (cnt / 1024.0)) except: showInfo(self.conErrMsg % cgi.escape(unicode(traceback.format_exc(), "utf-8", "replace"))) self.close() return finally: socket.setdefaulttimeout(None) self.parent.setProgressParent(None) self.parent.finishProgress() QDialog.accept(self) # file is fetched tmpfile.seek(0) self.handleFile(tmpfile) QDialog.accept(self)
def _updateCardFromPage(): # Update card/fact # get html newHtml = str(mw.bodyView.body.page().mainFrame().toHtml().toUtf8()) xml = libxml2.htmlParseDoc(newHtml, 'utf8') _updateAnchor(xml) context = xml.xpathNewContext() # find <div class="cardq" ...> tag to get only the main content res = context.xpathEval("//div[@class='cardq']") if len(res): # construct card content from serializations of children child = res[0].get_children() buf = u'' while child: # (strange behavior of libxml2: it replaces html entities by unicode chars) # replace our work-around that used res = child.serialize(encoding='utf-8').replace('<span>\xc2\xa0</span>', '') buf += res.decode('utf-8', 'replace') child = child.get_next() fact = mw.currentCard.fact fact.fields[0].value = buf #utils.showText("New value: " + buf) fact.setModified(textChanged=True, deck=mw.deck) mw.deck.save() mw.deck.s.commit() else: utils.showInfo("xpath failure (2)") # free resources xml.freeDoc() context.xpathFreeContext() # update view mw.bodyView.redisplay()
def fetchData(self): self.parent.setProgressParent(None) self.parent.startProgress() self.parent.updateProgress() try: socket.setdefaulttimeout(30) try: sock = urllib2.urlopen(URL + "search?t=%d&c=1" % self.type) data = sock.read() try: data = gzip.GzipFile( fileobj=cStringIO.StringIO(data)).read() except: # the server is sending gzipped data, but a transparent # proxy or antivirus software may be decompressing it # before we get it pass self.allList = simplejson.loads(unicode(data)) except: showInfo(self.conErrMsg % cgi.escape( unicode(traceback.format_exc(), "utf-8", "replace"))) self.close() self.ok = False return finally: self.parent.finishProgress() socket.setdefaulttimeout(None) self.form.search.setFocus() self.typeChanged() self.limit()
def getAudio(string, parent): "Record and return filename" # record first process = subprocess.Popen(audioRecordCommand) if not sys.platform.startswith("win32"): mb2 = QMessageBox(parent) but = QPushButton("Stop") mb2.addButton(but, QMessageBox.RejectRole) mb2.setText(string + "<br><br>Recording..") mb2.exec_() os.kill(process.pid, signal.SIGINT) process.wait() # postprocess try: subprocess.check_call(audioProcessCommand, stdout=tmpfile, stderr=tmpfile) subprocess.check_call(audioProcessCommand2, stdout=tmpfile, stderr=tmpfile) subprocess.check_call(audioProcessCommand3, stdout=tmpfile, stderr=tmpfile) except: tmpfile.flush() showInfo("Error occurred:\n%s\n%s" % (traceback.format_exc(), open(tempname).read())) return "tmp.mp3"
def askForQueryStrings(self): queryDialog = getKanaKanjiDialog(self.kana, self.kanji) if not queryDialog.exec_(): utils.showInfo('Debug: User reject dialog') return False self.kana = queryDialog.kana self.kanji = queryDialog.kanji return True
def downloadAudioQuery(): japaneseDownloader = JapaneseAudioDownloader() try: japaneseDownloader.maybeDownloadAudio(askForText=True) except ValueError as ve: utils.showInfo('JapaneseAudioDownload reported a problem: \'%s\'' \ %str(ve)) except IOError as ioe: utils.showInfo('JapaneseAudioDownload reported an IO problem: \'%s\'' % str(ioe))
def fetchData(self): try: sock = urllib2.urlopen( "http://anki.ichi2.net/file/search?t=%d" % self.type) self.allList = simplejson.loads(unicode(sock.read())) except: showInfo(_("Unable to connect to server.\n\n") + traceback.format_exc()) self.close() self.ok = False return self.form.search.setFocus() self.typeChanged() self.limit()
def run(): db = mw.deck.s mw.startProgress() # gather old ids data = [] for id in db.column0("select id from facts"): data.append(dict(new=genID(), old=id)) # update facts db.statements("update facts set id = :new where id = :old", data) # fields db.statements("update fields set id = random(), factId = :new where factId = :old", data) # cards db.statements("update cards set id = random(), factId = :new where factId = :old", data) mw.finishProgress() mw.deck.setModified() mw.deck.save() showInfo("Done.")
def _markSelection(): """ Helper method to mark the selected content with green background. Returns the selected content (as HTML) """ # copy selected text mw.bodyView.body.page().triggerAction(QWebPage.Copy) # convert to HTML, parse it as XML cb = QApplication.clipboard() html = str(cb.mimeData().html().toUtf8()) xml = libxml2.htmlParseDoc(html, 'utf-8') context = xml.xpathNewContext() # find correct node via XPath res = context.xpathEval('/html/body/span/span') if len(res): # prepare replacement HTML and place it into clipboard data = QMimeData() # strange work-around for stupid QT behavior if res[0].lsCountNode() == 1: outer = (u"<span style='background-color: rgb(0,255,0);'>", u"</span>") else: outer = (u"<div style='background-color: rgb(0,255,0);'>", u"</div>") data.setHtml( u"<html><body>" + outer[0] + u"<a name='new_extract_anchor'><span style='color: rgb(80,80,80); font-size:small;'>(Last Extract)</span></a>" + str(res[0]).decode('utf-8', 'replace') + outer[1] + u"</body></html>") cb.clear() cb.setMimeData(data) #utils.showText("Clipboard data: " + str(cb.mimeData().html().toUtf8())) # switch page to editable, paste replacement, make it uneditable again mw.bodyView.body.page().setContentEditable(True) mw.bodyView.body.page().triggerAction(QWebPage.Paste) mw.bodyView.body.page().setContentEditable(False) #utils.showText(str(res[0]) + "\n###\n" + mw.bodyView.body.page().mainFrame().toHtml()) else: utils.showInfo("xpath failure (1)") # free resources xml.freeDoc() context.xpathFreeContext() _updateCardFromPage() return html
def _markSelection(): """ Helper method to mark the selected content with green background. Returns the selected content (as HTML) """ # copy selected text mw.bodyView.body.page().triggerAction(QWebPage.Copy) # convert to HTML, parse it as XML cb = QApplication.clipboard() html = str(cb.mimeData().html().toUtf8()) xml = libxml2.htmlParseDoc(html, 'utf-8') context = xml.xpathNewContext() # find correct node via XPath res = context.xpathEval('/html/body/span/span') if len(res): # prepare replacement HTML and place it into clipboard data = QMimeData() # strange work-around for stupid QT behavior if res[0].lsCountNode() == 1: outer = (u"<span style='background-color: rgb(0,255,0);'>", u"</span>") else: outer = (u"<div style='background-color: rgb(0,255,0);'>", u"</div>") data.setHtml(u"<html><body>"+ outer[0] + u"<a name='new_extract_anchor'><span style='color: rgb(80,80,80); font-size:small;'>(Last Extract)</span></a>" + str(res[0]).decode('utf-8', 'replace') + outer[1] + u"</body></html>" ) cb.clear() cb.setMimeData(data) #utils.showText("Clipboard data: " + str(cb.mimeData().html().toUtf8())) # switch page to editable, paste replacement, make it uneditable again mw.bodyView.body.page().setContentEditable(True) mw.bodyView.body.page().triggerAction(QWebPage.Paste) mw.bodyView.body.page().setContentEditable(False) #utils.showText(str(res[0]) + "\n###\n" + mw.bodyView.body.page().mainFrame().toHtml()) else: utils.showInfo("xpath failure (1)") # free resources xml.freeDoc() context.xpathFreeContext() _updateCardFromPage() return html
def handleFile(self, file): ext = os.path.splitext(self.curRow[R_FNAME])[1] if ext == ".zip": z = zipfile.ZipFile(file) else: z = None tit = self.curRow[R_TITLE] tit = re.sub("[^][A-Za-z0-9 ()\-]", "", tit) tit = tit[0:40] if self.type == 0: # deck dd = self.parent.documentDir p = os.path.join(dd, tit + ".anki") if os.path.exists(p): tit += "%d" % time.time() for l in z.namelist(): if l == "shared.anki": dpath = os.path.join(dd, tit + ".anki") open(dpath, "wb").write(z.read(l)) elif l.startswith("shared.media/"): try: os.mkdir(os.path.join(dd, tit + ".media")) except OSError: pass open(os.path.join(dd, tit + ".media", os.path.basename(l)),"wb").write(z.read(l)) self.parent.loadDeck(dpath) else: pd = self.parent.pluginsFolder() if z: for l in z.infolist(): try: os.makedirs(os.path.join( pd, os.path.dirname(l.filename))) except OSError: pass if l.filename.endswith("/"): # directory continue path = os.path.join(pd, l.filename) open(path, "wb").write(z.read(l.filename)) else: open(os.path.join(pd, tit + ext), "wb").write(file.read()) showInfo(_("Plugin downloaded. Please restart Anki."), parent=self)
def handleFile(self, file): ext = os.path.splitext(self.curRow[R_FNAME])[1] if ext == ".zip": z = zipfile.ZipFile(file) else: z = None tit = self.curRow[R_TITLE] tit = re.sub("[^][A-Za-z0-9 ()\-]", "", tit) tit = tit[0:40] if self.type == 0: # deck dd = self.parent.documentDir p = os.path.join(dd, tit + ".anki") if os.path.exists(p): tit += "%d" % time.time() for l in z.namelist(): if l == "shared.anki": dpath = os.path.join(dd, tit + ".anki") open(dpath, "wb").write(z.read(l)) elif l.startswith("shared.media/"): try: os.mkdir(os.path.join(dd, tit + ".media")) except OSError: pass open(os.path.join(dd, tit + ".media", os.path.basename(l)), "wb").write(z.read(l)) self.parent.loadDeck(dpath) else: pd = self.parent.pluginsFolder() if z: for l in z.infolist(): try: os.makedirs( os.path.join(pd, os.path.dirname(l.filename))) except OSError: pass if l.filename.endswith("/"): # directory continue path = os.path.join(pd, l.filename) open(path, "wb").write(z.read(l.filename)) else: open(os.path.join(pd, tit + ext), "wb").write(file.read()) showInfo(_("Plugin downloaded. Please restart Anki."), parent=self)
def fetchData(self): self.parent.setProgressParent(None) self.parent.startProgress() self.parent.updateProgress() try: socket.setdefaulttimeout(30) try: sock = urllib2.urlopen("http://anki.ichi2.net/file/search?t=%d" % self.type) self.allList = simplejson.loads(unicode(sock.read())) except: showInfo(self.conErrMsg % cgi.escape(unicode(traceback.format_exc(), "utf-8", "replace"))) self.close() self.ok = False return finally: self.parent.finishProgress() socket.setdefaulttimeout(None) self.form.search.setFocus() self.typeChanged() self.limit()
def _updateAnchor(xml): """ Helper method to update the last extract anchor from the current page's HTML. Only changes the given XML structure. Caller must make changes to fact. """ context = xml.xpathNewContext() # is there a new anchor? nanchors = context.xpathEval("//a[@name='new_extract_anchor']") if len(nanchors): # remove existing anchors oanchors = context.xpathEval("//a[@name='last_extract_anchor']") for anchor in oanchors: anchor.unlinkNode() anchor.freeNode() # update new anchor (only property should be name=... name = nanchors[0].get_properties() name.setContent('last_extract_anchor') #utils.showText("Anchors updated: " + str(xml)) else: utils.showInfo("No new anchor found")
def run(): db = mw.deck.s mw.startProgress() # gather old ids data = [] for id in db.column0("select id from facts"): data.append(dict(new=genID(), old=id)) # update facts db.statements("update facts set id = :new where id = :old", data) # fields db.statements( "update fields set id = random(), factId = :new where factId = :old", data) # cards db.statements( "update cards set id = random(), factId = :new where factId = :old", data) mw.finishProgress() mw.deck.setModified() mw.deck.save() showInfo("Done.")
def fetchData(self): self.parent.setProgressParent(None) self.parent.startProgress() self.parent.updateProgress() try: socket.setdefaulttimeout(30) try: sock = urllib2.urlopen( "http://anki.ichi2.net/file/search?t=%d" % self.type) self.allList = simplejson.loads(unicode(sock.read())) except: showInfo(self.conErrMsg % cgi.escape( unicode(traceback.format_exc(), "utf-8", "replace"))) self.close() self.ok = False return finally: self.parent.finishProgress() socket.setdefaulttimeout(None) self.form.search.setFocus() self.typeChanged() self.limit()
def accept(self): if self.type == 0: if not self.parent.saveAndClose(hideWelcome=True, parent=self): return QDialog.accept(self) (fd, tmpname) = tempfile.mkstemp(prefix="anki") tmpfile = os.fdopen(fd, "w+b") cnt = 0 try: socket.setdefaulttimeout(30) self.parent.setProgressParent(self) self.parent.startProgress() self.parent.updateProgress() try: sock = urllib2.urlopen("http://anki.ichi2.net/file/get?id=%d" % self.curRow[R_ID]) while 1: data = sock.read(32768) if not data: break cnt += len(data) tmpfile.write(data) self.parent.updateProgress(label=_("Downloaded %dKB") % (cnt / 1024.0)) except: showInfo(self.conErrMsg % cgi.escape( unicode(traceback.format_exc(), "utf-8", "replace"))) self.close() return finally: socket.setdefaulttimeout(None) self.parent.setProgressParent(None) self.parent.finishProgress() QDialog.accept(self) # file is fetched tmpfile.seek(0) self.handleFile(tmpfile) QDialog.accept(self)
def onReqFin2(self, id, err): "File fetched." if id != self.conId: return try: self.parent.finishProgress() self.parent.setProgressParent(None) if err: showInfo(_("Unable to connect to server.") + "\n" + self.http.errorString(), parent=self) self.close() return data = self.http.readAll() ext = os.path.splitext(self.curRow[R_FNAME])[1] if ext == ".zip": f = cStringIO.StringIO() f.write(data) z = zipfile.ZipFile(f) else: z = None tit = self.curRow[R_TITLE] tit = re.sub("[^][A-Za-z0-9 ()\-]", "", tit) tit = tit[0:40] if self.type == 0: # deck dd = self.parent.documentDir p = os.path.join(dd, tit + ".anki") if os.path.exists(p): tit += "%d" % time.time() for l in z.namelist(): if l == "shared.anki": dpath = os.path.join(dd, tit + ".anki") open(dpath, "wb").write(z.read(l)) elif l.startswith("shared.media/"): try: os.mkdir(os.path.join(dd, tit + ".media")) except OSError: pass open(os.path.join(dd, tit + ".media", os.path.basename(l)),"wb").write(z.read(l)) self.parent.loadDeck(dpath) else: pd = self.parent.pluginsFolder() if z: for l in z.infolist(): if not l.file_size: continue try: os.makedirs(os.path.join( pd, os.path.dirname(l.filename))) except OSError: pass open(os.path.join(pd, l.filename), "wb").\ write(z.read(l.filename)) else: open(os.path.join(pd, tit + ext), "wb").write(data) showInfo(_("Plugin downloaded. Please restart Anki."), parent=self) return finally: QDialog.accept(self)
# import anki.media, anki.cards # import anki.cards from anki import sound from anki.deck import Deck from anki.facts import Fact from anki.hooks import addHook from anki.utils import addTags from ankiqt import mw, config from ankiqt.ui import utils try: from japanese.reading import KakasiController kakasi = KakasiController() except ImportError: utils.showInfo('JapaneseAudioDownload uses the Japanese plugin. Please download it.') kakasi = None ########################################################## ### CONFIGURATION SECTION ########################################################## ## Try to download as soon as a suitable card appears. (In this case ## errors are automatically ignored.) AUTO_DOWNLOAD_AUDIO = False ## Ask the user every time before a pronunciation gets saved ALWAYS_ASK_BEFORE_SAVE = False ## If this is not empty, that is, not [] only download when a fact has ## at least one of these tags. Use quotes, and commas to separate entries.
# import anki.media, anki.cards # import anki.cards from anki import sound from anki.deck import Deck from anki.facts import Fact from anki.hooks import addHook from anki.utils import addTags from ankiqt import mw, config from ankiqt.ui import utils try: from japanese.reading import KakasiController kakasi = KakasiController() except ImportError: utils.showInfo( 'JapaneseAudioDownload uses the Japanese plugin. Please download it.') kakasi = None ########################################################## ### CONFIGURATION SECTION ########################################################## ## Try to download as soon as a suitable card appears. (In this case ## errors are automatically ignored.) AUTO_DOWNLOAD_AUDIO = False ## Ask the user every time before a pronunciation gets saved ALWAYS_ASK_BEFORE_SAVE = False ## If this is not empty, that is, not [] only download when a fact has ## at least one of these tags. Use quotes, and commas to separate entries.
if canLoad: try: kakasi = KakasiController() mecab = MecabController() if USE_MECAB: mecab.ensureOpen() tool = mecab else: tool = kakasi addHook('fact.focusLost', onFocusLost) except Exception: if sys.platform.startswith("win32"): from PyQt4.QtGui import QDesktopServices from PyQt4.QtCore import QUrl from ankiqt.ui.utils import showInfo showInfo("Please install anki-reading.exe") QDesktopServices.openUrl(QUrl( "http://ichi2.net/anki/wiki/JapaneseSupport")) raise # Ctrl+g shortcut, based on Samson's regenerate reading field plugin ########################################################################## def genReading(self): # make sure current text is saved self.saveFieldsNow() # find the first src field available reading = None for f in srcFields: try: reading = tool.reading(self.fact[f])
if canLoad: try: kakasi = KakasiController() mecab = MecabController() if USE_MECAB: mecab.ensureOpen() tool = mecab else: tool = kakasi addHook('fact.focusLost', onFocusLost) except Exception: if sys.platform.startswith("win32"): from PyQt4.QtGui import QDesktopServices from PyQt4.QtCore import QUrl from ankiqt.ui.utils import showInfo showInfo("Please install anki-reading.exe") QDesktopServices.openUrl( QUrl("http://ichi2.net/anki/wiki/JapaneseSupport")) raise # Ctrl+g shortcut, based on Samson's regenerate reading field plugin ########################################################################## def genReading(self): # make sure current text is saved self.saveFieldsNow() # find the first src field available reading = None for f in srcFields: try: