-
Notifications
You must be signed in to change notification settings - Fork 1
/
gui.py
199 lines (165 loc) · 6.93 KB
/
gui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# Copyright: Ren Tatsumoto <tatsu at autistici.org>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from aqt import mw
from aqt.qt import *
from aqt.utils import saveGeom, restoreGeom
from .ajt_common.about_menu import menu_root_entry, tweak_window
from .ajt_common.addon_config import set_config_action
from .config import config
from .consts import *
from .enums import Color, Action
def key_to_label(key: str) -> str:
return key.replace('_', ' ').capitalize()
def make_checkboxes() -> dict[str, QCheckBox]:
checkboxes = {}
for key, val in config.toggleables():
label = key_to_label(key)
checkboxes[key] = QCheckBox(label)
checkboxes[key].setChecked(config[key])
return checkboxes
def make_flag_edit_widget() -> QComboBox:
flag_edit = QComboBox()
flag_edit.addItems(Color.names())
flag_edit.setCurrentText(config['flag'])
return flag_edit
def make_action_edit_widget() -> QComboBox:
action_edit = QComboBox()
action_edit.addItems(Action.names())
action_edit.setCurrentText(config['action'])
return action_edit
def make_tag_edit_widget() -> QLineEdit:
widget = QLineEdit(config['tag'])
widget.currentText = widget.text
return widget
def make_limits_widgets() -> dict[str, QSpinBox]:
widgets = {}
for key in INTEGER_OPTIONS.keys():
widgets[key] = QSpinBox()
widgets[key].setRange(1, 150)
widgets[key].setValue(int(config[key]))
return widgets
class SettingsDialog(QDialog):
name = "ajt__mortician_settings_dialog"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowTitle(OPTS_WINDOW_TITLE)
self.setMinimumSize(320, 240)
self._checkboxes = make_checkboxes()
self._edits: dict[str, QComboBox] = {
'action': make_action_edit_widget(),
'tag': make_tag_edit_widget(),
'flag': make_flag_edit_widget(),
}
self._limits = make_limits_widgets()
self._bottom_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
self.setLayout(self.setup_layout())
self.connect_buttons()
self.add_tooltips()
tweak_window(self)
restoreGeom(self, self.name)
def setup_layout(self) -> QLayout:
layout = QVBoxLayout(self)
layout.addLayout(self.make_edits_layout())
layout.addLayout(self.make_checkboxes_layout())
layout.addLayout(self.make_limits_layout())
layout.addWidget(self._bottom_box)
return layout
def make_checkboxes_layout(self) -> QLayout:
layout = QVBoxLayout()
for widget in self._checkboxes.values():
layout.addWidget(widget)
return layout
def make_edits_layout(self) -> QLayout:
layout = QFormLayout()
for label, widget in self._edits.items():
layout.addRow(label.capitalize(), widget)
return layout
def make_limits_layout(self) -> QLayout:
layout = QGridLayout()
lines = zip(
(QLabel(key_to_label(key)) for key in self._limits.keys()),
self._limits.values(),
(QLabel(unit) for unit in INTEGER_OPTIONS.values()),
)
for y, line in enumerate(lines):
for x, widget in enumerate(line):
layout.addWidget(widget, y, x)
return layout
def connect_buttons(self):
qconnect(self._bottom_box.accepted, self.accept)
qconnect(self._bottom_box.rejected, self.reject)
def accept(self):
for key, widget in self._checkboxes.items():
config[key] = widget.isChecked()
for key, widget in self._limits.items():
config[key] = int(widget.value())
for key, widget in self._edits.items():
config[key] = widget.currentText()
config.write_config()
return super().accept()
def add_tooltips(self):
self._limits['again_threshold'].setToolTip(
"How many times a card should be failed until it gets buried.\n"
"This setting applies to cards in the relearning queue,\n"
"i.e. the cards that graduated at least once before."
)
self._limits['new_again_threshold'].setToolTip(
"How many times a card should be failed until it gets buried.\n"
"This setting applies to new cards."
)
self._limits['timeframe'].setToolTip(
"From how many hours ago count the answers.\n"
"Has no effect if \"count from daystart\" is enabled."
)
self._limits['tooltip_duration'].setToolTip(
"How long tooltips should stay visible."
)
self._checkboxes['count_from_daystart'].setToolTip(
"Ignore the \"timeframe\" setting,\n"
"always count failed cards from the start of an Anki day.\n"
"Usually an Anki day starts at 4AM in the morning\n"
"but can be configured in Preferences."
)
self._checkboxes['again_notify'].setToolTip(
"Show card stats after every failed review.\n"
"This is a very annoying feature intended for debugging."
)
self._checkboxes['disable_tooltips'].setToolTip(
"No matter what never show tooltips."
)
self._checkboxes['ignore_new_cards'].setToolTip(
"Don't do anything to cards in the learning queue.\n"
"If enabled, the add-on is going to act only on cards that have graduated before."
)
self._checkboxes['show_bury_browser_action'].setToolTip(
"Add a button to the Anki Browser's context menu\n"
"that lets you manually bury selected cards."
)
self._edits['tag'].setToolTip(
"This tag is attached to cards when they get buried by Mortician.\n"
"You can use the tag to find the cards in the Anki Browser later."
)
self._edits['flag'].setToolTip(
"Similar to \"tag\" but adds a flag to the difficult cards.\n"
"You can filter cards by flag in the Anki Browser."
)
self._edits['action'].setToolTip(
"The main action Mortician performs on difficult cards.\n"
"You can either bury such cards, suspend them or do nothing.\n"
"If you choose \"No\", you can still tag or flag difficult cards\n"
"while keeping them in the learning queue."
)
def done(self, *args, **kwargs) -> None:
saveGeom(self, self.name)
return super().done(*args, **kwargs)
def on_open_settings():
dialog = SettingsDialog(mw)
dialog.exec()
def setup_settings_action(parent: QWidget) -> QAction:
action_settings = QAction(OPTS_WINDOW_TITLE + '...', parent)
qconnect(action_settings.triggered, on_open_settings)
return action_settings
def init():
root_menu = menu_root_entry()
root_menu.addAction(setup_settings_action(root_menu))
set_config_action(on_open_settings)