mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Improve debug console (#2435)
* List actions and locals in debug console * Ignore whitespace when wrapping line with pp * Scroll down after printing in debug console Was previously preserving relative vertical position. * Add feature to open and save debug scripts * Refactor debug console into own module * Add buffers to switch scripts * Add action to delete script
This commit is contained in:
parent
5afbf8934f
commit
b55161cd39
4 changed files with 357 additions and 179 deletions
322
qt/aqt/debug_console.py
Normal file
322
qt/aqt/debug_console.py
Normal file
|
@ -0,0 +1,322 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from typing import TextIO, cast
|
||||
|
||||
import anki.cards
|
||||
import aqt
|
||||
import aqt.forms
|
||||
from aqt import gui_hooks
|
||||
from aqt.profiles import ProfileManager
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
disable_help_button,
|
||||
restoreGeom,
|
||||
restoreSplitter,
|
||||
saveGeom,
|
||||
saveSplitter,
|
||||
send_to_trash,
|
||||
tr,
|
||||
)
|
||||
|
||||
|
||||
def show_debug_console() -> None:
|
||||
assert aqt.mw
|
||||
console = DebugConsole(aqt.mw)
|
||||
gui_hooks.debug_console_will_show(console)
|
||||
console.show()
|
||||
|
||||
|
||||
SCRIPT_FOLDER = "debug_scripts"
|
||||
UNSAVED_SCRIPT = "Unsaved script"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Action:
|
||||
name: str
|
||||
shortcut: str
|
||||
action: Callable[[], None]
|
||||
|
||||
|
||||
class DebugConsole(QDialog):
|
||||
silentlyClose = True
|
||||
_last_index = 0
|
||||
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
self._buffers: dict[int, str] = {}
|
||||
super().__init__(parent)
|
||||
self._setup_ui()
|
||||
disable_help_button(self)
|
||||
restoreGeom(self, "DebugConsoleWindow")
|
||||
restoreSplitter(self.frm.splitter, "DebugConsoleWindow")
|
||||
|
||||
def _setup_ui(self):
|
||||
self.frm = aqt.forms.debug.Ui_Dialog()
|
||||
self.frm.setupUi(self)
|
||||
self._text: QPlainTextEdit = self.frm.text
|
||||
self._log: QPlainTextEdit = self.frm.log
|
||||
self._script: QComboBox = self.frm.script
|
||||
self._setup_text_edits()
|
||||
self._setup_scripts()
|
||||
self._setup_actions()
|
||||
self._setup_context_menu()
|
||||
qconnect(self.frm.widgetsButton.clicked, self._on_widgetGallery)
|
||||
qconnect(self._script.currentIndexChanged, self._on_script_change)
|
||||
|
||||
def _setup_text_edits(self):
|
||||
font = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont)
|
||||
font.setPointSize(self._text.font().pointSize() + 1)
|
||||
self._text.setFont(font)
|
||||
self._log.setFont(font)
|
||||
|
||||
def _setup_scripts(self) -> None:
|
||||
self._dir = ProfileManager.get_created_base_folder(None).joinpath(SCRIPT_FOLDER)
|
||||
self._dir.mkdir(exist_ok=True)
|
||||
self._script.addItem(UNSAVED_SCRIPT)
|
||||
self._script.addItems(os.listdir(self._dir))
|
||||
|
||||
def _setup_actions(self) -> None:
|
||||
for action in self._actions():
|
||||
qconnect(
|
||||
QShortcut(QKeySequence(action.shortcut), self).activated, action.action
|
||||
)
|
||||
|
||||
def _actions(self):
|
||||
return [
|
||||
Action("Execute", "ctrl+return", self.onDebugRet),
|
||||
Action("Execute and print", "ctrl+shift+return", self.onDebugPrint),
|
||||
Action("Clear log", "ctrl+l", self._log.clear),
|
||||
Action("Clear code", "ctrl+shift+l", self._text.clear),
|
||||
Action("Save script", "ctrl+s", self._save_script),
|
||||
Action("Open script", "ctrl+o", self._open_script),
|
||||
Action("Delete script", "ctrl+d", self._delete_script),
|
||||
]
|
||||
|
||||
def reject(self) -> None:
|
||||
super().reject()
|
||||
saveSplitter(self.frm.splitter, "DebugConsoleWindow")
|
||||
saveGeom(self, "DebugConsoleWindow")
|
||||
|
||||
def _on_script_change(self, new_index: int) -> None:
|
||||
self._buffers[self._last_index] = self._text.toPlainText()
|
||||
self._text.setPlainText(self._get_script(new_index) or "")
|
||||
self._last_index = new_index
|
||||
|
||||
def _get_script(self, idx: int) -> str | None:
|
||||
if script := self._buffers.get(idx, ""):
|
||||
return script
|
||||
if path := self._get_item(idx):
|
||||
return path.read_text(encoding="utf8")
|
||||
return None
|
||||
|
||||
def _get_item(self, idx: int) -> Path | None:
|
||||
if not idx:
|
||||
return None
|
||||
path = Path(self._script.itemText(idx))
|
||||
return path if path.is_absolute() else self._dir.joinpath(path)
|
||||
|
||||
def _get_index(self, path: Path) -> int:
|
||||
return self._script.findText(self._path_to_item(path))
|
||||
|
||||
def _path_to_item(self, path: Path) -> str:
|
||||
return path.name if path.is_relative_to(self._dir) else str(path)
|
||||
|
||||
def _current_script_path(self) -> Path | None:
|
||||
return self._get_item(self._script.currentIndex())
|
||||
|
||||
def _save_script(self) -> None:
|
||||
if not (path := self._current_script_path()):
|
||||
new_file = QFileDialog.getSaveFileName(
|
||||
self, directory=str(self._dir), filter="Python file (*.py)"
|
||||
)[0]
|
||||
if not new_file:
|
||||
return
|
||||
path = Path(new_file)
|
||||
|
||||
path.write_text(self._text.toPlainText(), encoding="utf8")
|
||||
|
||||
item = self._path_to_item(path)
|
||||
if (idx := self._get_index(path)) == -1:
|
||||
self._script.addItem(item)
|
||||
idx = self._script.count() - 1
|
||||
# update existing buffer, so text edit doesn't change when index changes
|
||||
self._buffers[idx] = self._text.toPlainText()
|
||||
self._script.setCurrentIndex(idx)
|
||||
|
||||
def _open_script(self) -> None:
|
||||
file = QFileDialog.getOpenFileName(
|
||||
self, directory=str(self._dir), filter="Python file (*.py)"
|
||||
)[0]
|
||||
if not file:
|
||||
return
|
||||
|
||||
path = Path(file)
|
||||
item = self._path_to_item(path)
|
||||
if (idx := self._get_index(path)) == -1:
|
||||
self._script.addItem(item)
|
||||
idx = self._script.count() - 1
|
||||
elif idx in self._buffers:
|
||||
del self._buffers[idx]
|
||||
|
||||
if idx == self._script.currentIndex():
|
||||
self._text.setPlainText(path.read_text(encoding="utf8"))
|
||||
else:
|
||||
self._script.setCurrentIndex(idx)
|
||||
|
||||
def _delete_script(self) -> None:
|
||||
if not (path := self._current_script_path()):
|
||||
return
|
||||
send_to_trash(path)
|
||||
deleted_idx = self._script.currentIndex()
|
||||
self._script.setCurrentIndex(0)
|
||||
self._script.removeItem(deleted_idx)
|
||||
self._drop_buffer_and_shift_keys(deleted_idx)
|
||||
|
||||
def _drop_buffer_and_shift_keys(self, idx: int) -> None:
|
||||
def shift(old_idx: int) -> int:
|
||||
return old_idx - 1 if old_idx > idx else old_idx
|
||||
|
||||
self._buffers = {shift(i): val for i, val in self._buffers.items() if i != idx}
|
||||
|
||||
def _setup_context_menu(self) -> None:
|
||||
for text_edit in (self._log, self._text):
|
||||
text_edit.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||||
qconnect(
|
||||
text_edit.customContextMenuRequested,
|
||||
partial(self._on_context_menu, text_edit),
|
||||
)
|
||||
|
||||
def _on_context_menu(self, text_edit: QPlainTextEdit) -> None:
|
||||
menu = text_edit.createStandardContextMenu()
|
||||
menu.addSeparator()
|
||||
for action in self._actions():
|
||||
entry = menu.addAction(action.name)
|
||||
entry.setShortcut(QKeySequence(action.shortcut))
|
||||
qconnect(entry.triggered, action.action)
|
||||
menu.exec(QCursor.pos())
|
||||
|
||||
def _on_widgetGallery(self) -> None:
|
||||
from aqt.widgetgallery import WidgetGallery
|
||||
|
||||
self.widgetGallery = WidgetGallery(self)
|
||||
self.widgetGallery.show()
|
||||
|
||||
def _captureOutput(self, on: bool) -> None:
|
||||
mw2 = self
|
||||
|
||||
class Stream:
|
||||
def write(self, data: str) -> None:
|
||||
mw2._output += data
|
||||
|
||||
if on:
|
||||
self._output = ""
|
||||
self._oldStderr = sys.stderr
|
||||
self._oldStdout = sys.stdout
|
||||
s = cast(TextIO, Stream())
|
||||
sys.stderr = s
|
||||
sys.stdout = s
|
||||
else:
|
||||
sys.stderr = self._oldStderr
|
||||
sys.stdout = self._oldStdout
|
||||
|
||||
def _card_repr(self, card: anki.cards.Card) -> None:
|
||||
import copy
|
||||
import pprint
|
||||
|
||||
if not card:
|
||||
print("no card")
|
||||
return
|
||||
|
||||
print("Front:", card.question())
|
||||
print("\n")
|
||||
print("Back:", card.answer())
|
||||
|
||||
print("\nNote:")
|
||||
note = copy.copy(card.note())
|
||||
for k, v in note.items():
|
||||
print(f"- {k}:", v)
|
||||
|
||||
print("\n")
|
||||
del note.fields
|
||||
del note._fmap
|
||||
pprint.pprint(note.__dict__)
|
||||
|
||||
print("\nCard:")
|
||||
c = copy.copy(card)
|
||||
c._render_output = None
|
||||
pprint.pprint(c.__dict__)
|
||||
|
||||
def _debugCard(self) -> anki.cards.Card | None:
|
||||
assert aqt.mw
|
||||
card = aqt.mw.reviewer.card
|
||||
self._card_repr(card)
|
||||
return card
|
||||
|
||||
def _debugBrowserCard(self) -> anki.cards.Card | None:
|
||||
card = aqt.dialogs._dialogs["Browser"][1].card
|
||||
self._card_repr(card)
|
||||
return card
|
||||
|
||||
def onDebugPrint(self) -> None:
|
||||
cursor = self._text.textCursor()
|
||||
position = cursor.position()
|
||||
cursor.select(QTextCursor.SelectionType.LineUnderCursor)
|
||||
line = cursor.selectedText()
|
||||
whitespace, stripped = _split_off_leading_whitespace(line)
|
||||
pfx, sfx = "pp(", ")"
|
||||
if not stripped.startswith(pfx):
|
||||
line = f"{whitespace}{pfx}{stripped}{sfx}"
|
||||
cursor.insertText(line)
|
||||
cursor.setPosition(position + len(pfx))
|
||||
self._text.setTextCursor(cursor)
|
||||
self.onDebugRet()
|
||||
|
||||
def onDebugRet(self) -> None:
|
||||
import pprint
|
||||
import traceback
|
||||
|
||||
text = self._text.toPlainText()
|
||||
card = self._debugCard
|
||||
bcard = self._debugBrowserCard
|
||||
mw = aqt.mw
|
||||
pp = pprint.pprint
|
||||
self._captureOutput(True)
|
||||
try:
|
||||
# pylint: disable=exec-used
|
||||
exec(text)
|
||||
except:
|
||||
self._output += traceback.format_exc()
|
||||
self._captureOutput(False)
|
||||
buf = ""
|
||||
for c, line in enumerate(text.strip().split("\n")):
|
||||
if c == 0:
|
||||
buf += f">>> {line}\n"
|
||||
else:
|
||||
buf += f"... {line}\n"
|
||||
try:
|
||||
to_append = buf + (self._output or "<no output>")
|
||||
to_append = gui_hooks.debug_console_did_evaluate_python(
|
||||
to_append, text, self.frm
|
||||
)
|
||||
self._log.appendPlainText(to_append)
|
||||
except UnicodeDecodeError:
|
||||
to_append = tr.qt_misc_non_unicode_text()
|
||||
to_append = gui_hooks.debug_console_did_evaluate_python(
|
||||
to_append, text, self.frm
|
||||
)
|
||||
self._log.appendPlainText(to_append)
|
||||
slider = self._log.verticalScrollBar()
|
||||
slider.setValue(slider.maximum())
|
||||
self._log.ensureCursorVisible()
|
||||
|
||||
|
||||
def _split_off_leading_whitespace(text: str) -> tuple[str, str]:
|
||||
stripped = text.lstrip()
|
||||
whitespace = text[: len(text) - len(stripped)]
|
||||
return whitespace, stripped
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>643</width>
|
||||
<width>637</width>
|
||||
<height>582</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -14,10 +14,20 @@
|
|||
<string>qt_misc_debug_console</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="icons.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/anki.png</normaloff>:/icons/anki.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="script">
|
||||
<property name="currentText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
|
@ -49,7 +59,20 @@
|
|||
<enum>QPlainTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string notr="true">Type commands here (Enter to submit)</string>
|
||||
<string notr="true">Actions:
|
||||
Ctrl+Enter Execute
|
||||
Ctrl+Shift+Enter Execute and print current line
|
||||
Ctrl+L Clear log
|
||||
Ctrl+Shift+L Clear input
|
||||
Ctrl+S Save script
|
||||
Ctrl+O Open script
|
||||
Ctrl+D Delete script
|
||||
|
||||
Locals:
|
||||
mw: AnkiQt Main window
|
||||
card: Callable[[], Card | None] Reviewer card
|
||||
bcard: Callable[[], Card | None] Browser card
|
||||
pp: Callable[[object], None] Pretty print</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPlainTextEdit" name="log">
|
||||
|
|
173
qt/aqt/main.py
173
qt/aqt/main.py
|
@ -11,7 +11,7 @@ import signal
|
|||
import weakref
|
||||
from argparse import Namespace
|
||||
from concurrent.futures import Future
|
||||
from typing import Any, Literal, Sequence, TextIO, TypeVar, cast
|
||||
from typing import Any, Literal, Sequence, TypeVar, cast
|
||||
|
||||
import anki
|
||||
import anki.cards
|
||||
|
@ -46,6 +46,7 @@ from anki.utils import (
|
|||
from aqt import gui_hooks
|
||||
from aqt.addons import DownloadLogEntry, check_and_prompt_for_updates, show_log_to_user
|
||||
from aqt.dbcheck import check_db
|
||||
from aqt.debug_console import show_debug_console
|
||||
from aqt.emptycards import show_empty_cards
|
||||
from aqt.flags import FlagManager
|
||||
from aqt.import_export.exporting import ExportDialog
|
||||
|
@ -74,17 +75,14 @@ from aqt.utils import (
|
|||
askUser,
|
||||
checkInvalidFilename,
|
||||
current_window,
|
||||
disable_help_button,
|
||||
disallow_full_screen,
|
||||
getFile,
|
||||
getOnlyText,
|
||||
openHelp,
|
||||
openLink,
|
||||
restoreGeom,
|
||||
restoreSplitter,
|
||||
restoreState,
|
||||
saveGeom,
|
||||
saveSplitter,
|
||||
saveState,
|
||||
showInfo,
|
||||
showWarning,
|
||||
|
@ -1102,7 +1100,7 @@ title="{}" {}>{}</button>""".format(
|
|||
|
||||
def setupKeys(self) -> None:
|
||||
globalShortcuts = [
|
||||
("Ctrl+:", self.onDebug),
|
||||
("Ctrl+:", show_debug_console),
|
||||
("d", lambda: self.moveToState("deckBrowser")),
|
||||
("s", self.onStudyKey),
|
||||
("a", self.onAddCard),
|
||||
|
@ -1631,171 +1629,6 @@ title="{}" {}>{}</button>""".format(
|
|||
def onEmptyCards(self) -> None:
|
||||
show_empty_cards(self)
|
||||
|
||||
# Debugging
|
||||
######################################################################
|
||||
|
||||
def onDebug(self) -> None:
|
||||
frm = self.debug_diag_form = aqt.forms.debug.Ui_Dialog()
|
||||
|
||||
class DebugDialog(QDialog):
|
||||
silentlyClose = True
|
||||
|
||||
def reject(self) -> None:
|
||||
super().reject()
|
||||
saveSplitter(frm.splitter, "DebugConsoleWindow")
|
||||
saveGeom(self, "DebugConsoleWindow")
|
||||
|
||||
d = self.debugDiag = DebugDialog()
|
||||
disable_help_button(d)
|
||||
frm.setupUi(d)
|
||||
restoreGeom(d, "DebugConsoleWindow")
|
||||
restoreSplitter(frm.splitter, "DebugConsoleWindow")
|
||||
font = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont)
|
||||
font.setPointSize(frm.text.font().pointSize() + 1)
|
||||
frm.text.setFont(font)
|
||||
frm.log.setFont(font)
|
||||
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+return"), d)
|
||||
qconnect(s.activated, lambda: self.onDebugRet(frm))
|
||||
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+shift+return"), d)
|
||||
qconnect(s.activated, lambda: self.onDebugPrint(frm))
|
||||
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+l"), d)
|
||||
qconnect(s.activated, frm.log.clear)
|
||||
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+shift+l"), d)
|
||||
qconnect(s.activated, frm.text.clear)
|
||||
|
||||
qconnect(frm.widgetsButton.clicked, self._on_widgetGallery)
|
||||
|
||||
def addContextMenu(
|
||||
ev: Union[QCloseEvent, QContextMenuEvent], name: str
|
||||
) -> None:
|
||||
ev.accept()
|
||||
menu = frm.log.createStandardContextMenu(QCursor.pos())
|
||||
menu.addSeparator()
|
||||
if name == "log":
|
||||
a = menu.addAction("Clear Log")
|
||||
a.setShortcut(QKeySequence("ctrl+l"))
|
||||
qconnect(a.triggered, frm.log.clear)
|
||||
elif name == "text":
|
||||
a = menu.addAction("Clear Code")
|
||||
a.setShortcut(QKeySequence("ctrl+shift+l"))
|
||||
qconnect(a.triggered, frm.text.clear)
|
||||
menu.exec(QCursor.pos())
|
||||
|
||||
frm.log.contextMenuEvent = lambda ev: addContextMenu(ev, "log") # type: ignore[assignment]
|
||||
frm.text.contextMenuEvent = lambda ev: addContextMenu(ev, "text") # type: ignore[assignment]
|
||||
gui_hooks.debug_console_will_show(d)
|
||||
d.show()
|
||||
|
||||
def _on_widgetGallery(self) -> None:
|
||||
from aqt.widgetgallery import WidgetGallery
|
||||
|
||||
self.widgetGallery = WidgetGallery(self)
|
||||
self.widgetGallery.show()
|
||||
|
||||
def _captureOutput(self, on: bool) -> None:
|
||||
mw2 = self
|
||||
|
||||
class Stream:
|
||||
def write(self, data: str) -> None:
|
||||
mw2._output += data
|
||||
|
||||
if on:
|
||||
self._output = ""
|
||||
self._oldStderr = sys.stderr
|
||||
self._oldStdout = sys.stdout
|
||||
s = cast(TextIO, Stream())
|
||||
sys.stderr = s
|
||||
sys.stdout = s
|
||||
else:
|
||||
sys.stderr = self._oldStderr
|
||||
sys.stdout = self._oldStdout
|
||||
|
||||
def _card_repr(self, card: anki.cards.Card) -> None:
|
||||
import copy
|
||||
import pprint
|
||||
|
||||
if not card:
|
||||
print("no card")
|
||||
return
|
||||
|
||||
print("Front:", card.question())
|
||||
print("\n")
|
||||
print("Back:", card.answer())
|
||||
|
||||
print("\nNote:")
|
||||
note = copy.copy(card.note())
|
||||
for k, v in note.items():
|
||||
print(f"- {k}:", v)
|
||||
|
||||
print("\n")
|
||||
del note.fields
|
||||
del note._fmap
|
||||
pprint.pprint(note.__dict__)
|
||||
|
||||
print("\nCard:")
|
||||
c = copy.copy(card)
|
||||
c._render_output = None
|
||||
pprint.pprint(c.__dict__)
|
||||
|
||||
def _debugCard(self) -> anki.cards.Card | None:
|
||||
card = self.reviewer.card
|
||||
self._card_repr(card)
|
||||
return card
|
||||
|
||||
def _debugBrowserCard(self) -> anki.cards.Card | None:
|
||||
card = aqt.dialogs._dialogs["Browser"][1].card
|
||||
self._card_repr(card)
|
||||
return card
|
||||
|
||||
def onDebugPrint(self, frm: aqt.forms.debug.Ui_Dialog) -> None:
|
||||
cursor = frm.text.textCursor()
|
||||
position = cursor.position()
|
||||
cursor.select(QTextCursor.SelectionType.LineUnderCursor)
|
||||
line = cursor.selectedText()
|
||||
pfx, sfx = "pp(", ")"
|
||||
if not line.startswith(pfx):
|
||||
line = f"{pfx}{line}{sfx}"
|
||||
cursor.insertText(line)
|
||||
cursor.setPosition(position + len(pfx))
|
||||
frm.text.setTextCursor(cursor)
|
||||
self.onDebugRet(frm)
|
||||
|
||||
def onDebugRet(self, frm: aqt.forms.debug.Ui_Dialog) -> None:
|
||||
import pprint
|
||||
import traceback
|
||||
|
||||
text = frm.text.toPlainText()
|
||||
card = self._debugCard
|
||||
bcard = self._debugBrowserCard
|
||||
mw = self
|
||||
pp = pprint.pprint
|
||||
self._captureOutput(True)
|
||||
try:
|
||||
# pylint: disable=exec-used
|
||||
exec(text)
|
||||
except:
|
||||
self._output += traceback.format_exc()
|
||||
self._captureOutput(False)
|
||||
buf = ""
|
||||
for c, line in enumerate(text.strip().split("\n")):
|
||||
if c == 0:
|
||||
buf += f">>> {line}\n"
|
||||
else:
|
||||
buf += f"... {line}\n"
|
||||
try:
|
||||
to_append = buf + (self._output or "<no output>")
|
||||
to_append = gui_hooks.debug_console_did_evaluate_python(
|
||||
to_append, text, frm
|
||||
)
|
||||
frm.log.appendPlainText(to_append)
|
||||
except UnicodeDecodeError:
|
||||
to_append = tr.qt_misc_non_unicode_text()
|
||||
to_append = gui_hooks.debug_console_did_evaluate_python(
|
||||
to_append, text, frm
|
||||
)
|
||||
frm.log.appendPlainText(to_append)
|
||||
frm.log.ensureCursorVisible()
|
||||
|
||||
# System specific code
|
||||
##########################################################################
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import aqt
|
||||
import aqt.main
|
||||
from aqt.qt import QDialog, qconnect
|
||||
from aqt.qt import QDialog, QWidget, qconnect
|
||||
from aqt.theme import WidgetStyle
|
||||
from aqt.utils import restoreGeom, saveGeom
|
||||
|
||||
|
@ -11,9 +11,9 @@ from aqt.utils import restoreGeom, saveGeom
|
|||
class WidgetGallery(QDialog):
|
||||
silentlyClose = True
|
||||
|
||||
def __init__(self, mw: aqt.main.AnkiQt) -> None:
|
||||
super().__init__(mw)
|
||||
self.mw = mw.weakref()
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
assert aqt.mw
|
||||
super().__init__(parent)
|
||||
|
||||
self.form = aqt.forms.widgets.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
|
@ -29,10 +29,10 @@ class WidgetGallery(QDialog):
|
|||
self.form.styleComboBox.addItems(
|
||||
[member.name.lower().capitalize() for member in WidgetStyle]
|
||||
)
|
||||
self.form.styleComboBox.setCurrentIndex(self.mw.pm.get_widget_style())
|
||||
self.form.styleComboBox.setCurrentIndex(aqt.mw.pm.get_widget_style())
|
||||
qconnect(
|
||||
self.form.styleComboBox.currentIndexChanged,
|
||||
self.mw.pm.set_widget_style,
|
||||
aqt.mw.pm.set_widget_style,
|
||||
)
|
||||
|
||||
def reject(self) -> None:
|
||||
|
|
Loading…
Reference in a new issue