예제 #1
0
class MediaSyncDialog(QDialog):
    silentlyClose = True

    def __init__(self,
                 mw: aqt.main.AnkiQt,
                 syncer: MediaSyncer,
                 close_when_done: bool = False) -> None:
        super().__init__(mw)
        self.mw = mw
        self._syncer = syncer
        self._close_when_done = close_when_done
        self.form = aqt.forms.synclog.Ui_Dialog()
        self.form.setupUi(self)
        self.setWindowTitle(tr(TR.SYNC_MEDIA_LOG_TITLE))
        disable_help_button(self)
        self.abort_button = QPushButton(tr(TR.SYNC_ABORT_BUTTON))
        qconnect(self.abort_button.clicked, self._on_abort)
        self.abort_button.setAutoDefault(False)
        self.form.buttonBox.addButton(self.abort_button,
                                      QDialogButtonBox.ActionRole)
        self.abort_button.setHidden(not self._syncer.is_syncing())

        gui_hooks.media_sync_did_progress.append(self._on_log_entry)
        gui_hooks.media_sync_did_start_or_stop.append(self._on_start_stop)

        self.form.plainTextEdit.setPlainText("\n".join(
            self._entry_to_text(x) for x in syncer.entries()))
        self.form.plainTextEdit.moveCursor(QTextCursor.End)
        self.show()

    def reject(self) -> None:
        if self._close_when_done and self._syncer.is_syncing():
            # closing while syncing on close starts an abort
            self._on_abort()
            return

        aqt.dialogs.markClosed("sync_log")
        QDialog.reject(self)

    def reopen(self, mw, syncer, close_when_done: bool = False) -> None:
        self._close_when_done = close_when_done
        self.show()

    def _on_abort(self, *args) -> None:
        self._syncer.abort()
        self.abort_button.setHidden(True)

    def _time_and_text(self, stamp: int, text: str) -> str:
        asctime = time.asctime(time.localtime(stamp))
        return f"{asctime}: {text}"

    def _entry_to_text(self, entry: LogEntryWithTime):
        if isinstance(entry.entry, str):
            txt = entry.entry
        elif isinstance(entry.entry, MediaSyncProgress):
            txt = self._logentry_to_text(entry.entry)
        else:
            assert_exhaustive(entry.entry)
        return self._time_and_text(entry.time, txt)

    def _logentry_to_text(self, e: MediaSyncProgress) -> str:
        return f"{e.added}, {e.removed}, {e.checked}"

    def _on_log_entry(self, entry: LogEntryWithTime):
        self.form.plainTextEdit.appendPlainText(self._entry_to_text(entry))
        if not self._syncer.is_syncing():
            self.abort_button.setHidden(True)

    def _on_start_stop(self, running: bool) -> None:
        if not running and self._close_when_done:
            aqt.dialogs.markClosed("sync_log")
            self._close_when_done = False
            self.close()
예제 #2
0
 def __init__(self, parent, tags, alltags):
     QDialog.__init__(self, parent,
                      Qt.WindowType.Window)  # super().__init__(parent)
     self.basic_mode = gc("dialog type: basic_but_quick")
     self.parent = parent
     self.alltags = alltags
     self.gridLayout = QGridLayout(self)
     self.gridLayout.setObjectName("gridLayout")
     self.label = QLabel("Edit tags:")
     self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
     self.verticalLayout = QVBoxLayout()
     self.verticalLayout.setObjectName("verticalLayout")
     self.gridLayout.addLayout(self.verticalLayout, 1, 0, 1, 1)
     self.buttonBox = QDialogButtonBox(self)
     self.buttonBox.setOrientation(Qt.Orientation.Horizontal)
     self.buttonBox.setStandardButtons(
         QDialogButtonBox.StandardButton.Cancel
         | QDialogButtonBox.StandardButton.Ok)
     self.shortcut = QShortcut(QKeySequence("Ctrl+Return"), self)
     self.shortcut.activated.connect(self.accept)
     self.helpButton = QPushButton(
         "add empty line", clicked=lambda: self.maybe_add_line(force=True))
     self.buttonBox.addButton(self.helpButton,
                              QDialogButtonBox.ButtonRole.HelpRole)
     self.filterbutton = QPushButton("edit tag for current line",
                                     clicked=self.tagselector)
     self.buttonBox.addButton(self.filterbutton,
                              QDialogButtonBox.ButtonRole.ResetRole)
     self.searchButton = QPushButton(
         "search", clicked=lambda: self.do_browser_search(extra_search=""))
     self.buttonBox.addButton(self.searchButton,
                              QDialogButtonBox.ButtonRole.ResetRole)
     self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 1)
     self.buttonBox.accepted.connect(self.accept)
     self.buttonBox.rejected.connect(self.reject)
     self.setWindowTitle("Anki - Edit Tags")
     originalheight = self.height()
     restoreGeom(self, "TagDialogExtended")
     self.resize(self.width(), originalheight)
     if not tags:
         tags = [
             "",
         ]
     else:
         tags.append("")
     self.line_list = []
     for t in tags:
         self.maybe_add_line(t)
     self.cut = gc("in tag lines dialog: open filterdialog for single tag")
     if self.cut:
         self.filterbutton.setToolTip('shortcut: {}'.format(self.cut))
         self.selkey = QShortcut(QKeySequence(self.cut), self)
         self.selkey.activated.connect(self.tagselector)
     self.browser_scut = gc("in tag lines dialog: search browser for tag")
     if self.browser_scut:
         self.searchButton.setToolTip('shortcut: {}'.format(
             self.browser_scut))
         self.browser_scut_key = QShortcut(QKeySequence(self.browser_scut),
                                           self)
         self.browser_scut_key.activated.connect(
             lambda: self.do_browser_search(extra_search=""))
     # don't also set Ctrl+t,a/gc("editor: show filterdialog to add single tag") for
     # self.tagselector: What if the user has already set them to the same etc. I'd have
     # to do a lot of checking
     self.addnl = gc("in tag lines dialog: insert additional line")
     if self.addnl:
         self.helpButton.setToolTip('shortcut: {}'.format(self.addnl))
         self.addnlscut = QShortcut(QKeySequence(self.addnl), self)
         self.addnlscut.activated.connect(
             lambda: self.maybe_add_line(force=True))
예제 #3
0
class SingleCardPreviewerMod(SingleCardPreviewer):
    def _on_bridge_cmd(self, cmd):
        super()._on_bridge_cmd(cmd)

    def _create_gui(self):
        super()._create_gui()

        self.vbox.removeWidget(self.bbox)
        self.bottombar = QHBoxLayout()

        self.browser_button = QPushButton("show in browser")
        #self.browser_button.setShortcut(QKeySequence("b"))
        #self.browser_button.setToolTip("Shortcut key: %s" % "b")
        self.browser_button.clicked.connect(self._on_browser_button)
        self.bottombar.addWidget(self.browser_button)

        self.edit_button = self.bbox.addButton("edit", QDialogButtonBox.ButtonRole.HelpRole)
        #self.edit_button.setShortcut(QKeySequence("e"))
        #self.edit_button.setToolTip("Shortcut key: %s" % "e")
        self.edit_button.clicked.connect(self._on_edit_button)
        self.bottombar.addWidget(self.edit_button)

        self.showRate = QPushButton("G")  # grade - "R" is already used for replay audio
        self.showRate.setFixedWidth(25)
        # self.showRate.setShortcut(QKeySequence("g"))
        # self.showRate.setToolTip("Shortcut key: %s" % "G")
        self.showRate.clicked.connect(self.onShowRatingBar)
        # self.bottombar.addWidget(self.showRate)

        self.bottombar.addWidget(self.bbox)
        self.vbox.addLayout(self.bottombar)

    def _setup_web_view(self):
        super()._setup_web_view()
        for child in self.bbox.children():
            if isinstance(child, QCheckBox):
                self.both_sides_button = child
        self._show_both_sides = self.check_preview_both_config()
        self.both_sides_button.setChecked(self._show_both_sides)

    def check_preview_both_config(self):
        # if True both sides are shown
        showboth = False
        if gc("card_preview__default_is_answer"):
            showboth ^= True
        overrides = gc("card_preview__override_toggle_from_default_for_notetypes")
        if my_point_version() <= 49:
            name = self.card().model()['name']
        else:
            name = self.card().note_type()['name']
        if name in overrides:
            showboth ^= True
        return showboth

    def _on_browser_button(self):
        tooltip('browser clicked')
        browser = aqt.dialogs.open("Browser", self.mw)
        query = '"nid:' + str(self.card().nid) + '"'
        browser.form.searchEdit.lineEdit().setText(query)
        browser.onSearchActivated()

    def _on_edit_button(self):
        note = self.mw.col.getNote(self.card().nid)
        d = EditNoteWindowFromThisLinkAddon(self.mw, note)
        d.show()
        QDialog.reject(self)

    def onShowRatingBar(self):
        pass
예제 #4
0
    def setup(self):
        addonconfig = mw.addonManager.getConfig(__name__)
        config = types.SimpleNamespace(**addonconfig['defaults'])
        if addonconfig.get("_debug_time", False):
            self.timepoint = lambda c: print("%s: %0.3f" %
                                             (c, time.time() - self.time))
        else:
            self.timepoint = lambda _: None
        config.did = mw.col.conf['curDeck']

        swin = QDialog(mw)
        vl = QVBoxLayout()
        fl = QHBoxLayout()
        deckcb = QComboBox()
        deckcb.addItems(sorted(mw.col.decks.allNames()))
        deckcb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        fl.addWidget(QLabel("Deck: "))
        deckcb.setCurrentText(mw.col.decks.get(config.did)['name'])

        def change_did(deckname):
            config.did = mw.col.decks.byName(deckname)['id']

        deckcb.currentTextChanged.connect(change_did)
        fl.addWidget(deckcb)
        vl.addLayout(fl)
        frm = QGroupBox("Settings")
        vl.addWidget(frm)
        il = QVBoxLayout()
        fl = QHBoxLayout()
        field = QLineEdit()
        field.setPlaceholderText(
            "e.g. \"kanji\", \"hanzi\" or \"sentence-kanji\" (default: \"%s\")"
            % config.pattern)
        il.addWidget(
            QLabel("Pattern or Field names to search for (case insensitive):"))
        fl.addWidget(field)
        liter = QCheckBox("Match exactly")
        liter.setChecked(config.literal)
        fl.addWidget(liter)
        il.addLayout(fl)
        stint = QSpinBox()
        stint.setRange(1, 65536)
        stint.setValue(config.interval)
        il.addWidget(QLabel("Card interval considered strong:"))
        il.addWidget(stint)
        ttcol = QSpinBox()
        ttcol.setRange(1, 99)
        ttcol.setValue(config.thin)
        il.addWidget(QLabel("Number of Columns in the in-app table:"))
        il.addWidget(ttcol)
        wtcol = QSpinBox()
        wtcol.setRange(1, 99)
        wtcol.setValue(config.wide)
        il.addWidget(QLabel("Number of Columns in the exported table:"))
        il.addWidget(wtcol)
        groupby = QComboBox()
        groupby.addItems([
            *("None, sorted by " + x.pretty_value() for x in SortOrder),
            *(x.name for x in data.groups),
        ])
        groupby.setCurrentIndex(config.groupby)
        il.addWidget(QLabel("Group by:"))
        il.addWidget(groupby)
        shnew = QCheckBox("Show units not yet seen")
        shnew.setChecked(config.unseen)
        il.addWidget(shnew)
        toolt = QCheckBox("Show informational tooltips")
        toolt.setChecked(config.tooltips)
        il.addWidget(toolt)
        frm.setLayout(il)
        hl = QHBoxLayout()
        vl.addLayout(hl)
        gen = QPushButton("Generate", clicked=swin.accept)
        hl.addWidget(gen)
        cls = QPushButton("Close", clicked=swin.reject)
        hl.addWidget(cls)
        swin.setLayout(vl)
        swin.setTabOrder(gen, cls)
        swin.setTabOrder(cls, field)
        swin.setTabOrder(field, liter)
        swin.setTabOrder(liter, stint)
        swin.setTabOrder(stint, ttcol)
        swin.setTabOrder(ttcol, wtcol)
        swin.setTabOrder(wtcol, groupby)
        swin.setTabOrder(groupby, shnew)
        swin.setTabOrder(shnew, toolt)
        swin.resize(500, 400)
        if swin.exec_():
            mw.progress.start(immediate=True)
            if len(field.text().strip()) != 0:
                config.pattern = field.text().lower()
            config.pattern = config.pattern.split()
            config.literal = liter.isChecked()
            config.interval = stint.value()
            config.thin = ttcol.value()
            config.wide = wtcol.value()
            config.groupby = groupby.currentIndex()
            config.unseen = shnew.isChecked()
            config.tooltips = toolt.isChecked()
            self.makegrid(config)
            mw.progress.finish()
            self.win.show()
예제 #5
0
class TagDialogExtended__BasicOrTagEdit(QDialog):
    def __init__(self, parent, tags, alltags):
        QDialog.__init__(self, parent,
                         Qt.WindowType.Window)  # super().__init__(parent)
        self.basic_mode = gc("dialog type: basic_but_quick")
        self.parent = parent
        self.alltags = alltags
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.label = QLabel("Edit tags:")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.gridLayout.addLayout(self.verticalLayout, 1, 0, 1, 1)
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Orientation.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.StandardButton.Cancel
            | QDialogButtonBox.StandardButton.Ok)
        self.shortcut = QShortcut(QKeySequence("Ctrl+Return"), self)
        self.shortcut.activated.connect(self.accept)
        self.helpButton = QPushButton(
            "add empty line", clicked=lambda: self.maybe_add_line(force=True))
        self.buttonBox.addButton(self.helpButton,
                                 QDialogButtonBox.ButtonRole.HelpRole)
        self.filterbutton = QPushButton("edit tag for current line",
                                        clicked=self.tagselector)
        self.buttonBox.addButton(self.filterbutton,
                                 QDialogButtonBox.ButtonRole.ResetRole)
        self.searchButton = QPushButton(
            "search", clicked=lambda: self.do_browser_search(extra_search=""))
        self.buttonBox.addButton(self.searchButton,
                                 QDialogButtonBox.ButtonRole.ResetRole)
        self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 1)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.setWindowTitle("Anki - Edit Tags")
        originalheight = self.height()
        restoreGeom(self, "TagDialogExtended")
        self.resize(self.width(), originalheight)
        if not tags:
            tags = [
                "",
            ]
        else:
            tags.append("")
        self.line_list = []
        for t in tags:
            self.maybe_add_line(t)
        self.cut = gc("in tag lines dialog: open filterdialog for single tag")
        if self.cut:
            self.filterbutton.setToolTip('shortcut: {}'.format(self.cut))
            self.selkey = QShortcut(QKeySequence(self.cut), self)
            self.selkey.activated.connect(self.tagselector)
        self.browser_scut = gc("in tag lines dialog: search browser for tag")
        if self.browser_scut:
            self.searchButton.setToolTip('shortcut: {}'.format(
                self.browser_scut))
            self.browser_scut_key = QShortcut(QKeySequence(self.browser_scut),
                                              self)
            self.browser_scut_key.activated.connect(
                lambda: self.do_browser_search(extra_search=""))
        # don't also set Ctrl+t,a/gc("editor: show filterdialog to add single tag") for
        # self.tagselector: What if the user has already set them to the same etc. I'd have
        # to do a lot of checking
        self.addnl = gc("in tag lines dialog: insert additional line")
        if self.addnl:
            self.helpButton.setToolTip('shortcut: {}'.format(self.addnl))
            self.addnlscut = QShortcut(QKeySequence(self.addnl), self)
            self.addnlscut.activated.connect(
                lambda: self.maybe_add_line(force=True))

    def current_tags_list(self):
        return [t.text() for t in self.line_list if t]

    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 = shared_variables.focused_line.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")

    def tagselector(self):
        text = shared_variables.focused_line.text()
        d = FilterDialog(parent=self,
                         values=self.alltags,
                         allownew=True,
                         prefill=text)
        if d.exec():
            shared_variables.focused_line.setText(d.selkey)
        else:
            shared_variables.focused_line.setFocus()

    def change_focus_by_one(self, Down=True):
        for index, edit in enumerate(self.line_list):
            if edit == shared_variables.focused_line:
                if Down:
                    if index == len(
                            self.line_list) - 1:  # if in last line go up
                        self.line_list[0].setFocus()
                        break
                    else:
                        newidx = index + 1
                        self.line_list[newidx].setFocus()
                        break
                else:  # go up
                    if index == 0:  # if in last line go up
                        newidx = len(self.line_list) - 1
                        self.line_list[newidx].setFocus()
                        break
                    else:
                        self.line_list[index - 1].setFocus()
                        break

    def maybe_add_line(self, tag="", force=False):
        if self.line_list and not self.line_list[-1].text(
        ) and not force:  # last lineedit is empty:
            self.line_list[-1].setFocus()
            self.line_list[-1].setText(tag)
        else:
            if self.basic_mode:
                te = MyBasicEdit(self)
                te.setText(tag)
                self.verticalLayout.addWidget(te)
                te.setFocus()
                self.line_list.append(te)
            else:
                te = MyTagEdit(self)
                te.setCol(mw.col)
                te.setText(tag)
                self.verticalLayout.addWidget(te)
                te.hideCompleter()
                te.setFocus()
                self.line_list.append(te)

    def accept(self):
        self.tagstring = ""
        for t in self.line_list:
            if not self.basic_mode:
                t.hideCompleter()
            text = t.text()
            if text:
                self.tagstring += text + " "
        saveGeom(self, "TagDialogExtended")
        QDialog.accept(self)

    def reject(self):
        saveGeom(self, "TagDialogExtended")
        QDialog.reject(self)
예제 #6
0
class AddCards(QDialog):
    def __init__(self, mw):
        QDialog.__init__(self, None, Qt.Window)
        mw.setupDialogGC(self)
        self.mw = mw
        self.form = aqt.forms.addcards.Ui_Dialog()
        self.form.setupUi(self)
        self.setWindowTitle(_("Add"))
        self.setMinimumHeight(300)
        self.setMinimumWidth(400)
        self.setupChoosers()
        self.setupEditor()
        self.setupButtons()
        self.onReset()
        self.history = []
        restoreGeom(self, "add")
        addHook('reset', self.onReset)
        addHook('currentModelChanged', self.onModelChange)
        addCloseShortcut(self)
        self.show()

    def setupEditor(self):
        self.editor = aqt.editor.Editor(self.mw, self.form.fieldsArea, self,
                                        True)

    def setupChoosers(self):
        self.modelChooser = aqt.modelchooser.ModelChooser(
            self.mw, self.form.modelArea)
        self.deckChooser = aqt.deckchooser.DeckChooser(self.mw,
                                                       self.form.deckArea)

    def helpRequested(self):
        openHelp("addingnotes")

    def setupButtons(self):
        bb = self.form.buttonBox
        ar = QDialogButtonBox.ActionRole
        # add
        self.addButton = bb.addButton(_("Add"), ar)
        self.addButton.clicked.connect(self.addCards)
        self.addButton.setShortcut(QKeySequence("Ctrl+Return"))
        self.addButton.setToolTip(shortcut(_("Add (shortcut: ctrl+enter)")))
        # close
        self.closeButton = QPushButton(_("Close"))
        self.closeButton.setAutoDefault(False)
        bb.addButton(self.closeButton, QDialogButtonBox.RejectRole)
        # help
        self.helpButton = QPushButton(_("Help"), clicked=self.helpRequested)
        self.helpButton.setAutoDefault(False)
        bb.addButton(self.helpButton, QDialogButtonBox.HelpRole)
        # history
        b = bb.addButton(_("History") + " " + downArrow(), ar)
        if isMac:
            sc = "Ctrl+Shift+H"
        else:
            sc = "Ctrl+H"
        b.setShortcut(QKeySequence(sc))
        b.setToolTip(_("Shortcut: %s") % shortcut(sc))
        b.clicked.connect(self.onHistory)
        b.setEnabled(False)
        self.historyButton = b

    def setAndFocusNote(self, note):
        self.editor.setNote(note, focusTo=0)

    def onModelChange(self):
        oldNote = self.editor.note
        note = self.mw.col.newNote()
        if oldNote:
            oldFields = list(oldNote.keys())
            newFields = list(note.keys())
            for n, f in enumerate(note.model()['flds']):
                fieldName = f['name']
                try:
                    oldFieldName = oldNote.model()['flds'][n]['name']
                except IndexError:
                    oldFieldName = None
                # copy identical fields
                if fieldName in oldFields:
                    note[fieldName] = oldNote[fieldName]
                # set non-identical fields by field index
                elif oldFieldName and oldFieldName not in newFields:
                    try:
                        note.fields[n] = oldNote.fields[n]
                    except IndexError:
                        pass
            self.removeTempNote(oldNote)
        self.editor.setNote(note)

    def onReset(self, model=None, keep=False):
        oldNote = self.editor.note
        note = self.mw.col.newNote()
        flds = note.model()['flds']
        # copy fields from old note
        if oldNote:
            if not keep:
                self.removeTempNote(oldNote)
            for n in range(len(note.fields)):
                try:
                    if not keep or flds[n]['sticky']:
                        note.fields[n] = oldNote.fields[n]
                    else:
                        note.fields[n] = ""
                except IndexError:
                    break
        self.setAndFocusNote(note)

    def removeTempNote(self, note):
        if not note or not note.id:
            return
        # we don't have to worry about cards; just the note
        self.mw.col._remNotes([note.id])

    def addHistory(self, note):
        self.history.insert(0, note.id)
        self.history = self.history[:15]
        self.historyButton.setEnabled(True)

    def onHistory(self):
        m = QMenu(self)
        for nid in self.history:
            if self.mw.col.findNotes("nid:%s" % nid):
                fields = self.mw.col.getNote(nid).fields
                txt = htmlToTextLine(", ".join(fields))
                if len(txt) > 30:
                    txt = txt[:30] + "..."
                a = m.addAction(_("Edit \"%s\"") % txt)
                a.triggered.connect(lambda b, nid=nid: self.editHistory(nid))
            else:
                a = m.addAction(_("(Note deleted)"))
                a.setEnabled(False)
        runHook("AddCards.onHistory", self, m)
        m.exec_(self.historyButton.mapToGlobal(QPoint(0, 0)))

    def editHistory(self, nid):
        browser = aqt.dialogs.open("Browser", self.mw)
        browser.form.searchEdit.lineEdit().setText("nid:%d" % nid)
        browser.onSearchActivated()

    def addNote(self, note):
        note.model()['did'] = self.deckChooser.selectedId()
        ret = note.dupeOrEmpty()
        if ret == 1:
            showWarning(_("The first field is empty."),
                        help="AddItems#AddError")
            return
        if '{{cloze:' in note.model()['tmpls'][0]['qfmt']:
            if not self.mw.col.models._availClozeOrds(
                    note.model(), note.joinedFields(), False):
                if not askUser(
                        _("You have a cloze deletion note type "
                          "but have not made any cloze deletions. Proceed?")):
                    return
        cards = self.mw.col.addNote(note)
        if not cards:
            showWarning(_("""\
The input you have provided would make an empty \
question on all cards."""),
                        help="AddItems")
            return
        self.addHistory(note)
        self.mw.requireReset()
        return note

    def addCards(self):
        self.editor.saveNow(self._addCards)

    def _addCards(self):
        self.editor.saveAddModeVars()
        note = self.editor.note
        note = self.addNote(note)
        if not note:
            return
        tooltip(_("Added"), period=500)
        # stop anything playing
        clearAudioQueue()
        self.onReset(keep=True)
        self.mw.col.autosave()

    def keyPressEvent(self, evt):
        "Show answer on RET or register answer."
        if (evt.key() in (Qt.Key_Enter, Qt.Key_Return)
                and self.editor.tags.hasFocus()):
            evt.accept()
            return
        return QDialog.keyPressEvent(self, evt)

    def reject(self):
        self.ifCanClose(self._reject)

    def _reject(self):
        remHook('reset', self.onReset)
        remHook('currentModelChanged', self.onModelChange)
        clearAudioQueue()
        self.removeTempNote(self.editor.note)
        self.editor.cleanup()
        self.modelChooser.cleanup()
        self.deckChooser.cleanup()
        self.mw.maybeReset()
        saveGeom(self, "add")
        aqt.dialogs.markClosed("AddCards")
        QDialog.reject(self)

    def ifCanClose(self, onOk):
        def afterSave():
            ok = (self.editor.fieldsAreBlank()
                  or askUser(_("Close and lose current input?")))
            if ok:
                onOk()

        self.editor.saveNow(afterSave)

    def closeWithCallback(self, cb):
        def doClose():
            self._reject()
            cb()

        self.ifCanClose(doClose)
예제 #7
0
    def setupUI(self):
        mainLayout = QVBoxLayout()
        self.setLayout(mainLayout)

        # add widgets to set height and width
        widthLabel = QLabel('width')
        heightLabel = QLabel('height')
        self.widthEdit = QLineEdit(self)
        self.widthValidate = self.validate_label()
        self.heightValidate = self.validate_label()
        self.widthEdit.textEdited.connect(
            lambda i, v=self.widthValidate: self.onchange(i, v))
        self.heightEdit = QLineEdit(self)
        self.heightEdit.textEdited.connect(
            lambda i, v=self.heightValidate: self.onchange(i, v))
        self.attr2qt["width"] = self.widthEdit
        self.attr2qt["height"] = self.heightEdit

        wLayout = QHBoxLayout()
        wLayout.addWidget(widthLabel)
        wLayout.addWidget(self.widthEdit)

        hLayout = QHBoxLayout()
        hLayout.addWidget(heightLabel)
        hLayout.addWidget(self.heightEdit)

        sizeInputLayout = QHBoxLayout()
        sizeInputLayout.addLayout(wLayout)
        sizeInputLayout.addLayout(hLayout)

        labelLayout = QHBoxLayout()
        labelLayout.addWidget(self.widthValidate)
        labelLayout.addWidget(self.heightValidate)

        sizeLayout = QVBoxLayout()
        sizeLayout.addLayout(sizeInputLayout)
        sizeLayout.addLayout(labelLayout)

        # add final layout to main layout
        mainLayout.addLayout(sizeLayout)
        mainLayout.addWidget(self.hLine())

        # add min- sizes and max- sizes
        if self.config["min-size"]:
            minWidthLabel = QLabel("min-width")
            minHeightLabel = QLabel("min-height")
            self.minWidthEdit = QLineEdit(self)
            self.minHeightEdit = QLineEdit(self)
            minLayout = QHBoxLayout()
            minLayout.addWidget(minWidthLabel)
            minLayout.addWidget(self.minWidthEdit)
            minLayout.addWidget(minHeightLabel)
            minLayout.addWidget(self.minHeightEdit)
            self.minWidthEdit.textEdited.connect(
                lambda i, v=self.widthValidate: self.onchange(i, v))
            self.minHeightEdit.textEdited.connect(
                lambda i, v=self.heightValidate: self.onchange(i, v))
            self.attr2qt["min-width"] = self.minWidthEdit
            self.attr2qt["min-height"] = self.minHeightEdit

            mainLayout.addLayout(minLayout)
            mainLayout.addWidget(self.hLine())

        if self.config["max-size"]:
            maxWidthLabel = QLabel("max-width")
            maxHeightLabel = QLabel("max-height")
            self.maxWidthEdit = QLineEdit(self)
            self.maxHeightEdit = QLineEdit(self)
            maxLayout = QHBoxLayout()
            maxLayout.addWidget(maxWidthLabel)
            maxLayout.addWidget(self.maxWidthEdit)
            maxLayout.addWidget(maxHeightLabel)
            maxLayout.addWidget(self.maxHeightEdit)
            self.maxWidthEdit.textEdited.connect(
                lambda i, v=self.widthValidate: self.onchange(i, v))
            self.maxHeightEdit.textEdited.connect(
                lambda i, v=self.heightValidate: self.onchange(i, v))
            self.attr2qt["max-width"] = self.maxWidthEdit
            self.attr2qt["max-height"] = self.maxHeightEdit

            mainLayout.addLayout(maxLayout)
            mainLayout.addWidget(self.hLine())

        # add widgets to show original width, height
        owidthLabel = QLabel('original width')
        oheightLabel = QLabel('original height')
        self.originalWidth = QLineEdit(self)
        self.originalHeight = QLineEdit(self)
        self.disableLineEdit(self.originalWidth)
        self.disableLineEdit(self.originalHeight)

        sizeLayout2 = QHBoxLayout()
        sizeLayout2.addWidget(owidthLabel)
        sizeLayout2.addWidget(self.originalWidth)
        sizeLayout2.addWidget(oheightLabel)
        sizeLayout2.addWidget(self.originalHeight)
        mainLayout.addLayout(sizeLayout2)

        # add Image Occlusion related buttons
        if self.is_occl:
            mainLayout.addWidget(self.hLine())
            occlLabel = QLabel("Image Occlusion")
            occlLabel.setStyleSheet("QLabel {font-weight : bold;}")
            mainLayout.addWidget(occlLabel)
            occlAllNote = QCheckBox("Apply to all notes")
            self.occlAllNote = occlAllNote
            occlLayout = QHBoxLayout()
            occlLayout.addWidget(occlAllNote)
            self.attr2qt["Apply to all notes"] = self.occlAllNote
            if self.curr_fld in self.main.all_occl_flds:
                occlAllFld = QCheckBox("Apply to all fields")
                self.occlAllFld = occlAllFld
                occlLayout.addWidget(occlAllFld)
                self.attr2qt["Apply to all fields"] = self.occlAllFld
            mainLayout.addLayout(occlLayout)

        # add buttons
        okButton = QPushButton("OK")
        okButton.clicked.connect(self.clicked_ok)
        okButton.setDefault(True)
        okButton.setShortcut("Ctrl+Return")
        cancelButton = QPushButton("Cancel")
        cancelButton.clicked.connect(self.clicked_cancel)
        resetButton = QPushButton("Default")
        resetButton.clicked.connect(self.clicked_defaults)

        btnLayout = QHBoxLayout()
        btnLayout.addStretch(1)
        btnLayout.addWidget(okButton)
        btnLayout.addWidget(cancelButton)
        btnLayout.addWidget(resetButton)
        mainLayout.addLayout(btnLayout)

        self.setWindowTitle('Style Editor')
        self.show()
예제 #8
0
class DeckChooser(QHBoxLayout):

    def __init__(self, mw, widget, label=True, start=None):
        QHBoxLayout.__init__(self)
        self.widget = widget
        self.mw = mw
        self.deck = mw.col
        self.label = label
        self.setContentsMargins(0,0,0,0)
        self.setSpacing(8)
        self.setupDecks()
        self.widget.setLayout(self)
        addHook('currentModelChanged', self.onModelChange)

    def setupDecks(self):
        if self.label:
            self.deckLabel = QLabel(_("Deck"))
            self.addWidget(self.deckLabel)
        # decks box
        self.deck = QPushButton(clicked=self.onDeckChange)
        self.deck.setToolTip(shortcut(_("Target Deck (Ctrl+D)")))
        s = QShortcut(QKeySequence(_("Ctrl+D")), self.widget, activated=self.onDeckChange)
        self.addWidget(self.deck)
        # starting label
        if self.mw.col.conf.get("addToCur", True):
            col = self.mw.col
            did = col.conf['curDeck']
            if col.decks.isDyn(did):
                # if they're reviewing, try default to current card
                c = self.mw.reviewer.card
                if self.mw.state == "review" and c:
                    if not c.odid:
                        did = c.did
                    else:
                        did = c.odid
                else:
                    did = 1
            self.setDeckName(self.mw.col.decks.nameOrNone(
                did) or _("Default"))
        else:
            self.setDeckName(self.mw.col.decks.nameOrNone(
                self.mw.col.models.current()['did']) or _("Default"))
        # layout
        sizePolicy = QSizePolicy(
            QSizePolicy.Policy(7),
            QSizePolicy.Policy(0))
        self.deck.setSizePolicy(sizePolicy)

    def show(self):
        self.widget.show()

    def hide(self):
        self.widget.hide()

    def cleanup(self):
        remHook('currentModelChanged', self.onModelChange)

    def onModelChange(self):
        if not self.mw.col.conf.get("addToCur", True):
            self.setDeckName(self.mw.col.decks.nameOrNone(
                self.mw.col.models.current()['did']) or _("Default"))

    def onDeckChange(self):
        from aqt.studydeck import StudyDeck
        current = self.deckName()
        ret = StudyDeck(
            self.mw, current=current, accept=_("Choose"),
            title=_("Choose Deck"), help="addingnotes",
            cancel=False, parent=self.widget, geomKey="selectDeck")
        if ret.name:
            self.setDeckName(ret.name)

    def setDeckName(self, name):
        self.deck.setText(name.replace("&", "&&"))
        self._deckName = name

    def deckName(self):
        return self._deckName

    def selectedId(self):
        # save deck name
        name = self.deckName()
        if not name.strip():
            did = 1
        else:
            did = self.mw.col.decks.id(name)
        return did
예제 #9
0
class Hyperlink(QDialog):
    def __init__(self,
                 editor,
                 parent_window,
                 selected_text,
                 selected_is_url=False):
        QDialog.__init__(self, parent_window, Qt.Window)
        self.editor_instance = editor
        self.parent_window = parent_window
        self.selected_text = selected_text
        self.selected_is_url = selected_is_url
        self.setWindowTitle("Anki: Create a hyperlink")
        self.resize(DIALOG_SIZE_X, DIALOG_SIZE_Y)
        restoreGeom(self, "318752047__add_hyperlink")

        self.pb_ok = QPushButton("&OK", self)
        self.pb_ok.setEnabled(False)
        self.pb_ok.clicked.connect(
            lambda: self.insert_anchor(url_edit.text(), urltext_edit.text()))

        self.pb_cancel = QPushButton("&Cancel", self)
        self.pb_cancel.clicked.connect(self.reject)

        url_label = QLabel("Link to:")
        url_edit = QLineEdit()
        url_edit.setPlaceholderText("URL")
        url_edit.textChanged.connect(lambda: self.enable_ok_button(
            self.pb_ok, url_edit.text(), urltext_edit.text()))

        urltext_label = QLabel("Text to display:")
        urltext_edit = QLineEdit()
        urltext_edit.setPlaceholderText("Text")
        urltext_edit.textChanged.connect(lambda: self.enable_ok_button(
            self.pb_ok, url_edit.text(), urltext_edit.text()))

        self.button_bar = QHBoxLayout()
        self.button_bar.addStretch(1)
        self.button_bar.addWidget(self.pb_cancel)
        self.button_bar.addWidget(self.pb_ok)

        self.dialog_vbox = QVBoxLayout()
        self.dialog_vbox.addWidget(url_label)
        self.dialog_vbox.addWidget(url_edit)
        self.dialog_vbox.addWidget(urltext_label)
        self.dialog_vbox.addWidget(urltext_edit)
        self.dialog_vbox.addLayout(self.button_bar)
        self.setLayout(self.dialog_vbox)
        # if user already selected text, put it in urltext_edit
        if self.selected_text:
            if self.selected_is_url:
                url_edit.setText(self.selected_text)
                urltext_edit.setFocus()
            else:
                urltext_edit.setText(self.selected_text)
                url_edit.setFocus()

    @staticmethod
    def enable_ok_button(button, url, text):
        if url and text:
            button.setEnabled(True)
        else:
            button.setEnabled(False)

    @staticmethod
    def combine_to_hyperlink(url, text):
        # Create a hyperlink string, where `url` is the hyperlink reference
        # and `text` the content of the tag.
        text = escape_html_chars(text)
        if gc("remove whitespace from beginning and end of urls"):
            url = url.strip()
        if gc("encode_illegal_characters_in_links"):
            url = some_percent_encoding(url)
        out = "<a href=\"{0}\">{1}</a>".format(url, text)
        return out

    def reject(self):
        saveGeom(self, "318752047__add_hyperlink")
        QDialog.reject(self)

    def insert_anchor(self, url, text):
        # Inserts a HTML anchor `<a>` into the text field.
        self.replacement = self.combine_to_hyperlink(url, text)
        self.url = url
        self.text = text
        saveGeom(self, "318752047__add_hyperlink")
        self.accept()
예제 #10
0
class Hyperlink(QDialog):
    def __init__(self,
                 editor,
                 parent_window,
                 selected_visible_text,
                 selected_is_url=False):
        QDialog.__init__(self, parent_window, Qt.Window)
        self.editor_instance = editor
        self.parent_window = parent_window
        self.visible_text = selected_visible_text
        self.selected_is_url = selected_is_url
        self.setWindowTitle("Anki: Create a hyperlink")
        self.resize(500, 200)
        restoreGeom(self, "318752047__add_hyperlink")

        self.pb_ok = QPushButton("&OK", self)
        self.pb_ok.setEnabled(False)
        self.pb_ok.clicked.connect(self.store_hyperlink_and_close)

        self.pb_cancel = QPushButton("&Cancel", self)
        self.pb_cancel.clicked.connect(self.reject)

        self.url_label = QLabel("Link to:")
        self.url_edit = QLineEdit()
        self.url_edit.setPlaceholderText("URL")
        self.url_edit.textChanged.connect(self.maybe_enable_ok_button)

        self.text_label = QLabel("Text to display:")
        self.text_edit = QLineEdit()
        self.text_edit.setPlaceholderText("Text")
        self.text_edit.textChanged.connect(self.maybe_enable_ok_button)

        self.button_bar = QHBoxLayout()
        self.button_bar.addStretch(1)
        self.button_bar.addWidget(self.pb_cancel)
        self.button_bar.addWidget(self.pb_ok)

        self.dialog_vbox = QVBoxLayout()
        self.dialog_vbox.addWidget(self.url_label)
        self.dialog_vbox.addWidget(self.url_edit)
        self.dialog_vbox.addWidget(self.text_label)
        self.dialog_vbox.addWidget(self.text_edit)
        self.dialog_vbox.addLayout(self.button_bar)
        self.setLayout(self.dialog_vbox)

        # if user already selected text, put it in self.text_edit
        if self.visible_text:
            if self.selected_is_url:
                self.url_edit.setText(self.visible_text)
                self.text_edit.setFocus()
            else:
                self.text_edit.setText(self.visible_text)
                self.url_edit.setFocus()

    def maybe_enable_ok_button(self):
        if self.url_edit.text() and self.text_edit.text():
            self.pb_ok.setEnabled(True)
        else:
            self.pb_ok.setEnabled(False)

    def reject(self):
        saveGeom(self, "318752047__add_hyperlink")
        QDialog.reject(self)

    def store_hyperlink_and_close(self):
        self.url = self.url_edit.text()
        self.text = self.text_edit.text()
        self.replacement = combine_to_hyperlink(self.url, self.text)
        saveGeom(self, "318752047__add_hyperlink")
        self.accept()
예제 #11
0
파일: about.py 프로젝트: solarmist/anki
def show(mw):
    dialog = ClosableQDialog(mw)
    mw.setupDialogGC(dialog)
    abt = aqt.forms.about.Ui_About()
    abt.setupUi(dialog)

    # Copy debug info
    ######################################################################
    def onCopy():
        addmgr = mw.addonManager
        addons = "\n".join(addmgr.annotatedName(d) for d in addmgr.allAddons())
        info = "\n".join((supportText(), "Add-ons:\n\n{}".format(addons)))
        QApplication.clipboard().setText(info)
        tooltip(_("Copied to clipboard"), parent=dialog)

    btn = QPushButton(_("Copy Debug Info"))
    btn.clicked.connect(onCopy)
    abt.buttonBox.addButton(btn, QDialogButtonBox.ActionRole)
    abt.buttonBox.button(QDialogButtonBox.Ok).setFocus()

    # WebView contents
    ######################################################################
    abouttext = "<center><img src='/_anki/imgs/anki-logo-thin.png'></center>"
    abouttext += '<p>' + _("Anki is a friendly, intelligent spaced learning \
system. It's free and open source.")
    abouttext += "<p>" + _(
        "Anki is licensed under the AGPL3 license. Please see "
        "the license file in the source distribution for more information.")
    abouttext += '<p>' + _("Version %s") % versionWithBuild() + '<br>'
    abouttext += ("Qt %s PyQt %s<br>") % (QT_VERSION_STR, PYQT_VERSION_STR)
    abouttext += (_("<a href='%s'>Visit website</a>") % aqt.appWebsite) + \
"</span>"

    # automatically sorted; add new lines at the end
    allusers = sorted((
        "Aaron Harsh",
        "Alex Fraser",
        "Andreas Klauer",
        "Andrew Wright",
        "Aristotelis P.",
        "Bernhard Ibertsberger",
        "C. van Rooyen",
        "Charlene Barina",
        "Christian Krause",
        "Christian Rusche",
        "Dave Druelinger",
        "David Smith",
        "Dmitry Mikheev",
        "Dotan Cohen",
        "Emilio Wuerges",
        "Emmanuel Jarri",
        "Frank Harper",
        "Gregor Skumavc",
        "Guillem Palau Salvà",
        "H. Mijail",
        "Henrik Enggaard Hansen",
        "Houssam Salem",
        "Ian Lewis",
        "Immanuel Asmus",
        "Iroiro",
        "Jarvik7",
        "Jin Eun-Deok",
        "Jo Nakashima",
        "Johanna Lindh",
        "Joseph Lorimer",
        "Julien Baley",
        "Jussi Määttä",
        "Kieran Clancy",
        "LaC",
        "Laurent Steffan",
        "Luca Ban",
        "Luciano Esposito",
        "Marco Giancotti",
        "Marcus Rubeus",
        "Mari Egami",
        "Mark Wilbur",
        "Matthew Duggan",
        "Matthew Holtz",
        "Meelis Vasser",
        "Michael Jürges",
        "Michael Keppler",
        "Michael Montague",
        "Michael Penkov",
        "Michal Čadil",
        "Morteza Salehi",
        "Nathanael Law",
        "Nguyễn Hào Khôi",
        "Nick Cook",
        "Niklas Laxström",
        "Norbert Nagold",
        "Ole Guldberg",
        "Pcsl88",
        "Petr Michalec",
        "Piotr Kubowicz",
        "Richard Colley",
        "Roland Sieker",
        "Samson Melamed",
        "Silja Ijas",
        "Snezana Lukic",
        "Soren Bjornstad",
        "Stefaan De Pooter",
        "Susanna Björverud",
        "Sylvain Durand",
        "Tacutu",
        "Timm Preetz",
        "Timo Paulssen",
        "Ursus",
        "Victor Suba",
        "Volker Jansen",
        "Volodymyr Goncharenko",
        "Xtru",
        "Ádám Szegi",
        "赵金鹏",
        "黃文龍",
        "David Bailey",
        "Arman High",
        "Arthur Milchior",
    ))

    abouttext += '<p>' + _(
        "Written by Damien Elmes, with patches, translation,\
    testing and design from:<p>%(cont)s") % {
            'cont': ", ".join(allusers)
        }
    abouttext += '<p>' + _("If you have contributed and are not on this list, \
please get in touch.")
    abouttext += '<p>' + _("A big thanks to all the people who have provided \
suggestions, bug reports and donations.")
    abt.label.setMinimumWidth(800)
    abt.label.setMinimumHeight(600)
    dialog.show()
    abt.label.stdHtml(abouttext, js=" ")
    return dialog
예제 #12
0
class ModelChooser(QHBoxLayout):
    def __init__(self, mw, widget, label=True):
        QHBoxLayout.__init__(self)
        self.widget = widget
        self.mw = mw
        self.deck = mw.col
        self.label = label
        self.setContentsMargins(0, 0, 0, 0)
        self.setSpacing(8)
        self.setupModels()
        addHook('reset', self.onReset)
        self.widget.setLayout(self)

    def setupModels(self):
        if self.label:
            self.modelLabel = QLabel(_("Type"))
            self.addWidget(self.modelLabel)
        # models box
        self.models = QPushButton()
        #self.models.setStyleSheet("* { text-align: left; }")
        self.models.setToolTip(shortcut(_("Change Note Type (Ctrl+N)")))
        s = QShortcut(QKeySequence(_("Ctrl+N")),
                      self.widget,
                      activated=self.onModelChange)
        self.models.setAutoDefault(False)
        self.addWidget(self.models)
        self.models.clicked.connect(self.onModelChange)
        # layout
        sizePolicy = QSizePolicy(QSizePolicy.Policy(7), QSizePolicy.Policy(0))
        self.models.setSizePolicy(sizePolicy)
        self.updateModels()

    def cleanup(self):
        remHook('reset', self.onReset)

    def onReset(self):
        self.updateModels()

    def show(self):
        self.widget.show()

    def hide(self):
        self.widget.hide()

    def onEdit(self):
        import aqt.models
        aqt.models.Models(self.mw, self.widget)

    def onModelChange(self):
        from aqt.studydeck import StudyDeck
        current = self.deck.models.current()['name']
        # edit button
        edit = QPushButton(_("Manage"), clicked=self.onEdit)

        def nameFunc():
            return sorted(self.deck.models.allNames())

        ret = StudyDeck(self.mw,
                        names=nameFunc,
                        accept=_("Choose"),
                        title=_("Choose Note Type"),
                        help="_notes",
                        current=current,
                        parent=self.widget,
                        buttons=[edit],
                        cancel=True,
                        geomKey="selectModel")
        if not ret.name:
            return
        m = self.deck.models.byName(ret.name)
        self.deck.conf['curModel'] = m['id']
        cdeck = self.deck.decks.current()
        cdeck['mid'] = m['id']
        self.deck.decks.save(cdeck)
        runHook("currentModelChanged")
        self.mw.reset()

    def updateModels(self):
        self.models.setText(self.deck.models.current()['name'])
예제 #13
0
파일: clayout.py 프로젝트: solarmist/anki
 def setupButtons(self):
     l = self.buttons = QHBoxLayout()
     help = QPushButton(_("Help"))
     help.setAutoDefault(False)
     l.addWidget(help)
     help.clicked.connect(self.onHelp)
     l.addStretch()
     addField = QPushButton(_("Add Field"))
     addField.setAutoDefault(False)
     l.addWidget(addField)
     addField.clicked.connect(self.onAddField)
     if not self._isCloze():
         flip = QPushButton(_("Flip"))
         flip.setAutoDefault(False)
         l.addWidget(flip)
         flip.clicked.connect(self.onFlip)
     l.addStretch()
     close = QPushButton(_("Close"))
     close.setAutoDefault(False)
     l.addWidget(close)
     close.clicked.connect(self.accept)
예제 #14
0
def setup_evernote(self):
    global icoEvernoteWeb
    global imgEvernoteWeb
    global elements
    global evernote_query_last_updated
    global evernote_pagination_current_page_spinner

    def update_checkbox(setting):
        if setting is DECKS.EVERNOTE_NOTEBOOK_INTEGRATION and not elements[DECKS.BASE].text():
            return
        if setting.get.startswith(QUERY.get):
            update_evernote_query_visibilities()
        setting.save(elements[setting].isChecked())
        # mw.col.conf[setting] =
        if setting is QUERY.USE_TAGS:
            update_evernote_query_visibilities()
        if setting is QUERY.LAST_UPDATED.USE:
            evernote_query_last_updated_value_set_visibilities()

    def create_checkbox(setting, label=" ", default_value=False, is_fixed_size=False, fixed_width=None):
        if isinstance(label, bool):
            default_value = label
            label = " "
        checkbox = QCheckBox(label, self)
        sval = setting.fetch()
        if not isinstance(sval, bool):
            sval = default_value
        checkbox.setChecked(sval)
        # noinspection PyUnresolvedReferences
        checkbox.stateChanged.connect(lambda: update_checkbox(setting))
        if is_fixed_size or fixed_width:
            checkbox.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
            if fixed_width:
                checkbox.setFixedWidth(fixed_width)
        elements[setting] = checkbox
        return checkbox

    def create_checked_checkbox(*a, **kw):
        kw['default_value'] = True
        return create_checkbox(*a, **kw)

    def update_text(setting, text):
        text = text.strip()
        setting.save(text)
        if setting is DECKS.BASE:
            update_anki_deck_visibilities()
        if setting.get.startswith(QUERY.get):
            if text:
                use_key = getattr(QUERY, 'USE_' + setting.label.name)
                elements[use_key].setChecked(True)
            evernote_query_text_changed()
            if setting is QUERY.SEARCH_TERMS:
                update_evernote_query_visibilities()

    def create_textbox(setting, default_value=""):
        textbox = QLineEdit()
        textbox.setText(setting.fetch(default_value))
        textbox.connect(textbox,
                        SIGNAL("textEdited(QString)"),
                        lambda text: update_text(setting, text))
        elements[setting] = textbox
        return textbox

    def add_query_row(setting, is_checked=False, **kw):
        try:
            default_value = setting.val
        except:
            default_value = ''
        row_label = ' '.join(x.capitalize() for x in setting.replace('_', ' ').split())
        hbox = QHBoxLayout()
        hbox.addWidget(create_checkbox(getattr(QUERY, 'USE_' + setting),
                       default_value=is_checked, **kw))
        hbox.addWidget(create_textbox(getattr(QUERY, setting), default_value))
        form.addRow(row_label, hbox)

    def gen_qt_hr():
        vbox = QVBoxLayout()
        hr = QFrame()
        hr.setAutoFillBackground(True)
        hr.setFrameShape(QFrame.HLine)
        hr.setStyleSheet("QFrame { background-color: #0060bf; color: #0060bf; }")
        hr.setFixedHeight(2)
        vbox.addWidget(hr)
        vbox.addSpacing(4)
        return vbox

    # Begin setup_evernote()
    widget = QWidget()
    layout = QVBoxLayout()
    elements = {}
    rm_log_path('Dicts\\')
    evernote_query_last_updated = DictCaseInsensitive()


    ########################## QUERY ##########################
    ##################### QUERY: TEXTBOXES ####################
    group = QGroupBox("EVERNOTE SEARCH OPTIONS:")
    group.setStyleSheet('QGroupBox{    font-size: 10px;    font-weight: bold;  color: rgb(105, 170, 53);}')
    form = QFormLayout()

    form.addRow(gen_qt_hr())

    # Show Generated Evernote Query Button
    button_show_generated_evernote_query = QPushButton(icoEvernoteWeb, "Show Full Query", self)
    button_show_generated_evernote_query.setAutoDefault(False)
    button_show_generated_evernote_query.connect(button_show_generated_evernote_query,
                                                 SIGNAL("clicked()"),
                                                 handle_show_generated_evernote_query)


    # Add Form Row for Match Any Terms
    hbox = QHBoxLayout()
    hbox.addWidget(create_checked_checkbox(QUERY.ANY, "     Match Any Terms", is_fixed_size=True))
    hbox.addWidget(button_show_generated_evernote_query)
    form.addRow("<b>Search Parameters:</b>", hbox)

    # Add Form Rows for Evernote Query Textboxes
    for el in QUERY_TEXTBOXES:
        add_query_row(el, 'TAGS' in el)

    ################### QUERY: LAST UPDATED ###################
    # Evernote Query: Last Updated Type
    evernote_query_last_updated.type = QComboBox()
    evernote_query_last_updated.type.setStyleSheet(' QComboBox { color: rgb(45, 79, 201); font-weight: bold; } ')
    evernote_query_last_updated.type.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
    evernote_query_last_updated.type.addItems([u"Δ Day", u"Δ Week", u"Δ Month", u"Δ Year", "Date", "+ Time"])
    evernote_query_last_updated.type.setCurrentIndex(QUERY.LAST_UPDATED.TYPE.fetch(EvernoteQueryLocationType.RelativeDay))
    evernote_query_last_updated.type.activated.connect(update_evernote_query_last_updated_type)


    # Evernote Query: Last Updated Type: Relative Date
    evernote_query_last_updated.value.relative.spinner = EvernoteQueryLocationValueQSpinBox()
    evernote_query_last_updated.value.relative.spinner.setVisible(False)
    evernote_query_last_updated.value.relative.spinner.setStyleSheet(
        " QSpinBox, EvernoteQueryLocationValueQSpinBox { font-weight: bold;  color: rgb(173, 0, 0); } ")
    evernote_query_last_updated.value.relative.spinner.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
    evernote_query_last_updated.value.relative.spinner.connect(evernote_query_last_updated.value.relative.spinner,
                                                               SIGNAL("valueChanged(int)"),
                                                               update_evernote_query_last_updated_value_relative_spinner)

    # Evernote Query: Last Updated Type: Absolute Date
    evernote_query_last_updated.value.absolute.date = QDateEdit()
    evernote_query_last_updated.value.absolute.date.setDisplayFormat('M/d/yy')
    evernote_query_last_updated.value.absolute.date.setCalendarPopup(True)
    evernote_query_last_updated.value.absolute.date.setVisible(False)
    evernote_query_last_updated.value.absolute.date.setStyleSheet(
        "QDateEdit { font-weight: bold;  color: rgb(173, 0, 0); } ")
    evernote_query_last_updated.value.absolute.date.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
    evernote_query_last_updated.value.absolute.date.connect(evernote_query_last_updated.value.absolute.date,
                                                            SIGNAL("dateChanged(QDate)"),
                                                            update_evernote_query_last_updated_value_absolute_date)

    # Evernote Query: Last Updated Type: Absolute DateTime
    evernote_query_last_updated.value.absolute.datetime = QDateTimeEdit()
    evernote_query_last_updated.value.absolute.datetime.setDisplayFormat('M/d/yy h:mm AP')
    evernote_query_last_updated.value.absolute.datetime.setCalendarPopup(True)
    evernote_query_last_updated.value.absolute.datetime.setVisible(False)
    evernote_query_last_updated.value.absolute.datetime.setStyleSheet(
        "QDateTimeEdit { font-weight: bold;  color: rgb(173, 0, 0); } ")
    evernote_query_last_updated.value.absolute.datetime.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
    evernote_query_last_updated.value.absolute.datetime.connect(evernote_query_last_updated.value.absolute.datetime,
                                                                SIGNAL("dateTimeChanged(QDateTime)"),
                                                                update_evernote_query_last_updated_value_absolute_datetime)



    # Evernote Query: Last Updated Type: Absolute Time
    evernote_query_last_updated.value.absolute.time = QTimeEdit()
    evernote_query_last_updated.value.absolute.time.setDisplayFormat('h:mm AP')
    evernote_query_last_updated.value.absolute.time.setVisible(False)
    evernote_query_last_updated.value.absolute.time.setStyleSheet(
        "QTimeEdit { font-weight: bold;  color: rgb(143, 0, 30); } ")
    evernote_query_last_updated.value.absolute.time.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
    evernote_query_last_updated.value.absolute.time.connect(evernote_query_last_updated.value.absolute.time,
                                                            SIGNAL("timeChanged(QTime)"),
                                                            update_evernote_query_last_updated_value_absolute_time)

    # Create HBox for Separated Date & Time
    hbox_datetime = QHBoxLayout()
    hbox_datetime.addWidget(evernote_query_last_updated.value.absolute.date)
    hbox_datetime.addWidget(evernote_query_last_updated.value.absolute.time)

    # Evernote Query: Last Updated Type
    evernote_query_last_updated.value.stacked_layout = QStackedLayout()
    evernote_query_last_updated.value.stacked_layout.addWidget(evernote_query_last_updated.value.relative.spinner)
    evernote_query_last_updated.value.stacked_layout.addItem(hbox_datetime)

    # Add Form Row for Evernote Query: Last Updated
    hbox = QHBoxLayout()
    label = QLabel("Last Updated: ")
    label.setMinimumWidth(SETTINGS.FORM.LABEL_MINIMUM_WIDTH.val)
    hbox.addWidget(create_checkbox(QUERY.LAST_UPDATED.USE, is_fixed_size=True))
    hbox.addWidget(evernote_query_last_updated.type)
    hbox.addWidget(evernote_query_last_updated.value.relative.spinner)
    hbox.addWidget(evernote_query_last_updated.value.absolute.date)
    hbox.addWidget(evernote_query_last_updated.value.absolute.time)
    form.addRow(label, hbox)

    # Add Horizontal Row Separator
    form.addRow(gen_qt_hr())

    ############################ PAGINATION ##########################
    # Evernote Pagination: Current Page
    evernote_pagination_current_page_spinner = QSpinBox()
    evernote_pagination_current_page_spinner.setStyleSheet("QSpinBox { font-weight: bold;  color: rgb(173, 0, 0);  } ")
    evernote_pagination_current_page_spinner.setPrefix("PAGE: ")
    evernote_pagination_current_page_spinner.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
    evernote_pagination_current_page_spinner.setValue(EVERNOTE.PAGINATION_CURRENT_PAGE.fetch(1))
    evernote_pagination_current_page_spinner.connect(evernote_pagination_current_page_spinner,
                                                     SIGNAL("valueChanged(int)"),
                                                     update_evernote_pagination_current_page_spinner)

    # Evernote Pagination: Automation
    hbox = QHBoxLayout()
    hbox.addWidget(create_checked_checkbox(EVERNOTE.AUTO_PAGING, "     Automate", fixed_width=105))
    hbox.addWidget(evernote_pagination_current_page_spinner)

    # Add Form Row for Evernote Pagination
    form.addRow("<b>Pagination:</b>", hbox)

    # Add Query Form to Group Box
    group.setLayout(form)

    # Add Query Group Box to Main Layout
    layout.addWidget(group)

    ########################## DECK ##########################
    # Setup Group Box and Form
    group = QGroupBox("ANKI NOTE OPTIONS:")
    group.setStyleSheet('QGroupBox{    font-size: 10px;    font-weight: bold;  color: rgb(105, 170, 53);}')
    form = QFormLayout()

    # Add Horizontal Row Separator
    form.addRow(gen_qt_hr())

    # Add Form Row for Default Anki Deck
    hbox = QHBoxLayout()
    hbox.insertSpacing(0, 33)
    hbox.addWidget(create_textbox(DECKS.BASE, DECKS.BASE_DEFAULT_VALUE))
    label_deck = QLabel("<b>Anki Deck:</b>")
    label_deck.setMinimumWidth(SETTINGS.FORM.LABEL_MINIMUM_WIDTH.val)
    form.addRow(label_deck, hbox)

    # Add Form Row for Evernote Notebook Integration
    label_deck = QLabel("Evernote Notebook:")
    label_deck.setMinimumWidth(SETTINGS.FORM.LABEL_MINIMUM_WIDTH.val)
    form.addRow("", create_checked_checkbox(DECKS.EVERNOTE_NOTEBOOK_INTEGRATION, "      Append Evernote Notebook"))

    # Add Horizontal Row Separator
    form.addRow(gen_qt_hr())

    ############################ TAGS ##########################
    # Add Form Row for Evernote Tag Options
    label = QLabel("<b>Evernote Tags:</b>")
    label.setMinimumWidth(SETTINGS.FORM.LABEL_MINIMUM_WIDTH.val)

    # Tags: Save To Anki Note
    form.addRow(label, create_checkbox(TAGS.KEEP_TAGS, "     Save To Anki Note", TAGS.KEEP_TAGS_DEFAULT_VALUE))
    hbox = QHBoxLayout()
    hbox.insertSpacing(0, 33)
    hbox.addWidget(create_textbox(TAGS.TO_DELETE))

    # Tags: Tags To Delete
    form.addRow("Tags to Delete:", hbox)
    form.addRow(" ", create_checkbox(TAGS.DELETE_EVERNOTE_QUERY_TAGS, "     Also Delete Search Tags"))

    # Add Horizontal Row Separator
    form.addRow(gen_qt_hr())

    ############################ NOTE UPDATING ##########################
    # Note Update Method
    update_existing_notes = QComboBox()
    update_existing_notes.setStyleSheet(
        ' QComboBox { color: #3b679e; font-weight: bold; } QComboBoxItem { color: #A40F2D; font-weight: bold; } ')
    update_existing_notes.addItems(["Ignore Existing Notes", "Update In-Place",
                                    "Delete and Re-Add"])
    sval = ANKI.UPDATE_EXISTING_NOTES.fetch()
    if not isinstance(sval, int):
        sval = ANKI.UPDATE_EXISTING_NOTES.val
    update_existing_notes.setCurrentIndex(sval)
    update_existing_notes.activated.connect(update_update_existing_notes)

    # Add Form Row for Note Update Method
    hbox = QHBoxLayout()
    hbox.insertSpacing(0, 33)
    hbox.addWidget(update_existing_notes)
    form.addRow("<b>Note Updating:</b>", hbox)

    # Add Note Update Method Form to Group Box
    group.setLayout(form)

    # Add Note Update Method Group Box to Main Layout
    layout.addWidget(group)

    ######################### UPDATE VISIBILITIES #######################
    # Update Visibilities of Anki Deck Options
    update_anki_deck_visibilities()

    # Update Visibilities of Query Options
    evernote_query_text_changed()
    update_evernote_query_visibilities()

    ######################## ADD TO SETTINGS PANEL ######################
    # Vertical Spacer
    vertical_spacer = QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
    layout.addItem(vertical_spacer)

    # Parent Widget
    widget.setLayout(layout)

    # New Tab
    self.form.tabWidget.addTab(widget, "Anknotes")