def display_result(ilist):
    """Format and Display the report on a showText window."""
    r = "1min Interval Report:\n\n"
    r += "Deck\tCount\t% Total\t% in Learn\n"
    for l in ilist:
        r += "%s\t%d\t%0.1f\t%0.1f\n" % (l[0], l[1], l[2], l[3])
    showText(r)
Beispiel #2
0
def bulkCopy(nids):

    mw.progress.start(immediate=True)

    for nid in nids:
        note = mw.col.getNote(nid)
        word = note[srcField]
        try :    
                with warnings.catch_warnings():
                    warnings.simplefilter("error")
                    mw.progress.update(label=word)
                    GetExamples(word)
                    g = Google()
                    g.write(word)
                    dp = DictionaryParser(word)
                    dp.format()
        except :
#            mw.progress.clear()
#            utils.showInfo("Exception " + word)
            txt = "<h3>" + word + "</h3>" 
            txt += "<div style='white-space: pre-wrap'>" + traceback.format_exc() + "</div>"
            utils.showText(txt, type="html")
            pass

    mw.progress.finish()
Beispiel #3
0
    def onTimeout(self):
        error = cgi.escape(self.pool)
        self.pool = ""
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "Pyaudio not" in error:
            return showWarning(_("Please install PyAudio"))
        if "install mplayer" in error:
            return showWarning(_("Please install mplayer"))
        if "no default output" in error:
            return showWarning(_("Please connect a microphone, and ensure "
                                 "other programs are not using the audio device."))
        stdText = _("""\
An error occurred. It may have been caused by a harmless bug, <br>
or your deck may have a problem.
<p>To confirm it's not a problem with your deck, please run
<b>Tools &gt; Check Database</b>.
<p>If that doesn't fix the problem, please copy the following<br>
into a bug report:""")
        pluginText = _("""\
An error occurred in an add-on.<br>
Please post on the add-on forum:<br>%s<br>""")
        pluginText %= "https://groups.google.com/forum/#!forum/anki-addons"
        if "addon" in error:
            txt = pluginText
        else:
            txt = stdText
        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html")
Beispiel #4
0
def import_from_json():
    path = getFile(mw, "Org file to import", cb=None, dir=expanduser("~"))
    if not path:
        return
    with open(path, 'r') as f:
        content = f.read().decode('utf-8')

    entries = json.loads(content)
    import itertools
    get_deck = lambda e: e['deck']
    entries = sorted(entries, key=get_deck)

    mw.checkpoint(_("Import"))
    logs = []
    for deck_name, entries in itertools.groupby(entries, get_deck):
        # FIXME: If required we could group by model name also!
        importer = JsonImporter(mw.col, path, MODEL_NAME, deck_name)
        importer.initMapping()
        importer.run(list(entries))
        if importer.log:
            logs.append('\n'.join(importer.log))

    txt = _("Importing complete.") + "\n"
    txt += '\n'.join(logs)
    showText(txt)
    mw.reset()
Beispiel #5
0
    def onTimeout(self):
        error = self.pool
        self.pool = ""
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "Pyaudio not" in error:
            return showWarning(_("Please install PyAudio"))
        if "install mplayer" in error:
            return showWarning(_("Please install mplayer"))
        if "no default output" in error:
            return showWarning(_("Please connect a microphone."))
        stdText = _("""\
An error occurred. It may have been caused by a harmless bug, <br>
or your deck may have a problem.
<p>To confirm it's not a problem with your deck, please run
<b>Tools > Maintenance > Check Database</b>.
<p>If that doesn't fix the problem, please copy the following<br>
into a bug report:""")
        pluginText = _("""\
An error occurred in an add-on. Please contact the add-on author.<br>""")
        if "addon" in error:
            txt = pluginText
        else:
            txt = stdText
        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html")
def lookupPronunciation(expr):
    """ Show the pronunciation when the user does a manual lookup """
    ret = getPronunciations(expr)

    thehtml = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<style>
body {
font-size: 30px;
}
</style>
<TITLE>Pronunciations</TITLE>
<meta charset="UTF-8" />
</HEAD>
<BODY>
%s
</BODY>
</HTML>
""" % (
        "<br/><br/>\n".join(ret)
    )

    showText(thehtml, type="html")
    def accept(self):
        self.importer.importMode = 1
        self.mw.pm.profile['importMode'] = self.importer.importMode

        self.importer.allowHTML = True
        self.mw.pm.profile['allowHTML'] = self.importer.allowHTML

        did = self.deck.selectedId()
        if did != self.importer.model['did']:
            self.importer.model['did'] = did
            self.mw.col.models.save(self.importer.model)
        self.mw.col.decks.select(did)

        self.mw.progress.start(immediate=True)
        self.mw.checkpoint(_("Import"))

        self.importer.run()

        self.mw.progress.finish()
        txt = _("Importing complete.") + "\n"
        if self.importer.log:
            txt += "\n".join(self.importer.log)
        self.close()
        showText(txt)
        self.mw.reset()
Beispiel #8
0
    def _sync(self, auth=None):
        # to avoid gui widgets being garbage collected in the worker thread,
        # run gc in advance
        self._didFullUp = False
        self._didError = False
        gc.collect()
        # create the thread, setup signals and start running
        t = self.thread = SyncThread(
            self.pm.collectionPath(), self.pm.profile['syncKey'],
            auth=auth, media=self.pm.profile['syncMedia'])
        t.event.connect(self.onEvent)
        self.label = _("Connecting...")
        self.mw.progress.start(immediate=True, label=self.label)
        self.sentBytes = self.recvBytes = 0
        self._updateLabel()
        self.thread.start()
        while not self.thread.isFinished():
            self.mw.app.processEvents()
            self.thread.wait(100)
        self.mw.progress.finish()
        if self.thread.syncMsg:
            showText(self.thread.syncMsg)
        if self.thread.uname:
            self.pm.profile['syncUser'] = self.thread.uname
        def delayedInfo():
            if self._didFullUp and not self._didError:
                showInfo(_("""\
Your collection was successfully uploaded to AnkiWeb.

If you use any other devices, please sync them now, and choose \
to download the collection you have just uploaded from this computer. \
After doing so, future reviews and added cards will be merged \
automatically."""))
        self.mw.progress.timer(1000, delayedInfo, False)
Beispiel #9
0
    def onTimeout(self):
        error = cgi.escape(self.pool)
        self.pool = ""
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "Pyaudio not" in error:
            return showWarning(_("Please install PyAudio"))
        if "install mplayer" in error:
            return showWarning(_("Please install mplayer"))
        if "no default output" in error:
            return showWarning(
                _("Please connect a microphone, and ensure " "other programs are not using the audio device.")
            )
        if "invalidTempFolder" in error:
            return showWarning(self.tempFolderMsg())
        if "disk I/O error" in error:
            return showWarning(
                _(
                    """\
An error occurred while accessing the database.

Possible causes:

- Antivirus, firewall, backup, or synchronization software may be \
  interfering with Anki. Try disabling such software and see if the \
  problem goes away.
- Your disk may be full.
- The Documents/Anki folder may be on a network drive.
- Files in the Documents/Anki folder may not be writeable.
- Your hard disk may have errors.

It's a good idea to run Tools>Check Database to ensure your collection \
is not corrupt.
"""
                )
            )
        stdText = _(
            """\
An error occurred. It may have been caused by a harmless bug, <br>
or your deck may have a problem.
<p>To confirm it's not a problem with your deck, please run
<b>Tools &gt; Check Database</b>.
<p>If that doesn't fix the problem, please copy the following<br>
into a bug report:"""
        )
        pluginText = _(
            """\
An error occurred in an add-on.<br>
Please post on the add-on forum:<br>%s<br>"""
        )
        pluginText %= "https://anki.tenderapp.com/discussions/add-ons"
        if "addon" in error:
            txt = pluginText
        else:
            txt = stdText
        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html")
def buildCards():
    msg = ""
    mw.progress.start(immediate=True)
    for i in range(len(feeds_info)):
        msg += feeds_info[i]["DECK"] + ":\n"
        msg += buildCard(**feeds_info[i]) + "\n"
    mw.progress.finish()
    utils.showText(msg)
Beispiel #11
0
 def onCheckDB(self):
     "True if no problems"
     self.progress.start(immediate=True)
     ret, ok = self.col.fixIntegrity()
     self.progress.finish()
     if not ok:
         showText(ret)
     else:
         tooltip(ret)
     self.reset()
     return ret
Beispiel #12
0
	def alertUser(self):
		text ='%d new card(s) added. %d card(s) were duplicates' % (
																	len(self.added),
																	len(self.duplicates))
		text += '\n\nNEW CARDS:\n==========\n'
		for card in self.added:
			text += stripHTML(card.front) + '\n'
		
		text += '\nDUPLICATES:\n===========\n'
		for card in self.duplicates:
			text += stripHTML(card.front) + '\n'
			
		showText(text)
 def pause(self):
   self.responsive = False
   self.diag, box = showText('Pausing speech recognition, say "RESUME" to continue', run=False)
   def onReject(self):
     self.diag = None
   self.diag.connect(box, SIGNAL("rejected()"), lambda:onReject(self))
   self.diag.show()
def register(again=False):
    """Register the new importer with Anki's importers."""

    addonDir = os.path.dirname(os.path.abspath(__file__))
    libsDir = os.path.join(addonDir, "lib")
    if libsDir not in sys.path:
        sys.path.append(libsDir)

    from . import spreadsheet
    reload(spreadsheet)
    importer = (("Spreadsheet Import Plus (*.xlsx)",
                 spreadsheet.SpreadsheetImporter), )
    if again:
        importing.Importers = importing.Importers[0:-1] + importer
        showText(repr(importing.Importers))
    else:
        importing.Importers += importer
Beispiel #15
0
    def on_future_done(fut: Future) -> None:
        mw.col.db.begin()
        timer.stop()
        try:
            out: SyncOutput = fut.result()
        except Exception as err:
            handle_sync_error(mw, err)
            return on_done()

        mw.pm.set_host_number(out.host_number)
        if out.server_message:
            showText(out.server_message)
        if out.required == out.NO_CHANGES:
            # all done
            return on_done()
        else:
            full_sync(mw, out, on_done)
Beispiel #16
0
    def _sync(self, auth=None):
        # to avoid gui widgets being garbage collected in the worker thread,
        # run gc in advance
        self._didFullUp = False
        self._didError = False
        gc.collect()
        # create the thread, setup signals and start running
        t = self.thread = SyncThread(self.pm.collectionPath(),
                                     self.pm.profile['syncKey'],
                                     auth=auth,
                                     media=self.pm.profile['syncMedia'])
        t.event.connect(self.onEvent)
        self.label = _("Connecting...")
        prog = self.mw.progress.start(immediate=True,
                                      label=self.label,
                                      cancellable=True)
        self.sentBytes = self.recvBytes = 0
        self._updateLabel()
        self.thread.start()
        while not self.thread.isFinished():
            if prog.ankiCancel:
                self.thread.flagAbort()
                # make sure we don't display 'upload success' msg
                self._didFullUp = False
                # abort may take a while
                self.mw.progress.update(_("Stopping..."))
            self.mw.app.processEvents()
            self.thread.wait(100)
        self.mw.progress.finish()
        if self.thread.syncMsg:
            showText(self.thread.syncMsg)
        if self.thread.uname:
            self.pm.profile['syncUser'] = self.thread.uname

        def delayedInfo():
            if self._didFullUp and not self._didError:
                showInfo(
                    _("""\
Your collection was successfully uploaded to AnkiWeb.

If you use any other devices, please sync them now, and choose \
to download the collection you have just uploaded from this computer. \
After doing so, future reviews and added cards will be merged \
automatically."""))

        self.mw.progress.timer(1000, delayedInfo, False)
Beispiel #17
0
    def _on_render_latex(self):
        self.progress_dialog = self.mw.progress.start()
        try:
            out = self.mw.col.media.render_all_latex(
                self._on_render_latex_progress)
            if self.progress_dialog.wantCancel:
                return
        finally:
            self.mw.progress.finish()
            self.progress_dialog = None

        if out is not None:
            nid, err = out
            self.mw.browser_search(SearchTerm(nid=nid))
            showText(err, type="html")
        else:
            tooltip(tr(TR.MEDIA_CHECK_ALL_LATEX_RENDERED))
Beispiel #18
0
    def join_thread(self) -> None:
        """
        Gather up the results of a completed extract thread, and start the next one
        if appropriate.
        """
        assert self.extract_thread is not None, "Tried to join a nonexistent thread!"

        if self.handle_thread_exception():
            return None

        if not self.extract_thread.notes:
            # This is probably a mistake or misconfiguration. To avoid deleting
            # all the user's existing notes to "sync" the collection, abort now.
            showWarning(
                f"No notes were found in the wiki {self.extract_thread.wiki_name}. "
                f"Please check your add-on configuration. "
                f"Your collection has not been updated.")
            self.reject()
            return None

        # This is a set union, with object equality defined by the ID. Any
        # notes with an ID matching one already used in a previous wiki will be
        # discarded here.
        self.notes.update(self.extract_thread.notes)
        self.warnings.extend(self.extract_thread.warnings)

        self.form.wikiProgressBar.setValue(self.form.wikiProgressBar.value() +
                                           1)
        if self.wikis:
            # If there are any more wikis, handle the next one.
            # Eventually, parallelizing this might be nice
            # (might also not improve performance).
            return self.extract()
        else:
            # When all are completed...
            if self.warnings:
                showText(f"*** {len(self.warnings)} "
                         f"{pluralize('warning', len(self.warnings))}: ***\n" +
                         '\n'.join(self.warnings))
            if (not self.warnings) or askUser("Continue syncing?"):
                return self.sync()
            else:
                self.accept()
                self.mw.reset()
                return tooltip("Sync canceled.")
Beispiel #19
0
    def showDebugInfo():
        from aqt import mw
        from anki import version as anki_version
        from aqt.utils import showInfo, showText

        txt = """
    <h2>Bug Status: Affected</h2>

    <p>It seems like your system is affected by a module import bug.</p>

    <p>To report your findings, please copy the debug info below and post it 
    <a href="https://anki.tenderapp.com/discussions/add-ons/35343">here</a>. 
    (no account needed).
    Feel free to uninstall "Import Bug Test" once you're done</p>

    <p>Thanks so much for your help in tracking this issue down!</p>

    <p><b>Debug info</b>:</p>
    """
        txt += "<div style='white-space: pre-wrap'>"

        if not anki_version.startswith("2.0"):
            from aqt.utils import supportText
            txt += "\n" + supportText() + "\n"
            addmgr = mw.addonManager
            txt += "Add-ons:\n\n" + "\n".join(
                addmgr.annotatedName(d) for d in addmgr.allAddons()) + "\n\n"
        else:
            from aqt import appVersion
            from aqt.qt import QT_VERSION_STR, PYQT_VERSION_STR
            txt += '<p>' + "Version %s" % appVersion + '\n'
            txt += ("Qt %s PyQt %s\n\n") % (QT_VERSION_STR, PYQT_VERSION_STR)
            txt += "Add-ons:\n\n" + repr(mw.addonManager.files()) + "\n\n"

        txt += "Import Errors:\n\n"
        txt += "\n\n".join(error[0] + ":\n" + error[1] for error in errors)

        txt += "</div>"

        kwargs = dict(title="Import Bug Test", type="html")

        if not anki_version.startswith("2.0"):
            kwargs["copyBtn"] = True

        showText(txt, **kwargs)
Beispiel #20
0
    def _on_render_latex(self):
        self.progress_dialog = self.mw.progress.start()
        try:
            out = self.mw.col.media.render_all_latex(self._on_render_latex_progress)
            if self.progress_dialog.wantCancel:
                return
        finally:
            self.mw.progress.finish()
            self.progress_dialog = None

        if out is not None:
            nid, err = out
            browser = aqt.dialogs.open("Browser", self.mw)
            browser.form.searchEdit.lineEdit().setText("nid:%d" % nid)
            browser.onSearchActivated()
            showText(err, type="html")
        else:
            tooltip(tr(TR.MEDIA_CHECK_ALL_LATEX_RENDERED))
Beispiel #21
0
def importToAnki(dialog, temp_file_path):
    mw.progress.finish()
    if temp_file_path is not None:
        mw.progress.start(immediate=True, label="Importing...")
        dialog.setupImporter(temp_file_path)
        dialog.selectDeck()

        dialog.importer.run()
        mw.progress.finish()

        txt = _("Importing complete.") + "\n"
        if dialog.importer.log:
            txt += "\n".join(dialog.importer.log)

        os.remove(temp_file_path)
    else:
        txt = "Nothing to import!"
    showText(txt)
Beispiel #22
0
def touch_media(self, *args, **kwargs):
    media = []
    m = mw.col.media.dir()
    for f in os.listdir(m):
        fpath = join(m, f)
        if isfile(fpath):

            #TEST: set to 1979
            # os.utime(fpath,(315550000,315550000))

            if os.stat(fpath).st_mtime < DOS_EPOCH_TIME:
                t = time.time()
                os.utime(fpath, (t, t))
                media.append(f)

    if media:
        lst = "\n".join(media)
        showText("Incorrect mod time before 1980, auto updated:\n\n%s" % lst)
Beispiel #23
0
    def run(self):
        try:
            config = mw.addonManager.getConfig(__name__)

            cookies = {}
            if config["qlts"]:
                cookies = {"qlts": config["qlts"]}
            elif config["cookies"]:
                from http.cookies import SimpleCookie
                C = SimpleCookie()
                C.load(config["cookies"])
                cookies = {key: morsel.value for key, morsel in C.items()}

            r = requests.get(self.url,
                             verify=False,
                             headers=headers,
                             cookies=cookies)
            r.raise_for_status()

            regex = re.escape('window.Quizlet["setPasswordData"]')

            if re.search(regex, r.text):
                self.error = True
                self.errorCode = 403
                return

            regex = re.escape('window.Quizlet["cardsModeData"] = ')
            regex += r'(.+?)'
            regex += re.escape('; QLoad("Quizlet.cardsModeData");')

            data = re.search(regex, r.text).group(1).strip()
            self.results = json.loads(data)

            title = re.search(r'<title>(.*?) \| Quizlet</title>',
                              r.text).group(1).strip()
            self.results['title'] = title
        except requests.HTTPError as e:
            self.error = True
            self.errorCode = e.response.status_code
            self.errorMessage = e.response.text
        except ValueError as e:
            self.error = True
            self.errorReason = ("Invalid json: {0}".format(e))
            showText(_("Invalid json: ") + repr(e))
Beispiel #24
0
    def _on_render_latex(self) -> None:
        self.progress_dialog = self.mw.progress.start()
        try:
            out = self.mw.col.media.render_all_latex(
                self._on_render_latex_progress)
            if self.progress_dialog.wantCancel:
                return
        finally:
            self.mw.progress.finish()
            self.progress_dialog = None

        if out is not None:
            nid, err = out
            aqt.dialogs.open("Browser",
                             self.mw,
                             search=(SearchNode(nid=nid), ))
            showText(err, type="html")
        else:
            tooltip(tr.media_check_all_latex_rendered())
Beispiel #25
0
    def pause(self):
        self.responsive = False
        self.diag, box = showText(
            'Pausing speech recognition, say "RESUME" to continue', run=False)

        def onReject(self):
            self.diag = None

        self.diag.connect(box, SIGNAL("rejected()"), lambda: onReject(self))
        self.diag.show()
Beispiel #26
0
        def onDone(future: Future):
            self.progress.finish()
            ret, ok = future.result()

            if not ok:
                showText(ret)
            else:
                tooltip(ret)

            # if an error has directed the user to check the database,
            # silently clean up any broken reset hooks which distract from
            # the underlying issue
            while True:
                try:
                    self.reset()
                    break
                except Exception as e:
                    print("swallowed exception in reset hook:", e)
                    continue
Beispiel #27
0
 def accept(self):
     self.importer.mapping = self.mapping
     if not self.importer.mappingOk():
         showWarning(_("The first field of the note type must be mapped."))
         return
     self.importer.importMode = self.frm.importMode.currentIndex()
     self.mw.pm.profile["importMode"] = self.importer.importMode
     self.importer.allowHTML = self.frm.allowHTML.isChecked()
     self.mw.pm.profile["allowHTML"] = self.importer.allowHTML
     if self.frm.tagModifiedCheck.isChecked():
         self.importer.tagModified = self.frm.tagModifiedTag.toPlainText()
     self.mw.pm.profile["tagModified"] = self.importer.tagModified
     did = self.deck.selectedId()
     if did != self.importer.model["did"]:
         self.importer.model["did"] = did
         self.mw.col.models.save(self.importer.model, updateReqs=False)
     self.mw.col.decks.select(did)
     self.mw.progress.start(immediate=True)
     self.mw.checkpoint(_("Import"))
     try:
         self.importer.run()
     except UnicodeDecodeError:
         showUnicodeWarning()
         return
     except Exception as e:
         msg = _("Import failed.\n")
         err = repr(str(e))
         if "1-character string" in err:
             msg += err
         elif "invalidTempFolder" in err:
             msg += self.mw.errorHandler.tempFolderMsg()
         else:
             msg += traceback.format_exc()
         showText(msg)
         return
     finally:
         self.mw.progress.finish()
     txt = _("Importing complete.") + "\n"
     if self.importer.log:
         txt += "\n".join(self.importer.log)
     self.close()
     showText(txt)
     self.mw.reset()
Beispiel #28
0
def ImportToAnki(model_name, import_to_deck, *args, **kwargs):
    # get file
    file = kwargs.get("file", None)
    if not file:
        file = getFile(mw,
                       _("Import"),
                       None,
                       key="import",
                       filter=Importers[0][0])
    if not file:
        return
    file = str(file)

    # check default model
    try:
        model = mw.col.models.byName(model_name)
        if not model:
            raise Exception("没有找到【{}】".format(model_name))
    except:
        importFile(mw, settings.deck_template_file)
        try:
            model = mw.col.models.byName(model_name)
        except:
            model = None

    importer = TextImporter(mw.col, file)
    importer.delimiter = "\t"
    importer.importMode = 0
    importer.allowHTML = True
    importer.model = model

    did = mw.col.decks.id(import_to_deck)
    mw.col.conf['curDeck'] = did
    importer.model['did'] = did
    mw.col.decks.select(did)
    importer.mapping = [kwargs.get("first")]
    importer.run()
    mw.reset()
    txt = _("Importing complete.") + "\n"
    if importer.log:
        txt += "\n".join(importer.log)
    showText(txt)
Beispiel #29
0
    def onTimeout(self) -> None:
        error = html.escape(self.pool)
        self.pool = ""
        self.mw.progress.clear()
        if "AbortSchemaModification" in error:
            return
        if "DeprecationWarning" in error:
            return
        if "10013" in error:
            showWarning(tr.qt_misc_your_firewall_or_antivirus_program_is())
            return
        if "invalidTempFolder" in error:
            showWarning(self.tempFolderMsg())
            return
        if "Beautiful Soup is not an HTTP client" in error:
            return
        if "database or disk is full" in error or "Errno 28" in error:
            showWarning(tr.qt_misc_your_computers_storage_may_be_full())
            return
        if "disk I/O error" in error:
            showWarning(markdown(tr.errors_accessing_db()))
            return

        must_close = False
        if "PanicException" in error:
            must_close = True
            txt = markdown(
                "**A fatal error occurred, and Anki must close. Please report this message on the forums.**"
            )
            error = f"{supportText() + self._addonText(error)}\n{error}"
        elif self.mw.addonManager.dirty:
            txt = markdown(tr.errors_addons_active_popup())
            error = f"{supportText() + self._addonText(error)}\n{error}"
        else:
            txt = markdown(tr.errors_standard_popup())
            error = f"{supportText()}\n{error}"

        # show dialog
        txt = f"{txt}<div style='white-space: pre-wrap'>{error}</div>"
        showText(txt, type="html", copyBtn=True)
        if must_close:
            sys.exit(1)
Beispiel #30
0
def fix_occlbug():
    mw.progress.start(immediate=True, label="Please wait, this should not take long")
    nids = find_occlbug_affected_notes()
    tag_notes(nids)
    mw.progress.finish()
    if len(nids) > 0:
        showText("""
PLEASE READ THIS CAREFULLY. You will only see this message once. (You can find the text in the addon page though)

Sorry!!
There was a bug in previous version of the addon 'Image Style Editor'.
When editing image sizes in image occlusion notes, it made all the cards of the note have the same occlusion masks.
A total of %d notes were found affected by the bug, and they were tagged "image-style-occl-bugged".

To fix your notes, please do the following: 
1. Click Browse, search for "tag:image-style-occl-bugged" (without quotes)
2. For each note, remove "image-style-occl-bugged" tag, then press 'Edit Image Occlusion'(Ctrl + Shift + O) on top right. 
3. Move one of the masks by 1mm. There needs to be a change to the note.
4. Click 'Edit Cards' on the bottom.
"""%len(nids))
Beispiel #31
0
 def accept(self):
     self.importer.mapping = self.mapping
     if not self.importer.mappingOk():
         showWarning(
             _("The first field of the note type must be mapped."))
         return
     self.importer.importMode = self.frm.importMode.currentIndex()
     self.mw.pm.profile['importMode'] = self.importer.importMode
     self.importer.allowHTML = self.frm.allowHTML.isChecked()
     self.mw.pm.profile['allowHTML'] = self.importer.allowHTML
     did = self.deck.selectedId()
     if did != self.importer.model['did']:
         self.importer.model['did'] = did
         self.mw.col.models.save(self.importer.model)
     self.mw.col.decks.select(did)
     self.mw.progress.start(immediate=True)
     self.mw.checkpoint(_("Import"))
     try:
         self.importer.run()
     except UnicodeDecodeError:
         showUnicodeWarning()
         return
     except Exception as e:
         msg = _("Import failed.\n")
         err = repr(str(e))
         if "1-character string" in err:
             msg += err
         elif "invalidTempFolder" in err:
             msg += self.mw.errorHandler.tempFolderMsg()
         else:
             msg += str(traceback.format_exc(), "ascii", "replace")
         showText(msg)
         return
     finally:
         self.mw.progress.finish()
     txt = _("Importing complete.") + "\n"
     if self.importer.log:
         txt += "\n".join(self.importer.log)
     self.close()
     showText(txt)
     self.mw.reset()
Beispiel #32
0
    def onCheckDB(self):
        "True if no problems"
        self.progress.start(immediate=True)
        ret, ok = self.col.fixIntegrity()
        self.progress.finish()
        if not ok:
            showText(ret)
        else:
            tooltip(ret)

        # if an error has directed the user to check the database,
        # silently clean up any broken reset hooks which distract from
        # the underlying issue
        while True:
            try:
                self.reset()
                break
            except Exception as e:
                print("swallowed exception in reset hook:", e)
                continue
        return ret
Beispiel #33
0
    def select_model(self):
        if not self.mod_list:
            showText(_trans("USER DEFINED TEMPLATE ALERT"),
                     self,
                     "html",
                     title=_trans("AnKindle"))
            importFile(mw, DEFAULT_TEMPLATE)

        edit = QPushButton(_trans("USE LATEST TEMPLATE"),
                           clicked=lambda x: importFile(mw, DEFAULT_TEMPLATE))

        ret = StudyDeck(
            mw,
            names=lambda: sorted([f['name'] for f in self.mod_list]),
            accept=anki.lang._("Choose"),
            title=_trans("NOTE TYPE"),
            parent=self,
            buttons=[edit],
            help='',
            cancel=True)
        return ret
Beispiel #34
0
    def onCheckDB(self):
        "True if no problems"
        self.progress.start(immediate=True)
        ret, ok = self.col.fixIntegrity()
        self.progress.finish()
        if not ok:
            showText(ret)
        else:
            tooltip(ret)

        # if an error has directed the user to check the database,
        # silently clean up any broken reset hooks which distract from
        # the underlying issue
        while True:
            try:
                self.reset()
                break
            except Exception as e:
                print("swallowed exception in reset hook:", e)
                continue
        return ret
Beispiel #35
0
    def on_future_done(fut) -> None:
        timer.stop()
        ret, ok = fut.result()

        if not ok:
            showText(ret)
        else:
            tooltip(ret)

        # if an error has directed the user to check the database,
        # silently clean up any broken reset hooks which distract from
        # the underlying issue
        n = 0
        while n < 10:
            try:
                mw.reset()
                break
            except Exception as e:
                print("swallowed exception in reset hook:", e)
                n += 1
                continue
Beispiel #36
0
    def onTimeout(self):
        error = html.escape(self.pool)
        self.pool = ""
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "10013" in error:
            return showWarning(
                _("Your firewall or antivirus program is preventing Anki from creating a connection to itself. Please add an exception for Anki."
                  ))
        if "install mplayer" in error:
            return showWarning(
                _("Sound and video on cards will not function until mpv or mplayer is installed."
                  ))
        if "no default input" in error.lower():
            return showWarning(
                _("Please connect a microphone, and ensure "
                  "other programs are not using the audio device."))
        if "invalidTempFolder" in error:
            return showWarning(self.tempFolderMsg())
        if "Beautiful Soup is not an HTTP client" in error:
            return
        if "database or disk is full" in error or "Errno 28" in error:
            return showWarning(
                _("Your computer's storage may be full. Please delete some unneeded files, then try again."
                  ))
        if "disk I/O error" in error:
            showWarning(markdown(tr(FString.ERRORS_ACCESSING_DB)))
            return

        if self.mw.addonManager.dirty:
            txt = markdown(tr(FString.ERRORS_ADDONS_ACTIVE_POPUP))
            error = supportText() + self._addonText(error) + "\n" + error
        else:
            txt = markdown(tr(FString.ERRORS_STANDARD_POPUP))
            error = supportText() + "\n" + error

        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html", copyBtn=True)
Beispiel #37
0
    def onTimeout(self):
        error = self.pool
        self.pool = ""
        stdText = _("""\
An error occurred. It may have been caused by a harmless bug, <br>
or your deck may have a problem.
<p>To confirm it's not a problem with your deck, please run
<b>Tools > Advanced > Check Database</b>.
<p>If that doesn't fix the problem, please copy the following<br>
into a bug report:""")
        pluginText = _("""\
An error occurred in a plugin. Please contact the plugin author.<br>
Please do not file a bug report with Anki.<br>""")
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "addon" in error:
            txt = pluginText
        else:
            txt = stdText
        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html")
Beispiel #38
0
    def onTimeout(self):
        error = self.pool
        self.pool = ""
        stdText = _("""\
An error occurred. It may have been caused by a harmless bug, <br>
or your deck may have a problem.
<p>To confirm it's not a problem with your deck, please run
<b>Tools > Advanced > Check Database</b>.
<p>If that doesn't fix the problem, please copy the following<br>
into a bug report:""")
        pluginText = _("""\
An error occurred in a plugin. Please contact the plugin author.<br>
Please do not file a bug report with Anki.<br>""")
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "addon" in error:
            txt = pluginText
        else:
            txt = stdText
        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html")
Beispiel #39
0
def lookupPronunciation(expr):
    """ Show the pronunciation when the user does a manual lookup """
    ret = getPronunciations(expr)

    thehtml = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<style>
body {
font-size: 30px;
}
</style>
<TITLE>Pronunciations</TITLE>
<meta charset="UTF-8" />
</HEAD>
<BODY>
%s
</BODY>
</HTML>
""" % ("<br/><br/>\n".join(ret))

    showText(thehtml, type="html")
Beispiel #40
0
def debug():
    card = mw.col.sched.getCard()
    #showText(str(card.nid), title="anki-extended-scmhash debug output")

    note = card.note()
    #showText(str(note.model), title="anki-extended-scmhash debug output")

    model = note.model()

    # debugtext = str(model['tmpls'][0]['name'])
    # debugtext = str(model['css'])
    debugtext = str(model['name']) + str(model['tmpls'][0]['name']) \
        + ", qfmt:\n" + str(model['tmpls'][0]['qfmt'])
    # showText(debugtext, title="anki-extended-scmhash debug output")

    s = str(model['css'])
    for f in model['flds']:
        s += f['name']
    for t in model['tmpls']:
        s += t['name']
        for fmt in ('qfmt', 'afmt'):
            s += t[fmt]
    showText(s, title="anki-extended-scmhash debug output")
Beispiel #41
0
    def onTimeout(self) -> None:
        error = html.escape(self.pool)
        self.pool = ""
        self.mw.progress.clear()
        if "AbortSchemaModification" in error:
            return
        if "DeprecationWarning" in error:
            return
        if "10013" in error:
            showWarning(tr.qt_misc_your_firewall_or_antivirus_program_is())
            return
        if "no default input" in error.lower():
            showWarning(tr.qt_misc_please_connect_a_microphone_and_ensure())
            return
        if "invalidTempFolder" in error:
            showWarning(self.tempFolderMsg())
            return
        if "Beautiful Soup is not an HTTP client" in error:
            return
        if "database or disk is full" in error or "Errno 28" in error:
            showWarning(tr.qt_misc_your_computers_storage_may_be_full())
            return
        if "disk I/O error" in error:
            showWarning(markdown(tr.errors_accessing_db()))
            return

        if self.mw.addonManager.dirty:
            txt = markdown(tr.errors_addons_active_popup())
            error = f"{supportText() + self._addonText(error)}\n{error}"
        else:
            txt = markdown(tr.errors_standard_popup())
            error = f"{supportText()}\n{error}"

        # show dialog
        txt = f"{txt}<div style='white-space: pre-wrap'>{error}</div>"
        showText(txt, type="html", copyBtn=True)
Beispiel #42
0
    def onTimeout(self) -> None:
        error = html.escape(self.pool)
        self.pool = ""
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "DeprecationWarning" in error:
            return
        if "10013" in error:
            showWarning(tr(TR.QT_MISC_YOUR_FIREWALL_OR_ANTIVIRUS_PROGRAM_IS))
            return
        if "no default input" in error.lower():
            showWarning(tr(TR.QT_MISC_PLEASE_CONNECT_A_MICROPHONE_AND_ENSURE))
            return
        if "invalidTempFolder" in error:
            showWarning(self.tempFolderMsg())
            return
        if "Beautiful Soup is not an HTTP client" in error:
            return
        if "database or disk is full" in error or "Errno 28" in error:
            showWarning(tr(TR.QT_MISC_YOUR_COMPUTERS_STORAGE_MAY_BE_FULL))
            return
        if "disk I/O error" in error:
            showWarning(markdown(tr(TR.ERRORS_ACCESSING_DB)))
            return

        if self.mw.addonManager.dirty:
            txt = markdown(tr(TR.ERRORS_ADDONS_ACTIVE_POPUP))
            error = supportText() + self._addonText(error) + "\n" + error
        else:
            txt = markdown(tr(TR.ERRORS_STANDARD_POPUP))
            error = supportText() + "\n" + error

        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html", copyBtn=True)
Beispiel #43
0
def test_names():
    """Go through the collection and show possible new names

    Search the cards for sounds or images with file names that look
    like MD5 hashes, rename the files and change the notes.
    """
    test_string = u''
    nids = mw.col.db.list("select id from notes")
    for nid in progress(nids, "Dehashilating", "This is all wrong!"):
        n = mw.col.getNote(nid)
        for (name, value) in n.items():
            rs = re.search(hash_name_pat, value)
            if None == rs:
                continue
            try:
                new_name_ = new_media_name(rs.group(1), rs.group(2), n)
            except ValueError:
                continue
            test_string += u'{0}{1} → {2}\n'.format(
                rs.group(1), rs.group(2),
                new_name_)
    if (test_string):
        showText('These new names will be used:\n' + test_string)
    return test_string
Beispiel #44
0
 def on_clicked(self):
     if os.path.isfile(self.help_text_or_file):
         if IS_PY3K:
             with open(self.help_text_or_file, encoding="utf-8") as f:
                 text = f.read()
         else:
             with open(self.help_text_or_file) as f:
                 text = f.read()
                 text = text.decode("utf-8")
     else:
         text = self.help_text_or_file
     dlg, box = showText(text
                         , self.parent(), "html", title=anki.lang._("Help"), run=False)
     online_template_doc = QPushButton(_trans("MORE_DOC"), dlg)
     online_template_doc.clicked.connect(partial(openLink, ONLINE_DOC_URL))
     dlg.layout().insertWidget(1, online_template_doc)
     dlg.exec_()
Beispiel #45
0
 def __init__(self, parent, updater=None):
     super(_SharedFrame, self).__init__(parent)
     self.l_h_widgets = QHBoxLayout(self)
     wx = WeChatButton(
         self,
         os.path.join(os.path.dirname(__file__), "resource",
                      "AnKindle.jpg"))
     wx.setIcon(
         os.path.join(os.path.dirname(__file__), "resource", "wechat.png"))
     wx.setObjectName("wx")
     self.l_h_widgets.addWidget(wx)
     vt = VoteButton(self, ADDON_CD)
     vt.setObjectName("vt")
     vt.setIcon(
         os.path.join(os.path.dirname(__file__), "resource", "upvote.png"))
     self.l_h_widgets.addWidget(vt)
     mr = MoreAddonButton(self)
     mr.setObjectName("mr")
     mr.setIcon(
         os.path.join(os.path.dirname(__file__), "resource", "more.png"))
     self.l_h_widgets.addWidget(mr)
     self.help_btn = _HelpBtn(self)
     self.l_h_widgets.addSpacerItem(
         QSpacerItem(
             10,
             10,
             QSizePolicy.Expanding,
             QSizePolicy.Minimum,
         ))
     self.l_h_widgets.addWidget(self.help_btn)
     if updater:
         up_btn = UpgradeButton(self, updater)
         up_btn.setIcon(
             os.path.join(os.path.dirname(__file__), "resource",
                          "update.png"))
         self.l_h_widgets.addWidget(up_btn)
         if isWin:
             up_btn.clicked.disconnect()
             up_btn.clicked.connect(
                 lambda: showText(_trans("WIN UPDATE") % ADDON_CD,
                                  parent,
                                  title=_trans("ANKINDLE")))
Beispiel #46
0
 def onEmptyCards(self):
     self.progress.start(immediate=True)
     cids = self.col.emptyCids()
     if not cids:
         self.progress.finish()
         tooltip(_("No empty cards."))
         return
     report = self.col.emptyCardReport(cids)
     self.progress.finish()
     part1 = ngettext("%d card", "%d cards", len(cids)) % len(cids)
     part1 = _("%s to delete:") % part1
     diag, box = showText(part1 + "\n\n" + report, run=False)
     box.addButton(_("Delete Cards"), QDialogButtonBox.AcceptRole)
     box.button(QDialogButtonBox.Close).setDefault(True)
     def onDelete():
         QDialog.accept(diag)
         self.checkpoint(_("Delete Empty"))
         self.col.remCards(cids)
         tooltip(ngettext("%d card deleted.", "%d cards deleted.", len(cids)) % len(cids))
         self.reset()
     diag.connect(box, SIGNAL("accepted()"), onDelete)
     diag.show()
Beispiel #47
0
 def onEmptyCards(self):
     self.progress.start(immediate=True)
     cids = self.col.emptyCids()
     if not cids:
         self.progress.finish()
         tooltip(_("No empty cards."))
         return
     report = self.col.emptyCardReport(cids)
     self.progress.finish()
     part1 = ngettext("%d card", "%d cards", len(cids)) % len(cids)
     part1 = _("%s to delete:") % part1
     diag, box = showText(part1 + "\n\n" + report, run=False)
     box.addButton(_("Delete Cards"), QDialogButtonBox.AcceptRole)
     box.button(QDialogButtonBox.Close).setDefault(True)
     def onDelete():
         QDialog.accept(diag)
         self.checkpoint(_("Delete Empty"))
         self.col.remCards(cids)
         tooltip(ngettext("%d card deleted.", "%d cards deleted.", len(cids)) % len(cids))
         self.reset()
     diag.connect(box, SIGNAL("accepted()"), onDelete)
     diag.show()
Beispiel #48
0
Datei: sync.py Projekt: dae/anki
    def onEvent(self, evt, *args):
        pu = self.mw.progress.update
        if evt == "badAuth":
            tooltip(
                _("AnkiWeb ID or password was incorrect; please try again."),
                parent=self.mw)
            # blank the key so we prompt user again
            self.pm.profile['syncKey'] = None
            self.pm.save()
        elif evt == "corrupt":
            pass
        elif evt == "newKey":
            self.pm.profile['syncKey'] = args[0]
            self.pm.save()
        elif evt == "offline":
            tooltip(_("Syncing failed; internet offline."))
        elif evt == "upbad":
            self._didFullUp = False
            self._checkFailed()
        elif evt == "sync":
            m = None; t = args[0]
            if t == "login":
                m = _("Syncing...")
            elif t == "upload":
                self._didFullUp = True
                m = _("Uploading to AnkiWeb...")
            elif t == "download":
                m = _("Downloading from AnkiWeb...")
            elif t == "sanity":
                m = _("Checking...")
            elif t == "findMedia":
                m = _("Checking media...")
            elif t == "upgradeRequired":
                showText(_("""\
Please visit AnkiWeb, upgrade your deck, then try again."""))
            if m:
                self.label = m
                self._updateLabel()
        elif evt == "syncMsg":
            self.label = args[0]
            self._updateLabel()
        elif evt == "error":
            self._didError = True
            showText(_("Syncing failed:\n%s")%
                     self._rewriteError(args[0]))
        elif evt == "clockOff":
            self._clockOff()
        elif evt == "checkFailed":
            self._checkFailed()
        elif evt == "mediaSanity":
            showWarning(_("""\
A problem occurred while syncing media. Please use Tools>Check Media, then \
sync again to correct the issue."""))
        elif evt == "noChanges":
            pass
        elif evt == "fullSync":
            self._confirmFullSync()
        elif evt == "downloadClobber":
            showInfo(_("Your AnkiWeb collection does not contain any cards. Please sync again and choose 'Upload' instead."))
        elif evt == "send":
            # posted events not guaranteed to arrive in order
            self.sentBytes = max(self.sentBytes, int(args[0]))
            self._updateLabel()
        elif evt == "recv":
            self.recvBytes = max(self.recvBytes, int(args[0]))
            self._updateLabel()
Beispiel #49
0
def showMessages(mw, data):
    showText(data["msg"], parent=mw, type="html")
    mw.pm.meta["lastMsg"] = data["msgId"]
def advimport():
    Log('-'*80)

    filename = getFile(mw, "Select file to import", None, key="import")
    
    if len(filename) == 0:
        showText("invalid filename", mw, type="text", run=True)
        return 
    
    lines = []
    n = 0
    
    with open(filename) as f:
        reader = unicode_csv_reader(f)
        
        for i in range(N_HEADER_LINES):
            n += 1
            reader.next()
            
        for row in reader:
            #print row
            n += 1
            lines.append((n, row))


    for n, line in lines:
        
        #Log("--"*5)

        data = []
        
        _chapt = line[0]
        _sect = line[1]
        _keywords = line[2]
        _question = line[3]
        _solution = line[4]
        
        _type = line[5]
        _subtype = line[6]
        _symb = SYMBOLS.get(_type, "")
        
        _rests = line[7:]
        
        print "L%03i:"%n,
        
        if not _type:
            print "!!! No type, skipping"
            continue


        elif _type == u"rule":
            print "   Rule        ",
            
            model = "Rule"
            key = _question
            
            data = [key, _question, _solution, _chapt, _sect, _type, _symb]


        elif _type == u"pron":
            print "   Pronoun     ",
            
            model = "Simple"
            key = _solution
            
            data = [key, _question, _solution, _chapt, _sect, _type, _symb]


        elif _type == u"wend":
            print "   Sentence    ",
            
            model = "Simple"
            key = _solution
            
            data = [key, _question, _solution, _chapt, _sect, _type, _symb]
            

        elif _type == u"prep":
            print "   Prepos      ",
            
            model = "Simple"
            key = _solution
            
            data = [key, _question, _solution, _chapt, _sect, _type, _symb]


        elif _type == u"adv":
            print "   Adverb      ",
            
            model = "Simple"
            key = _solution
            
            data = [key, _question, _solution, _chapt, _sect, _type, _symb]


        elif _type == u"nom": # Noun
            print "   Noun        ",
            
            model = "Noun"
            
            key = _solution
            
            lst = _solution.split(' ')
            
            art = lst.pop(0)
            noun = " ".join(lst)
            
            
            if not _subtype or _subtype == u"":
                if   art == "el":    _subtype = u"♂"
                elif art == "la":    _subtype = u"♀"
                elif art == "los":   _subtype = u"♂♂/♂♀"
                elif art == "las":   _subtype = u"♀♀"
                elif art == "el/la": _subtype = u"♂/♀"
            elif _subtype[0] in ["F", "f"]: _subtype = u"♀"
            elif _subtype[0] in ["M", "m"]: _subtype = u"♂"
            
            data = [key, _question, _solution, _chapt, _sect, _type, _subtype, _symb]

            
        elif _type == u"verb":
            print "   Verb        ", 
            
            modus = _rests[0]
            temp = _rests[1]
            forms = _rests[2:]
            
            for ii, f in enumerate(forms):
                _ = f.split('|')
                if len(_)==2:
                    for i, (c, e) in enumerate(zip(["stem", "ext"], _)):
                        _[i] = '<span class="%s">%s</span>' % (c, e)
                
                for i, x in enumerate(_):
                    _[i] = _[i].replace("[", '<span class="irr">')
                    _[i] = _[i].replace("]", '</span>')
                    
                forms[ii] = "".join(_)
            
            model = "Verb"
            key = "%s (%s; %s)" % (_solution, modus, temp)
            jsforms = '''{'sg1':'%s','sg2':'%s','sg3':'%s','pl1':'%s','pl2':'%s','pl3':'%s'}''' % tuple(forms)
            #Log("JSF", jsforms)

            _question = _question.replace("[", '<span class="prp">')
            _question = _question.replace("]", '</span>')
            _solution = _solution.replace("[", '<span class="prp">')
            _solution = _solution.replace("]", '</span>')
            
            #print _question

            data = [key, _question, _solution, _chapt, _sect, _type, _subtype, _symb, modus, temp, jsforms]
          
          
        elif _type == u"adj":
            print "   Adjective   ",
            
            s = _solution
            
            def decline(stem, exts=['_o', '_a', '_os', '_as'], wrap=('<b>', '</b>')):
                return [stem+wrap[0]+_+wrap[1] for _ in exts]
            
            if '[' in s:
                _subtype = 'IRR'
                i = s.find('[')
                stem = s[:i]
                exts = s[i+1:s.find(']')].split('|')
                #Log("ir1: ", i, stem, exts, len(exts))
                
                if len(exts)==4:
                    pass
                elif len(exts)==2:
                    exts = [exts[0], exts[0], exts[1], exts[1]]
                elif len(exts)==3:
                    exts = [exts[0], exts[1], exts[2], exts[2]]
                else:
                    #TODO
                    exts = ['???']*4
                    
            elif '|' in s:
                _subtype = 'IRR'
                stem = ''
                exts = s.split('|')

                if len(exts)==4:
                    pass
                elif len(exts)==2:
                    exts = [exts[0], exts[0], exts[1], exts[1]]
                elif len(exts)==3:
                    exts = [exts[0], exts[1], exts[2], exts[2]]
                else:
                    exts = ['???']*4
                
            elif s[-1]=='o':
                _subtype = '-o'
                stem = s[:-1]
                exts = ['_o', '_a', '_os', '_as']

            elif s[-1]=='e':
                _subtype = '-e'
                stem = s[:-1]
                exts = ['e', 'e', '_es', '_es']
                
            elif s[-4:]=='ista':
                _subtype = '-ista'
                stem = s[:-4]
                exts = ['ist_a', 'ist_a', 'ist_as', 'ist_as']
            
            elif s[-2:] == u'ón':
                _subtype = u'-ón'
                stem = s[:-2]
                exts = [u'*ón_', '*on_a', '*on_es', '*on_as']

            elif s[-5:] == 'erior':
                _subtype = '-erior'
                stem = s[:-5]
                exts = [u'erior', 'erior', 'erior_s', 'erior_s']

            elif s[-2:] == u'or':
                _subtype = '-or'
                stem = s[:-2]
                exts = [u'or', 'or_a', 'or_es', 'or_as']
                
            elif s[-1] == 'z':
                _subtype = '-z'
                stem = s[:-1]
                exts = [u'*z', '*z', '*c_es', '*c_es']
                
            else: # consonant at end:
                _subtype = '-CONS'
                stem = s
                exts = ['', '', '_es', '_es']
                print '!!!! >> check this:', stem, exts ,"\n                     ",
                
                
            #decl = decline(stem, exts, wrap=('<span class="ext">', '</span>'))
            decl = decline(stem, exts, wrap=('', ''))
            #decl = [_.replace('_', '') for _ in decl]
            
            for i, d in enumerate(decl):
                while d.find('*')>=0:
                    fi = d.find('*')
                    #print fi, d
                    d = d[:fi] + '<span class="irr">' + d[fi+1] + '</span>' + d[fi+2:]
                if '_' in d:
                    d = d.replace('_', '<span class="ext">') + '</span>'
                decl[i] = d
            #print decl
            
            #Log(stem, exts, decl)
                
            model = "Adjectiv"
            key = stem + exts[0] # use masculine form sg as key
            key = key.replace('*', '').replace('_','')
            jsforms = '''{'MSg':'%s','FSg':'%s','MPl':'%s','FPl':'%s'}''' % tuple(decl)
            
            data = [key, _question, key, _chapt, _sect, _type, _subtype, _symb, jsforms]
        
        
        else:
            print "!!! Unknown type, skipping"
            continue
        
        
        
        if len(data) > 0:
            print data[1], " | ", data[2]
            with codecs.open('multiimport.tsv', 'w', encoding='utf-8') as f:
                #data = [_.encode("utf8") for _ in data]
                s = "\t".join(data)
                #f.write(s.decode("utf8"))
                f.write(s)
                #print s
            
            did = mw.col.decks.byName(deck_name)['id']
            mw.col.decks.select(did)

            m = mw.col.models.byName(model)
            mw.col.conf['curModel'] = m['id']
            cdeck = mw.col.decks.current()
            cdeck['mid'] = m['id']
            mw.col.decks.save(cdeck)
            mw.col.models.setCurrent(m)
            m['did'] = did
            mw.col.models.save(m)
            mw.reset()
            
            ti = TextImporter(mw.col,'multiimport.tsv')
            ti.delimiter = '\t'
            ti.allowHTML = True
            ti.initMapping()
            ti.run()
            #os.remove('multiimport.tsv')

      
    print('-'*80)
Beispiel #51
0
def showMessages(mw, data):
    showText(data['msg'], parent=mw, type="html")
    mw.pm.meta['lastMsg'] = data['msgId']
Beispiel #52
0
    def onTimeout(self):
        error = html.escape(self.pool)
        self.pool = ""
        self.mw.progress.clear()
        if "abortSchemaMod" in error:
            return
        if "10013" in error:
            return showWarning(_("Your firewall or antivirus program is preventing Anki from creating a connection to itself. Please add an exception for Anki."))
        if "Pyaudio not" in error:
            return showWarning(_("Please install PyAudio"))
        if "install mplayer" in error:
            return showWarning(_("Sound and video on cards will not function until mpv or mplayer is installed."))
        if "no default input" in error.lower():
            return showWarning(_("Please connect a microphone, and ensure "
                                 "other programs are not using the audio device."))
        if "invalidTempFolder" in error:
            return showWarning(self.tempFolderMsg())
        if "Beautiful Soup is not an HTTP client" in error:
            return
        if "database or disk is full" in error:
            return showWarning(_("Your computer's storage may be full. Please delete some unneeded files, then try again."))
        if "disk I/O error" in error:
            return showWarning(_("""\
An error occurred while accessing the database.

Possible causes:

- Antivirus, firewall, backup, or synchronization software may be \
  interfering with Anki. Try disabling such software and see if the \
  problem goes away.
- Your disk may be full.
- The Documents/Anki folder may be on a network drive.
- Files in the Documents/Anki folder may not be writeable.
- Your hard disk may have errors.

It's a good idea to run Tools>Check Database to ensure your collection \
is not corrupt.
"""))

        stdText = _("""\
<h1>Error</h1>

<p>An error occurred. Please use <b>Tools &gt; Check Database</b> to see if \
that fixes the problem.</p>

<p>If problems persist, please report the problem on our \
<a href="https://help.ankiweb.net">support site</a>. Please copy and paste \
 the information below into your report.</p>""")

        pluginText = _("""\
<h1>Error</h1>

<p>An error occurred. Please start Anki while holding down the shift \
key, which will temporarily disable the add-ons you have installed.</p>

<p>If the issue only occurs when add-ons are enabled, please use the \
Tools&gt;Add-ons menu item to disable some add-ons and restart Anki, \
repeating until you discover the add-on that is causing the problem.</p>

<p>When you've discovered the add-on that is causing the problem, please \
report the issue on the <a href="https://help.ankiweb.net/discussions/add-ons/">\
add-ons section</a> of our support site.

<p>Debug info:</p>
""")        
        if self.mw.addonManager.dirty:
            txt = pluginText
            error = supportText() + self._addonText(error) + "\n" + error
        else:
            txt = stdText
            error = supportText() + "\n" + error
        
        # show dialog
        txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
        showText(txt, type="html", copyBtn=True)
Beispiel #53
0
def importFile(mw, file):
    importerClass = None
    done = False
    for i in importing.Importers:
        if done:
            break
        for mext in re.findall(r"[( ]?\*\.(.+?)[) ]", i[0]):
            if file.endswith("." + mext):
                importerClass = i[1]
                done = True
                break
    if not importerClass:
        # if no matches, assume TSV
        importerClass = importing.Importers[0][1]
    importer = importerClass(mw.col, file)
    # need to show import dialog?
    if importer.needMapper:
        # make sure we can load the file first
        mw.progress.start(immediate=True)
        try:
            importer.open()
        except UnicodeDecodeError:
            showUnicodeWarning()
            return
        except Exception as e:
            msg = repr(str(e))
            if msg == "'unknownFormat'":
                showWarning(_("Unknown file format."))
            else:
                msg = _("Import failed. Debugging info:\n")
                msg += str(traceback.format_exc())
                showText(msg)
            return
        finally:
            mw.progress.finish()
        diag = ImportDialog(mw, importer)
    else:
        # if it's an apkg/zip, first test it's a valid file
        if importer.__class__.__name__ == "AnkiPackageImporter":
            try:
                z = zipfile.ZipFile(importer.file)
                z.getinfo("collection.anki2")
            except:
                showWarning(invalidZipMsg())
                return
            # we need to ask whether to import/replace
            if not setupApkgImport(mw, importer):
                return
        mw.progress.start(immediate=True)
        try:
            try:
                importer.run()
            finally:
                mw.progress.finish()
        except zipfile.BadZipfile:
            showWarning(invalidZipMsg())
        except Exception as e:
            err = repr(str(e))
            if "invalidFile" in err:
                msg = _("""\
Invalid file. Please restore from backup.""")
                showWarning(msg)
            elif "invalidTempFolder" in err:
                showWarning(mw.errorHandler.tempFolderMsg())
            elif "readonly" in err:
                showWarning(_("""\
Unable to import from a read-only file."""))
            else:
                msg = _("Import failed.\n")
                msg += str(traceback.format_exc())
                showText(msg)
        else:
            log = "\n".join(importer.log)
            if "\n" not in log:
                tooltip(log)
            else:
                showText(log)
        mw.reset()
Beispiel #54
0
def dehashilate():
    """Go through the collection and clean up MD5-ish names

    Search the cards for sounds or images with file names that
    look like MD5 hashes, rename the files and change the notes.

    """
    mdir = mw.col.media.dir()
    new_names_dict = {}
    rename_exec_list = []
    bad_mv_text = u''
    mw.checkpoint(_("Dehashilate"))
    nids = mw.col.db.list("select id from notes")
    for nid in progress(nids, "Dehashilating", "This is all wrong!"):
        n = mw.col.getNote(nid)
        for (name, value) in n.items():
            for match in re.findall(hash_name_pat, value):
                rs = re.search(hash_name_pat, value)
                if None == rs:
                    # Should be redundant with the for match ...:
                    # loop. RAS 2012-06-23
                    continue
                old_name = '{0}{1}'.format(rs.group(1), rs.group(2))
                try:
                    new_name = new_names_dict[old_name]
                except KeyError:
                    try:
                        new_name = new_media_name(rs.group(1), rs.group(2), n)
                    except ValueError:
                        continue
                    do_rename = True
                else:
                    do_rename = False
                if do_rename:
                    src = os.path.join(mdir, old_name)
                    dst = os.path.join(mdir, new_name)
                    try:
                        os.rename(src, dst)
                    except OSError:
                        # print u'Problem movivg {0} → {1}\n'.format(src, dst)
                        bad_mv_text += u'{0} → {1}\n'.format(src, dst)
                    else:
                        new_names_dict[old_name] = new_name
                    n[name] = value.replace(old_name, new_name)
                    n.flush()
                    rename_exec_list.append(dict(nid=nid,
                                                 flds=n.joinedFields()))
    mw.col.db.executemany("update notes set flds =:flds where id =:nid",
                          rename_exec_list)
    # This is a bit of voodo code. Without it the cards weren't
    # synced. Maybe this helps. (Cribbed from anki.find, but don't
    # keep extra list of nids.) RAS 2012-06-20
    # And it doesn't work. RAS 2012-07-13

    # """File
    # "/home/roland/Anki-tests/addons/dehashilator/dehashilator.py",
    # line 268, in dehashilate
    # mw.col.updateFieldCache([re_dict[nids] for re_dict in
    # rename_exec_list])
    # TypeError: unhashable type: 'list'"""
     # mw.col.updateFieldCache([re_dict[nids] for re_dict in rename_exec_list])
    mw.reset()
    if bad_mv_text:
        showText(_(u'These files weren’t renamed:\n') + bad_mv_text)