From 938c55ca01101775b6a30aa657079249677c2d3c Mon Sep 17 00:00:00 2001 From: Kris Cherven <50562493+krischerven@users.noreply.github.com> Date: Wed, 19 Mar 2025 10:58:42 +0000 Subject: [PATCH 1/5] Fix broken window decorations on unpackaged GNOME instances (#3858) * Fix broken window decorations on unpackaged GNOME instances * Fix CONTRIBUTORS detection * Fix CONTRIBUTORS --- pylib/anki/utils.py | 4 ++++ qt/aqt/__init__.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pylib/anki/utils.py b/pylib/anki/utils.py index b5382e6df..1b4212620 100644 --- a/pylib/anki/utils.py +++ b/pylib/anki/utils.py @@ -248,6 +248,10 @@ is_mac = sys.platform.startswith("darwin") is_win = sys.platform.startswith("win32") # also covers *BSD is_lin = not is_mac and not is_win +is_gnome = ( + "gnome" in os.getenv("XDG_CURRENT_DESKTOP", "").lower() + or "gnome" in os.getenv("DESKTOP_SESSION", "").lower() +) dev_mode = os.getenv("ANKIDEV", "") hmr_mode = os.getenv("HMR", "") diff --git a/qt/aqt/__init__.py b/qt/aqt/__init__.py index af3797049..fb9222521 100644 --- a/qt/aqt/__init__.py +++ b/qt/aqt/__init__.py @@ -59,7 +59,7 @@ from anki._backend import RustBackend from anki.buildinfo import version as _version from anki.collection import Collection from anki.consts import HELP_SITE -from anki.utils import checksum, is_lin, is_mac +from anki.utils import checksum, is_gnome, is_lin, is_mac from aqt import gui_hooks from aqt.log import setup_logging from aqt.qt import * @@ -614,7 +614,7 @@ def _run(argv: list[str] | None = None, exec: bool = True) -> AnkiApp | None: ) wayland_forced = os.getenv("ANKI_WAYLAND") - if packaged and wayland_configured: + if (packaged or is_gnome) and wayland_configured: if wayland_forced or not x11_available: # Work around broken fractional scaling in Wayland # https://bugreports.qt.io/browse/QTBUG-113574 From ab8692a91e1c22c4fcad4fd4bf484f6a24ce46ae Mon Sep 17 00:00:00 2001 From: Kris Cherven <50562493+krischerven@users.noreply.github.com> Date: Wed, 19 Mar 2025 11:16:51 +0000 Subject: [PATCH 2/5] Show "and others" at the end of the contributor list in the About dialog (#3863) * Show "and others" at the end of the contributor list in the about dialog * Make about addendum translatable * Fix CONTRIBUTORS * Fix CONTRIBUTORS * Update ftl/qt/about.ftl (dae) --- ftl/qt/about.ftl | 2 ++ qt/aqt/about.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ftl/qt/about.ftl b/ftl/qt/about.ftl index 6fd190638..b841e0843 100644 --- a/ftl/qt/about.ftl +++ b/ftl/qt/about.ftl @@ -8,3 +8,5 @@ about-if-you-have-contributed-and-are = If you have contributed and are not on t about-version = Version { $val } about-visit-website = Visit website about-written-by-damien-elmes-with-patches = Written by Damien Elmes, with patches, translation, testing and design from:
{ $cont } +# appended to the end of the contributor list in the about screen +about-and-others = and others diff --git a/qt/aqt/about.py b/qt/aqt/about.py index 659e380ea..d0d7157af 100644 --- a/qt/aqt/about.py +++ b/qt/aqt/about.py @@ -222,7 +222,7 @@ def show(mw: aqt.AnkiQt) -> QDialog: ) abouttext += "
" + tr.about_written_by_damien_elmes_with_patches( - cont=", ".join(allusers) + cont=", ".join(allusers) + f", {tr.about_and_others()}" ) abouttext += f"
{tr.about_if_you_have_contributed_and_are()}" abouttext += f"
{tr.about_a_big_thanks_to_all_the()}"
From d8c83ac075c3587da853a1aeef16300ff27fc357 Mon Sep 17 00:00:00 2001
From: llama <100429699+iamllama@users.noreply.github.com>
Date: Wed, 19 Mar 2025 19:56:17 +0800
Subject: [PATCH 3/5] Loosen csv metadata parsing (#3862)
* add qsv-sniffer crate
* use qsv-sniffer before falling back to old delimiter heuristic
* update test metadata macro
* revert impl
* trim potential suffixed delimiters from non-freeform meta lines
* add test
---
rslib/src/import_export/text/csv/metadata.rs | 55 +++++++++++++++++---
1 file changed, 49 insertions(+), 6 deletions(-)
diff --git a/rslib/src/import_export/text/csv/metadata.rs b/rslib/src/import_export/text/csv/metadata.rs
index a69acfe9e..7e2f64f5e 100644
--- a/rslib/src/import_export/text/csv/metadata.rs
+++ b/rslib/src/import_export/text/csv/metadata.rs
@@ -121,19 +121,34 @@ impl Collection {
}
fn parse_meta_value(&mut self, key: &str, value: &str, metadata: &mut CsvMetadata) {
+ // trim potential delimiters past the first char* if
+ // metadata line was mistakenly exported as a record
+ // *to allow cases like #separator:,
+ // ASSUMPTION: delimiters are not ascii-alphanumeric
+ let trimmed_value = value
+ .char_indices()
+ .nth(1)
+ .and_then(|(i, _)| {
+ value[i..] // SAFETY: char_indices are on char boundaries
+ .find(|c| !char::is_ascii_alphanumeric(&c))
+ .map(|j| value.split_at(i + j).0)
+ })
+ .unwrap_or(value);
+
match key.trim().to_ascii_lowercase().as_str() {
"separator" => {
- if let Some(delimiter) = delimiter_from_value(value) {
+ if let Some(delimiter) = delimiter_from_value(trimmed_value) {
metadata.delimiter = delimiter as i32;
metadata.force_delimiter = true;
}
}
"html" => {
- if let Ok(is_html) = value.to_lowercase().parse() {
+ if let Ok(is_html) = trimmed_value.to_lowercase().parse() {
metadata.is_html = is_html;
metadata.force_is_html = true;
}
}
+ // freeform values cannot be trimmed thus without knowing the exact delimiter
"tags" => metadata.global_tags = collect_tags(value),
"columns" => {
if let Ok(columns) = parse_columns(value, metadata.delimiter()) {
@@ -151,22 +166,22 @@ impl Collection {
}
}
"notetype column" => {
- if let Ok(n) = value.trim().parse() {
+ if let Ok(n) = trimmed_value.trim().parse() {
metadata.notetype = Some(CsvNotetype::NotetypeColumn(n));
}
}
"deck column" => {
- if let Ok(n) = value.trim().parse() {
+ if let Ok(n) = trimmed_value.trim().parse() {
metadata.deck = Some(CsvDeck::DeckColumn(n));
}
}
"tags column" => {
- if let Ok(n) = value.trim().parse() {
+ if let Ok(n) = trimmed_value.trim().parse() {
metadata.tags_column = n;
}
}
"guid column" => {
- if let Ok(n) = value.trim().parse() {
+ if let Ok(n) = trimmed_value.trim().parse() {
metadata.guid_column = n;
}
}
@@ -891,4 +906,32 @@ pub(in crate::import_export) mod test {
maybe_set_tags_column(&mut metadata, &meta_columns);
assert_eq!(metadata.tags_column, 4);
}
+
+ #[test]
+ fn should_allow_non_freeform_metadata_lines_to_be_suffixed_by_delimiters() {
+ let mut col = Collection::new();
+ let metadata = metadata!(
+ col,
+ r#"
+#separator:Pipe,,,,,,,
+#html:true|||||
+#tags:foo bar::世界,,,
+#guid column:8
+#tags column:123abc
+ "#
+ .trim()
+ );
+ assert_eq!(metadata.delimiter(), Delimiter::Pipe);
+ assert!(metadata.is_html);
+ assert_eq!(metadata.guid_column, 8);
+ // tags is freeform, potential delimiters aren't trimmed
+ assert_eq!(metadata.global_tags, ["foo", "bar::世界,,,"]);
+ // ascii alphanumerics aren't trimmed away
+ assert_eq!(metadata.tags_column, 0);
+
+ assert_eq!(
+ metadata!(col, "#separator:\t|,:\n").delimiter(),
+ Delimiter::Tab
+ );
+ }
}
From 5d7f6b25c0272e64923c83246b97cc3c8be22b34 Mon Sep 17 00:00:00 2001
From: Jarrett Ye