2019-02-05 04:59:03 +01:00
|
|
|
# Copyright: Ankitects Pty Ltd and contributors
|
2012-12-21 08:51:59 +01:00
|
|
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
|
|
|
|
from typing import Callable, List, Optional
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2019-12-20 10:19:03 +01:00
|
|
|
import aqt.deckchooser
|
|
|
|
import aqt.editor
|
2012-12-21 08:51:59 +01:00
|
|
|
import aqt.forms
|
2021-02-11 10:57:19 +01:00
|
|
|
from anki.collection import SearchNode
|
2020-04-07 07:02:53 +02:00
|
|
|
from anki.consts import MODEL_CLOZE
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
from anki.notes import DuplicateOrEmptyResult, Note
|
2019-03-04 08:25:19 +01:00
|
|
|
from anki.utils import htmlToTextLine, isMac
|
2020-01-15 03:46:53 +01:00
|
|
|
from aqt import AnkiQt, gui_hooks
|
2020-08-16 18:49:51 +02:00
|
|
|
from aqt.main import ResetReason
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
from aqt.notetypechooser import NoteTypeChooser
|
2019-12-20 10:19:03 +01:00
|
|
|
from aqt.qt import *
|
2020-01-20 11:10:38 +01:00
|
|
|
from aqt.sound import av_player
|
2019-12-23 01:34:10 +01:00
|
|
|
from aqt.utils import (
|
2020-11-17 08:42:43 +01:00
|
|
|
TR,
|
2021-01-25 14:45:47 +01:00
|
|
|
HelpPage,
|
2019-12-23 01:34:10 +01:00
|
|
|
addCloseShortcut,
|
|
|
|
askUser,
|
2021-01-07 05:24:49 +01:00
|
|
|
disable_help_button,
|
2019-12-23 01:34:10 +01:00
|
|
|
downArrow,
|
|
|
|
openHelp,
|
|
|
|
restoreGeom,
|
|
|
|
saveGeom,
|
|
|
|
shortcut,
|
|
|
|
showWarning,
|
|
|
|
tooltip,
|
2020-11-17 08:42:43 +01:00
|
|
|
tr,
|
2019-12-23 01:34:10 +01:00
|
|
|
)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2019-12-20 09:43:52 +01:00
|
|
|
|
2012-12-21 08:51:59 +01:00
|
|
|
class AddCards(QDialog):
|
2019-12-20 09:43:52 +01:00
|
|
|
def __init__(self, mw: AnkiQt) -> None:
|
2012-12-21 08:51:59 +01:00
|
|
|
QDialog.__init__(self, None, Qt.Window)
|
2021-03-05 04:07:52 +01:00
|
|
|
mw.garbage_collect_on_dialog_finish(self)
|
2012-12-21 08:51:59 +01:00
|
|
|
self.mw = mw
|
|
|
|
self.form = aqt.forms.addcards.Ui_Dialog()
|
|
|
|
self.form.setupUi(self)
|
2020-11-17 08:42:43 +01:00
|
|
|
self.setWindowTitle(tr(TR.ACTIONS_ADD))
|
2021-01-07 05:24:49 +01:00
|
|
|
disable_help_button(self)
|
2012-12-21 08:51:59 +01:00
|
|
|
self.setMinimumHeight(300)
|
|
|
|
self.setMinimumWidth(400)
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
self.setup_choosers()
|
2012-12-21 08:51:59 +01:00
|
|
|
self.setupEditor()
|
|
|
|
self.setupButtons()
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
self._load_new_note()
|
2019-12-16 10:46:40 +01:00
|
|
|
self.history: List[int] = []
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
self._last_added_note: Optional[Note] = None
|
2012-12-21 08:51:59 +01:00
|
|
|
restoreGeom(self, "add")
|
2012-12-22 01:11:29 +01:00
|
|
|
addCloseShortcut(self)
|
2020-04-03 10:54:54 +02:00
|
|
|
gui_hooks.add_cards_did_init(self)
|
2012-12-21 08:51:59 +01:00
|
|
|
self.show()
|
|
|
|
|
2019-12-20 09:43:52 +01:00
|
|
|
def setupEditor(self) -> None:
|
2019-12-23 01:34:10 +01:00
|
|
|
self.editor = aqt.editor.Editor(self.mw, self.form.fieldsArea, self, True)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
def setup_choosers(self) -> None:
|
|
|
|
defaults = self.mw.col.defaults_for_adding(
|
|
|
|
current_review_card=self.mw.reviewer.card
|
|
|
|
)
|
|
|
|
self.notetype_chooser = NoteTypeChooser(
|
|
|
|
mw=self.mw,
|
|
|
|
widget=self.form.modelArea,
|
|
|
|
starting_notetype_id=defaults.notetype_id,
|
|
|
|
on_button_activated=self.show_notetype_selector,
|
|
|
|
on_notetype_changed=self.on_notetype_change,
|
|
|
|
)
|
|
|
|
self.deck_chooser = aqt.deckchooser.DeckChooser(
|
|
|
|
self.mw, self.form.deckArea, starting_deck_id=defaults.deck_id
|
2020-10-05 05:33:54 +02:00
|
|
|
)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2021-02-01 14:28:21 +01:00
|
|
|
def helpRequested(self) -> None:
|
2021-01-25 14:45:47 +01:00
|
|
|
openHelp(HelpPage.ADDING_CARD_AND_NOTE)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2019-12-20 09:43:52 +01:00
|
|
|
def setupButtons(self) -> None:
|
2012-12-21 08:51:59 +01:00
|
|
|
bb = self.form.buttonBox
|
|
|
|
ar = QDialogButtonBox.ActionRole
|
|
|
|
# add
|
2020-11-17 08:42:43 +01:00
|
|
|
self.addButton = bb.addButton(tr(TR.ACTIONS_ADD), ar)
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
qconnect(self.addButton.clicked, self.add_current_note)
|
2012-12-21 08:51:59 +01:00
|
|
|
self.addButton.setShortcut(QKeySequence("Ctrl+Return"))
|
2020-11-17 08:42:43 +01:00
|
|
|
self.addButton.setToolTip(shortcut(tr(TR.ADDING_ADD_SHORTCUT_CTRLANDENTER)))
|
2012-12-21 08:51:59 +01:00
|
|
|
# close
|
2020-11-17 08:42:43 +01:00
|
|
|
self.closeButton = QPushButton(tr(TR.ACTIONS_CLOSE))
|
2012-12-21 08:51:59 +01:00
|
|
|
self.closeButton.setAutoDefault(False)
|
2016-05-31 10:51:40 +02:00
|
|
|
bb.addButton(self.closeButton, QDialogButtonBox.RejectRole)
|
2012-12-21 08:51:59 +01:00
|
|
|
# help
|
2020-11-17 08:42:43 +01:00
|
|
|
self.helpButton = QPushButton(tr(TR.ACTIONS_HELP), clicked=self.helpRequested) # type: ignore
|
2012-12-21 08:51:59 +01:00
|
|
|
self.helpButton.setAutoDefault(False)
|
2019-12-23 01:34:10 +01:00
|
|
|
bb.addButton(self.helpButton, QDialogButtonBox.HelpRole)
|
2012-12-21 08:51:59 +01:00
|
|
|
# history
|
2021-02-11 01:09:06 +01:00
|
|
|
b = bb.addButton(f"{tr(TR.ADDING_HISTORY)} {downArrow()}", ar)
|
2013-05-23 07:44:00 +02:00
|
|
|
if isMac:
|
|
|
|
sc = "Ctrl+Shift+H"
|
|
|
|
else:
|
|
|
|
sc = "Ctrl+H"
|
|
|
|
b.setShortcut(QKeySequence(sc))
|
2020-11-17 12:47:47 +01:00
|
|
|
b.setToolTip(tr(TR.ADDING_SHORTCUT, val=shortcut(sc)))
|
2020-05-04 05:23:08 +02:00
|
|
|
qconnect(b.clicked, self.onHistory)
|
2012-12-21 08:51:59 +01:00
|
|
|
b.setEnabled(False)
|
|
|
|
self.historyButton = b
|
|
|
|
|
2019-12-20 09:43:52 +01:00
|
|
|
def setAndFocusNote(self, note: Note) -> None:
|
2017-08-05 07:15:19 +02:00
|
|
|
self.editor.setNote(note, focusTo=0)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2020-10-05 05:33:54 +02:00
|
|
|
def show_notetype_selector(self) -> None:
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
self.editor.saveNow(self.notetype_chooser.choose_notetype)
|
|
|
|
|
|
|
|
def on_notetype_change(self, notetype_id: int) -> None:
|
|
|
|
# need to adjust current deck?
|
|
|
|
if deck_id := self.mw.col.default_deck_for_notetype(notetype_id):
|
|
|
|
self.deck_chooser.selected_deck_id = deck_id
|
|
|
|
|
|
|
|
# only used for detecting changed sticky fields on close
|
|
|
|
self._last_added_note = None
|
|
|
|
|
|
|
|
# copy fields into new note with the new notetype
|
|
|
|
old = self.editor.note
|
|
|
|
new = self._new_note()
|
|
|
|
if old:
|
|
|
|
old_fields = list(old.keys())
|
|
|
|
new_fields = list(new.keys())
|
|
|
|
for n, f in enumerate(new.model()["flds"]):
|
|
|
|
field_name = f["name"]
|
2016-04-10 13:11:25 +02:00
|
|
|
# copy identical fields
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
if field_name in old_fields:
|
|
|
|
new[field_name] = old[field_name]
|
|
|
|
elif n < len(old.model()["flds"]):
|
2020-04-26 16:52:35 +02:00
|
|
|
# set non-identical fields by field index
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
old_field_name = old.model()["flds"][n]["name"]
|
|
|
|
if old_field_name not in new_fields:
|
|
|
|
new.fields[n] = old.fields[n]
|
|
|
|
|
|
|
|
# and update editor state
|
|
|
|
self.editor.note = new
|
|
|
|
self.editor.loadNote()
|
|
|
|
|
|
|
|
def _load_new_note(self, sticky_fields_from: Optional[Note] = None) -> None:
|
|
|
|
note = self._new_note()
|
|
|
|
if old_note := sticky_fields_from:
|
|
|
|
flds = note.model()["flds"]
|
|
|
|
# copy fields from old note
|
|
|
|
if old_note:
|
|
|
|
for n in range(min(len(note.fields), len(old_note.fields))):
|
|
|
|
if flds[n]["sticky"]:
|
|
|
|
note.fields[n] = old_note.fields[n]
|
2017-08-05 07:15:19 +02:00
|
|
|
self.setAndFocusNote(note)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
def _new_note(self) -> Note:
|
|
|
|
return self.mw.col.new_note(
|
|
|
|
self.mw.col.models.get(self.notetype_chooser.selected_notetype_id)
|
|
|
|
)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2021-02-01 13:08:56 +01:00
|
|
|
def addHistory(self, note: Note) -> None:
|
2017-01-08 14:48:58 +01:00
|
|
|
self.history.insert(0, note.id)
|
2012-12-21 08:51:59 +01:00
|
|
|
self.history = self.history[:15]
|
|
|
|
self.historyButton.setEnabled(True)
|
|
|
|
|
2020-01-15 22:41:23 +01:00
|
|
|
def onHistory(self) -> None:
|
2012-12-21 08:51:59 +01:00
|
|
|
m = QMenu(self)
|
2017-01-08 14:48:58 +01:00
|
|
|
for nid in self.history:
|
2021-02-11 10:57:19 +01:00
|
|
|
if self.mw.col.findNotes(SearchNode(nid=nid)):
|
2021-03-05 13:45:55 +01:00
|
|
|
note = self.mw.col.get_note(nid)
|
2020-06-03 23:29:09 +02:00
|
|
|
fields = note.fields
|
2017-03-14 07:48:40 +01:00
|
|
|
txt = htmlToTextLine(", ".join(fields))
|
2017-02-05 08:45:08 +01:00
|
|
|
if len(txt) > 30:
|
2021-02-11 01:09:06 +01:00
|
|
|
txt = f"{txt[:30]}..."
|
2020-11-18 02:53:33 +01:00
|
|
|
line = tr(TR.ADDING_EDIT, val=txt)
|
2020-06-03 23:29:09 +02:00
|
|
|
line = gui_hooks.addcards_will_add_history_entry(line, note)
|
|
|
|
a = m.addAction(line)
|
2020-01-15 22:41:23 +01:00
|
|
|
qconnect(a.triggered, lambda b, nid=nid: self.editHistory(nid))
|
2017-01-09 11:55:30 +01:00
|
|
|
else:
|
2020-11-17 08:42:43 +01:00
|
|
|
a = m.addAction(tr(TR.ADDING_NOTE_DELETED))
|
2017-01-09 11:55:30 +01:00
|
|
|
a.setEnabled(False)
|
2020-01-15 08:45:35 +01:00
|
|
|
gui_hooks.add_cards_will_show_history_menu(self, m)
|
2019-12-23 01:34:10 +01:00
|
|
|
m.exec_(self.historyButton.mapToGlobal(QPoint(0, 0)))
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2021-02-02 15:00:29 +01:00
|
|
|
def editHistory(self, nid: int) -> None:
|
2021-02-11 10:57:19 +01:00
|
|
|
aqt.dialogs.open("Browser", self.mw, search=(SearchNode(nid=nid),))
|
2012-12-21 08:51:59 +01:00
|
|
|
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
def add_current_note(self) -> None:
|
|
|
|
self.editor.saveNow(self._add_current_note)
|
2012-12-21 08:51:59 +01:00
|
|
|
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
def _add_current_note(self) -> None:
|
|
|
|
note = self.editor.note
|
2016-07-14 12:23:44 +02:00
|
|
|
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
if not self._note_can_be_added(note):
|
2012-12-21 08:51:59 +01:00
|
|
|
return
|
2020-10-24 10:47:25 +02:00
|
|
|
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
target_deck_id = self.deck_chooser.selected_deck_id
|
|
|
|
self.mw.col.add_note(note, target_deck_id)
|
|
|
|
|
|
|
|
# only used for detecting changed sticky fields on close
|
|
|
|
self._last_added_note = note
|
|
|
|
|
|
|
|
self.addHistory(note)
|
|
|
|
self.mw.requireReset(reason=ResetReason.AddCardsAddNote, context=self)
|
|
|
|
|
2020-10-24 10:47:25 +02:00
|
|
|
# workaround for PyQt focus bug
|
|
|
|
self.editor.hideCompleters()
|
|
|
|
|
2020-11-17 08:42:43 +01:00
|
|
|
tooltip(tr(TR.ADDING_ADDED), period=500)
|
2020-01-20 11:10:38 +01:00
|
|
|
av_player.stop_and_clear_queue()
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
self._load_new_note(sticky_fields_from=note)
|
|
|
|
self.mw.col.autosave() # fixme:
|
|
|
|
|
|
|
|
gui_hooks.add_cards_did_add_note(note)
|
|
|
|
|
|
|
|
def _note_can_be_added(self, note: Note) -> bool:
|
|
|
|
result = note.duplicate_or_empty()
|
|
|
|
if result == DuplicateOrEmptyResult.EMPTY:
|
|
|
|
problem = tr(TR.ADDING_THE_FIRST_FIELD_IS_EMPTY)
|
|
|
|
else:
|
|
|
|
# duplicate entries are allowed these days
|
|
|
|
problem = None
|
|
|
|
|
|
|
|
# filter problem through add-ons
|
|
|
|
problem = gui_hooks.add_cards_will_add_note(problem, note)
|
|
|
|
if problem is not None:
|
|
|
|
showWarning(problem, help=HelpPage.ADDING_CARD_AND_NOTE)
|
|
|
|
return False
|
|
|
|
|
|
|
|
# missing cloze deletion?
|
|
|
|
if note.model()["type"] == MODEL_CLOZE:
|
|
|
|
if not note.cloze_numbers_in_fields():
|
|
|
|
if not askUser(tr(TR.ADDING_YOU_HAVE_A_CLOZE_DELETION_NOTE)):
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
2012-12-21 08:51:59 +01:00
|
|
|
|
2021-02-01 13:08:56 +01:00
|
|
|
def keyPressEvent(self, evt: QKeyEvent) -> None:
|
2012-12-21 08:51:59 +01:00
|
|
|
"Show answer on RET or register answer."
|
2019-12-23 01:34:10 +01:00
|
|
|
if evt.key() in (Qt.Key_Enter, Qt.Key_Return) and self.editor.tags.hasFocus():
|
2012-12-21 08:51:59 +01:00
|
|
|
evt.accept()
|
|
|
|
return
|
|
|
|
return QDialog.keyPressEvent(self, evt)
|
|
|
|
|
2019-12-20 09:43:52 +01:00
|
|
|
def reject(self) -> None:
|
2017-08-16 04:45:33 +02:00
|
|
|
self.ifCanClose(self._reject)
|
|
|
|
|
2019-12-20 09:43:52 +01:00
|
|
|
def _reject(self) -> None:
|
2020-01-20 11:10:38 +01:00
|
|
|
av_player.stop_and_clear_queue()
|
2017-08-16 04:45:33 +02:00
|
|
|
self.editor.cleanup()
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
self.notetype_chooser.cleanup()
|
2012-12-21 08:51:59 +01:00
|
|
|
self.mw.maybeReset()
|
|
|
|
saveGeom(self, "add")
|
2017-08-16 04:45:33 +02:00
|
|
|
aqt.dialogs.markClosed("AddCards")
|
2012-12-21 08:51:59 +01:00
|
|
|
QDialog.reject(self)
|
|
|
|
|
2019-12-20 09:43:52 +01:00
|
|
|
def ifCanClose(self, onOk: Callable) -> None:
|
2021-02-01 14:28:21 +01:00
|
|
|
def afterSave() -> None:
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
ok = self.editor.fieldsAreBlank(self._last_added_note) or askUser(
|
2020-11-17 08:42:43 +01:00
|
|
|
tr(TR.ADDING_CLOSE_AND_LOSE_CURRENT_INPUT), defaultno=True
|
2019-12-23 01:34:10 +01:00
|
|
|
)
|
2017-08-16 04:45:33 +02:00
|
|
|
if ok:
|
|
|
|
onOk()
|
|
|
|
|
|
|
|
self.editor.saveNow(afterSave)
|
|
|
|
|
2021-02-02 15:00:29 +01:00
|
|
|
def closeWithCallback(self, cb: Callable[[], None]) -> None:
|
2021-02-01 14:28:21 +01:00
|
|
|
def doClose() -> None:
|
2017-08-16 04:45:33 +02:00
|
|
|
self._reject()
|
|
|
|
cb()
|
2019-12-23 01:34:10 +01:00
|
|
|
|
2017-08-16 04:45:33 +02:00
|
|
|
self.ifCanClose(doClose)
|
Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:
- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.
It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.
To address these points:
- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-08 14:23:24 +01:00
|
|
|
|
|
|
|
# legacy aliases
|
|
|
|
|
|
|
|
addCards = add_current_note
|
|
|
|
_addCards = _add_current_note
|
|
|
|
onModelChange = on_notetype_change
|
|
|
|
|
|
|
|
def addNote(self, note: Note) -> None:
|
|
|
|
print("addNote() is obsolete")
|
|
|
|
|
|
|
|
def removeTempNote(self, note: Note) -> None:
|
|
|
|
print("removeTempNote() will go away")
|