Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "لا يمكن تشغيل المقطع",
"preset.half_size": "نصف الحجم",
"preset.half_size.donut": "نصف الحجم",
"preset.image_edit": "تعديل الصور",
"preset.image_edit.donut": "تعديل الصور",
"image_edit.count": "الصور: {0}",
"image_edit.hint": "اختر الحجم والتنسيق والتدوير لهذه الصور. يحتفظ Filee باختياراتك للمرة القادمة.",
"image_edit.convert": "تحويل",
"preset.grayscale": "تدرّج رمادي",
"preset.remove_background": "إزالة الخلفية",
"preset.trim_transparent": "قص الحواف الشفافة",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "Der Clip lässt sich nicht abspielen",
"preset.half_size": "Halbe Größe",
"preset.half_size.donut": "Halbe Größe",
"preset.image_edit": "Bilder bearbeiten",
"preset.image_edit.donut": "Bilder bearbeiten",
"image_edit.count": "{0} Bilder",
"image_edit.hint": "Wähle Größe, Format und Drehung für diese Bilder. Filee merkt sich deine Wahl für das nächste Mal.",
"image_edit.convert": "Konvertieren",
"preset.grayscale": "Graustufen",
"preset.remove_background": "Hintergrund entfernen",
"preset.trim_transparent": "Transparente Ränder abschneiden",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "Half size",
"preset.half_size.donut": "Half size",
"preset.image_edit": "Edit pictures",
"preset.image_edit.donut": "Edit pictures",
"image_edit.count": "{0} pictures",
"image_edit.hint": "Choose the size, format and rotation of these pictures. Filee keeps your choices for next time.",
"image_edit.convert": "Convert",
"preset.grayscale": "Grayscale",
"preset.remove_background": "Remove background",
"preset.trim_transparent": "Trim transparent borders",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "No se puede reproducir el clip",
"preset.half_size": "Reducir 50 %",
"preset.half_size.donut": "Reducir 50 %",
"preset.image_edit": "Editar imágenes",
"preset.image_edit.donut": "Editar imágenes",
"image_edit.count": "{0} imágenes",
"image_edit.hint": "Elige el tamaño, el formato y la rotación de estas imágenes. Filee recuerda tu elección para la próxima vez.",
"image_edit.convert": "Convertir",
"preset.grayscale": "Grises",
"preset.remove_background": "Quitar fondo",
"preset.trim_transparent": "Recortar bordes transparentes",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "Taille 50 %",
"preset.half_size.donut": "Taille 50 %",
"preset.image_edit": "Modifier les images",
"preset.image_edit.donut": "Modifier",
"image_edit.count": "{0} images",
"image_edit.hint": "Choisissez la taille, le format et la rotation de ces images. Filee garde vos choix pour la prochaine fois.",
"image_edit.convert": "Convertir",
"preset.grayscale": "Niveaux de gris",
"preset.remove_background": "Détourer",
"preset.trim_transparent": "Rogner les bords transparents",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "क्लिप नहीं चल सकती",
"preset.half_size": "आधा आकार",
"preset.half_size.donut": "आधा आकार",
"preset.image_edit": "इमेज संपादित करें",
"preset.image_edit.donut": "संपादन",
"image_edit.count": "{0} इमेज",
"image_edit.hint": "इन इमेज का आकार, फ़ॉर्मेट और घुमाव चुनें। Filee अगली बार के लिए आपकी पसंद याद रखता है।",
"image_edit.convert": "कन्वर्ट करें",
"preset.grayscale": "ग्रेस्केल",
"preset.remove_background": "बैकग्राउंड हटाएँ",
"preset.trim_transparent": "पारदर्शी किनारे काटें",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "クリップを再生できません",
"preset.half_size": "縮小 50%",
"preset.half_size.donut": "縮小 50%",
"preset.image_edit": "画像を編集",
"preset.image_edit.donut": "画像を編集",
"image_edit.count": "{0} 枚の画像",
"image_edit.hint": "この画像のサイズ、形式、回転を選んでください。選んだ内容は次回も使われます。",
"image_edit.convert": "変換",
"preset.grayscale": "グレースケール",
"preset.remove_background": "背景を削除",
"preset.trim_transparent": "透明な余白を切り取る",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "50% 축소",
"preset.half_size.donut": "50% 축소",
"preset.image_edit": "이미지 편집",
"preset.image_edit.donut": "이미지 편집",
"image_edit.count": "이미지 {0}개",
"image_edit.hint": "이 이미지들의 크기, 형식, 회전을 고르세요. 고른 값은 다음에도 그대로 쓰여요.",
"image_edit.convert": "변환",
"preset.grayscale": "흑백",
"preset.remove_background": "배경 제거",
"preset.trim_transparent": "투명 여백 자르기",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/ne.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "क्लिप बजाउन सकिँदैन",
"preset.half_size": "आधा आकार",
"preset.half_size.donut": "आधा आकार",
"preset.image_edit": "छविहरू सम्पादन गर्नुहोस्",
"preset.image_edit.donut": "सम्पादन",
"image_edit.count": "छविहरू: {0}",
"image_edit.hint": "यी छविहरूको आकार, ढाँचा र घुमाइ छान्नुहोस्। Filee ले अर्को पटकका लागि तपाईंको छनोट सम्झन्छ।",
"image_edit.convert": "रूपान्तरण गर्नुहोस्",
"preset.grayscale": "ग्रेस्केल",
"preset.remove_background": "पृष्ठभूमि हटाउनुहोस्",
"preset.trim_transparent": "पारदर्शी किनारा काट्नुहोस्",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "Połowa rozmiaru",
"preset.half_size.donut": "Połowa rozmiaru",
"preset.image_edit": "Edytuj obrazy",
"preset.image_edit.donut": "Edytuj obrazy",
"image_edit.count": "Obrazy: {0}",
"image_edit.hint": "Wybierz rozmiar, format i obrót tych obrazów. Filee zapamięta wybór na następny raz.",
"image_edit.convert": "Konwertuj",
"preset.grayscale": "Skala szarości",
"preset.remove_background": "Usuń tło",
"preset.trim_transparent": "Przytnij przezroczyste brzegi",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "Reduzir 50%",
"preset.half_size.donut": "Tamanho 50%",
"preset.image_edit": "Editar imagens",
"preset.image_edit.donut": "Editar imagens",
"image_edit.count": "{0} imagens",
"image_edit.hint": "Escolha o tamanho, o formato e a rotação dessas imagens. O Filee guarda suas escolhas para a próxima vez.",
"image_edit.convert": "Converter",
"preset.grayscale": "Tons de cinza",
"preset.remove_background": "Remover fundo",
"preset.trim_transparent": "Cortar bordas transparentes",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/pt-PT.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "Metade do tamanho",
"preset.half_size.donut": "Tamanho 50%",
"preset.image_edit": "Editar imagens",
"preset.image_edit.donut": "Editar imagens",
"image_edit.count": "{0} imagens",
"image_edit.hint": "Escolha o tamanho, o formato e a rotação destas imagens. O Filee guarda as suas escolhas para a próxima vez.",
"image_edit.convert": "Converter",
"preset.grayscale": "Escala de cinzentos",
"preset.remove_background": "Remover fundo",
"preset.trim_transparent": "Recortar margens transparentes",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "Вдвое меньше",
"preset.half_size.donut": "Вдвое меньше",
"preset.image_edit": "Изменить изображения",
"preset.image_edit.donut": "Изменить",
"image_edit.count": "Изображений: {0}",
"image_edit.hint": "Выберите размер, формат и поворот для этих изображений. Filee запомнит выбор на следующий раз.",
"image_edit.convert": "Преобразовать",
"preset.grayscale": "Оттенки серого",
"preset.remove_background": "Убрать фон",
"preset.trim_transparent": "Обрезать прозрачные края",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/th.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "เล่นคลิปนี้ไม่ได้",
"preset.half_size": "ขนาดครึ่งหนึ่ง",
"preset.half_size.donut": "ขนาดครึ่งหนึ่ง",
"preset.image_edit": "แก้ไขรูปภาพ",
"preset.image_edit.donut": "แก้ไขภาพ",
"image_edit.count": "รูปภาพ {0} รูป",
"image_edit.hint": "เลือกขนาด รูปแบบ และการหมุนของรูปภาพเหล่านี้ Filee จะจำตัวเลือกไว้ใช้ครั้งหน้า",
"image_edit.convert": "แปลง",
"preset.grayscale": "ขาวดำ (เกรย์สเกล)",
"preset.remove_background": "ลบพื้นหลัง",
"preset.trim_transparent": "ตัดขอบโปร่งใส",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
"clip.cannot_play": "Klip oynatılamıyor",
"preset.half_size": "Yarı boyut",
"preset.half_size.donut": "Yarı boyut",
"preset.image_edit": "Görselleri düzenle",
"preset.image_edit.donut": "Görselleri düzenle",
"image_edit.count": "{0} görsel",
"image_edit.hint": "Bu görsellerin boyutunu, biçimini ve yönünü seçin. Filee seçimlerinizi bir dahaki sefere hatırlar.",
"image_edit.convert": "Dönüştür",
"preset.grayscale": "Gri tonlama",
"preset.remove_background": "Arka planı kaldır",
"preset.trim_transparent": "Saydam kenarları kırp",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "缩小 50%",
"preset.half_size.donut": "缩小 50%",
"preset.image_edit": "编辑图片",
"preset.image_edit.donut": "编辑图片",
"image_edit.count": "{0} 张图片",
"image_edit.hint": "为这些图片选择尺寸、格式和旋转。Filee 会记住你的选择,下次继续使用。",
"image_edit.convert": "转换",
"preset.grayscale": "灰度",
"preset.remove_background": "去除背景",
"preset.trim_transparent": "裁掉透明边框",
Expand Down
5 changes: 5 additions & 0 deletions src/Filee.App/Assets/i18n/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@

"preset.half_size": "縮小 50%",
"preset.half_size.donut": "縮小 50%",
"preset.image_edit": "編輯圖片",
"preset.image_edit.donut": "編輯圖片",
"image_edit.count": "{0} 張圖片",
"image_edit.hint": "為這些圖片選擇尺寸、格式和旋轉。Filee 會記住你的選擇,下次繼續使用。",
"image_edit.convert": "轉換",
"preset.grayscale": "灰階",
"preset.remove_background": "去除背景",
"preset.trim_transparent": "裁掉透明邊框",
Expand Down
6 changes: 6 additions & 0 deletions src/Filee.App/Services/PresetAvailability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ private PresetJudgement Evaluate(Preset preset, IReadOnlyList<FileFormat> format
: new(PresetUse.Unusable, _loc["error.no_route"]);
}

// Any picture among the files: the others are left out when the window opens.
if (preset.IsImageEditTool)
return formats.Any(f => ImageEditTool.CanEdit(f.Id))
? new(PresetUse.Usable, null)
: new(PresetUse.Unusable, _loc["error.images_only"]);

if (preset.IsTool)
{
if (preset.Id == "tool-sheet-studio")
Expand Down
61 changes: 59 additions & 2 deletions src/Filee.App/Services/WindowService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ public sealed class WindowService(ILocalizer loc, IServiceProvider services, Mem

private CropOverlayWindow? _cropOverlay;
private ClipWindow? _clipWindow;
private ImageEditWindow? _imageEdit;

internal ClipWindow? ClipWindow => _clipWindow;
internal ImageEditWindow? ImageEdit => _imageEdit;
private readonly HashSet<SpreadsheetPrintStudioWindow> _spreadsheetStudios = [];

internal IReadOnlyCollection<SpreadsheetPrintStudioWindow> SpreadsheetStudios => _spreadsheetStudios;
Expand Down Expand Up @@ -121,13 +123,15 @@ public sealed class WindowService(ILocalizer loc, IServiceProvider services, Mem
public MainWindow? Main => _main;

/// <summary>
/// Opens the window of a tool preset (crop, cut a clip, the spreadsheet print studio: one per workbook, the PDF page
/// editor) on the files. A tool this version doesn't know opens nothing.
/// Opens the window of a tool preset (crop, cut a clip, edit pictures, the spreadsheet print studio: one per workbook,
/// the PDF page editor) on the files. A tool this version doesn't know opens nothing.
/// </summary>
public void ShowTool(IReadOnlyList<string> files, Preset preset, PixelPoint? near = null)
{
if (preset.IsClipTool)
ShowClipWindow(files, preset, near);
else if (preset.IsImageEditTool)
ShowImageEditWindow(files, preset);
// Before the crop: the print studio and the PDF page tools have no Tool of their own, which reads as a crop
// ("Crop PDF" is one and opens the crop overlay).
else if (preset.Id == "tool-sheet-studio")
Expand Down Expand Up @@ -173,6 +177,59 @@ public void ShowClipWindow(IReadOnlyList<string> files, Preset preset, PixelPoin
win.Activate();
}

/// <summary>
/// Opens the "Edit pictures" window on the pictures among the files. Its Convert starts ordinary conversions, shown
/// in the toast.
/// </summary>
public void ShowImageEditWindow(IReadOnlyList<string> files, Preset preset)
{
var pictures = files.Where(f => FormatRegistry.Detect(f) is { } format && ImageEditTool.CanEdit(format.Id)).ToList();
if (pictures.Count == 0)
return;
_imageEdit?.Close();
var store = services.GetRequiredService<UserDataStore>();
var catalog = services.GetRequiredService<ConverterCatalog>();
var conversions = services.GetRequiredService<ConversionService>();
var log = services.GetService<ILogger<ImageEditViewModel>>();
var planner = catalog.CreatePlanner();
var formats = pictures.Select(path => FormatRegistry.Detect(path)?.Id ?? "").ToList();
var vm = new ImageEditViewModel(pictures, preset, loc, store,
(path, chosen) => ImageEditTool.TargetFor(FormatRegistry.Detect(path)?.Id ?? "", chosen, planner),
(paths, conversion) => conversions.Start(paths, conversion), PictureSize, log, ImageEditTool.TargetsFrom(formats, planner));
var win = new ImageEditWindow { DataContext = vm };
PrepareWindow(win);
win.Closed += (_, _) =>
{
if (_imageEdit == win)
_imageEdit = null;
};
_imageEdit = win;
win.Show();
win.Activate();
}

/// <summary>
/// The pixel size of a picture as it is seen, read from its headers: turned as its EXIF orientation says, and the
/// largest of an icon's sizes (the one converted). Null when ImageMagick can't read it.
/// </summary>
internal static (int Width, int Height)? PictureSize(string path)
{
try
{
var info = ImageMagick.MagickImageInfo.ReadCollection(path).MaxBy(frame => (long)frame.Width * frame.Height);
if (info is null)
return null;
return info.Orientation is ImageMagick.OrientationType.LeftTop or ImageMagick.OrientationType.RightTop
or ImageMagick.OrientationType.RightBottom or ImageMagick.OrientationType.LeftBottom
? ((int)info.Height, (int)info.Width)
: ((int)info.Width, (int)info.Height);
}
catch (Exception ex) when (ex is ImageMagick.MagickException or IOException or UnauthorizedAccessException)
{
return null;
}
}

/// <summary>Opens the interactive crop overlay for the files.</summary>
public void ShowCropOverlay(IReadOnlyList<string> files, Preset preset, PixelPoint? near = null)
{
Expand Down
Loading
Loading