anki/qt/aqt/modelchooser.py

105 lines
3.4 KiB
Python
Raw Normal View History

2019-02-05 04:59:03 +01:00
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
2021-02-01 14:28:21 +01:00
from typing import List, Optional
from aqt import AnkiQt, gui_hooks
2019-12-20 10:19:03 +01:00
from aqt.qt import *
2021-03-26 04:48:26 +01:00
from aqt.utils import HelpPage, shortcut, tr
2019-12-20 10:19:03 +01:00
class ModelChooser(QHBoxLayout):
"New code should prefer NotetypeChooser."
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 __init__(
self,
mw: AnkiQt,
widget: QWidget,
label: bool = True,
on_activated: Optional[Callable[[], None]] = None,
) -> None:
"""If provided, on_activated() will be called when the button is clicked,
and the caller can call .onModelChange() to pull up the dialog when they
are ready."""
QHBoxLayout.__init__(self)
2021-02-02 14:30:53 +01:00
self._widget = widget # type: ignore
self.mw = mw
self.deck = mw.col
self.label = label
if on_activated:
self.on_activated = on_activated
else:
self.on_activated = self.onModelChange
2019-12-23 01:34:10 +01:00
self.setContentsMargins(0, 0, 0, 0)
self.setSpacing(8)
self.setupModels()
2020-01-15 07:53:24 +01:00
gui_hooks.state_did_reset.append(self.onReset)
2021-02-02 14:30:53 +01:00
self._widget.setLayout(self)
def setupModels(self) -> None:
if self.label:
2021-03-26 04:48:26 +01:00
self.modelLabel = QLabel(tr.notetypes_type())
self.addWidget(self.modelLabel)
# models box
self.models = QPushButton()
2021-03-26 04:48:26 +01:00
self.models.setToolTip(shortcut(tr.qt_misc_change_note_type_ctrlandn()))
2021-02-02 14:30:53 +01:00
QShortcut(QKeySequence("Ctrl+N"), self._widget, activated=self.on_activated) # type: ignore
self.models.setAutoDefault(False)
self.addWidget(self.models)
qconnect(self.models.clicked, self.onModelChange)
# layout
2019-12-23 01:34:10 +01:00
sizePolicy = QSizePolicy(QSizePolicy.Policy(7), QSizePolicy.Policy(0))
self.models.setSizePolicy(sizePolicy)
self.updateModels()
def cleanup(self) -> None:
2020-01-15 07:53:24 +01:00
gui_hooks.state_did_reset.remove(self.onReset)
def onReset(self) -> None:
self.updateModels()
def show(self) -> None:
2021-02-02 14:30:53 +01:00
self._widget.show() # type: ignore
def hide(self) -> None:
2021-02-02 14:30:53 +01:00
self._widget.hide() # type: ignore
def onEdit(self) -> None:
import aqt.models
2019-12-23 01:34:10 +01:00
2021-02-02 14:30:53 +01:00
aqt.models.Models(self.mw, self._widget)
def onModelChange(self) -> None:
from aqt.studydeck import StudyDeck
2019-12-23 01:34:10 +01:00
current = self.deck.models.current()["name"]
# edit button
2021-03-26 04:48:26 +01:00
edit = QPushButton(tr.qt_misc_manage(), clicked=self.onEdit) # type: ignore
2019-12-23 01:34:10 +01:00
2021-02-01 14:28:21 +01:00
def nameFunc() -> List[str]:
2021-06-27 05:49:58 +02:00
return sorted(self.deck.models.all_names())
2019-12-23 01:34:10 +01:00
ret = StudyDeck(
2019-12-23 01:34:10 +01:00
self.mw,
names=nameFunc,
2021-03-26 04:48:26 +01:00
accept=tr.actions_choose(),
title=tr.qt_misc_choose_note_type(),
help=HelpPage.NOTE_TYPE,
2019-12-23 01:34:10 +01:00
current=current,
2021-02-02 14:30:53 +01:00
parent=self._widget,
2019-12-23 01:34:10 +01:00
buttons=[edit],
cancel=True,
geomKey="selectModel",
)
if not ret.name:
return
2021-06-27 05:49:58 +02:00
m = self.deck.models.by_name(ret.name)
2019-12-23 01:34:10 +01:00
self.deck.conf["curModel"] = m["id"]
cdeck = self.deck.decks.current()
2019-12-23 01:34:10 +01:00
cdeck["mid"] = m["id"]
self.deck.decks.save(cdeck)
2020-01-15 07:53:24 +01:00
gui_hooks.current_note_type_did_change(current)
self.mw.reset()
def updateModels(self) -> None:
self.models.setText(self.deck.models.current()["name"].replace("&", "&&"))