From c2fddcaf42716682c46880b0d1bf7cb477674e27 Mon Sep 17 00:00:00 2001 From: Nechaiter <164061016+Nechaiter@users.noreply.github.com> Date: Mon, 10 Nov 2025 10:18:57 -0300 Subject: [PATCH 1/5] Fix FindDuplicates dialog size exceeding screen bounds (#4426) --- CONTRIBUTORS | 1 + qt/aqt/forms/finddupes.ui | 3 +++ qt/aqt/utils.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index d90b7dbcc..2ec25da2d 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -254,6 +254,7 @@ nav1s Ranjit Odedra Eltaurus jariji +Francisco Esteva ******************** diff --git a/qt/aqt/forms/finddupes.ui b/qt/aqt/forms/finddupes.ui index 9a7c44c06..9bc8be87b 100644 --- a/qt/aqt/forms/finddupes.ui +++ b/qt/aqt/forms/finddupes.ui @@ -47,6 +47,9 @@ QComboBox::NoInsert + + QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon + diff --git a/qt/aqt/utils.py b/qt/aqt/utils.py index 43efc513f..ae88dadcb 100644 --- a/qt/aqt/utils.py +++ b/qt/aqt/utils.py @@ -809,7 +809,7 @@ def ensureWidgetInScreenBoundaries(widget: QWidget) -> None: wsize = widget.size() cappedWidth = min(geom.width(), wsize.width()) cappedHeight = min(geom.height(), wsize.height()) - if cappedWidth > wsize.width() or cappedHeight > wsize.height(): + if cappedWidth < wsize.width() or cappedHeight < wsize.height(): widget.resize(QSize(cappedWidth, cappedHeight)) # ensure widget is inside top left From 9facea0a6616995458421abace3f54981a53909c Mon Sep 17 00:00:00 2001 From: Lee Doughty <32392044+leedoughty@users.noreply.github.com> Date: Wed, 12 Nov 2025 19:55:47 +0000 Subject: [PATCH 2/5] feat(tts): fallback to Apple Samantha voice for TTS on macOS (#4420) * Fallback to Apple Samantha voice for en_US TTS on macOS * Use prefix match for Apple Samantha voice fallback --- qt/aqt/tts.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/qt/aqt/tts.py b/qt/aqt/tts.py index d559fb41f..f77e5c975 100644 --- a/qt/aqt/tts.py +++ b/qt/aqt/tts.py @@ -94,8 +94,15 @@ class TTSPlayer: rank -= 1 - # if no preferred voices match, we fall back on language - # with a rank of -100 + # if no requested voices match, use a preferred fallback voice + # (for example, Apple Samantha) with rank of -50 + for avail in avail_voices: + if avail.lang == tag.lang: + if avail.lang == "en_US" and avail.name.startswith("Apple_Samantha"): + return TTSVoiceMatch(voice=avail, rank=-50) + + # if no requested or preferred voices match, we fall back on + # the first available voice for the language, with a rank of -100 for avail in avail_voices: if avail.lang == tag.lang: return TTSVoiceMatch(voice=avail, rank=-100) From 0abac06c39d900ec32ad961f51aaa87cff4fc60a Mon Sep 17 00:00:00 2001 From: junlu592 Date: Sat, 15 Nov 2025 12:51:21 +0100 Subject: [PATCH 3/5] Fixed overlapping ranges when all history is selected and days calcolation to prevent overlapping labels --- CONTRIBUTORS | 1 + ts/lib/tslib/time.ts | 6 ++++-- ts/routes/graphs/calendar.ts | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 2ec25da2d..0ef0d1eb8 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -255,6 +255,7 @@ Ranjit Odedra Eltaurus jariji Francisco Esteva +Junia Mannervik ******************** diff --git a/ts/lib/tslib/time.ts b/ts/lib/tslib/time.ts index 25d70eef3..0e6330f38 100644 --- a/ts/lib/tslib/time.ts +++ b/ts/lib/tslib/time.ts @@ -178,9 +178,11 @@ export function dayLabel(daysStart: number, daysEnd: number): string { daysEnd: daysEnd - 1, }); } else { + const mostRecent = daysEnd <= 0 ? Math.abs(daysEnd - 1) : 0; + const oldest = -daysStart; return tr.statisticsDaysAgoRange({ - daysStart: Math.abs(daysEnd - 1), - daysEnd: -daysStart, + daysStart: mostRecent, + daysEnd: oldest, }); } } diff --git a/ts/routes/graphs/calendar.ts b/ts/routes/graphs/calendar.ts index 863923095..14c32d089 100644 --- a/ts/routes/graphs/calendar.ts +++ b/ts/routes/graphs/calendar.ts @@ -118,6 +118,10 @@ export function renderCalendar( // don't fill out future dates continue; } + if (date.getFullYear() != targetYear) { + // only fill blanks for the target year + continue; + } if (revlogRange == RevlogRange.Year && date < oneYearAgoFromNow) { // don't fill out dates older than a year continue; From dda192f24c201fc6baf276cb243adfe2a5a95825 Mon Sep 17 00:00:00 2001 From: llama Date: Thu, 20 Nov 2025 03:48:14 +0800 Subject: [PATCH 4/5] fix(import): support variable field count with notetype column (#4421) --- rslib/src/import_export/text/csv/import.rs | 22 +++++++++++++++----- rslib/src/import_export/text/csv/metadata.rs | 7 ++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/rslib/src/import_export/text/csv/import.rs b/rslib/src/import_export/text/csv/import.rs index e45bbca1b..31dee84e4 100644 --- a/rslib/src/import_export/text/csv/import.rs +++ b/rslib/src/import_export/text/csv/import.rs @@ -1,6 +1,7 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html +use std::collections::HashSet; use std::io::BufRead; use std::io::BufReader; use std::io::Read; @@ -106,6 +107,8 @@ struct ColumnContext { notetype_column: Option, /// Source column indices for the fields of a notetype field_source_columns: FieldSourceColumns, + /// Metadata column indices (1-based) + meta_columns: HashSet, /// How fields are converted to strings. Used for escaping HTML if /// appropriate. stringify: fn(&str) -> String, @@ -119,6 +122,7 @@ impl ColumnContext { deck_column: metadata.deck()?.column(), notetype_column: metadata.notetype()?.column(), field_source_columns: metadata.field_source_columns()?, + meta_columns: metadata.meta_columns(), stringify: stringify_fn(metadata.is_html), }) } @@ -166,11 +170,19 @@ impl ColumnContext { } fn gather_note_fields(&self, record: &csv::StringRecord) -> Vec> { - let stringify = self.stringify; - self.field_source_columns - .iter() - .map(|opt| opt.and_then(|idx| record.get(idx - 1)).map(stringify)) - .collect() + let op = |i| record.get(i - 1).map(self.stringify); + if !self.field_source_columns.is_empty() { + self.field_source_columns + .iter() + .map(|opt| opt.and_then(op)) + .collect() + } else { + // notetype column provided, assume all non-metadata columns are notetype fields + (1..=record.len()) + .filter(|i| !self.meta_columns.contains(i)) + .map(op) + .collect() + } } } diff --git a/rslib/src/import_export/text/csv/metadata.rs b/rslib/src/import_export/text/csv/metadata.rs index d505c60d2..cd4150813 100644 --- a/rslib/src/import_export/text/csv/metadata.rs +++ b/rslib/src/import_export/text/csv/metadata.rs @@ -291,11 +291,8 @@ impl CsvMetadataHelpers for CsvMetadata { .map(|&i| (i > 0).then_some(i as usize)) .collect(), CsvNotetype::NotetypeColumn(_) => { - let meta_columns = self.meta_columns(); - (1..self.column_labels.len() + 1) - .filter(|idx| !meta_columns.contains(idx)) - .map(Some) - .collect() + // each row's notetype could have varying number of fields + vec![] } }) } From e4c6e082f09457f6b14e1a1149f21353b2146cc3 Mon Sep 17 00:00:00 2001 From: junlu592 Date: Thu, 20 Nov 2025 13:20:40 +0100 Subject: [PATCH 5/5] fix statistics calendar and review grapgh range labeling --- ts/routes/graphs/reviews.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ts/routes/graphs/reviews.ts b/ts/routes/graphs/reviews.ts index ed0e07f8c..8302cb4c9 100644 --- a/ts/routes/graphs/reviews.ts +++ b/ts/routes/graphs/reviews.ts @@ -111,9 +111,6 @@ export function renderReviews( const desiredBars = Math.min(70, Math.abs(xMin!)); const x = scaleLinear().domain([xMin!, xMax]); - if (range === GraphRange.AllTime) { - x.nice(desiredBars); - } const sourceMap = showTime ? sourceData.reviewTime : sourceData.reviewCount; const bins = bin() @@ -212,7 +209,9 @@ export function renderReviews( } function tooltipText(d: BinType, cumulative: number): string { - const day = dayLabel(d.x0!, d.x1!); + const startDay = Math.trunc(d.x0!); + const endDay = Math.trunc(d.x1!); + const day = dayLabel(startDay, endDay); const totals = totalsForBin(d); const dayTotal = valueLabel(sum(totals)); let buf = ``;
${day}${dayTotal}