Example #1
0
def on_js_message(handled, msg, context):
    if isinstance(context, CardLayout) and (msg.startswith("ct_click_")
                                            or msg.startswith("ct_dblclick_")):
        # card layout is a modal dialog, so we can't display there
        tooltip("Can't be used in card layout screen.")
        return handled

    if not isinstance(context, Reviewer) and not isinstance(
            context, PreviewDialog):
        # only function in review and preview screens
        return handled

    if msg.startswith("ct_click_"):
        tag = msg.replace("ct_click_", "")
        browser = dialogs.open("Browser", mw)
        browser.setFilter('"tag:%s"' % tag)
        return True, None
    elif msg.startswith("ct_dblclick_"):
        tag, deck = msg.replace("ct_dblclick_", "").split("|")
        browser = dialogs.open("Browser", mw)
        browser.setFilter('"tag:%s" "deck:%s"' % (tag, deck))
        browser.setWindowState(browser.windowState() & ~Qt.WindowMinimized
                               | Qt.WindowActive)
        return True, None

    return handled
def switchAddWindow(self):
    curDialogs = dialogs._dialogs
    # toggle between windows
    if curDialogs["AddCards"][1] == self.parentWindow:
        dialogs.open("AddCards2", self.mw)
    else:
        dialogs.open("AddCards", self.mw)
def switchAddWindow(self):
    curDialogs = dialogs._dialogs
    # toggle between windows
    if curDialogs["AddCards"][1] == self.parentWindow:
        dialogs.open("AddCards2", self.mw)
    else:
        dialogs.open("AddCards", self.mw)
Example #4
0
def linkHandler(self, url, _old):
    if url.startswith('ct_click_'):
        tag = url.replace('ct_click_', '')
        browser = dialogs.open('Browser', self.mw)
        browser.setFilter('"tag:%s"' % tag)
    elif url.startswith('ct_dblclick_'):
        tag, deck = url.replace('ct_dblclick_', '').split('|')
        browser = dialogs.open('Browser', self.mw)
        browser.setFilter('"tag:%s" "deck:%s"' % (tag, deck))
        browser.setWindowState(browser.windowState() & ~Qt.WindowMinimized
                               | Qt.WindowActive)
    else:
        return _old(self, url)
Example #5
0
 def browseMissingMedia(self, nohave, diag):
     #dialog blocks browser from being usable
     diag.close()
     from aqt import mw, dialogs
     browser = dialogs.open("Browser", mw, False)
     browser.form.searchEdit.lineEdit().setText("tag:MissingMedia")
     browser.onSearchActivated()
Example #6
0
    def onEdit(self):
        """
        This function needs to set the leech dialog to non-modal so the user
        can interact with the edit window. This actually only allows the user
        to interact with the editor -- it's not possible to click the "resume
        editing" button in the main window for example.

        I don't understand why, but it works fine to set the dialog to
        non-modal permanently here, but it doesn't work if the dialog is set to
        non-modal in the constructor!

        In order to make sure the user can't do funny things by pressing a
        button in the leech dialog while the editor is still open, we hide all
        the buttons and block reject. Then we temporarily wrap the close-window
        method in aqt to toggle the buttons back on (the normal version is
        restored as soon as it is called once on the edit-current dialog).
        """
        dlg = dialogs.open("EditCurrent", mw)
        oldCloseDlg = dialogs.close
        def newCloseDlg(name):
            if name == "EditCurrent":
                dialogs.close = oldCloseDlg # restore old functionality
                self._toggleDlgEnabled()
            oldCloseDlg(name)
        dialogs.close = newCloseDlg
        self.setModal(False)
        self._toggleDlgEnabled()
Example #7
0
def handle_kanji_command(handled, cmd, context):
    if not cmd.startswith(kLinkPrefix):
        return handled
    search = 'kanji:' + cmd[len(kLinkPrefix):].strip()
    browser = dialogs.open("Browser", mw)
    browser.form.searchEdit.lineEdit().setText(search)
    browser.onSearchActivated()
    return (True, None)
 def searchSelected(self, in_browser):
     if in_browser:
         b = dialogs.open('Browser', self.dictInt.mw)
         b.form.searchEdit.lineEdit().setText('Expression:*{0}*'.format(
             self.selectedText()))
         b.onSearchActivated()
     else:
         self.dictInt.initSearch(self.selectedText())
Example #9
0
def on_bridge_browser(handled, cmd, context):
    prefix = "Browser search:"
    if not cmd.startswith(prefix):
        return handled
    search = cmd[len(prefix):]
    browser = dialogs.open("Browser", mw)
    browser.form.searchEdit.lineEdit().setText(search)
    browser.onSearchActivated()
    return (True, None)
Example #10
0
 def do_browser_search(self, extra_search=""):
     # Use the current line's text or the last line if the current one is an empty line
     note_tags = self.current_tags_list()
     searched_tag = self.form.listWidget.currentItem().text() or (note_tags[-1] if len(note_tags)>0 else "")
     if searched_tag:
         browser = dialogs.open('Browser', mw)
         browser.setFilter('tag:"{}*" {}'.format(searched_tag, extra_search))
         self.accept()
     else:
         tooltip("empty tag was selected for search")
Example #11
0
def browseSameFocus( self ): #3
    '''Opens browser and displays all notes with the same focus morph.
    Useful to quickly find alternative notes to learn focus from'''
    try:
        n = self.card.note()
        if not focus( n ): return
        q = '%s:%s' % ( focusName( n ), focus( n ) )
        b = dialogs.open( 'Browser', self.mw )
        b.form.searchEdit.lineEdit().setText( q )
        b.onSearch()
    except KeyError: pass
Example #12
0
def browseSameFocus( self ): #3
    '''Opens browser and displays all notes with the same focus morph.
    Useful to quickly find alternative notes to learn focus from'''
    try:
        n = self.card.note()
        if not focus( n ): return
        q = u'%s:%s' % ( focusName( n ), focus( n ) )
        b = dialogs.open( 'Browser', self.mw )
        b.form.searchEdit.lineEdit().setText( q )
        b.onSearch()
    except KeyError: pass
    def onDelete():
        global cids
        cids = set(cids)  #change here to make a set

        saveGeom(diag, "emptyCards")
        QDialog.accept(diag)
        self.checkpoint(_("Delete Empty"))

        # Beginning of changes
        nidToCidsToDelete = dict()
        for cid in cids:
            card = self.col.getCard(cid)
            nid = card.note().id
            if nid not in nidToCidsToDelete:
                # print("note %s not yet in nidToCidsToDelete. Thus adding it"%nid)
                nidToCidsToDelete[nid] = 0
            # else:
            # print("note %s already in nidToCidsToDelete."%nid)
            nidToCidsToDelete[nid] += 1
            # print("Adding card %s to note %s."%(cid,nid))

        emptyNids = 0
        for nid in nidToCidsToDelete:
            note = self.col.getNote(nid)
            cidsOfNids = len(note.cards())

            if cidsOfNids <= nidToCidsToDelete[nid]:
                emptyNids += 1
                note.addTag("NoteWithNoCard")
                note.flush()
                cids -= set([note.cards()[0].id])  #keep one card
            # else
            # cloze type or normal delete
            # unlike note types, cloze types are never totally removed.

        self.col.remCards(cids, notes=False)
        nidsWithTag = set(self.col.findNotes("tag:NoteWithNoCard"))
        # print("emptyNids is %s, nidsWithTag is %s"%(emptyNids,nidsWithTag))

        if emptyNids:
            showWarning(
                """%d note(s) should have been deleted because they had no more cards. They now have the tag "NoteWithNoCard". Please go check them. Then either edit them to save their content, or delete them from the browser."""
                % emptyNids)
            browser = dialogs.open("Browser", mw)
            browser.form.searchEdit.lineEdit().setText("tag:NoteWithNoCard")

        # end of changes
        tooltip(
            ngettext("%d card deleted.", "%d cards deleted.", len(cids)) %
            len(cids))
        self.reset()
Example #14
0
def add_related_note(related_note_id, model_id, deck_id, fields_to_copy,
                     copy_tags, browser):
    browser.col.decks.select(deck_id)
    current_deck = browser.col.decks.current()
    current_deck['mid'] = model_id
    browser.col.decks.save(current_deck)
    browser.col.models.setCurrent(browser.col.models.get(model_id))
    note_to_copy = browser.col.getNote(related_note_id)
    add_cards: addcards.AddCards = dialogs.open('AddCards', mw)
    new_note = add_cards.editor.note
    if copy_tags:
        new_note.tags = note_to_copy.tags
    for field in fields_to_copy:
        new_note[field] = note_to_copy[field]
    add_cards.setAndFocusNote(new_note)
Example #15
0
def browseSameFocus(self):  # 3
    """Opens browser and displays all notes with the same focus morph.
    Useful to quickly find alternative notes to learn focus from"""
    try:
        n = self.card.note()
        focusMorphs = focus(n)
        if len(focusMorphs) == 0:
            return

        q = focusQuery(focusName(), focusMorphs)
        b = dialogs.open('Browser', self.mw)
        b.form.searchEdit.lineEdit().setText(q)
        b.onSearchActivated()
    except KeyError:
        pass
Example #16
0
def handle_click(handled, msg, context):
    if isinstance(context, CardLayout) and (msg.startswith('ct_click_')
                                            or msg.startswith('ct_dblclick_')):
        tooltip("Can't be used in card layout screen.")
        return handled

    if not isinstance(context, Reviewer) and not isinstance(
            context, PreviewDialog):
        return handled

    if msg.startswith('ct_click_'):
        tag = msg.replace('ct_click_', '')
        browser = dialogs.open('Browser', mw)
        browser.setFilter('"tag:%s"' % tag)
        return True, None
    elif msg.startswith('ct_dblclick_'):
        tag, deck = msg.replace('ct_dblclick_', '').split('|')
        browser = dialogs.open('Browser', mw)
        browser.setFilter('"tag:%s" "deck:%s"' % (tag, deck))
        browser.setWindowState(browser.windowState() & ~Qt.WindowMinimized
                               | Qt.WindowActive)
        return True, None

    return handled
 def onDelete():
     nonlocal cids
     saveGeom(diag, "emptyCards")
     QDialog.accept(diag)
     self.checkpoint(_("Delete Empty"))
     # Beginning of changes
     nidToCidsToDelete = dict()
     for cid in cids:
         card = self.col.getCard(cid)
         note = card.note()
         nid = note.id
         if nid not in nidToCidsToDelete:
             nidToCidsToDelete[nid] = set()
         nidToCidsToDelete[nid].add(cid)
     emptyNids = set()
     cardsOfEmptyNotes = set()
     for nid, cidsToDeleteOfNote in nidToCidsToDelete.items():
         note = self.col.getNote(nid)
         cidsOfNids = set([card.id for card in note.cards()])
         if cidsOfNids == cidsToDeleteOfNote:
             emptyNids.add(note.id)
             cids -= cidsOfNids
     self.col.remCards(cids, notes=False)
     nidsWithTag = set(self.col.findNotes("tag:NoteWithNoCard"))
     for nid in emptyNids - nidsWithTag:
         note = self.col.getNote(nid)
         note.addTag("NoteWithNoCard")
         note.flush()
     for nid in nidsWithTag - emptyNids:
         note = self.col.getNote(nid)
         note.delTag("NoteWithNoCard")
         note.flush()
     if emptyNids:
         showWarning(
             f"""{len(emptyNids)} note(s) should have been deleted because they had no more cards. They now have the tag "NoteWithNoCard". Please go check them. Then either edit them to save their content, or delete them from the browser."""
         )
         browser = dialogs.open("Browser", mw)
         browser.form.searchEdit.lineEdit().setText("tag:NoteWithNoCard")
         browser.onSearchActivated()
     # end of changes
     tooltip(
         ngettext("%d card deleted.", "%d cards deleted.", len(cids)) %
         len(cids))
     self.reset()
Example #18
0
 def onAdd(self):
     dialogs.open("AddCards", mw)
     self.setModal(False)
Example #19
0
def onDelete(mw, diag, cids):
    p(f"Calling new onDelete with cids {cids}")

    cids = set(mw.col.emptyCids())  #change here to make a set
    saveGeom(diag, "emptyCards")
    QDialog.accept(diag)
    mw.checkpoint(_("Delete Empty"))

    # Beginning of changes
    nidToCidsToDelete = dict()
    for cid in cids:
        card = mw.col.getCard(cid)
        note = card.note()
        nid = note.id
        if nid not in nidToCidsToDelete:
            p(f"note {nid} not yet in nidToCidsToDelete. Thus adding it")
            nidToCidsToDelete[nid] = set()
        else:
            p(f"note {nid} already in nidToCidsToDelete.")
        nidToCidsToDelete[nid].add(cid)
        p(f"Adding card {cid} to note {nid}.")

    emptyNids = set()
    cardsOfEmptyNotes = set()
    for nid, cidsToDeleteOfNote in nidToCidsToDelete.items():
        note = mw.col.getNote(nid)
        cidsOfNids = set([card.id for card in note.cards()])
        p(f"In note {nid}, the cards are {cidsOfNids}, and the cards to delete are {cidsToDeleteOfNote}"
          )
        if cidsOfNids == cidsToDeleteOfNote:
            p(f"Both sets are equal")
            emptyNids.add(note.id)
            cids -= cidsOfNids
        else:
            p(f"Both sets are different")

    mw.col.remCards(cids, notes=False)
    nidsWithTag = set(mw.col.findNotes("tag:NoteWithNoCard"))
    p(f"emptyNids is {emptyNids}, nidsWithTag is {nidsWithTag}")

    for nid in emptyNids - nidsWithTag:
        note = mw.col.getNote(nid)
        note.addTag("NoteWithNoCard")
        p(f"Adding tag to note {note.id}")
        note.flush()

    for nid in nidsWithTag - emptyNids:
        note = mw.col.getNote(nid)
        # TODO: If there's only 1 note, this method is never triggered.
        # So the tag stays.
        note.delTag("NoteWithNoCard")
        p(f"Removing tag from note {note.id}")
        note.flush()

    if emptyNids:
        showWarning(
            f"""{len(emptyNids)} note(s) should have been deleted because they had no more cards. They now have the tag "NoteWithNoCard". Please go check them. Then either edit them to save their content, or delete them from the browser."""
        )
        browser = dialogs.open("Browser", mw, False)
        browser.form.searchEdit.lineEdit().setText("tag:NoteWithNoCard")
        browser.onSearchActivated()

    # end of changes
    tooltip(
        ngettext("%d card deleted.", "%d cards deleted.", len(cids)) %
        len(cids))
    mw.reset()
Example #20
0
 def handle_doubleclick(self, index):
     nid = self.model.data(index, NID_Role)
     browser = dialogs.open('Browser', mw)
     # we shouldn't do this but idk if there is a better way
     browser._lastSearchTxt = "nid:" + str(nid)
     browser.model.search("nid:" + str(nid))
Example #21
0
def add_browser_search_link(self, cmd: str) -> Any:
    if cmd.startswith("browserSearch"):
        _, query = cmd.split(":", 1)
        browser = dialogs.open("Browser", self.mw)
        browser.search_for(query)
Example #22
0
def showBrowser(nid):
    browser = dialogs.open('Browser', mw)
    browser.form.searchEdit.lineEdit().setText('nid:' + str(nid))
    browser.onSearchActivated()
Example #23
0
def check(self, local=None):
    "Return (missingFiles, unusedFiles)."
    mdir = self.dir()
    # gather all media references in NFC form
    allRefs = set()
    refsToNid = dict()  # this dic is new
    for nid, mid, flds in self.col.db.execute(
            "select id, mid, flds from notes"):
        noteRefs = self.filesInStr(mid, flds)
        # check the refs are in NFC
        for f in noteRefs:
            # if they're not, we'll need to fix them first
            if f != unicodedata.normalize("NFC", f):
                self._normalizeNoteRefs(nid)
                noteRefs = self.filesInStr(mid, flds)
                break
        # new. update refsToNid
        for f in noteRefs:
            if f not in refsToNid:
                refsToNid[f] = set()
            refsToNid[f].add(nid)
        # end new
        allRefs.update(noteRefs)
    # loop through media folder
    unused = []
    if local is None:
        files = os.listdir(mdir)
    else:
        files = local
    renamedFiles = False
    dirFound = False
    warnings = []
    for file in files:
        if not local:
            if not os.path.isfile(file):
                # ignore directories
                dirFound = True
                continue
        if file.startswith("_"):
            # leading _ says to ignore file
            continue

        if self.hasIllegal(file):
            name = file.encode(sys.getfilesystemencoding(), errors="replace")
            name = str(name, sys.getfilesystemencoding())
            warnings.append(_("Invalid file name, please rename: %s") % name)
            continue

        nfcFile = unicodedata.normalize("NFC", file)
        # we enforce NFC fs encoding on non-macs
        if not isMac and not local:
            if file != nfcFile:
                # delete if we already have the NFC form, otherwise rename
                if os.path.exists(nfcFile):
                    os.unlink(file)
                    renamedFiles = True
                else:
                    os.rename(file, nfcFile)
                    renamedFiles = True
                file = nfcFile
        # compare
        if nfcFile not in allRefs:
            unused.append(file)
        else:
            allRefs.discard(nfcFile)
    # if we renamed any files to nfc format, we must rerun the check
    # to make sure the renamed files are not marked as unused
    if renamedFiles:
        return self.check(local=local)
    # NEW: A line here removed because it was a bug
    # New
    finder = Finder(mw.col)
    alreadyMissingNids = finder.findNotes("tag:MissingMedia")
    nidsOfMissingRefs = set()
    for ref in allRefs:
        nidsOfMissingRefs.update(refsToNid[ref])
        #print(f"nidsOfMissingRefs is now {nidsOfMissingRefs}")

    for nid in nidsOfMissingRefs:
        if nid not in alreadyMissingNids:
            print(f"missing nid {nid}")
            note = Note(mw.col, id=nid)
            note.addTag("MissingMedia")
            note.flush()

    for nid in alreadyMissingNids:
        if nid not in nidsOfMissingRefs:
            print(f"not missing anymore nid {nid}")
            note = Note(mw.col, id=nid)
            note.delTag("MissingMedia")
            note.flush()
    # end new

    # make sure the media DB is valid
    try:
        self.findChanges()
    except DBError:
        self._deleteDB()
    if dirFound:
        warnings.append(
            _("Anki does not support files in subfolders of the collection.media folder."
              ))
    if allRefs:
        browser = dialogs.open("Browser", mw)
        browser.form.searchEdit.lineEdit().setText("tag:MissingMedia")
        browser.onSearchActivated()
    return (allRefs, unused, warnings)
Example #24
0
 def browseCards(cids):
     from aqt import dialogs
     browser = dialogs.open("Browser", self, False)
     browser.form.searchEdit.lineEdit().setText("cid:%s"%ids2str(cids))
     browser.onSearchActivated()