From 6f764aeda4baa903ea0510e6b9ae40267dcee40f Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 21 Apr 2022 13:28:22 +1000 Subject: [PATCH 1/8] Fix custom browser font not being honored https://forums.ankiweb.net/t/on-anki-2-1-50-browser-table-font-override-is-not-respected/19259 --- qt/aqt/browser/table/model.py | 4 +++- qt/aqt/qt/__init__.py | 15 ++++++++++++++- qt/aqt/qt/qt5_compat.py | 4 +++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/qt/aqt/browser/table/model.py b/qt/aqt/browser/table/model.py index e1ff290a6..6d50d6174 100644 --- a/qt/aqt/browser/table/model.py +++ b/qt/aqt/browser/table/model.py @@ -309,13 +309,15 @@ class DataModel(QAbstractTableModel): return 0 return self.len_columns() + _QFont = without_qt5_compat_wrapper(QFont) + def data(self, index: QModelIndex = QModelIndex(), role: int = 0) -> Any: if not index.isValid(): return QVariant() if role == Qt.ItemDataRole.FontRole: if not self.column_at(index).uses_cell_font: return QVariant() - qfont = QFont() + qfont = self._QFont() row = self.get_row(index) qfont.setFamily(row.font_name) qfont.setPixelSize(row.font_size) diff --git a/qt/aqt/qt/__init__.py b/qt/aqt/qt/__init__.py index 631d12cf1..c60601fa8 100644 --- a/qt/aqt/qt/__init__.py +++ b/qt/aqt/qt/__init__.py @@ -7,7 +7,7 @@ import os import sys import traceback -from typing import Callable, Union +from typing import Callable, TypeVar, Union try: import PyQt6 @@ -58,3 +58,16 @@ def qconnect( ) -> None: """Helper to work around type checking not working with signal.connect(func).""" signal.connect(func) # type: ignore + + +_T = TypeVar("_T") + + +def without_qt5_compat_wrapper(cls: _T) -> _T: + """Remove Qt5 compat wrapper from Qt class, if active. + + Only needed for a few Qt APIs that deal with QVariants.""" + if fn := getattr(cls, "_without_compat_wrapper", None): + return fn() + else: + return cls diff --git a/qt/aqt/qt/qt5_compat.py b/qt/aqt/qt/qt5_compat.py index 98a054b1a..e549994b8 100644 --- a/qt/aqt/qt/qt5_compat.py +++ b/qt/aqt/qt/qt5_compat.py @@ -352,7 +352,9 @@ def _instrument_type( class QtClassProxy( type, metaclass=QtClassProxyType ): # pylint: disable=invalid-metaclass - pass + @staticmethod + def _without_compat_wrapper(): + return type setattr(module, type_name, QtClassProxy) From 6ea75df292f95d914185a013540ee37775d958df Mon Sep 17 00:00:00 2001 From: Abdo Date: Thu, 21 Apr 2022 07:10:53 +0300 Subject: [PATCH 2/8] Fix pasting of local links to unsupported types that contain spaces (#1813) This change causes local links to unsupported formats like PDF to be handled by _processUrls() instead of _processText, converting them to correct hyperlinks in case they contain spaces. --- qt/aqt/editor.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 073696c9a..7d081cde4 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -758,7 +758,9 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too def urlToLink(self, url: str) -> str | None: fname = self.urlToFile(url) if not fname: - return None + return '{}'.format( + url, html.escape(urllib.parse.unquote(url)) + ) return self.fnameToLink(fname) def fnameToLink(self, fname: str) -> str: @@ -1261,7 +1263,7 @@ class EditorWebView(AnkiWebView): url = qurl.toString() # chrome likes to give us the URL twice with a \n url = url.splitlines()[0] - buf += self.editor.urlToLink(url) or "" + buf += self.editor.urlToLink(url) return buf @@ -1279,16 +1281,9 @@ class EditorWebView(AnkiWebView): if extended and token.startswith("data:image/"): processed.append(self.editor.inlinedImageToLink(token)) elif extended and self.editor.isURL(token): - # if the user is pasting an image or sound link, convert it to local + # if the user is pasting an image or sound link, convert it to local, otherwise paste as a hyperlink link = self.editor.urlToLink(token) - if link: - processed.append(link) - else: - # not media; add it as a normal link - link = '{}'.format( - token, html.escape(urllib.parse.unquote(token)) - ) - processed.append(link) + processed.append(link) else: token = html.escape(token).replace("\t", " " * 4) # if there's more than one consecutive space, From e6d990a44e2f1d3ef9dfb1303c6049f749dd01f0 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 21 Apr 2022 16:38:32 +1000 Subject: [PATCH 3/8] Fix cwd changing on export No longer required after #1656 --- pylib/anki/exporting.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index 1c6398aaa..8e5954d84 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -370,7 +370,6 @@ class AnkiPackageExporter(AnkiExporter): p = path.replace(".apkg", ".media.db2") if os.path.exists(p): os.unlink(p) - os.chdir(self.mediaDir) shutil.rmtree(path.replace(".apkg", ".media")) return media From 280c06425db795a7389acf3c9b248c34b1781d63 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Fri, 22 Apr 2022 13:52:24 +1000 Subject: [PATCH 4/8] Increase compression on zstd packages --- qt/bundle/build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qt/bundle/build.py b/qt/bundle/build.py index b21294f53..72627ef97 100644 --- a/qt/bundle/build.py +++ b/qt/bundle/build.py @@ -343,13 +343,13 @@ def build_tarball(src_path: Path, variant: str) -> None: subprocess.run( [ "tar", - "--zstd", + "-I", + "zstd -c --long -T0 -18", "-cf", dist_folder / (dest_path.name + ".tar.zst"), dest_path.name, ], check=True, - env=dict(ZSTD_CLEVEL="9"), cwd=dest_path.parent, ) From 770fabd51b053a0d28a779ab1bd55876624218a7 Mon Sep 17 00:00:00 2001 From: Matthias Metelka <62722460+kleinerpirat@users.noreply.github.com> Date: Fri, 22 Apr 2022 06:17:43 +0200 Subject: [PATCH 5/8] Remove unnecessary night mode rule for typeans (#1815) which caused https://forums.ankiweb.net/t/shaddow-below-cloze-type-area-in-night-mode/19287/2 --- ts/reviewer/reviewer.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ts/reviewer/reviewer.scss b/ts/reviewer/reviewer.scss index 24f24a3cf..0c31bb6da 100644 --- a/ts/reviewer/reviewer.scss +++ b/ts/reviewer/reviewer.scss @@ -48,11 +48,6 @@ img { box-sizing: border-box; } -.night-mode #typeans { - background-color: var(--frame-bg); - color: var(--text-fg); -} - .typeGood { background: #afa; color: black; From 2b739d76b2edcda20cf8963f4cf7adc23ab6cdd2 Mon Sep 17 00:00:00 2001 From: Matthias Metelka <62722460+kleinerpirat@users.noreply.github.com> Date: Fri, 22 Apr 2022 06:18:11 +0200 Subject: [PATCH 6/8] Align list items to start (#1816) --- ts/reviewer/reviewer.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ts/reviewer/reviewer.scss b/ts/reviewer/reviewer.scss index 0c31bb6da..dab602efd 100644 --- a/ts/reviewer/reviewer.scss +++ b/ts/reviewer/reviewer.scss @@ -23,6 +23,10 @@ img { max-height: 95vh; } +li { + text-align: start; +} + #_flag { position: fixed; right: 10px; From aea7eb667e2c78de3a99436e458f413b9e765226 Mon Sep 17 00:00:00 2001 From: RumovZ Date: Fri, 22 Apr 2022 06:47:17 +0200 Subject: [PATCH 7/8] Fix progress of chained operations (#1817) * Fix progress of chained operations Especially aborting colpkg import. * Notify about missing progress dialog --- qt/aqt/importing.py | 7 ++++--- qt/aqt/operations/__init__.py | 11 +++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/qt/aqt/importing.py b/qt/aqt/importing.py index c45570486..0168d2c9c 100644 --- a/qt/aqt/importing.py +++ b/qt/aqt/importing.py @@ -14,7 +14,7 @@ import aqt.modelchooser from anki.errors import Interrupted from anki.importing.anki2 import V2ImportIntoV1 from anki.importing.apkg import AnkiPackageImporter -from aqt import AnkiQt, gui_hooks +from aqt.main import AnkiQt, gui_hooks from aqt.operations import QueryOp from aqt.qt import * from aqt.utils import ( @@ -460,12 +460,13 @@ def full_apkg_import(mw: AnkiQt, file: str) -> None: def replace_with_apkg( - mw: aqt.AnkiQt, filename: str, callback: Callable[[bool], None] + mw: AnkiQt, filename: str, callback: Callable[[bool], None] ) -> None: """Tries to replace the provided collection with the provided backup, then calls the callback. True if success. """ - dialog = mw.progress.start(immediate=True) + if not (dialog := mw.progress.start(immediate=True)): + print("No progress dialog during import; aborting will not work") timer = QTimer() timer.setSingleShot(False) timer.setInterval(100) diff --git a/qt/aqt/operations/__init__.py b/qt/aqt/operations/__init__.py index 0fd4dbad1..7d7ad8b91 100644 --- a/qt/aqt/operations/__init__.py +++ b/qt/aqt/operations/__init__.py @@ -217,6 +217,10 @@ class QueryOp(Generic[T]): def wrapped_done(future: Future) -> None: assert mw + + if self._progress: + mw.progress.finish() + mw._decrease_background_ops() # did something go wrong? if exception := future.exception(): @@ -230,11 +234,6 @@ class QueryOp(Generic[T]): # BaseException like SystemExit; rethrow it future.result() - result = future.result() - try: - self._success(result) - finally: - if self._progress: - mw.progress.finish() + self._success(future.result()) mw.taskman.run_in_background(wrapped_op, wrapped_done) From ee70006ec4d9c6c07d61b018bbf2f308d5b38d05 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Fri, 22 Apr 2022 15:45:50 +1000 Subject: [PATCH 8/8] Reset zoom on page transition https://forums.ankiweb.net/t/2-1-50-zooming-in-while-reviewing-results-in-an-unusably-huge-deck-list/19283 --- qt/aqt/webview.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qt/aqt/webview.py b/qt/aqt/webview.py index 955893e83..b2975fdeb 100644 --- a/qt/aqt/webview.py +++ b/qt/aqt/webview.py @@ -330,6 +330,7 @@ class AnkiWebView(QWebEngineView): self._domDone = True self._queueAction("setHtml", html) self.set_open_links_externally(True) + self.setZoomFactor(1) self.show() def _setHtml(self, html: str) -> None: @@ -681,6 +682,7 @@ html {{ {font} }} else: extra = "" self.hide_while_preserving_layout() + self.setZoomFactor(1) self.load_url(QUrl(f"{mw.serverURL()}_anki/pages/{name}.html{extra}")) self.inject_dynamic_style_and_show()