include report in MediaCheckOutput

This commit is contained in:
Damien Elmes 2020-02-14 16:15:18 +10:00
parent dc9362d4ed
commit 5c8e3df612
6 changed files with 152 additions and 71 deletions

View file

@ -271,9 +271,7 @@ message SyncMediaIn {
message MediaCheckOut { message MediaCheckOut {
repeated string unused = 1; repeated string unused = 1;
repeated string missing = 2; repeated string missing = 2;
repeated string dirs = 3; string report = 3;
repeated string oversize = 4;
map<string,string> renamed = 5;
} }
message TrashMediaFilesIn { message TrashMediaFilesIn {

View file

@ -60,7 +60,7 @@ class MediaChecker:
"Run the check on a background thread." "Run the check on a background thread."
return self.mw.col.media.check() return self.mw.col.media.check()
def _on_finished(self, future: Future): def _on_finished(self, future: Future) -> None:
hooks.bg_thread_progress_callback.remove(self._on_progress) hooks.bg_thread_progress_callback.remove(self._on_progress)
self.mw.progress.finish() self.mw.progress.finish()
self.progress_dialog = None self.progress_dialog = None
@ -70,8 +70,8 @@ class MediaChecker:
if isinstance(exc, Interrupted): if isinstance(exc, Interrupted):
return return
output = future.result() output: MediaCheckOutput = future.result()
report = describe_output(output) report = output.report
# show report and offer to delete # show report and offer to delete
diag = QDialog(self.mw) diag = QDialog(self.mw)
@ -156,56 +156,3 @@ class MediaChecker:
self.progress_dialog = None self.progress_dialog = None
tooltip(_("Files moved to trash.")) tooltip(_("Files moved to trash."))
def describe_output(output: MediaCheckOutput) -> str:
buf = []
buf.append(_("Missing files: {}").format(len(output.missing)))
buf.append(_("Unused files: {}").format(len(output.unused)))
if output.renamed:
buf.append(_("Renamed files: {}").format(len(output.renamed)))
if output.oversize:
buf.append(_("Over 100MB: {}".format(output.oversize)))
if output.dirs:
buf.append(_("Subfolders: {}".format(output.dirs)))
buf.append("")
if output.renamed:
buf.append(_("Some files have been renamed for compatibility:"))
buf.extend(
_("Renamed: %(old)s -> %(new)s") % dict(old=k, new=v)
for (k, v) in sorted(output.renamed.items())
)
buf.append("")
if output.oversize:
buf.append(_("Files over 100MB can not be synced with AnkiWeb."))
buf.extend(_("Over 100MB: {}").format(f) for f in sorted(output.oversize))
buf.append("")
if output.dirs:
buf.append(_("Folders inside the media folder are not supported."))
buf.extend(_("Folder: {}").format(f) for f in sorted(output.dirs))
buf.append("")
if output.missing:
buf.append(
_(
"The following files are referenced by cards, but were not found in the media folder:"
)
)
buf.extend(_("Missing: {}").format(f) for f in sorted(output.missing))
buf.append("")
if output.unused:
buf.append(
_(
"The following files were found in the media folder, but do not appear to be used on any cards:"
)
)
buf.extend(_("Unused: {}").format(f) for f in sorted(output.unused))
buf.append("")
return "\n".join(buf)

View file

@ -361,14 +361,14 @@ impl Backend {
let mgr = MediaManager::new(&self.media_folder, &self.media_db)?; let mgr = MediaManager::new(&self.media_folder, &self.media_db)?;
let mut checker = MediaChecker::new(&mgr, &self.col_path, callback, &self.i18n); let mut checker = MediaChecker::new(&mgr, &self.col_path, callback, &self.i18n);
let output = checker.check()?; let mut output = checker.check()?;
let report = checker.summarize_output(&mut output);
Ok(pb::MediaCheckOut { Ok(pb::MediaCheckOut {
unused: output.unused, unused: output.unused,
missing: output.missing, missing: output.missing,
renamed: output.renamed, report,
dirs: output.dirs,
oversize: output.oversize,
}) })
} }

View file

@ -0,0 +1,19 @@
missing-count = Missing files: {$count}
unused-count = Unused files: {$count}
renamed-count = Renamed files: {$count}
oversize-count = Over 100MB: {$count}
subfolder-count = Subfolders: {$count}
renamed-header = Some files have been renamed for compatibility:
oversize-header = Files over 100MB can not be synced with AnkiWeb.
subfolder-header = Folders inside the media folder are not supported.
missing-header =
The following files are referenced by cards, but were not found in the media folder:
unused-header =
The following files were found in the media folder, but do not appear to be used on any cards:
renamed-file = Renamed: {$old} -> {$new}
oversize-file = Over 100MB: {$filename}
subfolder-file = Folder: {$filename}
missing-file = Missing: {$filename}
unused-file = Unused: {$filename}

View file

@ -10,6 +10,21 @@ use unic_langid::LanguageIdentifier;
pub use fluent::fluent_args as tr_args; pub use fluent::fluent_args as tr_args;
/// Helper for creating args with &strs
#[macro_export]
macro_rules! tr_strs {
( $($key:expr => $value:expr),* ) => {
{
let mut args: fluent::FluentArgs = fluent::FluentArgs::new();
$(
args.insert($key, $value.to_string().into());
)*
args
}
};
}
pub use tr_strs;
/// All languages we (currently) support, excluding the fallback /// All languages we (currently) support, excluding the fallback
/// English. /// English.
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
@ -169,8 +184,8 @@ impl I18nCategory {
} }
/// Get translation with one or more arguments. /// Get translation with one or more arguments.
pub fn trn(&self, key: &str, args: FluentArgs) -> Cow<str> { pub fn trn(&self, key: &str, args: FluentArgs) -> String {
self.tr_(key, Some(args)) self.tr_(key, Some(args)).into()
} }
fn tr_<'a>(&'a self, key: &str, args: Option<FluentArgs>) -> Cow<'a, str> { fn tr_<'a>(&'a self, key: &str, args: Option<FluentArgs>) -> Cow<'a, str> {

View file

@ -3,7 +3,7 @@
use crate::cloze::expand_clozes_to_reveal_latex; use crate::cloze::expand_clozes_to_reveal_latex;
use crate::err::{AnkiError, Result}; use crate::err::{AnkiError, Result};
use crate::i18n::I18n; use crate::i18n::{tr_args, tr_strs, I18n, TranslationFile};
use crate::latex::extract_latex; use crate::latex::extract_latex;
use crate::media::col::{ use crate::media::col::{
for_every_note, get_note_types, mark_collection_modified, open_or_create_collection_db, for_every_note, get_note_types, mark_collection_modified, open_or_create_collection_db,
@ -78,9 +78,6 @@ where
let folder_check = self.check_media_folder(&mut ctx)?; let folder_check = self.check_media_folder(&mut ctx)?;
let referenced_files = self.check_media_references(&folder_check.renamed)?; let referenced_files = self.check_media_references(&folder_check.renamed)?;
let (unused, missing) = find_unused_and_missing(folder_check.files, referenced_files); let (unused, missing) = find_unused_and_missing(folder_check.files, referenced_files);
let _ = self.i18n;
Ok(MediaCheckOutput { Ok(MediaCheckOutput {
unused, unused,
missing, missing,
@ -90,6 +87,88 @@ where
}) })
} }
pub fn summarize_output(&self, output: &mut MediaCheckOutput) -> String {
let mut buf = String::new();
let cat = self.i18n.get(TranslationFile::MediaCheck);
// top summary area
buf += &cat.trn("missing-count", tr_args!["count"=>output.missing.len()]);
buf.push('\n');
buf += &cat.trn("unused-count", tr_args!["count"=>output.unused.len()]);
buf.push('\n');
if !output.renamed.is_empty() {
buf += &cat.trn("renamed-count", tr_args!["count"=>output.renamed.len()]);
buf.push('\n');
}
if !output.oversize.is_empty() {
buf += &cat.trn("oversize-count", tr_args!["count"=>output.oversize.len()]);
buf.push('\n');
}
if !output.dirs.is_empty() {
buf += &cat.trn("subfolder-count", tr_args!["count"=>output.dirs.len()]);
buf.push('\n');
}
buf.push('\n');
if !output.renamed.is_empty() {
buf += &cat.tr("renamed-header");
buf.push('\n');
for (old, new) in &output.renamed {
buf += &cat.trn("renamed-file", tr_strs!["old"=>old,"new"=>new]);
buf.push('\n');
}
buf.push('\n')
}
if !output.oversize.is_empty() {
output.oversize.sort();
buf += &cat.tr("oversize-header");
buf.push('\n');
for fname in &output.oversize {
buf += &cat.trn("oversize-file", tr_strs!["filename"=>fname]);
buf.push('\n');
}
buf.push('\n')
}
if !output.dirs.is_empty() {
output.dirs.sort();
buf += &cat.tr("subfolder-header");
buf.push('\n');
for fname in &output.dirs {
buf += &cat.trn("subfolder-file", tr_strs!["filename"=>fname]);
buf.push('\n');
}
buf.push('\n')
}
if !output.missing.is_empty() {
output.missing.sort();
buf += &cat.tr("missing-header");
buf.push('\n');
for fname in &output.missing {
buf += &cat.trn("missing-file", tr_strs!["filename"=>fname]);
buf.push('\n');
}
buf.push('\n')
}
if !output.unused.is_empty() {
output.unused.sort();
buf += &cat.tr("unused-header");
buf.push('\n');
for fname in &output.unused {
buf += &cat.trn("unused-file", tr_strs!["filename"=>fname]);
buf.push('\n');
}
}
buf
}
/// Check all the files in the media folder. /// Check all the files in the media folder.
/// ///
/// - Renames files with invalid names /// - Renames files with invalid names
@ -377,17 +456,18 @@ mod test {
fs::write(&mgr.media_folder.join("normal.jpg"), "normal")?; fs::write(&mgr.media_folder.join("normal.jpg"), "normal")?;
fs::write(&mgr.media_folder.join("foo[.jpg"), "foo")?; fs::write(&mgr.media_folder.join("foo[.jpg"), "foo")?;
fs::write(&mgr.media_folder.join("_under.jpg"), "foo")?; fs::write(&mgr.media_folder.join("_under.jpg"), "foo")?;
fs::write(&mgr.media_folder.join("unused.jpg"), "foo")?;
let i18n = I18n::new(&["zz"], "dummy"); let i18n = I18n::new(&["zz"], "dummy");
let progress = |_n| true; let progress = |_n| true;
let mut checker = MediaChecker::new(&mgr, &col_path, progress, &i18n); let mut checker = MediaChecker::new(&mgr, &col_path, progress, &i18n);
let output = checker.check()?; let mut output = checker.check()?;
assert_eq!( assert_eq!(
output, output,
MediaCheckOutput { MediaCheckOutput {
unused: vec![], unused: vec!["unused.jpg".into()],
missing: vec!["ぱぱ.jpg".into()], missing: vec!["ぱぱ.jpg".into()],
renamed: vec![("foo[.jpg".into(), "foo.jpg".into())] renamed: vec![("foo[.jpg".into(), "foo.jpg".into())]
.into_iter() .into_iter()
@ -400,6 +480,28 @@ mod test {
assert!(fs::metadata(&mgr.media_folder.join("foo[.jpg")).is_err()); assert!(fs::metadata(&mgr.media_folder.join("foo[.jpg")).is_err());
assert!(fs::metadata(&mgr.media_folder.join("foo.jpg")).is_ok()); assert!(fs::metadata(&mgr.media_folder.join("foo.jpg")).is_ok());
let report = checker.summarize_output(&mut output);
assert_eq!(
report,
"Missing files: 1
Unused files: 1
Renamed files: 1
Subfolders: 1
Some files have been renamed for compatibility:
Renamed: foo[.jpg -> foo.jpg
Folders inside the media folder are not supported.
Folder: folder
The following files are referenced by cards, but were not found in the media folder:
Missing: .jpg
The following files were found in the media folder, but do not appear to be used on any cards:
Unused: unused.jpg
"
);
Ok(()) Ok(())
} }