示例#1
0
def downloadMedia(url, editor):
    # Local file : just read the file content
    if url.startswith("file://"):
        try:
            url = url[7:]
            # On windows, paths tend to be prefixed by file:///
            # rather than file://, so we remove redundant slash.
            if re.match(r'^/[A-Za-z]:\\', url):
                url = url[1:]
            return open(url, 'rb').read()
        except OSError:
            pass

    app = editor.mw.app

    # Show download dialog
    d = QDialog(editor.parentWindow)
    d.setWindowTitle("Downloading media (0.0%)")
    d.setWindowModality(Qt.WindowModal)
    vbox = QVBoxLayout()
    label = QLabel(url)
    label.setWordWrap(True)
    vbox.addWidget(label)
    d.setLayout(vbox)
    d.show()

    # Download chunk by chunk for progress bar
    try:
        response = urllib2.urlopen(url)
        totSize = int(response.info().getheader('Content-Length').strip())
        currentRead = 0
        chunk_size = 16384
        chunks = []

        while True:
            chunk = response.read(chunk_size)
            currentRead += len(chunk)

            if not chunk:
                break

            d.setWindowTitle("Downloading media (%.1f%%)" %
                             (currentRead * 100.0 / totSize))
            app.processEvents()
            chunks.append(chunk)

        return ''.join(chunks)

    except urllib2.URLError:
        return None

    finally:
        d.close()
        del d
示例#2
0
文件: utils.py 项目: solarmist/anki
def chooseList(prompt, choices, startrow=0, parent=None):
    if not parent:
        parent = aqt.mw.app.activeWindow()
    d = QDialog(parent)
    d.setWindowModality(Qt.WindowModal)
    l = QVBoxLayout()
    d.setLayout(l)
    t = QLabel(prompt)
    l.addWidget(t)
    c = QListWidget()
    c.addItems(choices)
    c.setCurrentRow(startrow)
    l.addWidget(c)
    bb = QDialogButtonBox(QDialogButtonBox.Ok)
    bb.accepted.connect(d.accept)
    l.addWidget(bb)
    d.exec_()
    return c.currentRow()
示例#3
0
def get_id_and_pass_from_user(mw: aqt.main.AnkiQt,
                              username="",
                              password="") -> Tuple[str, str]:
    diag = QDialog(mw)
    diag.setWindowTitle("Anki")
    diag.setWindowFlags(self.windowFlags()
                        & ~Qt.WindowContextHelpButtonHint)  # type: ignore
    diag.setWindowModality(Qt.WindowModal)
    vbox = QVBoxLayout()
    info_label = QLabel(
        without_unicode_isolation(
            tr(TR.SYNC_ACCOUNT_REQUIRED,
               link="https://ankiweb.net/account/register")))
    info_label.setOpenExternalLinks(True)
    info_label.setWordWrap(True)
    vbox.addWidget(info_label)
    vbox.addSpacing(20)
    g = QGridLayout()
    l1 = QLabel(tr(TR.SYNC_ANKIWEB_ID_LABEL))
    g.addWidget(l1, 0, 0)
    user = QLineEdit()
    user.setText(username)
    g.addWidget(user, 0, 1)
    l2 = QLabel(tr(TR.SYNC_PASSWORD_LABEL))
    g.addWidget(l2, 1, 0)
    passwd = QLineEdit()
    passwd.setText(password)
    passwd.setEchoMode(QLineEdit.Password)
    g.addWidget(passwd, 1, 1)
    vbox.addLayout(g)
    bb = QDialogButtonBox(QDialogButtonBox.Ok
                          | QDialogButtonBox.Cancel)  # type: ignore
    bb.button(QDialogButtonBox.Ok).setAutoDefault(True)
    qconnect(bb.accepted, diag.accept)
    qconnect(bb.rejected, diag.reject)
    vbox.addWidget(bb)
    diag.setLayout(vbox)
    diag.show()

    accepted = diag.exec_()
    if not accepted:
        return ("", "")
    return (user.text().strip(), passwd.text())
示例#4
0
文件: sync.py 项目: rye761/anki
def get_id_and_pass_from_user(mw: aqt.main.AnkiQt,
                              username: str = "",
                              password: str = "") -> tuple[str, str]:
    diag = QDialog(mw)
    diag.setWindowTitle("Anki")
    disable_help_button(diag)
    diag.setWindowModality(Qt.WindowModality.WindowModal)
    vbox = QVBoxLayout()
    info_label = QLabel(
        without_unicode_isolation(
            tr.sync_account_required(
                link="https://ankiweb.net/account/register")))
    info_label.setOpenExternalLinks(True)
    info_label.setWordWrap(True)
    vbox.addWidget(info_label)
    vbox.addSpacing(20)
    g = QGridLayout()
    l1 = QLabel(tr.sync_ankiweb_id_label())
    g.addWidget(l1, 0, 0)
    user = QLineEdit()
    user.setText(username)
    g.addWidget(user, 0, 1)
    l2 = QLabel(tr.sync_password_label())
    g.addWidget(l2, 1, 0)
    passwd = QLineEdit()
    passwd.setText(password)
    passwd.setEchoMode(QLineEdit.EchoMode.Password)
    g.addWidget(passwd, 1, 1)
    vbox.addLayout(g)
    bb = QDialogButtonBox(
        QDialogButtonBox.StandardButton.Ok
        | QDialogButtonBox.StandardButton.Cancel)  # type: ignore
    bb.button(QDialogButtonBox.StandardButton.Ok).setAutoDefault(True)
    qconnect(bb.accepted, diag.accept)
    qconnect(bb.rejected, diag.reject)
    vbox.addWidget(bb)
    diag.setLayout(vbox)
    diag.show()

    accepted = diag.exec()
    if not accepted:
        return ("", "")
    return (user.text().strip(), passwd.text())
示例#5
0
    def _getUserPass(self):
        d = QDialog(self.mw)
        d.setWindowTitle("Anki")
        d.setWindowModality(Qt.WindowModal)
        vbox = QVBoxLayout()
        l = QLabel(
            _("""\
<h1>Account Required</h1>
A free account is required to keep your collection synchronized. Please \
<a href="%s">sign up</a> for an account, then \
enter your details below.""") % "https://ankiweb.net/account/login")
        l.setOpenExternalLinks(True)
        l.setWordWrap(True)
        vbox.addWidget(l)
        vbox.addSpacing(20)
        g = QGridLayout()
        l1 = QLabel(_("AnkiWeb ID:"))
        g.addWidget(l1, 0, 0)
        user = QLineEdit()
        g.addWidget(user, 0, 1)
        l2 = QLabel(_("Password:"))
        g.addWidget(l2, 1, 0)
        passwd = QLineEdit()
        passwd.setEchoMode(QLineEdit.Password)
        g.addWidget(passwd, 1, 1)
        vbox.addLayout(g)
        bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        bb.button(QDialogButtonBox.Ok).setAutoDefault(True)
        bb.accepted.connect(d.accept)
        bb.rejected.connect(d.reject)
        vbox.addWidget(bb)
        d.setLayout(vbox)
        d.show()
        accepted = d.exec_()
        u = user.text()
        p = passwd.text()
        if not accepted or not u or not p:
            return
        return (u, p)
示例#6
0
class Replacer:

    find: str
    replace: str
    tags: str
    case: int
    combo = "FindAndReplaceTags"
    find_history: List
    replace_history: List
    n_tags_changed = 0
    n_notes_changed = 0
    n_replacements = 0

    def __init__(self, browser):
        self.b = browser
        if not self.b.selectedNotes():
            tooltip("No cards selected.")
            return
        self.d = QDialog(self.b)
        self.f = Ui_Dialog()
        self.set_up_form()
        self.d.setWindowModality(Qt.WindowModal)
        r = self.d.exec_()
        if not r:
            return
        self.save_history()
        self.b.mw.checkpoint(_("Find and Replace Tags"))
        self.b.model.beginReset()
        self.b.mw.taskman.run_in_background(self.do_find_replace, self.on_done)

    def set_up_form(self):
        self.f.setupUi(self.d)
        self.connect_signals()
        self.restore_history()
        self.f.input_tags.setCol(self.b.col)
        self.on_input_changed()

    def connect_signals(self):
        self.f.input_find.currentTextChanged.connect(self.on_input_changed)
        self.f.input_replace.currentTextChanged.connect(self.on_input_changed)
        self.f.is_case.stateChanged.connect(self.on_input_changed)
        self.f.input_tags.textChanged.connect(self.on_input_changed)
        self.f.buttonBox.button(QDialogButtonBox.Help).pressed.connect(on_help)

    def restore_history(self):
        self.find_history = restore_combo_history(self.f.input_find,
                                                  self.combo + "Find")
        self.f.input_find.completer().setCaseSensitivity(True)
        self.replace_history = restore_combo_history(self.f.input_replace,
                                                     self.combo + "Replace")
        self.f.input_replace.completer().setCaseSensitivity(True)

    def save_history(self):
        save_combo_history(self.f.input_find, self.find_history,
                           self.combo + "Find")
        save_combo_history(self.f.input_replace, self.replace_history,
                           self.combo + "Replace")

    def on_input_changed(self):
        self.read_input()
        enable = False
        try:
            re.sub(self.find, self.replace, "")
        except re.error:
            out = "INVALID EXPRESSION"
        else:
            out = self.tag_preview()
            if self.find or self.replace:
                enable = True
        self.toggle_okay(enable)
        self.f.output_tags.setText(out)

    def read_input(self):
        self.find = self.f.input_find.currentText()
        self.replace = self.f.input_replace.currentText()
        self.case = 0 if self.f.is_case.isChecked() else re.I
        self.tags = self.f.input_tags.text().split()

    def tag_preview(self):
        pattern = re.compile(self.find, flags=self.case)
        new_tags = [pattern.sub(self.replace, t) for t in self.tags]
        return " ".join(set(new_tags))

    def toggle_okay(self, enabled):
        self.f.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enabled)

    def do_find_replace(self):
        nids = self.b.selectedNotes()
        pattern = re.compile(self.find, flags=self.case)
        for nid in nids:
            note = self.b.col.getNote(nid)
            tags_subs = [pattern.subn(self.replace, tag) for tag in note.tags]
            new_tags = [t[0] for t in tags_subs]
            note.tags = new_tags
            note.flush()
            replacements = [t[1] for t in tags_subs if t[1] != 0]
            self.n_replacements += sum(replacements)
            n_tags_changed = len(replacements)
            self.n_tags_changed += n_tags_changed
            self.n_notes_changed += (n_tags_changed > 0)

    def on_done(self, _):
        self.b.search()
        self.b.mw.requireReset()
        self.b.model.endReset()
        self.b.mw.reset()
        t1 = " was" if self.n_replacements == 1 else "s were"
        t2 = "" if self.n_tags_changed == 1 else "s"
        t3 = "" if self.n_notes_changed == 1 else "s"
        msg = f"{self.n_replacements} replacement{t1} made " \
              f"in {self.n_tags_changed} tag{t2} " \
              f"of {self.n_notes_changed} note{t3}." \
              f"<br>Do you wish to clear unused tags now?"
        if askUser(msg, parent=self.b):
            self.b.clearUnusedTags()