anki/qt/aqt/notetypechooser.py
Damien Elmes b9251290ca run pyupgrade over codebase [python upgrade required]
This adds Python 3.9 and 3.10 typing syntax to files that import
attributions from __future___. Python 3.9 should be able to cope with
the 3.10 syntax, but Python 3.8 will no longer work.

On Windows/Mac, install the latest Python 3.9 version from python.org.
There are currently no orjson wheels for Python 3.10 on Windows/Mac,
which will break the build unless you have Rust installed separately.

On Linux, modern distros should have Python 3.9 available already. If
you're on an older distro, you'll need to build Python from source first.
2021-10-04 15:05:48 +10:00

152 lines
5.1 KiB
Python

# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from typing import Optional
from anki.models import NotetypeId
from aqt import AnkiQt, gui_hooks
from aqt.qt import *
from aqt.utils import HelpPage, shortcut, tr
class NotetypeChooser(QHBoxLayout):
"""
Unlike the older modelchooser, this does not modify the "current model",
so changes made here do not affect other parts of the UI. To read the
currently selected notetype id, use .selected_notetype_id.
By default, a chooser will pop up when the button is pressed. You can
override this by providing `on_button_activated`. Call .choose_notetype()
to run the normal behaviour.
`on_notetype_changed` will be called with the new notetype ID if the user
selects a different notetype, or if the currently-selected notetype is
deleted.
"""
_selected_notetype_id: NotetypeId
def __init__(
self,
*,
mw: AnkiQt,
widget: QWidget,
starting_notetype_id: NotetypeId,
on_button_activated: Optional[Callable[[], None]] = None,
on_notetype_changed: Optional[Callable[[NotetypeId], None]] = None,
show_prefix_label: bool = True,
) -> None:
QHBoxLayout.__init__(self)
self._widget = widget # type: ignore
self.mw = mw
if on_button_activated:
self.on_button_activated = on_button_activated
else:
self.on_button_activated = self.choose_notetype
self._setup_ui(show_label=show_prefix_label)
gui_hooks.state_did_reset.append(self.reset_state)
self._selected_notetype_id = NotetypeId(0)
# triggers UI update; avoid firing changed hook on startup
self.on_notetype_changed = None
self.selected_notetype_id = starting_notetype_id
self.on_notetype_changed = on_notetype_changed
def _setup_ui(self, show_label: bool) -> None:
self.setContentsMargins(0, 0, 0, 0)
self.setSpacing(8)
if show_label:
self.label = QLabel(tr.notetypes_type())
self.addWidget(self.label)
# button
self.button = QPushButton()
self.button.setToolTip(shortcut(tr.qt_misc_change_note_type_ctrlandn()))
qconnect(
QShortcut(QKeySequence("Ctrl+N"), self._widget).activated,
self.on_button_activated,
)
self.button.setAutoDefault(False)
self.addWidget(self.button)
qconnect(self.button.clicked, self.on_button_activated)
sizePolicy = QSizePolicy(QSizePolicy.Policy(7), QSizePolicy.Policy(0))
self.button.setSizePolicy(sizePolicy)
self._widget.setLayout(self)
def cleanup(self) -> None:
gui_hooks.state_did_reset.remove(self.reset_state)
def reset_state(self) -> None:
self._ensure_selected_notetype_valid()
def show(self) -> None:
self._widget.show() # type: ignore
def hide(self) -> None:
self._widget.hide() # type: ignore
def onEdit(self) -> None:
import aqt.models
aqt.models.Models(self.mw, self._widget)
def choose_notetype(self) -> None:
from aqt.studydeck import StudyDeck
current = self.selected_notetype_name()
# edit button
edit = QPushButton(tr.qt_misc_manage())
qconnect(edit.clicked, self.onEdit)
def nameFunc() -> list[str]:
return sorted(self.mw.col.models.all_names())
ret = StudyDeck(
self.mw,
names=nameFunc,
accept=tr.actions_choose(),
title=tr.qt_misc_choose_note_type(),
help=HelpPage.NOTE_TYPE,
current=current,
parent=self._widget,
buttons=[edit],
cancel=True,
geomKey="selectModel",
)
if not ret.name:
return
notetype = self.mw.col.models.by_name(ret.name)
if (id := notetype["id"]) != self._selected_notetype_id:
self.selected_notetype_id = id
@property
def selected_notetype_id(self) -> NotetypeId:
# theoretically this should not be necessary, as we're listening to
# resets
self._ensure_selected_notetype_valid()
return self._selected_notetype_id
@selected_notetype_id.setter
def selected_notetype_id(self, id: NotetypeId) -> None:
if id != self._selected_notetype_id:
self._selected_notetype_id = id
self._ensure_selected_notetype_valid()
self._update_button_label()
if func := self.on_notetype_changed:
func(self._selected_notetype_id)
def selected_notetype_name(self) -> str:
return self.mw.col.models.get(self.selected_notetype_id)["name"]
def _ensure_selected_notetype_valid(self) -> None:
if not self.mw.col.models.get(self._selected_notetype_id):
self.selected_notetype_id = NotetypeId(
self.mw.col.models.all_names_and_ids()[0].id
)
def _update_button_label(self) -> None:
self.button.setText(self.selected_notetype_name().replace("&", "&&"))