commit
68ea2fce49
@ -24,6 +24,8 @@ browsing-change-to = Change { $val } to:
|
||||
browsing-clear-unused = Clear Unused
|
||||
browsing-clear-unused-tags = Clear Unused Tags
|
||||
browsing-created = Created
|
||||
browsing-create-filtered-deck = Create Filtered Deck...
|
||||
browsing-create-filtered-deck_2 = Create Filtered Deck (2nd Filter)...
|
||||
browsing-ctrlandshiftande = Ctrl+Shift+E
|
||||
browsing-current-deck = Current Deck
|
||||
browsing-current-note-type = Current note type:
|
||||
|
@ -35,3 +35,5 @@ search-card-modified = Card Modified
|
||||
|
||||
##
|
||||
|
||||
# Tooltip for search lines outside browser
|
||||
search-view-in-browser = View in browser
|
||||
|
@ -69,7 +69,7 @@ except ImportError as e:
|
||||
# - make preferences modal? cmd+q does wrong thing
|
||||
|
||||
|
||||
from aqt import addcards, addons, browser, editcurrent # isort:skip
|
||||
from aqt import addcards, addons, browser, editcurrent, dyndeckconf # isort:skip
|
||||
from aqt import stats, about, preferences, mediasync # isort:skip
|
||||
|
||||
|
||||
@ -80,6 +80,7 @@ class DialogManager:
|
||||
"AddonsDialog": [addons.AddonsDialog, None],
|
||||
"Browser": [browser.Browser, None],
|
||||
"EditCurrent": [editcurrent.EditCurrent, None],
|
||||
"DynDeckConfDialog": [dyndeckconf.DeckConf, None],
|
||||
"DeckStats": [stats.DeckStats, None],
|
||||
"NewDeckStats": [stats.NewDeckStats, None],
|
||||
"About": [about.show, None],
|
||||
@ -87,7 +88,7 @@ class DialogManager:
|
||||
"sync_log": [mediasync.MediaSyncDialog, None],
|
||||
}
|
||||
|
||||
def open(self, name: str, *args: Any) -> Any:
|
||||
def open(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
(creator, instance) = self._dialogs[name]
|
||||
if instance:
|
||||
if instance.windowState() & Qt.WindowMinimized:
|
||||
@ -95,12 +96,11 @@ class DialogManager:
|
||||
instance.activateWindow()
|
||||
instance.raise_()
|
||||
if hasattr(instance, "reopen"):
|
||||
instance.reopen(*args)
|
||||
return instance
|
||||
instance.reopen(*args, **kwargs)
|
||||
else:
|
||||
instance = creator(*args)
|
||||
instance = creator(*args, **kwargs)
|
||||
self._dialogs[name][1] = instance
|
||||
return instance
|
||||
return instance
|
||||
|
||||
def markClosed(self, name: str) -> None:
|
||||
self._dialogs[name] = [self._dialogs[name][0], None]
|
||||
|
@ -162,7 +162,7 @@ class AddCards(QDialog):
|
||||
m.exec_(self.historyButton.mapToGlobal(QPoint(0, 0)))
|
||||
|
||||
def editHistory(self, nid) -> None:
|
||||
self.mw.browser_search(SearchTerm(nid=nid))
|
||||
aqt.dialogs.open("Browser", self.mw, search=(SearchTerm(nid=nid),))
|
||||
|
||||
def addNote(self, note) -> Optional[Note]:
|
||||
note.model()["did"] = self.deckChooser.selectedId()
|
||||
|
@ -444,7 +444,12 @@ class Browser(QMainWindow):
|
||||
col: Collection
|
||||
editor: Optional[Editor]
|
||||
|
||||
def __init__(self, mw: AnkiQt) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
mw: AnkiQt,
|
||||
card: Optional[Card] = None,
|
||||
search: Optional[Tuple[Union[str, SearchTerm]]] = None,
|
||||
) -> None:
|
||||
QMainWindow.__init__(self, None, Qt.Window)
|
||||
self.mw = mw
|
||||
self.col = self.mw.col
|
||||
@ -468,7 +473,7 @@ class Browser(QMainWindow):
|
||||
self.setupEditor()
|
||||
self.updateFont()
|
||||
self.onUndoState(self.mw.form.actionUndo.isEnabled())
|
||||
self.setupSearch()
|
||||
self.setupSearch(card, search)
|
||||
gui_hooks.browser_will_show(self)
|
||||
self.show()
|
||||
|
||||
@ -483,6 +488,10 @@ class Browser(QMainWindow):
|
||||
qconnect(f.actionSelectNotes.triggered, self.selectNotes)
|
||||
if not isMac:
|
||||
f.actionClose.setVisible(False)
|
||||
qconnect(f.actionCreateFilteredDeck.triggered, self.createFilteredDeck)
|
||||
qconnect(f.actionCreateFilteredDeck2.triggered, self.createFilteredDeck2)
|
||||
if self.mw.col.schedVer() == 1:
|
||||
f.menuEdit.removeAction(f.actionCreateFilteredDeck2)
|
||||
# notes
|
||||
qconnect(f.actionAdd.triggered, self.mw.onAddCard)
|
||||
qconnect(f.actionAdd_Tags.triggered, lambda: self.addTags())
|
||||
@ -606,17 +615,41 @@ class Browser(QMainWindow):
|
||||
]
|
||||
self.columns.sort(key=itemgetter(1))
|
||||
|
||||
def reopen(
|
||||
self,
|
||||
_mw: AnkiQt,
|
||||
card: Optional[Card] = None,
|
||||
search: Optional[Tuple[Union[str, SearchTerm]]] = None,
|
||||
) -> None:
|
||||
if search is not None:
|
||||
self.search_for_terms(*search)
|
||||
self.form.searchEdit.setFocus()
|
||||
elif card:
|
||||
self.show_single_card(card)
|
||||
self.form.searchEdit.setFocus()
|
||||
|
||||
# Searching
|
||||
######################################################################
|
||||
|
||||
def setupSearch(self) -> None:
|
||||
def setupSearch(
|
||||
self,
|
||||
card: Optional[Card] = None,
|
||||
search: Optional[Tuple[Union[str, SearchTerm]]] = None,
|
||||
) -> None:
|
||||
qconnect(self.form.searchEdit.lineEdit().returnPressed, self.onSearchActivated)
|
||||
self.form.searchEdit.setCompleter(None)
|
||||
self.form.searchEdit.lineEdit().setPlaceholderText(
|
||||
tr(TR.BROWSING_SEARCH_BAR_HINT)
|
||||
)
|
||||
self.form.searchEdit.addItems(self.mw.pm.profile["searchHistory"])
|
||||
self.search_for(self.col.build_search_string(SearchTerm(deck="current")), "")
|
||||
if search is not None:
|
||||
self.search_for_terms(*search)
|
||||
elif card:
|
||||
self.show_single_card(card)
|
||||
else:
|
||||
self.search_for(
|
||||
self.col.build_search_string(SearchTerm(deck="current")), ""
|
||||
)
|
||||
self.form.searchEdit.setFocus()
|
||||
|
||||
# search triggered by user
|
||||
@ -675,15 +708,17 @@ class Browser(QMainWindow):
|
||||
)
|
||||
return selected
|
||||
|
||||
def show_single_card(self, card: Optional[Card]) -> None:
|
||||
"""Try to search for the according note and select the given card."""
|
||||
def search_for_terms(self, *search_terms: Union[str, SearchTerm]) -> None:
|
||||
search = self.col.build_search_string(*search_terms)
|
||||
self.form.searchEdit.setEditText(search)
|
||||
self.onSearchActivated()
|
||||
|
||||
nid: Optional[int] = card and card.nid or 0
|
||||
if nid:
|
||||
def show_single_card(self, card: Card) -> None:
|
||||
if card.nid:
|
||||
|
||||
def on_show_single_card() -> None:
|
||||
self.card = card
|
||||
search = self.col.build_search_string(SearchTerm(nid=nid))
|
||||
search = self.col.build_search_string(SearchTerm(nid=card.nid))
|
||||
search = gui_hooks.default_search(search, card)
|
||||
self.search_for(search, "")
|
||||
self.focusCid(card.id)
|
||||
@ -1162,6 +1197,14 @@ where id in %s"""
|
||||
if nids:
|
||||
ChangeModel(self, nids)
|
||||
|
||||
def createFilteredDeck(self) -> None:
|
||||
search = self.form.searchEdit.lineEdit().text()
|
||||
aqt.dialogs.open("DynDeckConfDialog", self.mw, search=search)
|
||||
|
||||
def createFilteredDeck2(self) -> None:
|
||||
search = self.form.searchEdit.lineEdit().text()
|
||||
aqt.dialogs.open("DynDeckConfDialog", self.mw, search_2=search)
|
||||
|
||||
# Preview
|
||||
######################################################################
|
||||
|
||||
|
@ -1,14 +1,16 @@
|
||||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# -*- coding: utf-8 -*-
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Callable, List, Optional
|
||||
|
||||
import aqt
|
||||
from anki.collection import SearchTerm
|
||||
from anki.decks import Deck, DeckRenameError
|
||||
from anki.errors import InvalidInput
|
||||
from anki.lang import without_unicode_isolation
|
||||
from aqt.main import AnkiQt
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.qt import *
|
||||
from aqt.theme import theme_manager
|
||||
from aqt.utils import (
|
||||
TR,
|
||||
HelpPage,
|
||||
@ -24,25 +26,55 @@ from aqt.utils import (
|
||||
|
||||
|
||||
class DeckConf(QDialog):
|
||||
"""Dialogue to modify and build a filtered deck."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mw: AnkiQt,
|
||||
first: bool = False,
|
||||
search: str = "",
|
||||
deck: Optional[Dict] = None,
|
||||
search: Optional[str] = None,
|
||||
search_2: Optional[str] = None,
|
||||
deck: Optional[Deck] = None,
|
||||
) -> None:
|
||||
"""If 'deck' is an existing filtered deck, load and modify its settings.
|
||||
Otherwise, build a new one and derive settings from the current deck.
|
||||
"""
|
||||
|
||||
QDialog.__init__(self, mw)
|
||||
self.mw = mw
|
||||
self.deck = deck or self.mw.col.decks.current()
|
||||
self.search = search
|
||||
self.did: Optional[int] = None
|
||||
self.form = aqt.forms.dyndconf.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
if first:
|
||||
label = tr(TR.DECKS_BUILD)
|
||||
else:
|
||||
label = tr(TR.ACTIONS_REBUILD)
|
||||
self.ok = self.form.buttonBox.addButton(label, QDialogButtonBox.AcceptRole)
|
||||
self.mw.checkpoint(tr(TR.ACTIONS_OPTIONS))
|
||||
self.initialSetup()
|
||||
self.old_deck = self.mw.col.decks.current()
|
||||
|
||||
if deck and deck["dyn"]:
|
||||
# modify existing dyn deck
|
||||
label = tr(TR.ACTIONS_REBUILD)
|
||||
self.deck = deck
|
||||
self.loadConf()
|
||||
elif self.old_deck["dyn"]:
|
||||
# create new dyn deck from other dyn deck
|
||||
label = tr(TR.DECKS_BUILD)
|
||||
self.loadConf(deck=self.old_deck)
|
||||
self.new_dyn_deck()
|
||||
else:
|
||||
# create new dyn deck from regular deck
|
||||
label = tr(TR.DECKS_BUILD)
|
||||
self.new_dyn_deck()
|
||||
self.loadConf()
|
||||
self.set_default_searches(self.old_deck["name"])
|
||||
|
||||
self.form.name.setText(self.deck["name"])
|
||||
self.form.name.setPlaceholderText(self.deck["name"])
|
||||
self.set_custom_searches(search, search_2)
|
||||
qconnect(self.form.search_button.clicked, self.on_search_button)
|
||||
qconnect(self.form.search_button_2.clicked, self.on_search_button_2)
|
||||
color = theme_manager.str_color("link")
|
||||
self.setStyleSheet(
|
||||
f"""QPushButton[flat=true] {{ text-align: left; color: {color}; padding: 0; border: 0 }}
|
||||
QPushButton[flat=true]:hover {{ text-decoration: underline }}"""
|
||||
)
|
||||
disable_help_button(self)
|
||||
self.setWindowModality(Qt.WindowModal)
|
||||
qconnect(
|
||||
@ -51,26 +83,63 @@ class DeckConf(QDialog):
|
||||
self.setWindowTitle(
|
||||
without_unicode_isolation(tr(TR.ACTIONS_OPTIONS_FOR, val=self.deck["name"]))
|
||||
)
|
||||
restoreGeom(self, "dyndeckconf")
|
||||
self.initialSetup()
|
||||
self.loadConf()
|
||||
if search:
|
||||
search = self.mw.col.build_search_string(
|
||||
search, SearchTerm(card_state=SearchTerm.CARD_STATE_DUE)
|
||||
)
|
||||
self.form.search.setText(search)
|
||||
search_2 = self.mw.col.build_search_string(
|
||||
search, SearchTerm(card_state=SearchTerm.CARD_STATE_NEW)
|
||||
)
|
||||
self.form.search_2.setText(search_2)
|
||||
self.form.search.selectAll()
|
||||
|
||||
self.form.buttonBox.button(QDialogButtonBox.Ok).setText(label)
|
||||
self.form.buttonBox.button(QDialogButtonBox.Cancel).setText(
|
||||
tr(TR.ACTIONS_CANCEL)
|
||||
)
|
||||
self.form.buttonBox.button(QDialogButtonBox.Help).setText(tr(TR.ACTIONS_HELP))
|
||||
if self.mw.col.schedVer() == 1:
|
||||
self.form.secondFilter.setVisible(False)
|
||||
restoreGeom(self, "dyndeckconf")
|
||||
|
||||
self.show()
|
||||
self.exec_()
|
||||
saveGeom(self, "dyndeckconf")
|
||||
|
||||
def reopen(
|
||||
self,
|
||||
_mw: AnkiQt,
|
||||
search: Optional[str] = None,
|
||||
search_2: Optional[str] = None,
|
||||
_deck: Optional[Deck] = None,
|
||||
) -> None:
|
||||
self.set_custom_searches(search, search_2)
|
||||
|
||||
def new_dyn_deck(self) -> None:
|
||||
suffix: int = 1
|
||||
while self.mw.col.decks.id_for_name(
|
||||
without_unicode_isolation(tr(TR.QT_MISC_FILTERED_DECK, val=suffix))
|
||||
):
|
||||
suffix += 1
|
||||
name: str = without_unicode_isolation(tr(TR.QT_MISC_FILTERED_DECK, val=suffix))
|
||||
self.did = self.mw.col.decks.new_filtered(name)
|
||||
self.deck = self.mw.col.decks.current()
|
||||
|
||||
def set_default_searches(self, deck_name: str) -> None:
|
||||
self.form.search.setText(
|
||||
self.mw.col.build_search_string(
|
||||
SearchTerm(deck=deck_name),
|
||||
SearchTerm(card_state=SearchTerm.CARD_STATE_DUE),
|
||||
)
|
||||
)
|
||||
self.form.search_2.setText(
|
||||
self.mw.col.build_search_string(
|
||||
SearchTerm(deck=deck_name),
|
||||
SearchTerm(card_state=SearchTerm.CARD_STATE_NEW),
|
||||
)
|
||||
)
|
||||
|
||||
def set_custom_searches(
|
||||
self, search: Optional[str], search_2: Optional[str]
|
||||
) -> None:
|
||||
if search is not None:
|
||||
self.form.search.setText(search)
|
||||
self.form.search.setFocus()
|
||||
self.form.search.selectAll()
|
||||
if search_2 is not None:
|
||||
self.form.secondFilter.setChecked(True)
|
||||
self.form.filter2group.setVisible(True)
|
||||
self.form.search_2.setText(search_2)
|
||||
self.form.search_2.setFocus()
|
||||
self.form.search_2.selectAll()
|
||||
|
||||
def initialSetup(self) -> None:
|
||||
import anki.consts as cs
|
||||
@ -80,14 +149,30 @@ class DeckConf(QDialog):
|
||||
|
||||
qconnect(self.form.resched.stateChanged, self._onReschedToggled)
|
||||
|
||||
def on_search_button(self) -> None:
|
||||
self._on_search_button(self.form.search)
|
||||
|
||||
def on_search_button_2(self) -> None:
|
||||
self._on_search_button(self.form.search_2)
|
||||
|
||||
def _on_search_button(self, line: QLineEdit) -> None:
|
||||
try:
|
||||
search = self.mw.col.build_search_string(line.text())
|
||||
except InvalidInput as err:
|
||||
line.setFocus()
|
||||
line.selectAll()
|
||||
show_invalid_search_error(err)
|
||||
else:
|
||||
aqt.dialogs.open("Browser", self.mw, search=(search,))
|
||||
|
||||
def _onReschedToggled(self, _state: int) -> None:
|
||||
self.form.previewDelayWidget.setVisible(
|
||||
not self.form.resched.isChecked() and self.mw.col.schedVer() > 1
|
||||
)
|
||||
|
||||
def loadConf(self) -> None:
|
||||
def loadConf(self, deck: Optional[Deck] = None) -> None:
|
||||
f = self.form
|
||||
d = self.deck
|
||||
d = deck or self.deck
|
||||
|
||||
f.resched.setChecked(d["resched"])
|
||||
self._onReschedToggled(0)
|
||||
@ -123,6 +208,11 @@ class DeckConf(QDialog):
|
||||
def saveConf(self) -> None:
|
||||
f = self.form
|
||||
d = self.deck
|
||||
|
||||
if f.name.text() and d["name"] != f.name.text():
|
||||
self.mw.col.decks.rename(d, f.name.text())
|
||||
gui_hooks.sidebar_should_refresh_decks()
|
||||
|
||||
d["resched"] = f.resched.isChecked()
|
||||
d["delays"] = None
|
||||
|
||||
@ -146,29 +236,45 @@ class DeckConf(QDialog):
|
||||
self.mw.col.decks.save(d)
|
||||
|
||||
def reject(self) -> None:
|
||||
self.ok = False
|
||||
if self.did:
|
||||
self.mw.col.decks.rem(self.did)
|
||||
self.mw.col.decks.select(self.old_deck["id"])
|
||||
saveGeom(self, "dyndeckconf")
|
||||
QDialog.reject(self)
|
||||
aqt.dialogs.markClosed("DynDeckConfDialog")
|
||||
|
||||
def accept(self) -> None:
|
||||
try:
|
||||
self.saveConf()
|
||||
except InvalidInput as err:
|
||||
show_invalid_search_error(err)
|
||||
return
|
||||
if not self.mw.col.sched.rebuild_filtered_deck(self.deck["id"]):
|
||||
if askUser(tr(TR.DECKS_THE_PROVIDED_SEARCH_DID_NOT_MATCH)):
|
||||
return
|
||||
self.mw.reset()
|
||||
QDialog.accept(self)
|
||||
except DeckRenameError as err:
|
||||
showWarning(err.description)
|
||||
else:
|
||||
if not self.mw.col.sched.rebuild_filtered_deck(self.deck["id"]):
|
||||
if askUser(tr(TR.DECKS_THE_PROVIDED_SEARCH_DID_NOT_MATCH)):
|
||||
return
|
||||
saveGeom(self, "dyndeckconf")
|
||||
self.mw.reset()
|
||||
QDialog.accept(self)
|
||||
aqt.dialogs.markClosed("DynDeckConfDialog")
|
||||
|
||||
def closeWithCallback(self, callback: Callable) -> None:
|
||||
self.reject()
|
||||
callback()
|
||||
|
||||
# Step load/save - fixme: share with std options screen
|
||||
########################################################
|
||||
|
||||
def listToUser(self, l) -> str:
|
||||
return " ".join([str(x) for x in l])
|
||||
def listToUser(self, values: List[Union[float, int]]) -> str:
|
||||
return " ".join(
|
||||
[str(int(val)) if int(val) == val else str(val) for val in values]
|
||||
)
|
||||
|
||||
def userToList(self, w, minSize=1) -> Optional[List[Union[float, int]]]:
|
||||
items = str(w.text()).split(" ")
|
||||
def userToList(
|
||||
self, line: QLineEdit, minSize: int = 1
|
||||
) -> Optional[List[Union[float, int]]]:
|
||||
items = str(line.text()).split(" ")
|
||||
ret = []
|
||||
for item in items:
|
||||
if not item:
|
||||
|
@ -542,12 +542,17 @@ class Editor:
|
||||
self.web.eval("setBackgrounds(%s);" % json.dumps(cols))
|
||||
|
||||
def showDupes(self) -> None:
|
||||
self.mw.browser_search(
|
||||
SearchTerm(
|
||||
dupe=SearchTerm.Dupe(
|
||||
notetype_id=self.note.model()["id"], first_field=self.note.fields[0]
|
||||
)
|
||||
)
|
||||
aqt.dialogs.open(
|
||||
"Browser",
|
||||
self.mw,
|
||||
search=(
|
||||
SearchTerm(
|
||||
dupe=SearchTerm.Dupe(
|
||||
notetype_id=self.note.model()["id"],
|
||||
first_field=self.note.fields[0],
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
def fieldsAreBlank(self, previousNote: Optional[Note] = None) -> bool:
|
||||
|
@ -66,7 +66,7 @@ class EmptyCardsDialog(QDialog):
|
||||
self._delete_button.clicked.connect(self._on_delete)
|
||||
|
||||
def _on_note_link_clicked(self, link) -> None:
|
||||
self.mw.browser_search(link)
|
||||
aqt.dialogs.open("Browser", self.mw, search=(link,))
|
||||
|
||||
def _on_delete(self) -> None:
|
||||
self.mw.progress.start()
|
||||
|
@ -230,6 +230,9 @@
|
||||
<addaction name="actionInvertSelection"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionClose"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCreateFilteredDeck"/>
|
||||
<addaction name="actionCreateFilteredDeck2"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuJump">
|
||||
<property name="title">
|
||||
@ -583,6 +586,22 @@
|
||||
<string notr="true">Ctrl+Shift+E</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCreateFilteredDeck">
|
||||
<property name="text">
|
||||
<string>BROWSING_CREATE_FILTERED_DECK</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string notr="true">Ctrl+G</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCreateFilteredDeck2">
|
||||
<property name="text">
|
||||
<string>BROWSING_CREATE_FILTERED_DECK_2</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string notr="true">Ctrl+Shift+G</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
|
@ -6,14 +6,56 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>392</width>
|
||||
<height>472</height>
|
||||
<width>757</width>
|
||||
<height>589</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>DECKS_DECK</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>ACTIONS_NAME</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="name">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
@ -21,20 +63,28 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>DECKS_LIMIT_TO</string>
|
||||
<widget class="QPushButton" name="search_button">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>SEARCH_VIEW_IN_BROWSER</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>ACTIONS_SEARCH</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="search"/>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QSpinBox" name="limit">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
@ -50,18 +100,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="2" column="4" colspan="2">
|
||||
<widget class="QComboBox" name="order"/>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>DECKS_CARDS_SELECTED_BY</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QLineEdit" name="search"/>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QComboBox" name="order"/>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>DECKS_LIMIT_TO</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -72,23 +126,32 @@
|
||||
<string>DECKS_FILTER_2</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="search_button_2">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>SEARCH_VIEW_IN_BROWSER</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>DECKS_LIMIT_TO</string>
|
||||
<string>ACTIONS_SEARCH</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QComboBox" name="order_2"/>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QLineEdit" name="search_2"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>ACTIONS_SEARCH</string>
|
||||
<string>DECKS_LIMIT_TO</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -108,6 +171,9 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QComboBox" name="order_2"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
@ -203,16 +269,19 @@
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help</set>
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>name</tabstop>
|
||||
<tabstop>search_button</tabstop>
|
||||
<tabstop>search</tabstop>
|
||||
<tabstop>limit</tabstop>
|
||||
<tabstop>order</tabstop>
|
||||
<tabstop>search_button_2</tabstop>
|
||||
<tabstop>search_2</tabstop>
|
||||
<tabstop>limit_2</tabstop>
|
||||
<tabstop>order_2</tabstop>
|
||||
|
@ -14,7 +14,7 @@ import weakref
|
||||
import zipfile
|
||||
from argparse import Namespace
|
||||
from threading import Thread
|
||||
from typing import Any, Callable, List, Optional, Sequence, TextIO, Tuple, Union, cast
|
||||
from typing import Any, Callable, List, Optional, Sequence, TextIO, Tuple, cast
|
||||
|
||||
import anki
|
||||
import aqt
|
||||
@ -27,10 +27,9 @@ import aqt.toolbar
|
||||
import aqt.webview
|
||||
from anki import hooks
|
||||
from anki._backend import RustBackend as _RustBackend
|
||||
from anki.collection import Collection, SearchTerm
|
||||
from anki.collection import Collection
|
||||
from anki.decks import Deck
|
||||
from anki.hooks import runHook
|
||||
from anki.lang import without_unicode_isolation
|
||||
from anki.sound import AVTag, SoundOrVideoTag
|
||||
from anki.utils import devMode, ids2str, intTime, isMac, isWin, splitFields
|
||||
from aqt import gui_hooks
|
||||
@ -1055,22 +1054,19 @@ title="%s" %s>%s</button>""" % (
|
||||
aqt.dialogs.open("AddCards", self)
|
||||
|
||||
def onBrowse(self) -> None:
|
||||
browser = aqt.dialogs.open("Browser", self)
|
||||
browser.show_single_card(self.reviewer.card)
|
||||
aqt.dialogs.open("Browser", self, card=self.reviewer.card)
|
||||
|
||||
def onEditCurrent(self) -> None:
|
||||
aqt.dialogs.open("EditCurrent", self)
|
||||
|
||||
def onDeckConf(self, deck=None) -> None:
|
||||
def onDeckConf(self, deck: Optional[Deck] = None) -> None:
|
||||
import aqt.deckconf
|
||||
|
||||
if not deck:
|
||||
deck = self.col.decks.current()
|
||||
if deck["dyn"]:
|
||||
import aqt.dyndeckconf
|
||||
|
||||
aqt.dyndeckconf.DeckConf(self, deck=deck)
|
||||
aqt.dialogs.open("DynDeckConfDialog", self, deck=deck)
|
||||
else:
|
||||
import aqt.deckconf
|
||||
|
||||
aqt.deckconf.DeckConf(self, deck)
|
||||
|
||||
def onOverview(self) -> None:
|
||||
@ -1145,25 +1141,8 @@ title="%s" %s>%s</button>""" % (
|
||||
# Cramming
|
||||
##########################################################################
|
||||
|
||||
def onCram(self, search: str = "") -> None:
|
||||
import aqt.dyndeckconf
|
||||
|
||||
n = 1
|
||||
deck = self.col.decks.current()
|
||||
if not search:
|
||||
if not deck["dyn"]:
|
||||
search = self.col.build_search_string(SearchTerm(deck=deck["name"]))
|
||||
while self.col.decks.id_for_name(
|
||||
without_unicode_isolation(tr(TR.QT_MISC_FILTERED_DECK, val=n))
|
||||
):
|
||||
n += 1
|
||||
name = without_unicode_isolation(tr(TR.QT_MISC_FILTERED_DECK, val=n))
|
||||
did = self.col.decks.new_filtered(name)
|
||||
diag = aqt.dyndeckconf.DeckConf(self, first=True, search=search)
|
||||
if not diag.ok:
|
||||
# user cancelled first config
|
||||
self.col.decks.rem(did)
|
||||
self.col.decks.select(deck["id"])
|
||||
def onCram(self) -> None:
|
||||
aqt.dialogs.open("DynDeckConfDialog", self)
|
||||
|
||||
# Menu, title bar & status
|
||||
##########################################################################
|
||||
@ -1630,14 +1609,3 @@ title="%s" %s>%s</button>""" % (
|
||||
|
||||
def serverURL(self) -> str:
|
||||
return "http://127.0.0.1:%d/" % self.mediaServer.getPort()
|
||||
|
||||
# Helpers for all windows
|
||||
##########################################################################
|
||||
|
||||
def browser_search(self, *terms: Union[str, SearchTerm]) -> None:
|
||||
"""Wrapper for col.build_search_string() to look up the result in the browser."""
|
||||
|
||||
search = self.col.build_search_string(*terms)
|
||||
browser = aqt.dialogs.open("Browser", self)
|
||||
browser.form.searchEdit.lineEdit().setText(search)
|
||||
browser.onSearchActivated()
|
||||
|
@ -148,7 +148,7 @@ class MediaChecker:
|
||||
|
||||
if out is not None:
|
||||
nid, err = out
|
||||
self.mw.browser_search(SearchTerm(nid=nid))
|
||||
aqt.dialogs.open("Browser", self.mw, search=(SearchTerm(nid=nid),))
|
||||
showText(err, type="html")
|
||||
else:
|
||||
tooltip(tr(TR.MEDIA_CHECK_ALL_LATEX_RENDERED))
|
||||
|
@ -7,7 +7,6 @@ from dataclasses import dataclass
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||
|
||||
import aqt
|
||||
from anki.collection import SearchTerm
|
||||
from aqt import gui_hooks
|
||||
from aqt.sound import av_player
|
||||
from aqt.toolbar import BottomBar
|
||||
@ -72,8 +71,7 @@ class Overview:
|
||||
elif url == "opts":
|
||||
self.mw.onDeckConf()
|
||||
elif url == "cram":
|
||||
deck = self.mw.col.decks.current()["name"]
|
||||
self.mw.onCram(self.mw.col.build_search_string(SearchTerm(deck=deck)))
|
||||
aqt.dialogs.open("DynDeckConfDialog", self.mw)
|
||||
elif url == "refresh":
|
||||
self.mw.col.sched.rebuild_filtered_deck(self.mw.col.decks.selected())
|
||||
self.mw.reset()
|
||||
|
Loading…
Reference in New Issue
Block a user