From 2f1fa29b5c43fbc8036a7508f31b28090d402a1c Mon Sep 17 00:00:00 2001 From: Tichau Date: Mon, 22 Aug 2016 08:11:27 +0200 Subject: [PATCH 01/36] Add the possibility to cancel image conversions. --- .../ConversionJobs/ConversionJob_ImageMagick.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs index 4ccda9f9..3103bfb4 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs @@ -14,10 +14,12 @@ public class ConversionJob_ImageMagick : ConversionJob public ConversionJob_ImageMagick() : base() { + this.IsCancelable = true; } public ConversionJob_ImageMagick(ConversionPreset conversionPreset) : base(conversionPreset) { + this.IsCancelable = true; } protected override void Initialize() @@ -199,6 +201,12 @@ private void ConvertImage(MagickImage image, bool ignoreScale = false) private void Image_Progress(object sender, ProgressEventArgs eventArgs) { + if (this.CancelIsRequested) + { + eventArgs.Cancel = true; + return; + } + float alreadyCompletedPages = this.CurrentOuputFilePathIndex / (float)this.pageCount; this.Progress = alreadyCompletedPages + (float)eventArgs.Progress.ToDouble() / (100f * this.pageCount); } From 010a68c2c0925a591a6180cd71eb205f74b010fa Mon Sep 17 00:00:00 2001 From: Tichau Date: Mon, 22 Aug 2016 08:26:26 +0200 Subject: [PATCH 02/36] Add the possibility to cancel CDA extraction, gif and ico. --- .../ConversionJobs/ConversionJob_ExtractCDA.cs | 15 +++++++++++++++ .../ConversionJobs/ConversionJob_Gif.cs | 9 +++++++++ .../ConversionJobs/ConversionJob_Ico.cs | 9 +++++++++ 3 files changed, 33 insertions(+) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs index 85e87261..71635691 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs @@ -22,10 +22,12 @@ public class ConversionJob_ExtractCDA : ConversionJob public ConversionJob_ExtractCDA() : base() { + this.IsCancelable = true; } public ConversionJob_ExtractCDA(ConversionPreset conversionPreset) : base(conversionPreset) { + this.IsCancelable = true; } protected override InputPostConversionAction InputPostConversionAction @@ -186,6 +188,13 @@ protected override void Convert() File.Delete(this.intermediateFilePath); } + public override void Cancel() + { + base.Cancel(); + + this.compressionConversionJob.Cancel(); + } + private void WriteWaveData(object sender, DataReadEventArgs eventArgs) { this.waveWriter?.Write(eventArgs.Data, 0, (int)eventArgs.DataSize); @@ -193,6 +202,12 @@ private void WriteWaveData(object sender, DataReadEventArgs eventArgs) private void CdReadProgress(object sender, ReadProgressEventArgs eventArgs) { + if (this.CancelIsRequested) + { + eventArgs.CancelRead = true; + return; + } + this.Progress = (float)eventArgs.BytesRead / (float)eventArgs.Bytes2Read; eventArgs.CancelRead |= this.State != ConversionState.InProgress; diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs index d14f6cdb..b8dfe1f5 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs @@ -14,6 +14,15 @@ public class ConversionJob_Gif : ConversionJob public ConversionJob_Gif(ConversionPreset conversionPreset) : base(conversionPreset) { + this.IsCancelable = true; + } + + public override void Cancel() + { + base.Cancel(); + + this.pngConversionJob.Cancel(); + this.gifConversionJob.Cancel(); } protected override void Initialize() diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs index e8d0ff52..5f381793 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs @@ -13,6 +13,15 @@ public class ConversionJob_Ico : ConversionJob public ConversionJob_Ico(ConversionPreset conversionPreset) : base(conversionPreset) { + this.IsCancelable = true; + } + + public override void Cancel() + { + base.Cancel(); + + this.pngConversionJob.Cancel(); + this.icoConversionJob.Cancel(); } protected override void Initialize() From 0b3ccca685cab24be5fcea481e7af4d43b29c408 Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 1 Sep 2016 22:45:29 +0200 Subject: [PATCH 03/36] Rename localization key --- .../ConversionJobs/ConversionJob_ImageMagick.cs | 2 +- .../FileConverter/Properties/Resources.Designer.cs | 12 ++++++------ .../FileConverter/Properties/Resources.en.resx | 2 +- .../FileConverter/Properties/Resources.fr.resx | 2 +- Application/FileConverter/Properties/Resources.resx | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs index 3103bfb4..06c3c77b 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs @@ -95,7 +95,7 @@ private void ConvertPdf() Debug.Log("Density: {0}dpi.", dpi); settings.Density = new Density(dpi, dpi); - this.UserState = Properties.Resources.ConversionStateReadPdf; + this.UserState = Properties.Resources.ConversionStateReadDocument; using (MagickImageCollection images = new MagickImageCollection()) { diff --git a/Application/FileConverter/Properties/Resources.Designer.cs b/Application/FileConverter/Properties/Resources.Designer.cs index cc90056d..961b4c42 100644 --- a/Application/FileConverter/Properties/Resources.Designer.cs +++ b/Application/FileConverter/Properties/Resources.Designer.cs @@ -268,20 +268,20 @@ public static string ConversionStateInQueue { } /// - /// Looks up a localized string similar to Read input image. + /// Looks up a localized string similar to Read document. /// - public static string ConversionStateReadIntputImage { + public static string ConversionStateReadDocument { get { - return ResourceManager.GetString("ConversionStateReadIntputImage", resourceCulture); + return ResourceManager.GetString("ConversionStateReadDocument", resourceCulture); } } /// - /// Looks up a localized string similar to Read document. + /// Looks up a localized string similar to Read input image. /// - public static string ConversionStateReadPdf { + public static string ConversionStateReadIntputImage { get { - return ResourceManager.GetString("ConversionStateReadPdf", resourceCulture); + return ResourceManager.GetString("ConversionStateReadIntputImage", resourceCulture); } } diff --git a/Application/FileConverter/Properties/Resources.en.resx b/Application/FileConverter/Properties/Resources.en.resx index c178ff17..f215cf1d 100644 --- a/Application/FileConverter/Properties/Resources.en.resx +++ b/Application/FileConverter/Properties/Resources.en.resx @@ -400,7 +400,7 @@ use maj for uppercase version Read input image - + Read document diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index 9ccf4355..1f6a8cef 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -414,7 +414,7 @@ utilisez maj pour une version en majuscules Lecture de l'image d'origine - + Lecture du document diff --git a/Application/FileConverter/Properties/Resources.resx b/Application/FileConverter/Properties/Resources.resx index be70475c..d7b87251 100644 --- a/Application/FileConverter/Properties/Resources.resx +++ b/Application/FileConverter/Properties/Resources.resx @@ -403,7 +403,7 @@ use maj for uppercase version Read input image - + Read document From 77d33cbb95a37d50d04fbf7eef92621dc9b4f1d2 Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 1 Sep 2016 22:58:00 +0200 Subject: [PATCH 04/36] Add possibility to convert word documents to pdf. --- .../ConversionJobs/ConversionJobFactory.cs | 13 +++- .../ConversionJobs/ConversionJob_Word.cs | 75 +++++++++++++++++++ .../FileConverter/FileConverter.csproj | 13 ++-- Application/FileConverter/Helpers.cs | 4 +- Installer/Product.wxs | 2 +- 5 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 Application/FileConverter/ConversionJobs/ConversionJob_Word.cs diff --git a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs index 83c8834d..3059cbd5 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs @@ -13,6 +13,11 @@ public static ConversionJob Create(ConversionPreset conversionPreset, string inp return new ConversionJob_ExtractCDA(conversionPreset); } + if (inputFileExtension == "doc" || inputFileExtension == "docx") + { + return new ConversionJob_Word(conversionPreset); + } + if (conversionPreset.OutputType == OutputType.Ico) { return new ConversionJob_Ico(conversionPreset); @@ -23,17 +28,17 @@ public static ConversionJob Create(ConversionPreset conversionPreset, string inp return new ConversionJob_Gif(conversionPreset); } - if (Helpers.GetExtensionCategory(inputFileExtension) == Helpers.InputCategoryNames.Image || - Helpers.GetExtensionCategory(inputFileExtension) == Helpers.InputCategoryNames.Document) + if (conversionPreset.OutputType == OutputType.Pdf) { return new ConversionJob_ImageMagick(conversionPreset); } - if (conversionPreset.OutputType == OutputType.Pdf) + if (Helpers.GetExtensionCategory(inputFileExtension) == Helpers.InputCategoryNames.Image || + Helpers.GetExtensionCategory(inputFileExtension) == Helpers.InputCategoryNames.Document) { return new ConversionJob_ImageMagick(conversionPreset); } - + return new ConversionJob_FFMPEG(conversionPreset); } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs new file mode 100644 index 00000000..d23d41e7 --- /dev/null +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -0,0 +1,75 @@ +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. + +namespace FileConverter.ConversionJobs +{ + using System; + + public class ConversionJob_Word : ConversionJob + { + private static Microsoft.Office.Interop.Word.Application wordApplication; + private static int wordApplicationRefCount = 0; + + public ConversionJob_Word() : base() + { + } + + public ConversionJob_Word(ConversionPreset conversionPreset) : base(conversionPreset) + { + } + + protected override void Initialize() + { + base.Initialize(); + + if (this.ConversionPreset == null) + { + throw new Exception("The conversion preset must be valid."); + } + + if (this.ConversionPreset.OutputType != OutputType.Pdf) + { + this.ConversionFailed("This conversion is not allowed"); + return; + } + + System.Threading.Interlocked.Increment(ref ConversionJob_Word.wordApplicationRefCount); + if (ConversionJob_Word.wordApplication == null) + { + Diagnostics.Debug.Log("Instantiate word application via interop."); + ConversionJob_Word.wordApplication = new Microsoft.Office.Interop.Word.Application + { + Visible = false + }; + } + } + + protected override void Convert() + { + if (this.ConversionPreset == null) + { + throw new Exception("The conversion preset must be valid."); + } + + this.UserState = Properties.Resources.ConversionStateReadDocument; + + object inputFilePath = this.InputFilePath; + Microsoft.Office.Interop.Word.Document document = ConversionJob_Word.wordApplication.Documents.Open(ref inputFilePath); + + // Make this document the active document. + document.Activate(); + + this.UserState = Properties.Resources.ConversionStateConversion; + + object outputFilePath = this.OutputFilePath; + object outputFileFormat = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatPDF; + document.SaveAs(ref outputFilePath, ref outputFileFormat); + + System.Threading.Interlocked.Decrement(ref ConversionJob_Word.wordApplicationRefCount); + if (ConversionJob_Word.wordApplicationRefCount == 0) + { + Diagnostics.Debug.Log("Quit word application via interop."); + ConversionJob_Word.wordApplication.Quit(); + } + } + } +} diff --git a/Application/FileConverter/FileConverter.csproj b/Application/FileConverter/FileConverter.csproj index f4f9c49f..bd8b04bf 100644 --- a/Application/FileConverter/FileConverter.csproj +++ b/Application/FileConverter/FileConverter.csproj @@ -66,7 +66,6 @@ true - ..\..\packages\Magick.NET-Q16-AnyCPU.7.0.2.900\lib\net40-client\Magick.NET-Q16-AnyCPU.dll True @@ -74,23 +73,19 @@ ..\..\Middleware\Markdown.Xaml.dll + + True + - False ..\..\Middleware\Ripper.dll - - - - - - 4.0 @@ -126,6 +121,7 @@ + @@ -257,6 +253,7 @@ PublicResXFileCodeGenerator Resources.Designer.cs + Designer diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index e748b31d..77e8fb9f 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -73,6 +73,8 @@ public static string GetExtensionCategory(string extension) return InputCategoryNames.AnimatedImage; case "pdf": + case "doc": + case "docx": return InputCategoryNames.Document; } @@ -112,7 +114,7 @@ public static bool IsOutputTypeCompatibleWithCategory(OutputType outputType, str return category == InputCategoryNames.Image || category == InputCategoryNames.Video || category == InputCategoryNames.AnimatedImage; case OutputType.Pdf: - return category == InputCategoryNames.Image; + return category == InputCategoryNames.Image || category == InputCategoryNames.Document; default: return false; diff --git a/Installer/Product.wxs b/Installer/Product.wxs index 9ffc5239..43e0207c 100644 --- a/Installer/Product.wxs +++ b/Installer/Product.wxs @@ -142,7 +142,7 @@ - + From fc000f36b2dcf516ee2b900cf258e092f2d9d66b Mon Sep 17 00:00:00 2001 From: Tichau Date: Fri, 2 Sep 2016 19:16:38 +0200 Subject: [PATCH 05/36] Add new input type: odt --- .../FileConverter/ConversionJobs/ConversionJobFactory.cs | 2 +- Application/FileConverter/Helpers.cs | 1 + Installer/Product.wxs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs index 3059cbd5..de947d03 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs @@ -13,7 +13,7 @@ public static ConversionJob Create(ConversionPreset conversionPreset, string inp return new ConversionJob_ExtractCDA(conversionPreset); } - if (inputFileExtension == "doc" || inputFileExtension == "docx") + if (inputFileExtension == "doc" || inputFileExtension == "docx" || inputFileExtension == "odt") { return new ConversionJob_Word(conversionPreset); } diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index 77e8fb9f..d797a847 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -75,6 +75,7 @@ public static string GetExtensionCategory(string extension) case "pdf": case "doc": case "docx": + case "odt": return InputCategoryNames.Document; } diff --git a/Installer/Product.wxs b/Installer/Product.wxs index 43e0207c..dc2cbd10 100644 --- a/Installer/Product.wxs +++ b/Installer/Product.wxs @@ -142,7 +142,7 @@ - + From 30574c8bb1a43f9faad31a1e2e6a3e8a38044ae9 Mon Sep 17 00:00:00 2001 From: Tichau Date: Fri, 2 Sep 2016 19:17:08 +0200 Subject: [PATCH 06/36] Missing localization key --- .../FileConverter/Properties/Resources.Designer.cs | 9 +++++++++ Application/FileConverter/Properties/Resources.en.resx | 3 +++ Application/FileConverter/Properties/Resources.fr.resx | 3 +++ Application/FileConverter/Properties/Resources.resx | 3 +++ 4 files changed, 18 insertions(+) diff --git a/Application/FileConverter/Properties/Resources.Designer.cs b/Application/FileConverter/Properties/Resources.Designer.cs index 961b4c42..520c82b4 100644 --- a/Application/FileConverter/Properties/Resources.Designer.cs +++ b/Application/FileConverter/Properties/Resources.Designer.cs @@ -1003,6 +1003,15 @@ public static string StringImageName { } } + /// + /// Looks up a localized string similar to Misc. + /// + public static string StringMiscName { + get { + return ResourceManager.GetString("StringMiscName", resourceCulture); + } + } + /// /// Looks up a localized string similar to Video. /// diff --git a/Application/FileConverter/Properties/Resources.en.resx b/Application/FileConverter/Properties/Resources.en.resx index f215cf1d..eafd3c2a 100644 --- a/Application/FileConverter/Properties/Resources.en.resx +++ b/Application/FileConverter/Properties/Resources.en.resx @@ -514,4 +514,7 @@ use maj for uppercase version The application will automatically terminate in 1 second. + + Misc + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index 1f6a8cef..2001f649 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -532,4 +532,7 @@ utilisez maj pour une version en majuscules L'application se fermera automatiquement dans 1 seconde. + + Autre + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.resx b/Application/FileConverter/Properties/Resources.resx index d7b87251..03c20a75 100644 --- a/Application/FileConverter/Properties/Resources.resx +++ b/Application/FileConverter/Properties/Resources.resx @@ -514,4 +514,7 @@ use maj for uppercase version The application will automatically terminate in 1 second. + + Misc + \ No newline at end of file From 8831babb8c28862b9da4d0668e0bcd6dd589c24e Mon Sep 17 00:00:00 2001 From: Tichau Date: Tue, 6 Sep 2016 22:55:58 +0200 Subject: [PATCH 07/36] Add missing localization keys --- .../ConversionJobs/ConversionJob.cs | 4 ++-- .../Properties/Resources.Designer.cs | 20 ++++++++++++++++++- .../Properties/Resources.en.resx | 6 ++++++ .../Properties/Resources.fr.resx | 6 ++++++ .../FileConverter/Properties/Resources.resx | 8 +++++++- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob.cs b/Application/FileConverter/ConversionJobs/ConversionJob.cs index be28ce92..d2ca75ff 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob.cs @@ -336,11 +336,11 @@ public void StartConvertion() if (this.State == ConversionJob.ConversionState.Done && !this.AllOuputFilesExists()) { - Debug.LogError("Can't find the output file(s)."); + Debug.LogError(Properties.Resources.ErrorCantFindOutputFiles); } else if (this.State == ConversionJob.ConversionState.Failed && this.AtLeastOneOuputFilesExists()) { - Debug.Log("The conversion job failed but there is an output file that does exists."); + Debug.Log(Properties.Resources.ErrorConversionFailedWithOutput); } } diff --git a/Application/FileConverter/Properties/Resources.Designer.cs b/Application/FileConverter/Properties/Resources.Designer.cs index 520c82b4..d7722b9b 100644 --- a/Application/FileConverter/Properties/Resources.Designer.cs +++ b/Application/FileConverter/Properties/Resources.Designer.cs @@ -412,7 +412,16 @@ public static string ErrorCantFindFFMPEG { } /// - /// Looks up a localized string similar to Audio CD track extraction failed. + /// Looks up a localized string similar to Can't find the output file(s).. + /// + public static string ErrorCantFindOutputFiles { + get { + return ResourceManager.GetString("ErrorCantFindOutputFiles", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Audio CD track extraction failed.. /// public static string ErrorCDAExtractionFailed { get { @@ -429,6 +438,15 @@ public static string ErrorCDDriveNotReady { } } + /// + /// Looks up a localized string similar to The conversion job failed but there is an output file that does exists.. + /// + public static string ErrorConversionFailedWithOutput { + get { + return ResourceManager.GetString("ErrorConversionFailedWithOutput", resourceCulture); + } + } + /// /// Looks up a localized string similar to Fail to launch ffmpeg.. /// diff --git a/Application/FileConverter/Properties/Resources.en.resx b/Application/FileConverter/Properties/Resources.en.resx index eafd3c2a..3a2c44ed 100644 --- a/Application/FileConverter/Properties/Resources.en.resx +++ b/Application/FileConverter/Properties/Resources.en.resx @@ -517,4 +517,10 @@ use maj for uppercase version Misc + + Can't find the output file(s). + + + The conversion job failed but there is an output file that does exists. + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index 2001f649..5da88889 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -535,4 +535,10 @@ utilisez maj pour une version en majuscules Autre + + Les fichiers n'ont pas pu être converti. + + + Des fichiers sont présents malgré l'echec de la conversion. + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.resx b/Application/FileConverter/Properties/Resources.resx index 03c20a75..2c392768 100644 --- a/Application/FileConverter/Properties/Resources.resx +++ b/Application/FileConverter/Properties/Resources.resx @@ -446,7 +446,7 @@ use maj for uppercase version Fail to find ffmpeg executable. You should try to reinstall the application. - Audio CD track extraction failed + Audio CD track extraction failed. CD drive is not ready. @@ -517,4 +517,10 @@ use maj for uppercase version Misc + + Can't find the output file(s). + + + The conversion job failed but there is an output file that does exists. + \ No newline at end of file From 7daa49e95d91368e0662bfd971a5547d7d7fb59f Mon Sep 17 00:00:00 2001 From: Tichau Date: Tue, 6 Sep 2016 23:02:40 +0200 Subject: [PATCH 08/36] Add possibility to convert word documents to images. --- .../ConversionJobs/ConversionJob.cs | 53 ++++--- .../ConversionJobs/ConversionJob_Word.cs | 137 +++++++++++++++--- .../ConversionPreset/ConversionPreset.cs | 9 +- 3 files changed, 157 insertions(+), 42 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob.cs b/Application/FileConverter/ConversionJobs/ConversionJob.cs index d2ca75ff..45374c3e 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob.cs @@ -19,7 +19,6 @@ public class ConversionJob : INotifyPropertyChanged private CancelConversionJobCommand cancelCommand; private string initialInputPath = string.Empty; - private string[] outputFilePaths; private int currentOuputFilePathIndex; public ConversionJob() @@ -67,22 +66,22 @@ public string OutputFilePath { get { - if (this.outputFilePaths == null) + if (this.OutputFilePaths == null) { return string.Empty; } if (this.CurrentOuputFilePathIndex < 0) { - return this.outputFilePaths[0]; + return this.OutputFilePaths[0]; } - if (this.CurrentOuputFilePathIndex >= this.outputFilePaths.Length) + if (this.CurrentOuputFilePathIndex >= this.OutputFilePaths.Length) { - return this.outputFilePaths[this.outputFilePaths.Length - 1]; + return this.OutputFilePaths[this.OutputFilePaths.Length - 1]; } - return this.outputFilePaths[this.CurrentOuputFilePathIndex]; + return this.OutputFilePaths[this.CurrentOuputFilePathIndex]; } } @@ -200,12 +199,18 @@ protected virtual InputPostConversionAction InputPostConversionAction } } + protected string[] OutputFilePaths + { + get; + private set; + } + public virtual bool CanStartConversion(ConversionFlags conversionFlags) { return (conversionFlags & ConversionFlags.CdDriveExtraction) == 0; } - public void PrepareConversion(string inputFilePath, string outputFilePath = null) + public void PrepareConversion(string inputFilePath, params string[] outputFilePaths) { if (string.IsNullOrEmpty(inputFilePath)) { @@ -229,12 +234,22 @@ public void PrepareConversion(string inputFilePath, string outputFilePath = null this.initialInputPath = inputFilePath; this.InputFilePath = inputFilePath; - int outputFilesCount = this.GetOuputFilesCount(); - this.outputFilePaths = new string[outputFilesCount]; + this.OutputFilePaths = outputFilePaths; + if (this.OutputFilePaths.Length == 0) + { + int outputFilesCount = this.GetOuputFilesCount(); + this.OutputFilePaths = new string[outputFilesCount]; + } - for (int index = 0; index < outputFilesCount; index++) + for (int index = 0; index < this.OutputFilePaths.Length; index++) { - string path = outputFilePath ?? this.ConversionPreset.GenerateOutputFilePath(inputFilePath, index + 1, outputFilesCount); + if (!string.IsNullOrEmpty(this.OutputFilePaths[index])) + { + // Don't generate a path if it has already been set. + continue; + } + + string path = this.ConversionPreset.GenerateOutputFilePath(inputFilePath, index + 1, this.OutputFilePaths.Length); if (!PathHelpers.IsPathValid(path)) { @@ -266,7 +281,7 @@ public void PrepareConversion(string inputFilePath, string outputFilePath = null // Make the output path valid. try { - path = PathHelpers.GenerateUniquePath(path, this.outputFilePaths); + path = PathHelpers.GenerateUniquePath(path, this.OutputFilePaths); } catch (Exception exception) { @@ -275,7 +290,7 @@ public void PrepareConversion(string inputFilePath, string outputFilePath = null return; } - this.outputFilePaths[index] = path; + this.OutputFilePaths[index] = path; } this.CurrentOuputFilePathIndex = 0; @@ -372,9 +387,9 @@ protected virtual void OnConversionFailed() { Debug.Log("Conversion Failed."); - for (int index = 0; index < this.outputFilePaths.Length; index++) + for (int index = 0; index < this.OutputFilePaths.Length; index++) { - string outputFilePath = this.outputFilePaths[index]; + string outputFilePath = this.OutputFilePaths[index]; try { if (System.IO.File.Exists(outputFilePath)) @@ -453,9 +468,9 @@ protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "" private bool AllOuputFilesExists() { - for (int index = 0; index < this.outputFilePaths.Length; index++) + for (int index = 0; index < this.OutputFilePaths.Length; index++) { - string outputFilePath = this.outputFilePaths[index]; + string outputFilePath = this.OutputFilePaths[index]; if (!System.IO.File.Exists(outputFilePath)) { return false; @@ -467,9 +482,9 @@ private bool AllOuputFilesExists() private bool AtLeastOneOuputFilesExists() { - for (int index = 0; index < this.outputFilePaths.Length; index++) + for (int index = 0; index < this.OutputFilePaths.Length; index++) { - string outputFilePath = this.outputFilePaths[index]; + string outputFilePath = this.OutputFilePaths[index]; if (System.IO.File.Exists(outputFilePath)) { return true; diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index d23d41e7..5ad13288 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -2,19 +2,43 @@ namespace FileConverter.ConversionJobs { - using System; + using System.IO; + using System.Threading.Tasks; + + using Word = Microsoft.Office.Interop.Word; public class ConversionJob_Word : ConversionJob { - private static Microsoft.Office.Interop.Word.Application wordApplication; + private static Word.Application wordApplication; private static int wordApplicationRefCount = 0; + private string intermediateFilePath = string.Empty; + private ConversionJob pdf2ImageConversionJob = null; + private Word.Document document; + public ConversionJob_Word() : base() { + ConversionJob_Word.InitializeWordApplicationInstance(); } public ConversionJob_Word(ConversionPreset conversionPreset) : base(conversionPreset) { + ConversionJob_Word.InitializeWordApplicationInstance(); + } + + protected override int GetOuputFilesCount() + { + if (this.ConversionPreset.OutputType == OutputType.Pdf) + { + return 1; + } + + Diagnostics.Debug.Log("Load word document '{0}'.", this.InputFilePath); + this.document = ConversionJob_Word.wordApplication.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); + + int pagesCount = this.document.ComputeStatistics(Word.WdStatistic.wdStatisticPages); + + return pagesCount; } protected override void Initialize() @@ -23,23 +47,24 @@ protected override void Initialize() if (this.ConversionPreset == null) { - throw new Exception("The conversion preset must be valid."); + throw new System.Exception("The conversion preset must be valid."); } - if (this.ConversionPreset.OutputType != OutputType.Pdf) + // Initialize converters. + if (this.ConversionPreset.OutputType == OutputType.Pdf) { - this.ConversionFailed("This conversion is not allowed"); - return; + this.intermediateFilePath = this.OutputFilePath; } - - System.Threading.Interlocked.Increment(ref ConversionJob_Word.wordApplicationRefCount); - if (ConversionJob_Word.wordApplication == null) + else { - Diagnostics.Debug.Log("Instantiate word application via interop."); - ConversionJob_Word.wordApplication = new Microsoft.Office.Interop.Word.Application - { - Visible = false - }; + // Generate intermediate file path. + string fileName = Path.GetFileNameWithoutExtension(this.InputFilePath); + string tempPath = Path.GetTempPath(); + this.intermediateFilePath = PathHelpers.GenerateUniquePath(tempPath + fileName + ".pdf"); + + ConversionPreset intermediatePreset = new ConversionPreset("Pdf to image", this.ConversionPreset, "pdf"); + this.pdf2ImageConversionJob = ConversionJobFactory.Create(intermediatePreset, this.intermediateFilePath); + this.pdf2ImageConversionJob.PrepareConversion(this.intermediateFilePath, this.OutputFilePaths); } } @@ -47,22 +72,28 @@ protected override void Convert() { if (this.ConversionPreset == null) { - throw new Exception("The conversion preset must be valid."); + throw new System.Exception("The conversion preset must be valid."); } this.UserState = Properties.Resources.ConversionStateReadDocument; - object inputFilePath = this.InputFilePath; - Microsoft.Office.Interop.Word.Document document = ConversionJob_Word.wordApplication.Documents.Open(ref inputFilePath); + if (this.document == null) + { + Diagnostics.Debug.Log("Load word document '{0}'.", this.InputFilePath); + this.document = ConversionJob_Word.wordApplication.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); + } // Make this document the active document. - document.Activate(); + this.document.Activate(); this.UserState = Properties.Resources.ConversionStateConversion; - object outputFilePath = this.OutputFilePath; - object outputFileFormat = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatPDF; - document.SaveAs(ref outputFilePath, ref outputFileFormat); + Diagnostics.Debug.Log("Load word document to pdf."); + this.document.SaveAs(this.intermediateFilePath, Word.WdSaveFormat.wdFormatPDF); + + Diagnostics.Debug.Log("Close word document '{0}'.", this.InputFilePath); + this.document.Close(Word.WdSaveOptions.wdDoNotSaveChanges); + this.document = null; System.Threading.Interlocked.Decrement(ref ConversionJob_Word.wordApplicationRefCount); if (ConversionJob_Word.wordApplicationRefCount == 0) @@ -70,6 +101,70 @@ protected override void Convert() Diagnostics.Debug.Log("Quit word application via interop."); ConversionJob_Word.wordApplication.Quit(); } + + if (this.pdf2ImageConversionJob != null) + { + if (!System.IO.File.Exists(this.intermediateFilePath)) + { + this.ConversionFailed(Properties.Resources.ErrorCantFindOutputFiles); + return; + } + + Task updateProgress = this.UpdateProgress(); + + Diagnostics.Debug.Log("Convert pdf to images."); + + this.pdf2ImageConversionJob.StartConvertion(); + + if (this.pdf2ImageConversionJob.State != ConversionState.Done) + { + this.ConversionFailed(this.pdf2ImageConversionJob.ErrorMessage); + return; + } + + if (!string.IsNullOrEmpty(this.intermediateFilePath)) + { + Diagnostics.Debug.Log("Delete intermediate file {0}.", this.intermediateFilePath); + + File.Delete(this.intermediateFilePath); + } + + updateProgress.Wait(); + } + } + + private static void InitializeWordApplicationInstance() + { + // Initialize word application. + System.Threading.Interlocked.Increment(ref ConversionJob_Word.wordApplicationRefCount); + if (ConversionJob_Word.wordApplication == null) + { + Diagnostics.Debug.Log("Instantiate word application via interop."); + ConversionJob_Word.wordApplication = new Microsoft.Office.Interop.Word.Application + { + Visible = false + }; + } + } + + private async Task UpdateProgress() + { + while (this.pdf2ImageConversionJob.State != ConversionState.Done && + this.pdf2ImageConversionJob.State != ConversionState.Failed) + { + if (this.pdf2ImageConversionJob != null && this.pdf2ImageConversionJob.State == ConversionState.InProgress) + { + this.Progress = this.pdf2ImageConversionJob.Progress; + } + + if (this.pdf2ImageConversionJob != null && this.pdf2ImageConversionJob.State == ConversionState.InProgress) + { + this.Progress = this.pdf2ImageConversionJob.Progress; + this.UserState = this.pdf2ImageConversionJob.UserState; + } + + await Task.Delay(40); + } } } } diff --git a/Application/FileConverter/ConversionPreset/ConversionPreset.cs b/Application/FileConverter/ConversionPreset/ConversionPreset.cs index 5228799e..2a261e8c 100644 --- a/Application/FileConverter/ConversionPreset/ConversionPreset.cs +++ b/Application/FileConverter/ConversionPreset/ConversionPreset.cs @@ -30,7 +30,7 @@ public ConversionPreset() this.Name = Properties.Resources.DefaultPresetName; } - public ConversionPreset(string name, OutputType outputType, string[] inputTypes) + public ConversionPreset(string name, OutputType outputType, params string[] inputTypes) { this.Name = name; this.OutputType = outputType; @@ -41,7 +41,7 @@ public ConversionPreset(string name, OutputType outputType, string[] inputTypes) this.outputFileNameTemplate = "(p)(f)"; } - public ConversionPreset(string name, ConversionPreset source) + public ConversionPreset(string name, ConversionPreset source, params string[] additionalInputTypes) { this.Name = name; this.OutputType = source.outputType; @@ -51,6 +51,11 @@ public ConversionPreset(string name, ConversionPreset source) inputTypeList.AddRange(source.inputTypes); } + if (additionalInputTypes != null) + { + inputTypeList.AddRange(additionalInputTypes); + } + this.InputTypes = inputTypeList; this.outputFileNameTemplate = source.OutputFileNameTemplate; From b01d577f6b35838f0804ed3c5e641d6f3fdc0bf7 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:03:14 +0200 Subject: [PATCH 09/36] Improve application reactivity. The conversion preparation is now threaded since it can take a big amount of time to do it (for document conversions) --- Application/FileConverter/Application.xaml.cs | 11 +++++-- .../ConversionJobs/ConversionJob.cs | 33 ++++++++++--------- .../ConversionJobs/ConversionJobFactory.cs | 14 ++++---- .../ConversionJob_ExtractCDA.cs | 4 +-- .../ConversionJobs/ConversionJob_FFMPEG.cs | 2 +- .../ConversionJobs/ConversionJob_Gif.cs | 8 ++--- .../ConversionJobs/ConversionJob_Ico.cs | 8 ++--- .../ConversionJob_ImageMagick.cs | 2 +- .../ConversionJobs/ConversionJob_Word.cs | 2 +- .../Properties/Resources.Designer.cs | 9 +++++ .../Properties/Resources.en.resx | 3 ++ .../Properties/Resources.fr.resx | 3 ++ .../FileConverter/Properties/Resources.resx | 3 ++ 13 files changed, 64 insertions(+), 38 deletions(-) diff --git a/Application/FileConverter/Application.xaml.cs b/Application/FileConverter/Application.xaml.cs index 04318e5a..aad57b69 100644 --- a/Application/FileConverter/Application.xaml.cs +++ b/Application/FileConverter/Application.xaml.cs @@ -341,8 +341,7 @@ private void Initialize() { string inputFilePath = filePaths[index]; ConversionJob conversionJob = ConversionJobFactory.Create(conversionPreset, inputFilePath); - conversionJob.PrepareConversion(inputFilePath); - + this.conversionJobs.Add(conversionJob); } } @@ -358,8 +357,14 @@ private void Initialize() private void ConvertFiles() { - Thread[] jobThreads = new Thread[this.numberOfConversionThread]; + // Prepare conversions. + for (int index = 0; index < this.ConvertionJobs.Count; index++) + { + this.ConvertionJobs[index].PrepareConversion(); + } + // Convert! + Thread[] jobThreads = new Thread[this.numberOfConversionThread]; while (true) { // Compute conversion flags. diff --git a/Application/FileConverter/ConversionJobs/ConversionJob.cs b/Application/FileConverter/ConversionJobs/ConversionJob.cs index 45374c3e..463a8e0a 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob.cs @@ -25,17 +25,26 @@ public ConversionJob() { this.State = ConversionState.Unknown; this.ConversionPreset = null; + this.initialInputPath = string.Empty; this.InputFilePath = string.Empty; } - public ConversionJob(ConversionPreset conversionPreset) : this() + public ConversionJob(ConversionPreset conversionPreset, string inputFilePath) : this() { if (conversionPreset == null) { - throw new ArgumentNullException("conversionPreset"); + throw new ArgumentNullException(nameof(conversionPreset)); } + if (string.IsNullOrEmpty(inputFilePath)) + { + throw new ArgumentNullException(nameof(inputFilePath)); + } + + this.initialInputPath = inputFilePath; + this.InputFilePath = inputFilePath; this.ConversionPreset = conversionPreset; + this.UserState = Properties.Resources.ConversionStatePrepareConversion; } public event PropertyChangedEventHandler PropertyChanged; @@ -66,7 +75,7 @@ public string OutputFilePath { get { - if (this.OutputFilePaths == null) + if (this.OutputFilePaths == null || this.OutputFilePaths.Length == 0) { return string.Empty; } @@ -210,19 +219,16 @@ public virtual bool CanStartConversion(ConversionFlags conversionFlags) return (conversionFlags & ConversionFlags.CdDriveExtraction) == 0; } - public void PrepareConversion(string inputFilePath, params string[] outputFilePaths) + public void PrepareConversion(params string[] outputFilePaths) { - if (string.IsNullOrEmpty(inputFilePath)) - { - throw new ArgumentNullException(nameof(inputFilePath)); - } - if (this.ConversionPreset == null) { throw new Exception("The conversion preset must be valid."); } - string extension = System.IO.Path.GetExtension(inputFilePath); + this.InputFilePath = this.initialInputPath; + + string extension = System.IO.Path.GetExtension(this.initialInputPath); extension = extension.Substring(1, extension.Length - 1); string extensionCategory = Helpers.GetExtensionCategory(extension); if (!Helpers.IsOutputTypeCompatibleWithCategory(this.ConversionPreset.OutputType, extensionCategory)) @@ -231,9 +237,6 @@ public void PrepareConversion(string inputFilePath, params string[] outputFilePa return; } - this.initialInputPath = inputFilePath; - this.InputFilePath = inputFilePath; - this.OutputFilePaths = outputFilePaths; if (this.OutputFilePaths.Length == 0) { @@ -249,7 +252,7 @@ public void PrepareConversion(string inputFilePath, params string[] outputFilePa continue; } - string path = this.ConversionPreset.GenerateOutputFilePath(inputFilePath, index + 1, this.OutputFilePaths.Length); + string path = this.ConversionPreset.GenerateOutputFilePath(this.initialInputPath, index + 1, this.OutputFilePaths.Length); if (!PathHelpers.IsPathValid(path)) { @@ -267,7 +270,7 @@ public void PrepareConversion(string inputFilePath, params string[] outputFilePa string inputExtension = System.IO.Path.GetExtension(this.InputFilePath); string pathWithoutExtension = this.InputFilePath.Substring(0, this.InputFilePath.Length - inputExtension.Length); this.InputFilePath = PathHelpers.GenerateUniquePath(pathWithoutExtension + "_TEMP" + inputExtension); - System.IO.File.Move(inputFilePath, this.InputFilePath); + System.IO.File.Move(this.initialInputPath, this.InputFilePath); } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs index de947d03..b6ffb916 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs @@ -10,36 +10,36 @@ public static ConversionJob Create(ConversionPreset conversionPreset, string inp inputFileExtension = inputFileExtension.ToLowerInvariant().Substring(1, inputFileExtension.Length - 1); if (inputFileExtension == "cda") { - return new ConversionJob_ExtractCDA(conversionPreset); + return new ConversionJob_ExtractCDA(conversionPreset, inputFilePath); } if (inputFileExtension == "doc" || inputFileExtension == "docx" || inputFileExtension == "odt") { - return new ConversionJob_Word(conversionPreset); + return new ConversionJob_Word(conversionPreset, inputFilePath); } if (conversionPreset.OutputType == OutputType.Ico) { - return new ConversionJob_Ico(conversionPreset); + return new ConversionJob_Ico(conversionPreset, inputFilePath); } if (conversionPreset.OutputType == OutputType.Gif) { - return new ConversionJob_Gif(conversionPreset); + return new ConversionJob_Gif(conversionPreset, inputFilePath); } if (conversionPreset.OutputType == OutputType.Pdf) { - return new ConversionJob_ImageMagick(conversionPreset); + return new ConversionJob_ImageMagick(conversionPreset, inputFilePath); } if (Helpers.GetExtensionCategory(inputFileExtension) == Helpers.InputCategoryNames.Image || Helpers.GetExtensionCategory(inputFileExtension) == Helpers.InputCategoryNames.Document) { - return new ConversionJob_ImageMagick(conversionPreset); + return new ConversionJob_ImageMagick(conversionPreset, inputFilePath); } - return new ConversionJob_FFMPEG(conversionPreset); + return new ConversionJob_FFMPEG(conversionPreset, inputFilePath); } } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs index 71635691..5adcc3c5 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs @@ -25,7 +25,7 @@ public ConversionJob_ExtractCDA() : base() this.IsCancelable = true; } - public ConversionJob_ExtractCDA(ConversionPreset conversionPreset) : base(conversionPreset) + public ConversionJob_ExtractCDA(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) { this.IsCancelable = true; } @@ -105,7 +105,7 @@ protected override void Initialize() // Sub conversion job (for compression). this.compressionConversionJob = ConversionJobFactory.Create(this.ConversionPreset, this.intermediateFilePath); - this.compressionConversionJob.PrepareConversion(this.intermediateFilePath, this.OutputFilePath); + this.compressionConversionJob.PrepareConversion(this.OutputFilePath); this.compressionThread = Helpers.InstantiateThread("CDACompressionThread", this.CompressAsync); } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.cs b/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.cs index 6cb53ef8..df6d9912 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.cs @@ -28,7 +28,7 @@ public ConversionJob_FFMPEG() : base() this.IsCancelable = true; } - public ConversionJob_FFMPEG(ConversionPreset conversionPreset) : base(conversionPreset) + public ConversionJob_FFMPEG(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) { this.IsCancelable = true; } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs index b8dfe1f5..8035b126 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Gif.cs @@ -12,7 +12,7 @@ public class ConversionJob_Gif : ConversionJob private ConversionJob pngConversionJob = null; private ConversionJob gifConversionJob = null; - public ConversionJob_Gif(ConversionPreset conversionPreset) : base(conversionPreset) + public ConversionJob_Gif(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) { this.IsCancelable = true; } @@ -50,7 +50,7 @@ protected override void Initialize() // Convert input in png file to send it to ffmpeg for the gif conversion. ConversionPreset intermediatePreset = new ConversionPreset("To compatible image", OutputType.Png, this.ConversionPreset.InputTypes.ToArray()); this.pngConversionJob = ConversionJobFactory.Create(intermediatePreset, this.InputFilePath); - this.pngConversionJob.PrepareConversion(this.InputFilePath, this.intermediateFilePath); + this.pngConversionJob.PrepareConversion(this.intermediateFilePath); inputFilePath = this.intermediateFilePath; } @@ -60,8 +60,8 @@ protected override void Initialize() } // Convert png file into ico. - this.gifConversionJob = new ConversionJob_FFMPEG(this.ConversionPreset); - this.gifConversionJob.PrepareConversion(inputFilePath, this.OutputFilePath); + this.gifConversionJob = new ConversionJob_FFMPEG(this.ConversionPreset, inputFilePath); + this.gifConversionJob.PrepareConversion(this.OutputFilePath); } protected override void Convert() diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs index 5f381793..46f8b737 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Ico.cs @@ -11,7 +11,7 @@ public class ConversionJob_Ico : ConversionJob private ConversionJob pngConversionJob; private ConversionJob icoConversionJob; - public ConversionJob_Ico(ConversionPreset conversionPreset) : base(conversionPreset) + public ConversionJob_Ico(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) { this.IsCancelable = true; } @@ -43,11 +43,11 @@ protected override void Initialize() intermediatePreset.SetSettingsValue(ConversionPreset.ConversionSettingKeys.ImageClampSizePowerOf2, "True"); intermediatePreset.SetSettingsValue(ConversionPreset.ConversionSettingKeys.ImageMaximumSize, "256"); this.pngConversionJob = ConversionJobFactory.Create(intermediatePreset, this.InputFilePath); - this.pngConversionJob.PrepareConversion(this.InputFilePath, this.intermediateFilePath); + this.pngConversionJob.PrepareConversion(this.intermediateFilePath); // Convert png file into ico. - this.icoConversionJob = new ConversionJob_FFMPEG(this.ConversionPreset); - this.icoConversionJob.PrepareConversion(this.intermediateFilePath, this.OutputFilePath); + this.icoConversionJob = new ConversionJob_FFMPEG(this.ConversionPreset, this.intermediateFilePath); + this.icoConversionJob.PrepareConversion(this.OutputFilePath); } protected override void Convert() diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs index 06c3c77b..8e2d7d79 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs @@ -17,7 +17,7 @@ public ConversionJob_ImageMagick() : base() this.IsCancelable = true; } - public ConversionJob_ImageMagick(ConversionPreset conversionPreset) : base(conversionPreset) + public ConversionJob_ImageMagick(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) { this.IsCancelable = true; } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index 5ad13288..db0b8de1 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -21,7 +21,7 @@ public ConversionJob_Word() : base() ConversionJob_Word.InitializeWordApplicationInstance(); } - public ConversionJob_Word(ConversionPreset conversionPreset) : base(conversionPreset) + public ConversionJob_Word(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) { ConversionJob_Word.InitializeWordApplicationInstance(); } diff --git a/Application/FileConverter/Properties/Resources.Designer.cs b/Application/FileConverter/Properties/Resources.Designer.cs index d7722b9b..521691d8 100644 --- a/Application/FileConverter/Properties/Resources.Designer.cs +++ b/Application/FileConverter/Properties/Resources.Designer.cs @@ -267,6 +267,15 @@ public static string ConversionStateInQueue { } } + /// + /// Looks up a localized string similar to Prepare conversion. + /// + public static string ConversionStatePrepareConversion { + get { + return ResourceManager.GetString("ConversionStatePrepareConversion", resourceCulture); + } + } + /// /// Looks up a localized string similar to Read document. /// diff --git a/Application/FileConverter/Properties/Resources.en.resx b/Application/FileConverter/Properties/Resources.en.resx index 3a2c44ed..cfd3a0e0 100644 --- a/Application/FileConverter/Properties/Resources.en.resx +++ b/Application/FileConverter/Properties/Resources.en.resx @@ -523,4 +523,7 @@ use maj for uppercase version The conversion job failed but there is an output file that does exists. + + Prepare conversion + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index 5da88889..1571b89d 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -541,4 +541,7 @@ utilisez maj pour une version en majuscules Des fichiers sont présents malgré l'echec de la conversion. + + Préparation + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.resx b/Application/FileConverter/Properties/Resources.resx index 2c392768..37aa21b0 100644 --- a/Application/FileConverter/Properties/Resources.resx +++ b/Application/FileConverter/Properties/Resources.resx @@ -523,4 +523,7 @@ use maj for uppercase version The conversion job failed but there is an output file that does exists. + + Prepare conversion + \ No newline at end of file From 9ba447e1229b37f2fd20ba4feba4dd9379cbd3e9 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:04:29 +0200 Subject: [PATCH 10/36] Fix concurrent access issues with the use of word from multiple threads --- .../ConversionJobs/ConversionJob_Word.cs | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index db0b8de1..e30bfe9d 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -9,21 +9,18 @@ namespace FileConverter.ConversionJobs public class ConversionJob_Word : ConversionJob { - private static Word.Application wordApplication; - private static int wordApplicationRefCount = 0; + private Word.Document document; + private Word.Application wordApplication; private string intermediateFilePath = string.Empty; private ConversionJob pdf2ImageConversionJob = null; - private Word.Document document; public ConversionJob_Word() : base() { - ConversionJob_Word.InitializeWordApplicationInstance(); } public ConversionJob_Word(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) { - ConversionJob_Word.InitializeWordApplicationInstance(); } protected override int GetOuputFilesCount() @@ -33,8 +30,7 @@ protected override int GetOuputFilesCount() return 1; } - Diagnostics.Debug.Log("Load word document '{0}'.", this.InputFilePath); - this.document = ConversionJob_Word.wordApplication.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); + this.LoadDocumentIfNecessary(); int pagesCount = this.document.ComputeStatistics(Word.WdStatistic.wdStatisticPages); @@ -64,7 +60,7 @@ protected override void Initialize() ConversionPreset intermediatePreset = new ConversionPreset("Pdf to image", this.ConversionPreset, "pdf"); this.pdf2ImageConversionJob = ConversionJobFactory.Create(intermediatePreset, this.intermediateFilePath); - this.pdf2ImageConversionJob.PrepareConversion(this.intermediateFilePath, this.OutputFilePaths); + this.pdf2ImageConversionJob.PrepareConversion(this.OutputFilePaths); } } @@ -77,30 +73,21 @@ protected override void Convert() this.UserState = Properties.Resources.ConversionStateReadDocument; - if (this.document == null) - { - Diagnostics.Debug.Log("Load word document '{0}'.", this.InputFilePath); - this.document = ConversionJob_Word.wordApplication.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); - } + this.LoadDocumentIfNecessary(); // Make this document the active document. this.document.Activate(); this.UserState = Properties.Resources.ConversionStateConversion; - Diagnostics.Debug.Log("Load word document to pdf."); + Diagnostics.Debug.Log("Convert word document to pdf."); this.document.SaveAs(this.intermediateFilePath, Word.WdSaveFormat.wdFormatPDF); Diagnostics.Debug.Log("Close word document '{0}'.", this.InputFilePath); this.document.Close(Word.WdSaveOptions.wdDoNotSaveChanges); this.document = null; - System.Threading.Interlocked.Decrement(ref ConversionJob_Word.wordApplicationRefCount); - if (ConversionJob_Word.wordApplicationRefCount == 0) - { - Diagnostics.Debug.Log("Quit word application via interop."); - ConversionJob_Word.wordApplication.Quit(); - } + this.ReleaseWordApplicationInstanceIfNeeded(); if (this.pdf2ImageConversionJob != null) { @@ -133,20 +120,6 @@ protected override void Convert() } } - private static void InitializeWordApplicationInstance() - { - // Initialize word application. - System.Threading.Interlocked.Increment(ref ConversionJob_Word.wordApplicationRefCount); - if (ConversionJob_Word.wordApplication == null) - { - Diagnostics.Debug.Log("Instantiate word application via interop."); - ConversionJob_Word.wordApplication = new Microsoft.Office.Interop.Word.Application - { - Visible = false - }; - } - } - private async Task UpdateProgress() { while (this.pdf2ImageConversionJob.State != ConversionState.Done && @@ -166,5 +139,38 @@ private async Task UpdateProgress() await Task.Delay(40); } } + + private void LoadDocumentIfNecessary() + { + this.InitializeWordApplicationInstanceIfNecessary(); + + if (this.document == null) + { + Diagnostics.Debug.Log("Load word document '{0}'.", this.InputFilePath); + + this.document = this.wordApplication.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); + } + } + + private void InitializeWordApplicationInstanceIfNecessary() + { + if (this.wordApplication != null) + { + return; + } + + // Initialize word application. + Diagnostics.Debug.Log("Instantiate word application via interop."); + this.wordApplication = new Microsoft.Office.Interop.Word.Application + { + Visible = false + }; + } + + private void ReleaseWordApplicationInstanceIfNeeded() + { + Diagnostics.Debug.Log("Quit word application via interop."); + this.wordApplication.Quit(); + } } } From 897c9c5fcbe2efa0f73d7915a56d64b546463bbd Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:05:01 +0200 Subject: [PATCH 11/36] Improve diagnostics data naming --- Application/FileConverter/Diagnostics/Debug.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Application/FileConverter/Diagnostics/Debug.cs b/Application/FileConverter/Diagnostics/Debug.cs index 2eb8fdfa..350999c7 100644 --- a/Application/FileConverter/Diagnostics/Debug.cs +++ b/Application/FileConverter/Diagnostics/Debug.cs @@ -5,9 +5,9 @@ namespace FileConverter.Diagnostics using System; using System.Collections.Generic; using System.ComponentModel; - using System.Diagnostics; using System.IO; using System.Linq; + using System.Threading; using System.Windows; public static class Debug @@ -54,12 +54,14 @@ public static void Log(string message, params object[] arguments) { DiagnosticsData diagnosticsData; - int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId; + Thread currentThread = System.Threading.Thread.CurrentThread; + int threadId = currentThread.ManagedThreadId; lock (Debug.diagnosticsDataById) { if (!Debug.diagnosticsDataById.TryGetValue(threadId, out diagnosticsData)) { - diagnosticsData = new DiagnosticsData(Debug.threadCount > 0 ? string.Format("Thread {0}", Debug.threadCount) : "Application"); + string threadName = Debug.threadCount > 0 ? $"{currentThread.Name} ({Debug.threadCount})" : "Application"; + diagnosticsData = new DiagnosticsData(threadName); diagnosticsData.Initialize(Debug.diagnosticsFolderPath, threadId); Debug.diagnosticsDataById.Add(threadId, diagnosticsData); Debug.threadCount++; From cfa6757312ce3b5ad4b7e976c7233d0630b85c5d Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:06:26 +0200 Subject: [PATCH 12/36] Improve diagnostics data naming --- Application/FileConverter/Application.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/FileConverter/Application.xaml.cs b/Application/FileConverter/Application.xaml.cs index aad57b69..9b621d2d 100644 --- a/Application/FileConverter/Application.xaml.cs +++ b/Application/FileConverter/Application.xaml.cs @@ -401,7 +401,7 @@ private void ConvertFiles() Thread thread = jobThreads[threadIndex]; if (thread == null || !thread.IsAlive) { - jobThread = Helpers.InstantiateThread("ConversionThread", this.ExecuteConversionJob); + jobThread = Helpers.InstantiateThread(conversionJob.GetType().Name, this.ExecuteConversionJob); jobThreads[threadIndex] = jobThread; break; } From 569dedcf65731dafaa5c32724e3b26ec7674db96 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:07:40 +0200 Subject: [PATCH 13/36] Fix multi threading issue Fix an issue where multiple conversion jobs was created for the same file in some cases. --- Application/FileConverter/Application.xaml.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Application/FileConverter/Application.xaml.cs b/Application/FileConverter/Application.xaml.cs index 9b621d2d..02eee853 100644 --- a/Application/FileConverter/Application.xaml.cs +++ b/Application/FileConverter/Application.xaml.cs @@ -410,6 +410,12 @@ private void ConvertFiles() if (jobThread != null) { jobThread.Start(conversionJob); + + while (conversionJob.State == ConversionJob.ConversionState.Ready) + { + Debug.Log("Wait the launch of the conversion thread before launching any other thread."); + Thread.Sleep(20); + } } break; From 1513aa19df9903c3cbb1270de12cceba6ac7a975 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:25:41 +0200 Subject: [PATCH 14/36] Stylecop --- .../ConversionJob_ExtractCDA.cs | 16 +++---- .../ConversionJob_FFMPEG.Converters.cs | 2 +- .../ConversionJob_ImageMagick.cs | 10 ++--- .../ConversionJobs/ConversionJob_Word.cs | 2 +- .../FileConverter/FileConverter.csproj | 2 + Application/FileConverter/Helpers.cs | 6 +-- Application/FileConverter/PathHelpers.cs | 2 +- .../FileConverter/Settings.Settings.cs | 5 +-- Application/FileConverter/Upgrade/Helpers.cs | 2 +- .../Upgrade/UpgradeVersionDescription.cs | 9 ++-- .../Generic/CultureInfoToStringConverter.cs | 4 +- .../Generic/ObjectToLocalizedString.cs | 2 +- .../OutputTypeEnumToViewModel.cs | 5 ++- .../FileConverter/Windows/MainWindow.xaml.cs | 2 +- .../Windows/OutputTypeViewModel.cs | 2 +- .../Windows/SettingsWindow.xaml.cs | 42 +++++++++---------- .../Windows/UpgradeWindow.xaml.cs | 3 +- 17 files changed, 58 insertions(+), 58 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs index 5adcc3c5..187c0c17 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ExtractCDA.cs @@ -37,7 +37,14 @@ protected override InputPostConversionAction InputPostConversionAction return InputPostConversionAction.None; } } - + + public override void Cancel() + { + base.Cancel(); + + this.compressionConversionJob.Cancel(); + } + protected override void Initialize() { base.Initialize(); @@ -188,13 +195,6 @@ protected override void Convert() File.Delete(this.intermediateFilePath); } - public override void Cancel() - { - base.Cancel(); - - this.compressionConversionJob.Cancel(); - } - private void WriteWaveData(object sender, DataReadEventArgs eventArgs) { this.waveWriter?.Write(eventArgs.Data, 0, (int)eventArgs.DataSize); diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.Converters.cs b/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.Converters.cs index a2e32103..4862d7ef 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.Converters.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_FFMPEG.Converters.cs @@ -197,7 +197,7 @@ private int OGGVBRBitrateToQualityIndex(int bitrate) } /// - /// Convert video quality index to lib theora video quality level. + /// Convert video quality index to lib theora video quality level. /// /// The quality index. /// Returns the video quality index. diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs index 8e2d7d79..99b779b6 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs @@ -87,7 +87,7 @@ private void ConvertPdf() float scaleFactor = this.ConversionPreset.GetSettingsValue(ConversionPreset.ConversionSettingKeys.ImageScale); if (Math.Abs(scaleFactor - 1f) >= 0.005f) { - Debug.Log("Apply scale factor: {0}%.", scaleFactor*100); + Debug.Log("Apply scale factor: {0}%.", scaleFactor * 100); dpi *= scaleFactor; } @@ -126,9 +126,9 @@ private void ConvertImage(MagickImage image, bool ignoreScale = false) float scaleFactor = this.ConversionPreset.GetSettingsValue(ConversionPreset.ConversionSettingKeys.ImageScale); if (Math.Abs(scaleFactor - 1f) >= 0.005f) { - Debug.Log("Apply scale factor: {0}%.", scaleFactor*100); + Debug.Log("Apply scale factor: {0}%.", scaleFactor * 100); - image.Scale(new Percentage(scaleFactor*100f)); + image.Scale(new Percentage(scaleFactor * 100f)); } } @@ -150,7 +150,7 @@ private void ConvertImage(MagickImage image, bool ignoreScale = false) { int referenceSize = System.Math.Min(image.Width, image.Height); int size = 2; - while (size*2 <= referenceSize) + while (size * 2 <= referenceSize) { size *= 2; } @@ -208,7 +208,7 @@ private void Image_Progress(object sender, ProgressEventArgs eventArgs) } float alreadyCompletedPages = this.CurrentOuputFilePathIndex / (float)this.pageCount; - this.Progress = alreadyCompletedPages + (float)eventArgs.Progress.ToDouble() / (100f * this.pageCount); + this.Progress = alreadyCompletedPages + ((float)eventArgs.Progress.ToDouble() / (100f * this.pageCount)); } } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index e30bfe9d..67dc1f4d 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -1,4 +1,4 @@ -// License: http://www.gnu.org/licenses/gpl.html GPL version 3. +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. namespace FileConverter.ConversionJobs { diff --git a/Application/FileConverter/FileConverter.csproj b/Application/FileConverter/FileConverter.csproj index bd8b04bf..43909efc 100644 --- a/Application/FileConverter/FileConverter.csproj +++ b/Application/FileConverter/FileConverter.csproj @@ -137,11 +137,13 @@ Resources.fr.resx True True + True Resources.en.resx True True + True diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index d797a847..11be8b5b 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -14,13 +14,13 @@ public static class Helpers { public static IEnumerable GetSupportedCultures() { - //Get all culture + // Get all cultures. CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); - //Find the location where application installed. + // Find the location where application installed. string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); - //Return all culture for which satellite folder found with culture code. + // Return all culture for which satellite folder found with culture code. return cultures.Where(cultureInfo => Directory.Exists(Path.Combine(exeLocation, "Languages", cultureInfo.Name))); } diff --git a/Application/FileConverter/PathHelpers.cs b/Application/FileConverter/PathHelpers.cs index d4e67b3f..bf8a484d 100644 --- a/Application/FileConverter/PathHelpers.cs +++ b/Application/FileConverter/PathHelpers.cs @@ -3,8 +3,8 @@ namespace FileConverter { using System; - using System.Text; using System.Collections.Generic; + using System.Text; using System.Text.RegularExpressions; using FileConverter.Diagnostics; diff --git a/Application/FileConverter/Settings.Settings.cs b/Application/FileConverter/Settings.Settings.cs index 5d3f5824..022700d3 100644 --- a/Application/FileConverter/Settings.Settings.cs +++ b/Application/FileConverter/Settings.Settings.cs @@ -1,12 +1,9 @@ // License: http://www.gnu.org/licenses/gpl.html GPL version 3. -using System.Globalization; -using System.Windows; -using System.Windows.Markup; - namespace FileConverter { using System.Collections.ObjectModel; + using System.Globalization; using System.Linq; using System.Xml.Serialization; diff --git a/Application/FileConverter/Upgrade/Helpers.cs b/Application/FileConverter/Upgrade/Helpers.cs index dfcb2b4f..8d100320 100644 --- a/Application/FileConverter/Upgrade/Helpers.cs +++ b/Application/FileConverter/Upgrade/Helpers.cs @@ -128,7 +128,7 @@ public static async Task DownloadInstallerAsync(UpgradeVersionDescription upgrad Helpers.currentlyDownloadedVersionDescription = upgradeVersionDescription; Helpers.webClient.DownloadProgressChanged += Helpers.WebClient_DownloadProgressChanged; - Helpers.webClient.DownloadFileCompleted += Helpers.WebClient_DownloadFileCompleted; ; + Helpers.webClient.DownloadFileCompleted += Helpers.WebClient_DownloadFileCompleted; Task downloadTask = Helpers.webClient.DownloadFileTaskAsync(uri, installerPath); } diff --git a/Application/FileConverter/Upgrade/UpgradeVersionDescription.cs b/Application/FileConverter/Upgrade/UpgradeVersionDescription.cs index 081d403a..844f0e91 100644 --- a/Application/FileConverter/Upgrade/UpgradeVersionDescription.cs +++ b/Application/FileConverter/Upgrade/UpgradeVersionDescription.cs @@ -1,17 +1,18 @@ // License: http://www.gnu.org/licenses/gpl.html GPL version 3. -using System.ComponentModel; -using System.Runtime.CompilerServices; -using FileConverter.Annotations; - namespace FileConverter { + using System.ComponentModel; + using System.Runtime.CompilerServices; using System.Xml.Serialization; + using FileConverter.Annotations; + public class UpgradeVersionDescription : INotifyPropertyChanged { private int installerDownloadProgress; private bool installerDownloadInProgress; + public event PropertyChangedEventHandler PropertyChanged; [XmlElement("Latest")] diff --git a/Application/FileConverter/ValueConverters/Generic/CultureInfoToStringConverter.cs b/Application/FileConverter/ValueConverters/Generic/CultureInfoToStringConverter.cs index 76798ba8..640fa079 100644 --- a/Application/FileConverter/ValueConverters/Generic/CultureInfoToStringConverter.cs +++ b/Application/FileConverter/ValueConverters/Generic/CultureInfoToStringConverter.cs @@ -1,4 +1,4 @@ -// License: http://www.gnu.org/licenses/gpl.html GPL version 3. +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. namespace FileConverter.ValueConverters.Generic { @@ -27,7 +27,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn return nativeName.ToUpper(cultureInfo); } - return nativeName.Substring(0, 1).ToUpper(cultureInfo) + nativeName.Substring(1, nativeName.Length - 1); ; + return nativeName.Substring(0, 1).ToUpper(cultureInfo) + nativeName.Substring(1, nativeName.Length - 1); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/Application/FileConverter/ValueConverters/Generic/ObjectToLocalizedString.cs b/Application/FileConverter/ValueConverters/Generic/ObjectToLocalizedString.cs index 434a55ed..e7e6edd5 100644 --- a/Application/FileConverter/ValueConverters/Generic/ObjectToLocalizedString.cs +++ b/Application/FileConverter/ValueConverters/Generic/ObjectToLocalizedString.cs @@ -1,4 +1,4 @@ -// License: http://www.gnu.org/licenses/gpl.html GPL version 3. +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. namespace FileConverter.ValueConverters.Generic { diff --git a/Application/FileConverter/ValueConverters/OutputTypeEnumToViewModel.cs b/Application/FileConverter/ValueConverters/OutputTypeEnumToViewModel.cs index 377665cc..caa05ee3 100644 --- a/Application/FileConverter/ValueConverters/OutputTypeEnumToViewModel.cs +++ b/Application/FileConverter/ValueConverters/OutputTypeEnumToViewModel.cs @@ -1,11 +1,12 @@ -// License: http://www.gnu.org/licenses/gpl.html GPL version 3. +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. namespace FileConverter.ValueConverters { using System; using System.Globalization; - using System.Windows.Data; using System.Linq; + using System.Windows.Data; + using FileConverter.Windows; public class OutputTypeEnumToViewModel : IValueConverter diff --git a/Application/FileConverter/Windows/MainWindow.xaml.cs b/Application/FileConverter/Windows/MainWindow.xaml.cs index 70f2514b..0e6fe953 100644 --- a/Application/FileConverter/Windows/MainWindow.xaml.cs +++ b/Application/FileConverter/Windows/MainWindow.xaml.cs @@ -147,7 +147,7 @@ private void ShowUpgradeWindow() else if (this.upgradeWindow == null) { this.upgradeWindow = new UpgradeWindow(); - this.upgradeWindow.Closed += UpgradeWindow_Closed; + this.upgradeWindow.Closed += this.UpgradeWindow_Closed; } Application application = Application.Current as Application; diff --git a/Application/FileConverter/Windows/OutputTypeViewModel.cs b/Application/FileConverter/Windows/OutputTypeViewModel.cs index 0f46b960..ffe7d015 100644 --- a/Application/FileConverter/Windows/OutputTypeViewModel.cs +++ b/Application/FileConverter/Windows/OutputTypeViewModel.cs @@ -1,4 +1,4 @@ -// License: http://www.gnu.org/licenses/gpl.html GPL version 3. +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. namespace FileConverter.Windows { diff --git a/Application/FileConverter/Windows/SettingsWindow.xaml.cs b/Application/FileConverter/Windows/SettingsWindow.xaml.cs index 8d962da7..78d163f5 100644 --- a/Application/FileConverter/Windows/SettingsWindow.xaml.cs +++ b/Application/FileConverter/Windows/SettingsWindow.xaml.cs @@ -13,10 +13,10 @@ namespace FileConverter using System.Windows.Data; using System.Windows.Input; - using FileConverter.Windows; using FileConverter.Annotations; using FileConverter.Commands; using FileConverter.ConversionJobs; + using FileConverter.Windows; using Microsoft.Win32; /// @@ -57,6 +57,25 @@ public SettingsWindow() public event EventHandler OnSettingsWindowHide; + public static OutputTypeViewModel[] OutputTypeViewModels => new[] + { + new OutputTypeViewModel(OutputType.Ogg), + new OutputTypeViewModel(OutputType.Mp3), + new OutputTypeViewModel(OutputType.Aac), + new OutputTypeViewModel(OutputType.Flac), + new OutputTypeViewModel(OutputType.Wav), + new OutputTypeViewModel(OutputType.Mkv), + new OutputTypeViewModel(OutputType.Mp4), + new OutputTypeViewModel(OutputType.Ogv), + new OutputTypeViewModel(OutputType.Webm), + new OutputTypeViewModel(OutputType.Avi), + new OutputTypeViewModel(OutputType.Png), + new OutputTypeViewModel(OutputType.Jpg), + new OutputTypeViewModel(OutputType.Ico), + new OutputTypeViewModel(OutputType.Gif), + new OutputTypeViewModel(OutputType.Pdf), + }; + public ICommand OpenUrlCommand { get @@ -148,26 +167,7 @@ public CultureInfo[] SupportedCultures get; set; } - - public static OutputTypeViewModel[] OutputTypeViewModels => new[] - { - new OutputTypeViewModel(OutputType.Ogg), - new OutputTypeViewModel(OutputType.Mp3), - new OutputTypeViewModel(OutputType.Aac), - new OutputTypeViewModel(OutputType.Flac), - new OutputTypeViewModel(OutputType.Wav), - new OutputTypeViewModel(OutputType.Mkv), - new OutputTypeViewModel(OutputType.Mp4), - new OutputTypeViewModel(OutputType.Ogv), - new OutputTypeViewModel(OutputType.Webm), - new OutputTypeViewModel(OutputType.Avi), - new OutputTypeViewModel(OutputType.Png), - new OutputTypeViewModel(OutputType.Jpg), - new OutputTypeViewModel(OutputType.Ico), - new OutputTypeViewModel(OutputType.Gif), - new OutputTypeViewModel(OutputType.Pdf), - }; - + public InputPostConversionAction[] InputPostConversionActions => new[] { InputPostConversionAction.None, diff --git a/Application/FileConverter/Windows/UpgradeWindow.xaml.cs b/Application/FileConverter/Windows/UpgradeWindow.xaml.cs index 6cd43ea1..3bbad114 100644 --- a/Application/FileConverter/Windows/UpgradeWindow.xaml.cs +++ b/Application/FileConverter/Windows/UpgradeWindow.xaml.cs @@ -2,12 +2,11 @@ namespace FileConverter.Windows { - using System; - using System.Windows.Input; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; + using System.Windows.Input; using FileConverter.Annotations; using FileConverter.Commands; From 91b75338c485d929170e60c170e55b195290e39e Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:27:11 +0200 Subject: [PATCH 15/36] Remove languages.wxs file from git because it is automatically generated --- .gitignore | 5 ++++- Installer/Languages.wxs | 28 ---------------------------- 2 files changed, 4 insertions(+), 29 deletions(-) delete mode 100644 Installer/Languages.wxs diff --git a/.gitignore b/.gitignore index 3285e5b9..d656489f 100644 --- a/.gitignore +++ b/.gitignore @@ -194,4 +194,7 @@ FakesAssemblies/ *.opt # Ignore the installer signing commands file -Installer/Installer.sign \ No newline at end of file +Installer/Installer.sign + +# Ignore the installer languages file because it is automatically generated +Installer/Languages.wxs diff --git a/Installer/Languages.wxs b/Installer/Languages.wxs deleted file mode 100644 index e154616e..00000000 --- a/Installer/Languages.wxs +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 4e1999d2af358224280ee6af133ca675ea541177 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 7 Sep 2016 08:32:55 +0200 Subject: [PATCH 16/36] Update changelog. --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34ae3bae..6b4552b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## Version 1.2 +- New: Possibility to convert word documents (docx, odt and doc) to pdf and images (this feature is only available if you have Microsoft Office installed). +- New: Add the possibility to cancel image, CDA extraction and gif conversions. +- Fixed: Issue where multiple conversion jobs was created for the same file resulting in an error message. +- Tech: Improve application performances on startup. +- Tech: Improve diagnostics. + ## Version 1.1 - New: Localization system. File Converter can now be translated in multiple languages. The default language is the same than your OS language (if available). - New: Add the possibility to choose the application language in the application settings. From 72305ad71f94ff5cbce513c5821e2471776a2021 Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 8 Sep 2016 07:57:31 +0200 Subject: [PATCH 17/36] Add support of Excel files (xlsx, xls and ods) --- .../ConversionJobs/ConversionJobFactory.cs | 5 + .../ConversionJobs/ConversionJob_Excel.cs | 184 ++++++++++++++++++ .../FileConverter/FileConverter.csproj | 4 + Application/FileConverter/Helpers.cs | 3 + 4 files changed, 196 insertions(+) create mode 100644 Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs diff --git a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs index b6ffb916..b2f6d1c9 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs @@ -18,6 +18,11 @@ public static ConversionJob Create(ConversionPreset conversionPreset, string inp return new ConversionJob_Word(conversionPreset, inputFilePath); } + if (inputFileExtension == "xls" || inputFileExtension == "xlsx" || inputFileExtension == "ods") + { + return new ConversionJob_Excel(conversionPreset, inputFilePath); + } + if (conversionPreset.OutputType == OutputType.Ico) { return new ConversionJob_Ico(conversionPreset, inputFilePath); diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs new file mode 100644 index 00000000..b3002407 --- /dev/null +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs @@ -0,0 +1,184 @@ +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. + +namespace FileConverter.ConversionJobs +{ + using System.IO; + using System.Threading.Tasks; + + using Excel = Microsoft.Office.Interop.Excel; + + public class ConversionJob_Excel : ConversionJob + { + private Excel.Workbook document; + private Excel.Application application; + + private string intermediateFilePath = string.Empty; + private ConversionJob pdf2ImageConversionJob = null; + + public ConversionJob_Excel() : base() + { + } + + public ConversionJob_Excel(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) + { + } + + protected override int GetOuputFilesCount() + { + if (this.ConversionPreset.OutputType == OutputType.Pdf) + { + return 1; + } + + this.LoadDocumentIfNecessary(); + + int pagesCount = 0; + foreach (object sheet in this.document.Sheets) + { + Excel.Worksheet worksheet = sheet as Excel.Worksheet; + if (worksheet != null) + { + pagesCount = worksheet.PageSetup.Pages.Count; + } + } + + return pagesCount; + } + + protected override void Initialize() + { + base.Initialize(); + + if (this.ConversionPreset == null) + { + throw new System.Exception("The conversion preset must be valid."); + } + + // Initialize converters. + if (this.ConversionPreset.OutputType == OutputType.Pdf) + { + this.intermediateFilePath = this.OutputFilePath; + } + else + { + // Generate intermediate file path. + string fileName = Path.GetFileNameWithoutExtension(this.InputFilePath); + string tempPath = Path.GetTempPath(); + this.intermediateFilePath = PathHelpers.GenerateUniquePath(tempPath + fileName + ".pdf"); + + ConversionPreset intermediatePreset = new ConversionPreset("Pdf to image", this.ConversionPreset, "pdf"); + this.pdf2ImageConversionJob = ConversionJobFactory.Create(intermediatePreset, this.intermediateFilePath); + this.pdf2ImageConversionJob.PrepareConversion(this.OutputFilePaths); + } + } + + protected override void Convert() + { + if (this.ConversionPreset == null) + { + throw new System.Exception("The conversion preset must be valid."); + } + + this.UserState = Properties.Resources.ConversionStateReadDocument; + + this.LoadDocumentIfNecessary(); + + // Make this document the active document. + this.document.Activate(); + + this.UserState = Properties.Resources.ConversionStateConversion; + + Diagnostics.Debug.Log("Convert excel document to pdf."); + this.document.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, this.intermediateFilePath); + + Diagnostics.Debug.Log("Close excel document '{0}'.", this.InputFilePath); + this.document.Close(false); + this.document = null; + + this.ReleaseApplicationInstanceIfNeeded(); + + if (this.pdf2ImageConversionJob != null) + { + if (!System.IO.File.Exists(this.intermediateFilePath)) + { + this.ConversionFailed(Properties.Resources.ErrorCantFindOutputFiles); + return; + } + + Task updateProgress = this.UpdateProgress(); + + Diagnostics.Debug.Log("Convert pdf to images."); + + this.pdf2ImageConversionJob.StartConvertion(); + + if (this.pdf2ImageConversionJob.State != ConversionState.Done) + { + this.ConversionFailed(this.pdf2ImageConversionJob.ErrorMessage); + return; + } + + if (!string.IsNullOrEmpty(this.intermediateFilePath)) + { + Diagnostics.Debug.Log("Delete intermediate file {0}.", this.intermediateFilePath); + + File.Delete(this.intermediateFilePath); + } + + updateProgress.Wait(); + } + } + + private async Task UpdateProgress() + { + while (this.pdf2ImageConversionJob.State != ConversionState.Done && + this.pdf2ImageConversionJob.State != ConversionState.Failed) + { + if (this.pdf2ImageConversionJob != null && this.pdf2ImageConversionJob.State == ConversionState.InProgress) + { + this.Progress = this.pdf2ImageConversionJob.Progress; + } + + if (this.pdf2ImageConversionJob != null && this.pdf2ImageConversionJob.State == ConversionState.InProgress) + { + this.Progress = this.pdf2ImageConversionJob.Progress; + this.UserState = this.pdf2ImageConversionJob.UserState; + } + + await Task.Delay(40); + } + } + + private void LoadDocumentIfNecessary() + { + this.InitializeApplicationInstanceIfNecessary(); + + if (this.document == null) + { + Diagnostics.Debug.Log("Load excel document '{0}'.", this.InputFilePath); + + this.document = this.application.Workbooks.Open(this.InputFilePath, System.Reflection.Missing.Value, true); + } + } + + private void InitializeApplicationInstanceIfNecessary() + { + if (this.application != null) + { + return; + } + + // Initialize excel application. + Diagnostics.Debug.Log("Instantiate excel application via interop."); + this.application = new Excel.Application + { + Visible = false + }; + } + + private void ReleaseApplicationInstanceIfNeeded() + { + Diagnostics.Debug.Log("Quit excel application via interop."); + this.application.Quit(); + } + } +} diff --git a/Application/FileConverter/FileConverter.csproj b/Application/FileConverter/FileConverter.csproj index 43909efc..f495537f 100644 --- a/Application/FileConverter/FileConverter.csproj +++ b/Application/FileConverter/FileConverter.csproj @@ -73,6 +73,9 @@ ..\..\Middleware\Markdown.Xaml.dll + + True + True @@ -121,6 +124,7 @@ + diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index 11be8b5b..3a8b112c 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -75,7 +75,10 @@ public static string GetExtensionCategory(string extension) case "pdf": case "doc": case "docx": + case "ods": case "odt": + case "xls": + case "xlsx": return InputCategoryNames.Document; } From 83d85cb93c9147505e66c8716ea71536bb05b427 Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 8 Sep 2016 08:32:44 +0200 Subject: [PATCH 18/36] Add support of PowerPoint files (pptx, ppt and odp) --- .../ConversionJobs/ConversionJobFactory.cs | 9 +- .../ConversionJob_PowerPoint.cs | 173 ++++++++++++++++++ .../FileConverter/FileConverter.csproj | 7 + Application/FileConverter/Helpers.cs | 3 + Installer/Product.wxs | 2 +- 5 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs diff --git a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs index b2f6d1c9..9791a661 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJobFactory.cs @@ -13,16 +13,21 @@ public static ConversionJob Create(ConversionPreset conversionPreset, string inp return new ConversionJob_ExtractCDA(conversionPreset, inputFilePath); } - if (inputFileExtension == "doc" || inputFileExtension == "docx" || inputFileExtension == "odt") + if (inputFileExtension == "docx" || inputFileExtension == "odt" || inputFileExtension == "doc") { return new ConversionJob_Word(conversionPreset, inputFilePath); } - if (inputFileExtension == "xls" || inputFileExtension == "xlsx" || inputFileExtension == "ods") + if (inputFileExtension == "xlsx" || inputFileExtension == "ods" || inputFileExtension == "xls") { return new ConversionJob_Excel(conversionPreset, inputFilePath); } + if (inputFileExtension == "pptx" || inputFileExtension == "odp" || inputFileExtension == "ppt") + { + return new ConversionJob_PowerPoint(conversionPreset, inputFilePath); + } + if (conversionPreset.OutputType == OutputType.Ico) { return new ConversionJob_Ico(conversionPreset, inputFilePath); diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs new file mode 100644 index 00000000..c7949267 --- /dev/null +++ b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs @@ -0,0 +1,173 @@ +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. + +namespace FileConverter.ConversionJobs +{ + using System.IO; + using System.Threading.Tasks; + + using Microsoft.Office.Core; + using PowerPoint = Microsoft.Office.Interop.PowerPoint; + + public class ConversionJob_PowerPoint : ConversionJob + { + private PowerPoint.Presentation document; + private PowerPoint.Application application; + + private string intermediateFilePath = string.Empty; + private ConversionJob pdf2ImageConversionJob = null; + + public ConversionJob_PowerPoint() : base() + { + } + + public ConversionJob_PowerPoint(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) + { + } + + protected override int GetOuputFilesCount() + { + if (this.ConversionPreset.OutputType == OutputType.Pdf) + { + return 1; + } + + this.LoadDocumentIfNecessary(); + + int pagesCount = this.document.Slides.Count; + return pagesCount; + } + + protected override void Initialize() + { + base.Initialize(); + + if (this.ConversionPreset == null) + { + throw new System.Exception("The conversion preset must be valid."); + } + + // Initialize converters. + if (this.ConversionPreset.OutputType == OutputType.Pdf) + { + this.intermediateFilePath = this.OutputFilePath; + } + else + { + // Generate intermediate file path. + string fileName = Path.GetFileNameWithoutExtension(this.InputFilePath); + string tempPath = Path.GetTempPath(); + this.intermediateFilePath = PathHelpers.GenerateUniquePath(tempPath + fileName + ".pdf"); + + ConversionPreset intermediatePreset = new ConversionPreset("Pdf to image", this.ConversionPreset, "pdf"); + this.pdf2ImageConversionJob = ConversionJobFactory.Create(intermediatePreset, this.intermediateFilePath); + this.pdf2ImageConversionJob.PrepareConversion(this.OutputFilePaths); + } + } + + protected override void Convert() + { + if (this.ConversionPreset == null) + { + throw new System.Exception("The conversion preset must be valid."); + } + + this.UserState = Properties.Resources.ConversionStateReadDocument; + + this.LoadDocumentIfNecessary(); + + // Make this document the active document. + //this.document.Activate(); + + this.UserState = Properties.Resources.ConversionStateConversion; + + Diagnostics.Debug.Log("Convert PowerPoint document to pdf."); + this.document.ExportAsFixedFormat(this.intermediateFilePath, PowerPoint.PpFixedFormatType.ppFixedFormatTypePDF); + + Diagnostics.Debug.Log("Close PowerPoint document '{0}'.", this.InputFilePath); + this.document.Close(); + this.document = null; + + this.ReleaseApplicationInstanceIfNeeded(); + + if (this.pdf2ImageConversionJob != null) + { + if (!System.IO.File.Exists(this.intermediateFilePath)) + { + this.ConversionFailed(Properties.Resources.ErrorCantFindOutputFiles); + return; + } + + Task updateProgress = this.UpdateProgress(); + + Diagnostics.Debug.Log("Convert pdf to images."); + + this.pdf2ImageConversionJob.StartConvertion(); + + if (this.pdf2ImageConversionJob.State != ConversionState.Done) + { + this.ConversionFailed(this.pdf2ImageConversionJob.ErrorMessage); + return; + } + + if (!string.IsNullOrEmpty(this.intermediateFilePath)) + { + Diagnostics.Debug.Log("Delete intermediate file {0}.", this.intermediateFilePath); + + File.Delete(this.intermediateFilePath); + } + + updateProgress.Wait(); + } + } + + private async Task UpdateProgress() + { + while (this.pdf2ImageConversionJob.State != ConversionState.Done && + this.pdf2ImageConversionJob.State != ConversionState.Failed) + { + if (this.pdf2ImageConversionJob != null && this.pdf2ImageConversionJob.State == ConversionState.InProgress) + { + this.Progress = this.pdf2ImageConversionJob.Progress; + } + + if (this.pdf2ImageConversionJob != null && this.pdf2ImageConversionJob.State == ConversionState.InProgress) + { + this.Progress = this.pdf2ImageConversionJob.Progress; + this.UserState = this.pdf2ImageConversionJob.UserState; + } + + await Task.Delay(40); + } + } + + private void LoadDocumentIfNecessary() + { + this.InitializeApplicationInstanceIfNecessary(); + + if (this.document == null) + { + Diagnostics.Debug.Log("Load PowerPoint document '{0}'.", this.InputFilePath); + + this.document = this.application.Presentations.Open(this.InputFilePath, ReadOnly:MsoTriState.msoTrue, WithWindow:MsoTriState.msoFalse); + } + } + + private void InitializeApplicationInstanceIfNecessary() + { + if (this.application != null) + { + return; + } + + // Initialize PowerPoint application. + Diagnostics.Debug.Log("Instantiate PowerPoint application via interop."); + this.application = new PowerPoint.Application(); + } + + private void ReleaseApplicationInstanceIfNeeded() + { + Diagnostics.Debug.Log("Quit PowerPoint application via interop."); + this.application.Quit(); + } + } +} diff --git a/Application/FileConverter/FileConverter.csproj b/Application/FileConverter/FileConverter.csproj index f495537f..9d0ffdd0 100644 --- a/Application/FileConverter/FileConverter.csproj +++ b/Application/FileConverter/FileConverter.csproj @@ -76,9 +76,15 @@ True + + True + True + + True + False @@ -118,6 +124,7 @@ + diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index 3a8b112c..776ff60a 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -75,6 +75,9 @@ public static string GetExtensionCategory(string extension) case "pdf": case "doc": case "docx": + case "ppt": + case "pptx": + case "odp": case "ods": case "odt": case "xls": diff --git a/Installer/Product.wxs b/Installer/Product.wxs index dc2cbd10..fdc7043d 100644 --- a/Installer/Product.wxs +++ b/Installer/Product.wxs @@ -142,7 +142,7 @@ - + From dc54a7eae0882525b14c0da821fbf3ae0ff276db Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 8 Sep 2016 20:39:01 +0200 Subject: [PATCH 19/36] Add webp output type --- .../ConversionJobs/ConversionJob_ImageMagick.cs | 4 ++++ .../FileConverter/ConversionPreset/ConversionPreset.cs | 8 ++++++++ Application/FileConverter/Helpers.cs | 2 ++ Application/FileConverter/OutputType.cs | 1 + .../Windows/ConversionSettingsTemplateSelector.cs | 9 +++++++++ Application/FileConverter/Windows/SettingsWindow.xaml | 3 ++- Application/FileConverter/Windows/SettingsWindow.xaml.cs | 1 + 7 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs index 99b779b6..f6cf8405 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_ImageMagick.cs @@ -189,6 +189,10 @@ private void ConvertImage(MagickImage image, bool ignoreScale = false) case OutputType.Pdf: break; + case OutputType.Webp: + image.Quality = this.ConversionPreset.GetSettingsValue(ConversionPreset.ConversionSettingKeys.ImageQuality); + break; + default: this.ConversionFailed(string.Format(Properties.Resources.ErrorUnsupportedOutputFormat, this.ConversionPreset.OutputType)); image.Progress -= this.Image_Progress; diff --git a/Application/FileConverter/ConversionPreset/ConversionPreset.cs b/Application/FileConverter/ConversionPreset/ConversionPreset.cs index 2a261e8c..bd550bf2 100644 --- a/Application/FileConverter/ConversionPreset/ConversionPreset.cs +++ b/Application/FileConverter/ConversionPreset/ConversionPreset.cs @@ -508,6 +508,14 @@ private void InitializeDefaultSettings(OutputType outputType) this.InitializeSettingsValue(ConversionPreset.ConversionSettingKeys.ImageMaximumSize, "0"); break; + case OutputType.Webp: + this.InitializeSettingsValue(ConversionPreset.ConversionSettingKeys.ImageQuality, "40"); + this.InitializeSettingsValue(ConversionPreset.ConversionSettingKeys.ImageScale, "1"); + this.InitializeSettingsValue(ConversionPreset.ConversionSettingKeys.ImageRotation, "0"); + this.InitializeSettingsValue(ConversionPreset.ConversionSettingKeys.ImageClampSizePowerOf2, "False"); + this.InitializeSettingsValue(ConversionPreset.ConversionSettingKeys.ImageMaximumSize, "0"); + break; + case OutputType.Ico: break; diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index 776ff60a..995beeef 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -67,6 +67,7 @@ public static string GetExtensionCategory(string extension) case "tiff": case "svg": case "xcf": + case "webp": return InputCategoryNames.Image; case "gif": @@ -115,6 +116,7 @@ public static bool IsOutputTypeCompatibleWithCategory(OutputType outputType, str case OutputType.Ico: case OutputType.Jpg: case OutputType.Png: + case OutputType.Webp: return category == InputCategoryNames.Image || category == InputCategoryNames.Document; case OutputType.Gif: diff --git a/Application/FileConverter/OutputType.cs b/Application/FileConverter/OutputType.cs index 15d5c773..fda2caf1 100644 --- a/Application/FileConverter/OutputType.cs +++ b/Application/FileConverter/OutputType.cs @@ -21,5 +21,6 @@ public enum OutputType Png, Wav, Webm, + Webp, } } \ No newline at end of file diff --git a/Application/FileConverter/Windows/ConversionSettingsTemplateSelector.cs b/Application/FileConverter/Windows/ConversionSettingsTemplateSelector.cs index 16bf79e7..202fb6d3 100644 --- a/Application/FileConverter/Windows/ConversionSettingsTemplateSelector.cs +++ b/Application/FileConverter/Windows/ConversionSettingsTemplateSelector.cs @@ -91,6 +91,12 @@ public DataTemplate WebmSettingsDataTemplate set; } + public DataTemplate WebpSettingsDataTemplate + { + get; + set; + } + public override DataTemplate SelectTemplate(object item, DependencyObject container) { if (item == null) @@ -140,6 +146,9 @@ public override DataTemplate SelectTemplate(object item, DependencyObject contai case OutputType.Webm: return this.WebmSettingsDataTemplate; + + case OutputType.Webp: + return this.WebpSettingsDataTemplate; } return this.DefaultDataTemplate; diff --git a/Application/FileConverter/Windows/SettingsWindow.xaml b/Application/FileConverter/Windows/SettingsWindow.xaml index 4cfec490..25925011 100644 --- a/Application/FileConverter/Windows/SettingsWindow.xaml +++ b/Application/FileConverter/Windows/SettingsWindow.xaml @@ -710,7 +710,8 @@ OgvSettingsDataTemplate="{StaticResource OgvSettingsDataTemplate}" PngSettingsDataTemplate="{StaticResource PngSettingsDataTemplate}" WavSettingsDataTemplate="{StaticResource WavSettingsDataTemplate}" - WebmSettingsDataTemplate="{StaticResource WebmSettingsDataTemplate}" /> + WebmSettingsDataTemplate="{StaticResource WebmSettingsDataTemplate}" + WebpSettingsDataTemplate="{StaticResource JpgSettingsDataTemplate}" /> diff --git a/Application/FileConverter/Windows/SettingsWindow.xaml.cs b/Application/FileConverter/Windows/SettingsWindow.xaml.cs index 78d163f5..3d563cdd 100644 --- a/Application/FileConverter/Windows/SettingsWindow.xaml.cs +++ b/Application/FileConverter/Windows/SettingsWindow.xaml.cs @@ -71,6 +71,7 @@ public SettingsWindow() new OutputTypeViewModel(OutputType.Avi), new OutputTypeViewModel(OutputType.Png), new OutputTypeViewModel(OutputType.Jpg), + new OutputTypeViewModel(OutputType.Webp), new OutputTypeViewModel(OutputType.Ico), new OutputTypeViewModel(OutputType.Gif), new OutputTypeViewModel(OutputType.Pdf), From d24c3327f2781a7a7f7c7039a270a5e987d689f6 Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 8 Sep 2016 20:39:16 +0200 Subject: [PATCH 20/36] Fixed: French localization error --- Application/FileConverter/Properties/Resources.fr.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index 1571b89d..7e60fad7 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -494,7 +494,7 @@ utilisez maj pour une version en majuscules Invalid output path generated by output file path template. - Format de fichier de destion non supporté '{0}'. + Format de fichier de destination non supporté '{0}'. Nombre de canaux : From b34eec532764df9be550967e52801cc47aab948b Mon Sep 17 00:00:00 2001 From: Tichau Date: Tue, 13 Sep 2016 08:04:27 +0200 Subject: [PATCH 21/36] Add webp input file extension --- Installer/Product.wxs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installer/Product.wxs b/Installer/Product.wxs index fdc7043d..dc7a33d7 100644 --- a/Installer/Product.wxs +++ b/Installer/Product.wxs @@ -142,7 +142,7 @@ - + From 5a9a00d153334863aed8d046ae78715ad2a3d0a7 Mon Sep 17 00:00:00 2001 From: Tichau Date: Tue, 13 Sep 2016 23:11:55 +0200 Subject: [PATCH 22/36] Fixed: Fixed word export. --- Application/FileConverter/ConversionJobs/ConversionJob_Word.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index 67dc1f4d..38ac9575 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -81,7 +81,7 @@ protected override void Convert() this.UserState = Properties.Resources.ConversionStateConversion; Diagnostics.Debug.Log("Convert word document to pdf."); - this.document.SaveAs(this.intermediateFilePath, Word.WdSaveFormat.wdFormatPDF); + this.document.ExportAsFixedFormat(this.intermediateFilePath, Word.WdExportFormat.wdExportFormatPDF); Diagnostics.Debug.Log("Close word document '{0}'.", this.InputFilePath); this.document.Close(Word.WdSaveOptions.wdDoNotSaveChanges); From f5290b05379dadebfc99d1088a66e39ecccebe5c Mon Sep 17 00:00:00 2001 From: Tichau Date: Tue, 13 Sep 2016 23:13:03 +0200 Subject: [PATCH 23/36] Fixed: Issue where user state was not updated correctly when job initialization failed. --- Application/FileConverter/ConversionJobs/ConversionJob.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob.cs b/Application/FileConverter/ConversionJobs/ConversionJob.cs index 463a8e0a..a2dbe7bd 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob.cs @@ -313,7 +313,10 @@ public void PrepareConversion(params string[] outputFilePaths) Debug.Log("Job initialized: Preset: '{0}' Input: {1} Output: {2}", this.ConversionPreset.Name, this.InputFilePath, this.OutputFilePath); - this.UserState = Properties.Resources.ConversionStateInQueue; + if (this.State != ConversionState.Failed) + { + this.UserState = Properties.Resources.ConversionStateInQueue; + } } public void StartConvertion() From ec16879572cc3044bf74789642b8bd601654df07 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 14 Sep 2016 08:03:03 +0200 Subject: [PATCH 24/36] Add some feedback when office is not installed. --- .../ConversionJobs/ConversionJob_Excel.cs | 7 ++- .../ConversionJobs/ConversionJob_Office.cs | 26 ++++++++ .../ConversionJob_PowerPoint.cs | 7 ++- .../ConversionJobs/ConversionJob_Word.cs | 7 ++- .../FileConverter/FileConverter.csproj | 1 + Application/FileConverter/Helpers.cs | 60 ++++++++++++++++++- .../Properties/Resources.Designer.cs | 9 +++ .../Properties/Resources.en.resx | 3 + .../Properties/Resources.fr.resx | 3 + .../FileConverter/Properties/Resources.resx | 3 + .../FileConverter/Windows/InputExtension.cs | 44 ++++++++++++++ .../FileConverter/Windows/SettingsWindow.xaml | 2 +- 12 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 Application/FileConverter/ConversionJobs/ConversionJob_Office.cs diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs index b3002407..2da528a1 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs @@ -7,7 +7,7 @@ namespace FileConverter.ConversionJobs using Excel = Microsoft.Office.Interop.Excel; - public class ConversionJob_Excel : ConversionJob + public class ConversionJob_Excel : ConversionJob_Office { private Excel.Workbook document; private Excel.Application application; @@ -49,6 +49,11 @@ protected override void Initialize() { base.Initialize(); + if (this.State == ConversionState.Failed) + { + return; + } + if (this.ConversionPreset == null) { throw new System.Exception("The conversion preset must be valid."); diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs new file mode 100644 index 00000000..cd0c1c56 --- /dev/null +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs @@ -0,0 +1,26 @@ +// License: http://www.gnu.org/licenses/gpl.html GPL version 3. + +namespace FileConverter.ConversionJobs +{ + public abstract class ConversionJob_Office : ConversionJob + { + protected ConversionJob_Office() : base() + { + } + + protected ConversionJob_Office(ConversionPreset conversionPreset, string inputFilePath) : base(conversionPreset, inputFilePath) + { + } + + protected override void Initialize() + { + base.Initialize(); + + if (!Helpers.IsMicrosoftOfficeAvailable()) + { + this.ConversionFailed(Properties.Resources.ErrorMicrosoftOfficeIsNotAvailable); + return; + } + } + } +} \ No newline at end of file diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs index c7949267..040d175f 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs @@ -8,7 +8,7 @@ namespace FileConverter.ConversionJobs using Microsoft.Office.Core; using PowerPoint = Microsoft.Office.Interop.PowerPoint; - public class ConversionJob_PowerPoint : ConversionJob + public class ConversionJob_PowerPoint : ConversionJob_Office { private PowerPoint.Presentation document; private PowerPoint.Application application; @@ -41,6 +41,11 @@ protected override void Initialize() { base.Initialize(); + if (this.State == ConversionState.Failed) + { + return; + } + if (this.ConversionPreset == null) { throw new System.Exception("The conversion preset must be valid."); diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index 38ac9575..e7ed35fd 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -7,7 +7,7 @@ namespace FileConverter.ConversionJobs using Word = Microsoft.Office.Interop.Word; - public class ConversionJob_Word : ConversionJob + public class ConversionJob_Word : ConversionJob_Office { private Word.Document document; private Word.Application wordApplication; @@ -41,6 +41,11 @@ protected override void Initialize() { base.Initialize(); + if (this.State == ConversionState.Failed) + { + return; + } + if (this.ConversionPreset == null) { throw new System.Exception("The conversion preset must be valid."); diff --git a/Application/FileConverter/FileConverter.csproj b/Application/FileConverter/FileConverter.csproj index 9d0ffdd0..dad77ed6 100644 --- a/Application/FileConverter/FileConverter.csproj +++ b/Application/FileConverter/FileConverter.csproj @@ -124,6 +124,7 @@ + diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index 995beeef..1266ba1b 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -10,8 +10,23 @@ namespace FileConverter using System.Reflection; using System.Threading; + using Microsoft.Win32; + public static class Helpers { + private static readonly string[] CompatibleOfficeVersions = new string[] + { + "16.0", // Office 2016 + "15.0", // Office 2013 + ////"14.0", // Office 2010 + ////"12.0", // Office 2007 + ////"11.0", // Office 2003 + ////"10.0", // Office XP + ////"9.0", // Office 2000 + ////"8.0", // Office 98 + ////"7.0", // Office 97 + }; + public static IEnumerable GetSupportedCultures() { // Get all cultures. @@ -163,7 +178,50 @@ public static Thread InstantiateThread(string name, ParameterizedThreadStart par return thread; } - + + /// + /// Check whether Microsoft office is available or not. + /// + /// Returns true if Office is installed on the computer. + /// source: http://stackoverflow.com/questions/3266675/how-to-detect-installed-version-of-ms-office/3267832#3267832 + public static bool IsMicrosoftOfficeAvailable() + { + string registryKeyPattern = @"Software\Microsoft\Office\{0}\Common"; + + for (int index = 0; index < Helpers.CompatibleOfficeVersions.Length; index++) + { + string registryKeyPath = string.Format(registryKeyPattern, Helpers.CompatibleOfficeVersions[index]); + RegistryKey officeRegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(registryKeyPath); + if (officeRegistryKey != null) + { + Diagnostics.Debug.Log($"Registry key '{registryKeyPath}' found"); + return true; + } + } + + Diagnostics.Debug.Log("No compatible office version found."); + return false; + } + + public static bool IsExtensionCompatibleWithOffice(string extension) + { + switch (extension) + { + case "doc": + case "docx": + case "ppt": + case "pptx": + case "odp": + case "ods": + case "odt": + case "xls": + case "xlsx": + return true; + } + + return false; + } + public static class InputCategoryNames { public const string Audio = "Audio"; diff --git a/Application/FileConverter/Properties/Resources.Designer.cs b/Application/FileConverter/Properties/Resources.Designer.cs index 521691d8..dec3e861 100644 --- a/Application/FileConverter/Properties/Resources.Designer.cs +++ b/Application/FileConverter/Properties/Resources.Designer.cs @@ -537,6 +537,15 @@ public static string ErrorInvalidOutputPath { } } + /// + /// Looks up a localized string similar to Microsoft Office must be installed in order to convert Office documents.. + /// + public static string ErrorMicrosoftOfficeIsNotAvailable { + get { + return ResourceManager.GetString("ErrorMicrosoftOfficeIsNotAvailable", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unsupported output format '{0}'.. /// diff --git a/Application/FileConverter/Properties/Resources.en.resx b/Application/FileConverter/Properties/Resources.en.resx index cfd3a0e0..834ae0d9 100644 --- a/Application/FileConverter/Properties/Resources.en.resx +++ b/Application/FileConverter/Properties/Resources.en.resx @@ -526,4 +526,7 @@ use maj for uppercase version Prepare conversion + + Microsoft Office must be installed in order to convert Office documents. + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index 7e60fad7..1edd951a 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -544,4 +544,7 @@ utilisez maj pour une version en majuscules Préparation + + Microsoft Office doit être installé pour pouvoir convertir les documents Office. + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.resx b/Application/FileConverter/Properties/Resources.resx index 37aa21b0..5934303d 100644 --- a/Application/FileConverter/Properties/Resources.resx +++ b/Application/FileConverter/Properties/Resources.resx @@ -526,4 +526,7 @@ use maj for uppercase version Prepare conversion + + Microsoft Office must be installed in order to convert Office documents. + \ No newline at end of file diff --git a/Application/FileConverter/Windows/InputExtension.cs b/Application/FileConverter/Windows/InputExtension.cs index ea8c7e77..437d5447 100644 --- a/Application/FileConverter/Windows/InputExtension.cs +++ b/Application/FileConverter/Windows/InputExtension.cs @@ -4,16 +4,32 @@ namespace FileConverter { using System.ComponentModel; using System.Runtime.CompilerServices; + using System.Windows.Media; using FileConverter.Annotations; public class InputExtension : INotifyPropertyChanged { + private readonly Brush DefaultBrush = new SolidColorBrush(Color.FromRgb(0, 0, 0)); + private readonly Brush ErrorBrush = new SolidColorBrush(Color.FromRgb(255, 0, 0)); + private string name; + private Brush foregroundBrush; + private string toolTip; public InputExtension(string name) { this.Name = name; + + if (!Helpers.IsExtensionCompatibleWithOffice(name) || Helpers.IsMicrosoftOfficeAvailable()) + { + this.ForegroundBrush = this.DefaultBrush; + } + else + { + this.ForegroundBrush = this.ErrorBrush; + this.ToolTip = Properties.Resources.ErrorMicrosoftOfficeIsNotAvailable; + } } public event PropertyChangedEventHandler PropertyChanged; @@ -32,6 +48,34 @@ public string Name } } + public Brush ForegroundBrush + { + get + { + return this.foregroundBrush; + } + + set + { + this.foregroundBrush = value; + this.OnPropertyChanged(); + } + } + + public string ToolTip + { + get + { + return this.toolTip; + } + + set + { + this.toolTip = value; + this.OnPropertyChanged(); + } + } + [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { diff --git a/Application/FileConverter/Windows/SettingsWindow.xaml b/Application/FileConverter/Windows/SettingsWindow.xaml index 25925011..e54f66ea 100644 --- a/Application/FileConverter/Windows/SettingsWindow.xaml +++ b/Application/FileConverter/Windows/SettingsWindow.xaml @@ -827,7 +827,7 @@ - + From a1b70b12380e23a3a7c05bf025706367f7b5e91e Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 14 Sep 2016 08:35:38 +0200 Subject: [PATCH 25/36] Change error color --- Application/FileConverter/Windows/InputExtension.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/FileConverter/Windows/InputExtension.cs b/Application/FileConverter/Windows/InputExtension.cs index 437d5447..f47d0f4b 100644 --- a/Application/FileConverter/Windows/InputExtension.cs +++ b/Application/FileConverter/Windows/InputExtension.cs @@ -11,7 +11,7 @@ namespace FileConverter public class InputExtension : INotifyPropertyChanged { private readonly Brush DefaultBrush = new SolidColorBrush(Color.FromRgb(0, 0, 0)); - private readonly Brush ErrorBrush = new SolidColorBrush(Color.FromRgb(255, 0, 0)); + private readonly Brush ErrorBrush = new SolidColorBrush(Color.FromRgb(255, 65, 0)); private string name; private Brush foregroundBrush; From 50d0008558763f0eeac7385755ee7c56439d0432 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 14 Sep 2016 08:36:14 +0200 Subject: [PATCH 26/36] Update default settings --- .../FileConverter/Settings.default.xml | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/Application/FileConverter/Settings.default.xml b/Application/FileConverter/Settings.default.xml index 4489b1c9..b5da24fa 100644 --- a/Application/FileConverter/Settings.default.xml +++ b/Application/FileConverter/Settings.default.xml @@ -1,7 +1,9 @@ - + + fr true 3 + 2 3gp avi @@ -208,6 +210,7 @@ webm wmv gif + webp None @@ -239,6 +242,7 @@ webm wmv gif + webp None @@ -266,8 +270,10 @@ ogv webm wmv + oga None + (p)(f) @@ -276,6 +282,7 @@ wma aiff None + (p)(f) @@ -302,6 +309,7 @@ mpeg None + (p)(f) @@ -329,6 +337,7 @@ None + (p)(f) @@ -355,6 +364,7 @@ oga None + (p)(f) @@ -382,12 +392,14 @@ vob None + (p:m)DVD Extraction\(f) vob None + (p:m)DVD Extraction\(f) @@ -395,17 +407,20 @@ None + (p:m)DVD Extraction\(f) cda None + (p:m)CDA Extraction\(f) cda None + (p:m)CDA Extraction\(f) @@ -413,6 +428,7 @@ None + (p:m)CDA Extraction\(f) @@ -427,6 +443,7 @@ tga tiff xcf + webp None @@ -436,7 +453,16 @@ xcf + doc + docx + odp + ods + odt pdf + ppt + pptx + xls + xlsx None @@ -444,6 +470,27 @@ (p)(f) (n:i) of (n:c) + + bmp + exr + ico + jpg + jpeg + png + psd + svg + tga + tiff + xcf + webp + None + + + + + + (p)(f) + bmp exr @@ -456,6 +503,7 @@ tga tiff xcf + webp None @@ -474,6 +522,7 @@ svg tga tiff + webp None @@ -492,6 +541,7 @@ svg tga tiff + webp None @@ -511,6 +561,7 @@ tga tiff xcf + webp None @@ -531,6 +582,7 @@ tga tiff xcf + webp None (p)(f) @@ -545,6 +597,16 @@ tga tiff xcf + webp + doc + docx + odp + ods + odt + ppt + pptx + xls + xlsx None (p)(f) From fa019b1d19b3d0c456077ce55bc71ee9bd7e3478 Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 14 Sep 2016 08:36:34 +0200 Subject: [PATCH 27/36] Add file converter color list --- Resources/Colors.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Resources/Colors.md diff --git a/Resources/Colors.md b/Resources/Colors.md new file mode 100644 index 00000000..fa131df2 --- /dev/null +++ b/Resources/Colors.md @@ -0,0 +1,9 @@ +# File Converter Colors + +Color | Code | Description +------------|-----------|------------------------------- +Blue | #0171BB | File Converter main color +Dark Blue | #004B82 | File Converter main dark color +Red | #FF4100 | Error +Red | #DF3900 | Title +Grey | #786C71 | Light text \ No newline at end of file From 1fdf0893de0eb91b53ac552547a7c9dd3152eded Mon Sep 17 00:00:00 2001 From: Tichau Date: Wed, 14 Sep 2016 08:40:35 +0200 Subject: [PATCH 28/36] Update change log --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b4552b5..17c3c4ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ # Change Log ## Version 1.2 -- New: Possibility to convert word documents (docx, odt and doc) to pdf and images (this feature is only available if you have Microsoft Office installed). +- New: Possibility to convert Word documents (docx, odt and doc) to pdf and images (this feature is only available if you have Microsoft Office installed). +- New: Possibility to convert Excel documents (xlsx, ods and xls) to pdf and images (this feature is only available if you have Microsoft Office installed). +- New: Possibility to convert PowerPoint documents (pptx, odp and ppt) to pdf and images (this feature is only available if you have Microsoft Office installed). +- New: Possibility to convert images and documents to webp format. +- New: Support new image input format: webp. - New: Add the possibility to cancel image, CDA extraction and gif conversions. - Fixed: Issue where multiple conversion jobs was created for the same file resulting in an error message. - Tech: Improve application performances on startup. From 5d328b08b78de7fa46bfa05b61708b8092f73f54 Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 15 Sep 2016 07:23:26 +0200 Subject: [PATCH 29/36] Add compatibility with office 2010 --- Application/FileConverter/Helpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index 1266ba1b..43413a3c 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -18,7 +18,7 @@ public static class Helpers { "16.0", // Office 2016 "15.0", // Office 2013 - ////"14.0", // Office 2010 + "14.0", // Office 2010 ////"12.0", // Office 2007 ////"11.0", // Office 2003 ////"10.0", // Office XP From f57e9ce7acac9af962ed7558231c71dbe2afbbf6 Mon Sep 17 00:00:00 2001 From: Tichau Date: Thu, 15 Sep 2016 07:23:53 +0200 Subject: [PATCH 30/36] Add compatibility with all office version --- Application/FileConverter/Helpers.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index 43413a3c..a7a71eed 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -19,12 +19,12 @@ public static class Helpers "16.0", // Office 2016 "15.0", // Office 2013 "14.0", // Office 2010 - ////"12.0", // Office 2007 - ////"11.0", // Office 2003 - ////"10.0", // Office XP - ////"9.0", // Office 2000 - ////"8.0", // Office 98 - ////"7.0", // Office 97 + "12.0", // Office 2007 + "11.0", // Office 2003 + "10.0", // Office XP + "9.0", // Office 2000 + "8.0", // Office 98 + "7.0", // Office 97 }; public static IEnumerable GetSupportedCultures() From 962f29d35a9f72e14c0641df8b896777fabef17a Mon Sep 17 00:00:00 2001 From: Tichau Date: Mon, 3 Oct 2016 08:38:59 +0200 Subject: [PATCH 31/36] Close office applications when conversion fail. --- .../ConversionJobs/ConversionJob_Excel.cs | 46 +++++++++---------- .../ConversionJobs/ConversionJob_Office.cs | 11 +++++ .../ConversionJob_PowerPoint.cs | 45 +++++++++--------- .../ConversionJobs/ConversionJob_Word.cs | 46 +++++++++---------- 4 files changed, 78 insertions(+), 70 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs index 2da528a1..c1bd5137 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs @@ -100,7 +100,7 @@ protected override void Convert() this.document.Close(false); this.document = null; - this.ReleaseApplicationInstanceIfNeeded(); + this.ReleaseOfficeApplicationInstanceIfNeeded(); if (this.pdf2ImageConversionJob != null) { @@ -133,6 +133,27 @@ protected override void Convert() } } + protected override void InitializeOfficeApplicationInstanceIfNecessary() + { + if (this.application != null) + { + return; + } + + // Initialize excel application. + Diagnostics.Debug.Log("Instantiate excel application via interop."); + this.application = new Excel.Application + { + Visible = false + }; + } + + protected override void ReleaseOfficeApplicationInstanceIfNeeded() + { + Diagnostics.Debug.Log("Quit excel application via interop."); + this.application.Quit(); + } + private async Task UpdateProgress() { while (this.pdf2ImageConversionJob.State != ConversionState.Done && @@ -155,7 +176,7 @@ private async Task UpdateProgress() private void LoadDocumentIfNecessary() { - this.InitializeApplicationInstanceIfNecessary(); + this.InitializeOfficeApplicationInstanceIfNecessary(); if (this.document == null) { @@ -164,26 +185,5 @@ private void LoadDocumentIfNecessary() this.document = this.application.Workbooks.Open(this.InputFilePath, System.Reflection.Missing.Value, true); } } - - private void InitializeApplicationInstanceIfNecessary() - { - if (this.application != null) - { - return; - } - - // Initialize excel application. - Diagnostics.Debug.Log("Instantiate excel application via interop."); - this.application = new Excel.Application - { - Visible = false - }; - } - - private void ReleaseApplicationInstanceIfNeeded() - { - Diagnostics.Debug.Log("Quit excel application via interop."); - this.application.Quit(); - } } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs index cd0c1c56..088b27bb 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs @@ -22,5 +22,16 @@ protected override void Initialize() return; } } + + protected override void OnConversionFailed() + { + base.OnConversionFailed(); + + this.ReleaseOfficeApplicationInstanceIfNeeded(); + } + + protected abstract void InitializeOfficeApplicationInstanceIfNecessary(); + + protected abstract void ReleaseOfficeApplicationInstanceIfNeeded(); } } \ No newline at end of file diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs index 040d175f..619025f1 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs @@ -80,9 +80,6 @@ protected override void Convert() this.LoadDocumentIfNecessary(); - // Make this document the active document. - //this.document.Activate(); - this.UserState = Properties.Resources.ConversionStateConversion; Diagnostics.Debug.Log("Convert PowerPoint document to pdf."); @@ -92,7 +89,7 @@ protected override void Convert() this.document.Close(); this.document = null; - this.ReleaseApplicationInstanceIfNeeded(); + this.ReleaseOfficeApplicationInstanceIfNeeded(); if (this.pdf2ImageConversionJob != null) { @@ -125,6 +122,24 @@ protected override void Convert() } } + protected override void InitializeOfficeApplicationInstanceIfNecessary() + { + if (this.application != null) + { + return; + } + + // Initialize PowerPoint application. + Diagnostics.Debug.Log("Instantiate PowerPoint application via interop."); + this.application = new PowerPoint.Application(); + } + + protected override void ReleaseOfficeApplicationInstanceIfNeeded() + { + Diagnostics.Debug.Log("Quit PowerPoint application via interop."); + this.application.Quit(); + } + private async Task UpdateProgress() { while (this.pdf2ImageConversionJob.State != ConversionState.Done && @@ -147,32 +162,14 @@ private async Task UpdateProgress() private void LoadDocumentIfNecessary() { - this.InitializeApplicationInstanceIfNecessary(); + this.InitializeOfficeApplicationInstanceIfNecessary(); if (this.document == null) { Diagnostics.Debug.Log("Load PowerPoint document '{0}'.", this.InputFilePath); - this.document = this.application.Presentations.Open(this.InputFilePath, ReadOnly:MsoTriState.msoTrue, WithWindow:MsoTriState.msoFalse); + this.document = this.application.Presentations.Open(this.InputFilePath, ReadOnly: MsoTriState.msoTrue, WithWindow: MsoTriState.msoFalse); } } - - private void InitializeApplicationInstanceIfNecessary() - { - if (this.application != null) - { - return; - } - - // Initialize PowerPoint application. - Diagnostics.Debug.Log("Instantiate PowerPoint application via interop."); - this.application = new PowerPoint.Application(); - } - - private void ReleaseApplicationInstanceIfNeeded() - { - Diagnostics.Debug.Log("Quit PowerPoint application via interop."); - this.application.Quit(); - } } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index e7ed35fd..27acaedb 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -92,7 +92,7 @@ protected override void Convert() this.document.Close(Word.WdSaveOptions.wdDoNotSaveChanges); this.document = null; - this.ReleaseWordApplicationInstanceIfNeeded(); + this.ReleaseOfficeApplicationInstanceIfNeeded(); if (this.pdf2ImageConversionJob != null) { @@ -125,6 +125,27 @@ protected override void Convert() } } + protected override void InitializeOfficeApplicationInstanceIfNecessary() + { + if (this.wordApplication != null) + { + return; + } + + // Initialize word application. + Diagnostics.Debug.Log("Instantiate word application via interop."); + this.wordApplication = new Microsoft.Office.Interop.Word.Application + { + Visible = false + }; + } + + protected override void ReleaseOfficeApplicationInstanceIfNeeded() + { + Diagnostics.Debug.Log("Quit word application via interop."); + this.wordApplication.Quit(); + } + private async Task UpdateProgress() { while (this.pdf2ImageConversionJob.State != ConversionState.Done && @@ -147,7 +168,7 @@ private async Task UpdateProgress() private void LoadDocumentIfNecessary() { - this.InitializeWordApplicationInstanceIfNecessary(); + this.InitializeOfficeApplicationInstanceIfNecessary(); if (this.document == null) { @@ -156,26 +177,5 @@ private void LoadDocumentIfNecessary() this.document = this.wordApplication.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); } } - - private void InitializeWordApplicationInstanceIfNecessary() - { - if (this.wordApplication != null) - { - return; - } - - // Initialize word application. - Diagnostics.Debug.Log("Instantiate word application via interop."); - this.wordApplication = new Microsoft.Office.Interop.Word.Application - { - Visible = false - }; - } - - private void ReleaseWordApplicationInstanceIfNeeded() - { - Diagnostics.Debug.Log("Quit word application via interop."); - this.wordApplication.Quit(); - } } } From 92c96f03e83add4e69b8082021b0cc2fb562bb74 Mon Sep 17 00:00:00 2001 From: Tichau Date: Mon, 3 Oct 2016 08:39:29 +0200 Subject: [PATCH 32/36] Stylecop --- Application/FileConverter/Windows/InputExtension.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Application/FileConverter/Windows/InputExtension.cs b/Application/FileConverter/Windows/InputExtension.cs index f47d0f4b..1187fa62 100644 --- a/Application/FileConverter/Windows/InputExtension.cs +++ b/Application/FileConverter/Windows/InputExtension.cs @@ -10,8 +10,8 @@ namespace FileConverter public class InputExtension : INotifyPropertyChanged { - private readonly Brush DefaultBrush = new SolidColorBrush(Color.FromRgb(0, 0, 0)); - private readonly Brush ErrorBrush = new SolidColorBrush(Color.FromRgb(255, 65, 0)); + private readonly Brush defaultBrush = new SolidColorBrush(Color.FromRgb(0, 0, 0)); + private readonly Brush errorBrush = new SolidColorBrush(Color.FromRgb(255, 65, 0)); private string name; private Brush foregroundBrush; @@ -23,11 +23,11 @@ public InputExtension(string name) if (!Helpers.IsExtensionCompatibleWithOffice(name) || Helpers.IsMicrosoftOfficeAvailable()) { - this.ForegroundBrush = this.DefaultBrush; + this.ForegroundBrush = this.defaultBrush; } else { - this.ForegroundBrush = this.ErrorBrush; + this.ForegroundBrush = this.errorBrush; this.ToolTip = Properties.Resources.ErrorMicrosoftOfficeIsNotAvailable; } } From c9b07e71628a6f17137ae70b22f6733707c6648d Mon Sep 17 00:00:00 2001 From: Tichau Date: Tue, 4 Oct 2016 08:31:40 +0200 Subject: [PATCH 33/36] Improve error handling in office converters --- .../ConversionJobs/ConversionJob_Excel.cs | 40 ++++++++++++++-- .../ConversionJob_PowerPoint.cs | 40 ++++++++++++++-- .../ConversionJobs/ConversionJob_Word.cs | 48 +++++++++++++++---- .../Diagnostics/DiagnosticsData.cs | 2 +- .../Properties/Resources.Designer.cs | 9 ++++ .../Properties/Resources.en.resx | 3 ++ .../Properties/Resources.fr.resx | 3 ++ .../FileConverter/Properties/Resources.resx | 3 ++ 8 files changed, 128 insertions(+), 20 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs index c1bd5137..b0d6ec12 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs @@ -2,10 +2,12 @@ namespace FileConverter.ConversionJobs { + using System; using System.IO; using System.Threading.Tasks; using Excel = Microsoft.Office.Interop.Excel; + using FileConverter.Diagnostics; public class ConversionJob_Excel : ConversionJob_Office { @@ -30,7 +32,10 @@ protected override int GetOuputFilesCount() return 1; } - this.LoadDocumentIfNecessary(); + if (!this.TryLoadDocumentIfNecessary()) + { + return 1; + } int pagesCount = 0; foreach (object sheet in this.document.Sheets) @@ -86,7 +91,11 @@ protected override void Convert() this.UserState = Properties.Resources.ConversionStateReadDocument; - this.LoadDocumentIfNecessary(); + if (!this.TryLoadDocumentIfNecessary()) + { + this.ConversionFailed(Properties.Resources.ErrorUnableToUseMicrosoftOffice); + return; + } // Make this document the active document. this.document.Activate(); @@ -150,8 +159,14 @@ protected override void InitializeOfficeApplicationInstanceIfNecessary() protected override void ReleaseOfficeApplicationInstanceIfNeeded() { + if (this.application == null) + { + return; + } + Diagnostics.Debug.Log("Quit excel application via interop."); this.application.Quit(); + this.application = null; } private async Task UpdateProgress() @@ -173,10 +188,23 @@ private async Task UpdateProgress() await Task.Delay(40); } } - - private void LoadDocumentIfNecessary() + + private bool TryLoadDocumentIfNecessary() { - this.InitializeOfficeApplicationInstanceIfNecessary(); + try + { + this.InitializeOfficeApplicationInstanceIfNecessary(); + } + catch (Exception exception) + { + Debug.Log(exception.ToString()); + Debug.Log("Failed to initialize office application."); + } + + if (this.application == null) + { + return false; + } if (this.document == null) { @@ -184,6 +212,8 @@ private void LoadDocumentIfNecessary() this.document = this.application.Workbooks.Open(this.InputFilePath, System.Reflection.Missing.Value, true); } + + return this.document != null; } } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs index 619025f1..5d19d427 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs @@ -2,11 +2,13 @@ namespace FileConverter.ConversionJobs { + using System; using System.IO; using System.Threading.Tasks; using Microsoft.Office.Core; using PowerPoint = Microsoft.Office.Interop.PowerPoint; + using FileConverter.Diagnostics; public class ConversionJob_PowerPoint : ConversionJob_Office { @@ -31,7 +33,10 @@ protected override int GetOuputFilesCount() return 1; } - this.LoadDocumentIfNecessary(); + if (!this.TryLoadDocumentIfNecessary()) + { + return 1; + } int pagesCount = this.document.Slides.Count; return pagesCount; @@ -78,7 +83,11 @@ protected override void Convert() this.UserState = Properties.Resources.ConversionStateReadDocument; - this.LoadDocumentIfNecessary(); + if (!this.TryLoadDocumentIfNecessary()) + { + this.ConversionFailed(Properties.Resources.ErrorUnableToUseMicrosoftOffice); + return; + } this.UserState = Properties.Resources.ConversionStateConversion; @@ -136,8 +145,14 @@ protected override void InitializeOfficeApplicationInstanceIfNecessary() protected override void ReleaseOfficeApplicationInstanceIfNeeded() { + if (this.application == null) + { + return; + } + Diagnostics.Debug.Log("Quit PowerPoint application via interop."); this.application.Quit(); + this.application = null; } private async Task UpdateProgress() @@ -159,10 +174,23 @@ private async Task UpdateProgress() await Task.Delay(40); } } - - private void LoadDocumentIfNecessary() + + private bool TryLoadDocumentIfNecessary() { - this.InitializeOfficeApplicationInstanceIfNecessary(); + try + { + this.InitializeOfficeApplicationInstanceIfNecessary(); + } + catch (Exception exception) + { + Debug.Log(exception.ToString()); + Debug.Log("Failed to initialize office application."); + } + + if (this.application == null) + { + return false; + } if (this.document == null) { @@ -170,6 +198,8 @@ private void LoadDocumentIfNecessary() this.document = this.application.Presentations.Open(this.InputFilePath, ReadOnly: MsoTriState.msoTrue, WithWindow: MsoTriState.msoFalse); } + + return this.document != null; } } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index 27acaedb..dd7e7d29 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -2,15 +2,17 @@ namespace FileConverter.ConversionJobs { + using System; using System.IO; using System.Threading.Tasks; using Word = Microsoft.Office.Interop.Word; + using FileConverter.Diagnostics; public class ConversionJob_Word : ConversionJob_Office { private Word.Document document; - private Word.Application wordApplication; + private Word.Application application; private string intermediateFilePath = string.Empty; private ConversionJob pdf2ImageConversionJob = null; @@ -30,7 +32,10 @@ protected override int GetOuputFilesCount() return 1; } - this.LoadDocumentIfNecessary(); + if (!this.TryLoadDocumentIfNecessary()) + { + return 1; + } int pagesCount = this.document.ComputeStatistics(Word.WdStatistic.wdStatisticPages); @@ -78,7 +83,11 @@ protected override void Convert() this.UserState = Properties.Resources.ConversionStateReadDocument; - this.LoadDocumentIfNecessary(); + if (!this.TryLoadDocumentIfNecessary()) + { + this.ConversionFailed(Properties.Resources.ErrorUnableToUseMicrosoftOffice); + return; + } // Make this document the active document. this.document.Activate(); @@ -127,14 +136,14 @@ protected override void Convert() protected override void InitializeOfficeApplicationInstanceIfNecessary() { - if (this.wordApplication != null) + if (this.application != null) { return; } // Initialize word application. Diagnostics.Debug.Log("Instantiate word application via interop."); - this.wordApplication = new Microsoft.Office.Interop.Word.Application + this.application = new Microsoft.Office.Interop.Word.Application { Visible = false }; @@ -142,8 +151,14 @@ protected override void InitializeOfficeApplicationInstanceIfNecessary() protected override void ReleaseOfficeApplicationInstanceIfNeeded() { + if (this.application == null) + { + return; + } + Diagnostics.Debug.Log("Quit word application via interop."); - this.wordApplication.Quit(); + this.application.Quit(); + this.application = null; } private async Task UpdateProgress() @@ -166,16 +181,31 @@ private async Task UpdateProgress() } } - private void LoadDocumentIfNecessary() + private bool TryLoadDocumentIfNecessary() { - this.InitializeOfficeApplicationInstanceIfNecessary(); + try + { + this.InitializeOfficeApplicationInstanceIfNecessary(); + } + catch (Exception exception) + { + Debug.Log(exception.ToString()); + Debug.Log("Failed to initialize office application."); + } + + if (this.application == null) + { + return false; + } if (this.document == null) { Diagnostics.Debug.Log("Load word document '{0}'.", this.InputFilePath); - this.document = this.wordApplication.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); + this.document = this.application.Documents.Open(this.InputFilePath, System.Reflection.Missing.Value, true); } + + return this.document != null; } } } diff --git a/Application/FileConverter/Diagnostics/DiagnosticsData.cs b/Application/FileConverter/Diagnostics/DiagnosticsData.cs index ac2efc61..1507bcbc 100644 --- a/Application/FileConverter/Diagnostics/DiagnosticsData.cs +++ b/Application/FileConverter/Diagnostics/DiagnosticsData.cs @@ -77,7 +77,7 @@ public void Release() public void Log(string message, params object[] arguments) { - string log = string.Format(message, arguments); + string log = arguments.Length > 0 ? string.Format(message, arguments) : message; this.logMessages.Add(log); this.logFileWriter.WriteLine(log); diff --git a/Application/FileConverter/Properties/Resources.Designer.cs b/Application/FileConverter/Properties/Resources.Designer.cs index dec3e861..9f68979d 100644 --- a/Application/FileConverter/Properties/Resources.Designer.cs +++ b/Application/FileConverter/Properties/Resources.Designer.cs @@ -546,6 +546,15 @@ public static string ErrorMicrosoftOfficeIsNotAvailable { } } + /// + /// Looks up a localized string similar to Fail to open document with Microsoft Office (check if your licence/installation is valid).. + /// + public static string ErrorUnableToUseMicrosoftOffice { + get { + return ResourceManager.GetString("ErrorUnableToUseMicrosoftOffice", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unsupported output format '{0}'.. /// diff --git a/Application/FileConverter/Properties/Resources.en.resx b/Application/FileConverter/Properties/Resources.en.resx index 834ae0d9..f27bf539 100644 --- a/Application/FileConverter/Properties/Resources.en.resx +++ b/Application/FileConverter/Properties/Resources.en.resx @@ -529,4 +529,7 @@ use maj for uppercase version Microsoft Office must be installed in order to convert Office documents. + + Fail to open document with Microsoft Office (check if your licence/installation are valid). + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index 1edd951a..ea24a333 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -547,4 +547,7 @@ utilisez maj pour une version en majuscules Microsoft Office doit être installé pour pouvoir convertir les documents Office. + + Impossible d'ouvrir le document avec Microsoft Office (vérifiez que la licence/l'installation sont valides). + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.resx b/Application/FileConverter/Properties/Resources.resx index 5934303d..ad8c030f 100644 --- a/Application/FileConverter/Properties/Resources.resx +++ b/Application/FileConverter/Properties/Resources.resx @@ -529,4 +529,7 @@ use maj for uppercase version Microsoft Office must be installed in order to convert Office documents. + + Fail to open document with Microsoft Office (check if your licence/installation is valid). + \ No newline at end of file From 92b56299567e9790d39bb5dd5c345b65d43e3bd2 Mon Sep 17 00:00:00 2001 From: Tichau Date: Mon, 10 Oct 2016 18:42:20 +0200 Subject: [PATCH 34/36] Fixed: Microsoft office applications detection --- .../ConversionJobs/ConversionJob_Excel.cs | 11 ++- .../ConversionJobs/ConversionJob_Office.cs | 36 +++++++++- .../ConversionJob_PowerPoint.cs | 11 ++- .../ConversionJobs/ConversionJob_Word.cs | 11 ++- Application/FileConverter/Helpers.cs | 70 ++++++++++++------- .../Properties/Resources.Designer.cs | 27 +++++++ .../Properties/Resources.en.resx | 9 +++ .../Properties/Resources.fr.resx | 9 +++ .../FileConverter/Properties/Resources.resx | 9 +++ .../FileConverter/Windows/InputExtension.cs | 20 +++++- 10 files changed, 180 insertions(+), 33 deletions(-) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs index b0d6ec12..bd80a7b2 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Excel.cs @@ -6,9 +6,10 @@ namespace FileConverter.ConversionJobs using System.IO; using System.Threading.Tasks; - using Excel = Microsoft.Office.Interop.Excel; using FileConverter.Diagnostics; + using Excel = Microsoft.Office.Interop.Excel; + public class ConversionJob_Excel : ConversionJob_Office { private Excel.Workbook document; @@ -25,6 +26,14 @@ public ConversionJob_Excel(ConversionPreset conversionPreset, string inputFilePa { } + protected override ApplicationName Application + { + get + { + return ApplicationName.Excel; + } + } + protected override int GetOuputFilesCount() { if (this.ConversionPreset.OutputType == OutputType.Pdf) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs index 088b27bb..15193027 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Office.cs @@ -12,14 +12,44 @@ protected ConversionJob_Office(ConversionPreset conversionPreset, string inputFi { } + public enum ApplicationName + { + None, + + Word, + Excel, + PowerPoint + } + + protected abstract ApplicationName Application + { + get; + } + protected override void Initialize() { base.Initialize(); - if (!Helpers.IsMicrosoftOfficeAvailable()) + if (!Helpers.IsMicrosoftOfficeApplicationAvailable(this.Application)) { - this.ConversionFailed(Properties.Resources.ErrorMicrosoftOfficeIsNotAvailable); - return; + switch (this.Application) + { + case ApplicationName.Word: + this.ConversionFailed(Properties.Resources.ErrorMicrosoftWordIsNotAvailable); + return; + + case ApplicationName.PowerPoint: + this.ConversionFailed(Properties.Resources.ErrorMicrosoftPowerPointIsNotAvailable); + return; + + case ApplicationName.Excel: + this.ConversionFailed(Properties.Resources.ErrorMicrosoftExcelIsNotAvailable); + return; + + default: + this.ConversionFailed(Properties.Resources.ErrorMicrosoftOfficeIsNotAvailable); + return; + } } } diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs index 5d19d427..1c463442 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_PowerPoint.cs @@ -6,9 +6,10 @@ namespace FileConverter.ConversionJobs using System.IO; using System.Threading.Tasks; + using FileConverter.Diagnostics; using Microsoft.Office.Core; + using PowerPoint = Microsoft.Office.Interop.PowerPoint; - using FileConverter.Diagnostics; public class ConversionJob_PowerPoint : ConversionJob_Office { @@ -26,6 +27,14 @@ public ConversionJob_PowerPoint(ConversionPreset conversionPreset, string inputF { } + protected override ApplicationName Application + { + get + { + return ApplicationName.PowerPoint; + } + } + protected override int GetOuputFilesCount() { if (this.ConversionPreset.OutputType == OutputType.Pdf) diff --git a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs index dd7e7d29..c102c004 100644 --- a/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs +++ b/Application/FileConverter/ConversionJobs/ConversionJob_Word.cs @@ -6,9 +6,10 @@ namespace FileConverter.ConversionJobs using System.IO; using System.Threading.Tasks; - using Word = Microsoft.Office.Interop.Word; using FileConverter.Diagnostics; + using Word = Microsoft.Office.Interop.Word; + public class ConversionJob_Word : ConversionJob_Office { private Word.Document document; @@ -25,6 +26,14 @@ public ConversionJob_Word(ConversionPreset conversionPreset, string inputFilePat { } + protected override ApplicationName Application + { + get + { + return ApplicationName.Word; + } + } + protected override int GetOuputFilesCount() { if (this.ConversionPreset.OutputType == OutputType.Pdf) diff --git a/Application/FileConverter/Helpers.cs b/Application/FileConverter/Helpers.cs index a7a71eed..a4c022b2 100644 --- a/Application/FileConverter/Helpers.cs +++ b/Application/FileConverter/Helpers.cs @@ -10,23 +10,11 @@ namespace FileConverter using System.Reflection; using System.Threading; + using FileConverter.ConversionJobs; using Microsoft.Win32; public static class Helpers { - private static readonly string[] CompatibleOfficeVersions = new string[] - { - "16.0", // Office 2016 - "15.0", // Office 2013 - "14.0", // Office 2010 - "12.0", // Office 2007 - "11.0", // Office 2003 - "10.0", // Office XP - "9.0", // Office 2000 - "8.0", // Office 98 - "7.0", // Office 97 - }; - public static IEnumerable GetSupportedCultures() { // Get all cultures. @@ -184,42 +172,74 @@ public static Thread InstantiateThread(string name, ParameterizedThreadStart par /// /// Returns true if Office is installed on the computer. /// source: http://stackoverflow.com/questions/3266675/how-to-detect-installed-version-of-ms-office/3267832#3267832 - public static bool IsMicrosoftOfficeAvailable() + /// source: http://www.codeproject.com/Articles/26520/Getting-Office-s-Version + public static bool IsMicrosoftOfficeApplicationAvailable(ConversionJobs.ConversionJob_Office.ApplicationName application) { - string registryKeyPattern = @"Software\Microsoft\Office\{0}\Common"; + string registryKeyPattern = @"Software\Microsoft\Windows\CurrentVersion\App Paths\"; + switch (application) + { + case ConversionJob_Office.ApplicationName.Word: + registryKeyPattern += "winword.exe"; + break; + + case ConversionJob_Office.ApplicationName.PowerPoint: + registryKeyPattern += "powerpnt.exe"; + break; + + case ConversionJob_Office.ApplicationName.Excel: + registryKeyPattern += "excel.exe"; + break; + + case ConversionJob_Office.ApplicationName.None: + return false; + } + + // Looks inside CURRENT_USER. + RegistryKey winwordKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(registryKeyPattern, false); + if (winwordKey != null) + { + string winwordPath = winwordKey.GetValue(string.Empty).ToString(); + if (!string.IsNullOrEmpty(winwordPath)) + { + return true; + } + } - for (int index = 0; index < Helpers.CompatibleOfficeVersions.Length; index++) + // If not found, looks inside LOCAL_MACHINE. + winwordKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(registryKeyPattern, false); + if (winwordKey != null) { - string registryKeyPath = string.Format(registryKeyPattern, Helpers.CompatibleOfficeVersions[index]); - RegistryKey officeRegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(registryKeyPath); - if (officeRegistryKey != null) + string winwordPath = winwordKey.GetValue(string.Empty).ToString(); + if (!string.IsNullOrEmpty(winwordPath)) { - Diagnostics.Debug.Log($"Registry key '{registryKeyPath}' found"); return true; } } - Diagnostics.Debug.Log("No compatible office version found."); return false; } - public static bool IsExtensionCompatibleWithOffice(string extension) + public static ConversionJob_Office.ApplicationName GetOfficeApplicationCompatibleWithExtension(string extension) { switch (extension) { case "doc": case "docx": + case "odt": + return ConversionJob_Office.ApplicationName.Word; + case "ppt": case "pptx": case "odp": + return ConversionJob_Office.ApplicationName.PowerPoint; + case "ods": - case "odt": case "xls": case "xlsx": - return true; + return ConversionJob_Office.ApplicationName.Excel; } - return false; + return ConversionJob_Office.ApplicationName.None; } public static class InputCategoryNames diff --git a/Application/FileConverter/Properties/Resources.Designer.cs b/Application/FileConverter/Properties/Resources.Designer.cs index 9f68979d..6d7be31f 100644 --- a/Application/FileConverter/Properties/Resources.Designer.cs +++ b/Application/FileConverter/Properties/Resources.Designer.cs @@ -537,6 +537,15 @@ public static string ErrorInvalidOutputPath { } } + /// + /// Looks up a localized string similar to Microsoft Excel must be installed in order to convert Excel documents.. + /// + public static string ErrorMicrosoftExcelIsNotAvailable { + get { + return ResourceManager.GetString("ErrorMicrosoftExcelIsNotAvailable", resourceCulture); + } + } + /// /// Looks up a localized string similar to Microsoft Office must be installed in order to convert Office documents.. /// @@ -546,6 +555,24 @@ public static string ErrorMicrosoftOfficeIsNotAvailable { } } + /// + /// Looks up a localized string similar to Microsoft PowerPoint must be installed in order to convert PowerPoint documents.. + /// + public static string ErrorMicrosoftPowerPointIsNotAvailable { + get { + return ResourceManager.GetString("ErrorMicrosoftPowerPointIsNotAvailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Microsoft Word must be installed in order to convert Word documents.. + /// + public static string ErrorMicrosoftWordIsNotAvailable { + get { + return ResourceManager.GetString("ErrorMicrosoftWordIsNotAvailable", resourceCulture); + } + } + /// /// Looks up a localized string similar to Fail to open document with Microsoft Office (check if your licence/installation is valid).. /// diff --git a/Application/FileConverter/Properties/Resources.en.resx b/Application/FileConverter/Properties/Resources.en.resx index f27bf539..ca362acb 100644 --- a/Application/FileConverter/Properties/Resources.en.resx +++ b/Application/FileConverter/Properties/Resources.en.resx @@ -532,4 +532,13 @@ use maj for uppercase version Fail to open document with Microsoft Office (check if your licence/installation are valid). + + Microsoft Excel must be installed in order to convert Excel documents. + + + Microsoft PowerPoint must be installed in order to convert PowerPoint documents. + + + Microsoft Word must be installed in order to convert Word documents. + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.fr.resx b/Application/FileConverter/Properties/Resources.fr.resx index ea24a333..59dbeefb 100644 --- a/Application/FileConverter/Properties/Resources.fr.resx +++ b/Application/FileConverter/Properties/Resources.fr.resx @@ -550,4 +550,13 @@ utilisez maj pour une version en majuscules Impossible d'ouvrir le document avec Microsoft Office (vérifiez que la licence/l'installation sont valides). + + Microsoft Excel doit être installé pour pouvoir convertir les documents Excel. + + + Microsoft PowerPoint doit être installé pour pouvoir convertir les documents PowerPoint. + + + Microsoft Word doit être installé pour pouvoir convertir les documents Word. + \ No newline at end of file diff --git a/Application/FileConverter/Properties/Resources.resx b/Application/FileConverter/Properties/Resources.resx index ad8c030f..8857064f 100644 --- a/Application/FileConverter/Properties/Resources.resx +++ b/Application/FileConverter/Properties/Resources.resx @@ -532,4 +532,13 @@ use maj for uppercase version Fail to open document with Microsoft Office (check if your licence/installation is valid). + + Microsoft Excel must be installed in order to convert Excel documents. + + + Microsoft PowerPoint must be installed in order to convert PowerPoint documents. + + + Microsoft Word must be installed in order to convert Word documents. + \ No newline at end of file diff --git a/Application/FileConverter/Windows/InputExtension.cs b/Application/FileConverter/Windows/InputExtension.cs index 1187fa62..fcebe970 100644 --- a/Application/FileConverter/Windows/InputExtension.cs +++ b/Application/FileConverter/Windows/InputExtension.cs @@ -7,6 +7,7 @@ namespace FileConverter using System.Windows.Media; using FileConverter.Annotations; + using FileConverter.ConversionJobs; public class InputExtension : INotifyPropertyChanged { @@ -21,14 +22,29 @@ public InputExtension(string name) { this.Name = name; - if (!Helpers.IsExtensionCompatibleWithOffice(name) || Helpers.IsMicrosoftOfficeAvailable()) + ConversionJob_Office.ApplicationName officeApplication = Helpers.GetOfficeApplicationCompatibleWithExtension(name); + + if (officeApplication == ConversionJob_Office.ApplicationName.None || Helpers.IsMicrosoftOfficeApplicationAvailable(officeApplication)) { this.ForegroundBrush = this.defaultBrush; } else { this.ForegroundBrush = this.errorBrush; - this.ToolTip = Properties.Resources.ErrorMicrosoftOfficeIsNotAvailable; + switch (officeApplication) + { + case ConversionJob_Office.ApplicationName.Word: + this.ToolTip = Properties.Resources.ErrorMicrosoftWordIsNotAvailable; + break; + + case ConversionJob_Office.ApplicationName.PowerPoint: + this.ToolTip = Properties.Resources.ErrorMicrosoftPowerPointIsNotAvailable; + break; + + case ConversionJob_Office.ApplicationName.Excel: + this.ToolTip = Properties.Resources.ErrorMicrosoftExcelIsNotAvailable; + break; + } } } From 4ff01248ad0bc79d6171d7e6e74662635a97cd83 Mon Sep 17 00:00:00 2001 From: Tichau Date: Mon, 10 Oct 2016 19:01:50 +0200 Subject: [PATCH 35/36] Udpate change log --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c3c4ee..34e6f8eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,13 @@ # Change Log ## Version 1.2 -- New: Possibility to convert Word documents (docx, odt and doc) to pdf and images (this feature is only available if you have Microsoft Office installed). -- New: Possibility to convert Excel documents (xlsx, ods and xls) to pdf and images (this feature is only available if you have Microsoft Office installed). -- New: Possibility to convert PowerPoint documents (pptx, odp and ppt) to pdf and images (this feature is only available if you have Microsoft Office installed). +- New: Possibility to convert Word documents (docx, odt and doc) to pdf and images (this feature is only available if you have Microsoft Word installed). +- New: Possibility to convert Excel documents (xlsx, ods and xls) to pdf and images (this feature is only available if you have Microsoft Excel installed). +- New: Possibility to convert PowerPoint documents (pptx, odp and ppt) to pdf and images (this feature is only available if you have Microsoft PowerPoint installed). - New: Possibility to convert images and documents to webp format. - New: Support new image input format: webp. - New: Add the possibility to cancel image, CDA extraction and gif conversions. -- Fixed: Issue where multiple conversion jobs was created for the same file resulting in an error message. +- Fixed: Issue where multiple conversion jobs were created for the same file resulting in an error message. - Tech: Improve application performances on startup. - Tech: Improve diagnostics. From a47ea62c839ce8e562af711734fcba0391e019d0 Mon Sep 17 00:00:00 2001 From: Tichau Date: Mon, 10 Oct 2016 19:04:44 +0200 Subject: [PATCH 36/36] Change version number to 1.2 --- Application/FileConverter/Application.xaml.cs | 2 +- Installer/Product.wxs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Application/FileConverter/Application.xaml.cs b/Application/FileConverter/Application.xaml.cs index 02eee853..467c9736 100644 --- a/Application/FileConverter/Application.xaml.cs +++ b/Application/FileConverter/Application.xaml.cs @@ -31,7 +31,7 @@ public partial class Application : System.Windows.Application private static readonly Version Version = new Version() { Major = 1, - Minor = 1, + Minor = 2, Patch = 0, }; diff --git a/Installer/Product.wxs b/Installer/Product.wxs index dc7a33d7..2eb586ad 100644 --- a/Installer/Product.wxs +++ b/Installer/Product.wxs @@ -12,7 +12,7 @@ - +