From 6f47b225bff805c6446c80c0eda091ae10498f6f Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 25 Apr 2024 15:26:54 +0700 Subject: [PATCH 01/15] Renamed project to SIL.Windows.Forms.Archiving To align with all other WinForms projects --- CHANGELOG.md | 14 +++++++------- Palaso.sln | 4 ++-- .../AccessProtocolListTests.cs | 4 ++-- .../ArchivingFileSystemTests.cs | 4 ++-- .../IMDI30Tests.cs | 10 +++++----- .../IMDIArchivingDlgViewModelTests.cs | 4 ++-- .../JSONUtilsTests.cs | 2 +- .../LanguageListTests.cs | 4 ++-- .../RampArchivingDlgViewModelTests.cs | 2 +- .../SIL.Windows.Forms.Archiving.Tests.csproj | 8 ++++---- .../SimpleObjectTests.cs | 4 ++-- .../ArchivingDlg.Designer.cs | 4 ++-- .../ArchivingDlg.cs | 2 +- .../ArchivingDlg.resx | 0 .../ArchivingDlgViewModel.cs | 4 ++-- .../ArchivingEnumerations.cs | 2 +- .../ArchivingLanguage.cs | 2 +- .../ArchivingPrograms.cs | 2 +- .../Extensions.cs | 2 +- .../Generic/AccessProtocol/AccessProtocolList.cs | 4 ++-- .../Generic/ArchivingAccess.cs | 2 +- .../Generic/ArchivingActor.cs | 2 +- .../Generic/ArchivingContact.cs | 2 +- .../Generic/ArchivingFile.cs | 4 ++-- .../Generic/ArchivingFileSystem.cs | 2 +- .../Generic/ArchivingPackage.cs | 4 ++-- .../Generic/ArchivingSession.cs | 2 +- .../Generic/FileMimeType.cs | 2 +- .../Generic/GenericObject.cs | 4 ++-- .../Generic/LanguageString.cs | 2 +- .../Generic/SimpleObjects.cs | 2 +- .../IMDI/IMDIArchivingDlg.cs | 2 +- .../IMDI/IMDIArchivingDlgViewModel.cs | 6 +++--- .../IMDI/IMDIContributor.cs | 4 ++-- .../IMDI/IMDIFile.cs | 8 ++++---- .../IMDI/IMDIPackage.cs | 8 ++++---- .../IMDI/Lists/BooleanEnum.cs | 2 +- .../IMDI/Lists/ItemListBase.cs | 6 +++--- .../IMDI/Lists/LanguageList.cs | 4 ++-- .../IMDI/Lists/ListConstructor.cs | 2 +- .../IMDI/Lists/ListType.cs | 2 +- .../IMDI/Schema/IMDIDescription.cs | 4 ++-- .../IMDI/Schema/IMDIExtensions.cs | 6 +++--- .../IMDI/Schema/IMDIInterfaces.cs | 2 +- .../IMDI/Schema/IMDISchemaHelper.cs | 2 +- .../IMDI/Schema/IMDI_3_0.cs | 8 ++++---- .../IMDI/Schema/IMDI_3_0_Fix.py | 2 +- .../IMDI/Schema/IMDI_3_0_NotUsed.cs | 2 +- .../IMDI/xsd/GenerateClasses.bat | 6 +++--- .../IMDI/xsd/imdi-v3.xsd | 0 .../JSONUtils.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/Resources.Designer.cs | 4 ++-- .../Properties/Resources.resx | 0 .../Properties/Settings.Designer.cs | 2 +- .../Properties/Settings.settings | 2 +- .../RampArchivingDlgViewModel.cs | 6 +++--- .../Resources/AccessProtocols.json | 0 .../Resources/CustomAccessProtocols.json | 0 .../Resources/EmptyMets.xml | 0 .../Resources/ailca.html | 0 .../Resources/ailla.html | 0 .../Resources/anla.html | 0 .../Resources/elar.html | 0 .../Resources/reap.html | 0 .../Resources/tla.html | 0 .../SIL.Windows.Forms.Archiving.csproj | 6 +++--- .../app.config | 6 +++--- 68 files changed, 108 insertions(+), 108 deletions(-) rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/AccessProtocolListTests.cs (93%) rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/ArchivingFileSystemTests.cs (90%) rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/IMDI30Tests.cs (97%) rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/IMDIArchivingDlgViewModelTests.cs (99%) rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/JSONUtilsTests.cs (99%) mode change 100755 => 100644 rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/LanguageListTests.cs (95%) rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/RampArchivingDlgViewModelTests.cs (99%) mode change 100755 => 100644 rename SIL.Archiving.Tests/SIL.Archiving.Tests.csproj => SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj (75%) rename {SIL.Archiving.Tests => SIL.Windows.Forms.Archiving.Tests}/SimpleObjectTests.cs (93%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/ArchivingDlg.Designer.cs (99%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/ArchivingDlg.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/ArchivingDlg.resx (100%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/ArchivingDlgViewModel.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/ArchivingEnumerations.cs (99%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/ArchivingLanguage.cs (99%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/ArchivingPrograms.cs (98%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Extensions.cs (99%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/AccessProtocol/AccessProtocolList.cs (98%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/ArchivingAccess.cs (84%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/ArchivingActor.cs (98%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/ArchivingContact.cs (97%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/ArchivingFile.cs (96%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/ArchivingFileSystem.cs (97%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/ArchivingPackage.cs (96%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/ArchivingSession.cs (97%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/FileMimeType.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/GenericObject.cs (86%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/LanguageString.cs (97%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Generic/SimpleObjects.cs (94%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/IMDIArchivingDlg.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/IMDIArchivingDlgViewModel.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/IMDIContributor.cs (92%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/IMDIFile.cs (96%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/IMDIPackage.cs (97%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Lists/BooleanEnum.cs (87%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Lists/ItemListBase.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Lists/LanguageList.cs (98%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Lists/ListConstructor.cs (98%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Lists/ListType.cs (98%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Schema/IMDIDescription.cs (96%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Schema/IMDIExtensions.cs (96%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Schema/IMDIInterfaces.cs (93%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Schema/IMDISchemaHelper.cs (93%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Schema/IMDI_3_0.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Schema/IMDI_3_0_Fix.py (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/Schema/IMDI_3_0_NotUsed.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/xsd/GenerateClasses.bat (53%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/IMDI/xsd/imdi-v3.xsd (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/JSONUtils.cs (98%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Properties/AssemblyInfo.cs (91%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Properties/Resources.Designer.cs (98%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Properties/Resources.resx (100%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Properties/Settings.Designer.cs (97%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Properties/Settings.settings (91%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/RampArchivingDlgViewModel.cs (99%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/AccessProtocols.json (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/CustomAccessProtocols.json (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/EmptyMets.xml (100%) mode change 100755 => 100644 rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/ailca.html (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/ailla.html (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/anla.html (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/elar.html (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/reap.html (100%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/Resources/tla.html (100%) rename SIL.Archiving/SIL.Archiving.csproj => SIL.Windows.Forms.Archiving/SIL.Windows.Forms.Archiving.csproj (84%) rename {SIL.Archiving => SIL.Windows.Forms.Archiving}/app.config (74%) mode change 100755 => 100644 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0889a6b86..9fb99bfb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed -- [SIL.Archiving] Upgraded to L10nSharp 7.0.0 +- [SIL.Windows.Forms.Archiving] Upgraded to L10nSharp 7.0.0 - [SIL.Windows.Forms] Upgraded to L10nSharp 7.0.0 - [SIL.Windows.Forms.DblBundle] Upgraded to L10nSharp 7.0.0 - [SIL.Windows.Forms.Keyboarding] Upgraded to L10nSharp 7.0.0 @@ -130,14 +130,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.DblBundle] Attempting to construct a UsxNode based on an invalid XmlNode now throws an exception in the constructor in most cases rather than later when properties are accessed. - [SIL.DblBundle] Accessing UsxChapter.ChapterNumber on a chapter end node returns the chapter number (from the eid attribute) instead of throwing an exception. - [SIL.WritingSystems] Prevent (and clean up) duplicate URLs in LDML files for Fonts, Keyboards, and Spell Check Dictionaries. -- [SIL.Archiving] Set UseZip64WhenSaving to Zip64Option.AsNecessary to prevent crash with large archives +- [SIL.Windows.Forms.Archiving] Set UseZip64WhenSaving to Zip64Option.AsNecessary to prevent crash with large archives ### Changed -- [SIL.Archiving] Changed REAP access protocol label from "Insite users" to "REAP users" -- [SIL.Archiving] Fixed typo in name of ArchiveAccessProtocol.GetDocumentationUri methods -- [SIL.Archiving] Changed ArchiveAccessProtocol.GetDocumentationUri methods -- [SIL.Archiving] Changed ArchiveAccessProtocol.SetChoicesFromCsv to thow ArgumentNullException instead of NullReferenceException. Also made it discard duplicate choices if the list contains duplicates. +- [SIL.Windows.Forms.Archiving] Changed REAP access protocol label from "Insite users" to "REAP users" +- [SIL.Windows.Forms.Archiving] Fixed typo in name of ArchiveAccessProtocol.GetDocumentationUri methods +- [SIL.Windows.Forms.Archiving] Changed ArchiveAccessProtocol.GetDocumentationUri methods +- [SIL.Windows.Forms.Archiving] Changed ArchiveAccessProtocol.SetChoicesFromCsv to thow ArgumentNullException instead of NullReferenceException. Also made it discard duplicate choices if the list contains duplicates. - [SIL.Core] `FileLocationUtilities.GetDirectoryDistributedWithApplication` checks not only in `DistFiles`, `common`, and `src` subdirectories, but also directly in the application or solution directory. - [SIL.Core] Store URLs in Sets instead of Lists in `IKeyboardDefinition` (to prevent duplicates) @@ -193,7 +193,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- [SIL.Archiving] Fixed formatting of DateTimes +- [SIL.Windows.Forms.Archiving] Fixed formatting of DateTimes - [SIL.Core] Fixed SIL.IO.PathUtilities.DeleteToRecycleBin and .GetDefaultFileManager to work in a flatpak environment. - [SIL.Lexicon] Fixed crash caused by incorrect processing of keyboard data - [SIL.Scripture] Fixed SIL.Scripture.MultilingScrBooks.VerseRefRegex to make punctuation more specific diff --git a/Palaso.sln b/Palaso.sln index c8cae8d01..0821796fd 100755 --- a/Palaso.sln +++ b/Palaso.sln @@ -25,9 +25,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Reporting.TestApp", "TestAp {DB44F49C-D8C6-434F-81ED-28EA5C9E8195} = {DB44F49C-D8C6-434F-81ED-28EA5C9E8195} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving", "SIL.Archiving\SIL.Archiving.csproj", "{BCE1F124-5479-4B23-90B1-B7A4EBE44FA3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Windows.Forms.Archiving", "SIL.Windows.Forms.Archiving\SIL.Windows.Forms.Archiving.csproj", "{BCE1F124-5479-4B23-90B1-B7A4EBE44FA3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving.Tests", "SIL.Archiving.Tests\SIL.Archiving.Tests.csproj", "{892C7F20-FBBB-4AB3-BAC2-E40A135567B6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Windows.Forms.Archiving.Tests", "SIL.Windows.Forms.Archiving.Tests\SIL.Windows.Forms.Archiving.Tests.csproj", "{892C7F20-FBBB-4AB3-BAC2-E40A135567B6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Scripture", "SIL.Scripture\SIL.Scripture.csproj", "{F71BA7B9-D9DC-4F8C-A307-87B503D0E05B}" EndProject diff --git a/SIL.Archiving.Tests/AccessProtocolListTests.cs b/SIL.Windows.Forms.Archiving.Tests/AccessProtocolListTests.cs similarity index 93% rename from SIL.Archiving.Tests/AccessProtocolListTests.cs rename to SIL.Windows.Forms.Archiving.Tests/AccessProtocolListTests.cs index bcbb325f0..d5aff3aa9 100644 --- a/SIL.Archiving.Tests/AccessProtocolListTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/AccessProtocolListTests.cs @@ -2,9 +2,9 @@ using System.IO; using System.Linq; using NUnit.Framework; -using SIL.Archiving.Generic.AccessProtocol; +using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] [Category("Archiving")] diff --git a/SIL.Archiving.Tests/ArchivingFileSystemTests.cs b/SIL.Windows.Forms.Archiving.Tests/ArchivingFileSystemTests.cs similarity index 90% rename from SIL.Archiving.Tests/ArchivingFileSystemTests.cs rename to SIL.Windows.Forms.Archiving.Tests/ArchivingFileSystemTests.cs index f71d16630..fc9180bf5 100644 --- a/SIL.Archiving.Tests/ArchivingFileSystemTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/ArchivingFileSystemTests.cs @@ -4,10 +4,10 @@ using System; using System.IO; using NUnit.Framework; -using SIL.Archiving.Generic; +using SIL.Windows.Forms.Archiving.Generic; using SIL.IO; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] public class ArchivingFileSystemTests diff --git a/SIL.Archiving.Tests/IMDI30Tests.cs b/SIL.Windows.Forms.Archiving.Tests/IMDI30Tests.cs similarity index 97% rename from SIL.Archiving.Tests/IMDI30Tests.cs rename to SIL.Windows.Forms.Archiving.Tests/IMDI30Tests.cs index 43b367b6d..42c080313 100644 --- a/SIL.Archiving.Tests/IMDI30Tests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/IMDI30Tests.cs @@ -2,13 +2,13 @@ using System.Globalization; using System.Linq; using NUnit.Framework; -using SIL.Archiving.Generic; -using SIL.Archiving.IMDI; -using SIL.Archiving.IMDI.Lists; -using SIL.Archiving.IMDI.Schema; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.IMDI; +using SIL.Windows.Forms.Archiving.IMDI.Lists; +using SIL.Windows.Forms.Archiving.IMDI.Schema; using SIL.TestUtilities; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] [OfflineSldr] diff --git a/SIL.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs b/SIL.Windows.Forms.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs similarity index 99% rename from SIL.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs rename to SIL.Windows.Forms.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs index 6577854de..95fa9b83e 100644 --- a/SIL.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Xml; using NUnit.Framework; -using SIL.Archiving.IMDI; +using SIL.Windows.Forms.Archiving.IMDI; using SIL.Reporting; using SIL.TestUtilities; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] [OfflineSldr] diff --git a/SIL.Archiving.Tests/JSONUtilsTests.cs b/SIL.Windows.Forms.Archiving.Tests/JSONUtilsTests.cs old mode 100755 new mode 100644 similarity index 99% rename from SIL.Archiving.Tests/JSONUtilsTests.cs rename to SIL.Windows.Forms.Archiving.Tests/JSONUtilsTests.cs index f0544ea46..fd7b9b0fe --- a/SIL.Archiving.Tests/JSONUtilsTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/JSONUtilsTests.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using NUnit.Framework; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] [Category("Archiving")] diff --git a/SIL.Archiving.Tests/LanguageListTests.cs b/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs similarity index 95% rename from SIL.Archiving.Tests/LanguageListTests.cs rename to SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs index 02e14549a..4129205a1 100644 --- a/SIL.Archiving.Tests/LanguageListTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs @@ -1,8 +1,8 @@ using NUnit.Framework; -using SIL.Archiving.IMDI.Lists; +using SIL.Windows.Forms.Archiving.IMDI.Lists; using SIL.TestUtilities; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] [OfflineSldr] diff --git a/SIL.Archiving.Tests/RampArchivingDlgViewModelTests.cs b/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs old mode 100755 new mode 100644 similarity index 99% rename from SIL.Archiving.Tests/RampArchivingDlgViewModelTests.cs rename to SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs index 08f86a709..d1a50d5e9 --- a/SIL.Archiving.Tests/RampArchivingDlgViewModelTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs @@ -10,7 +10,7 @@ using SIL.TestUtilities; using SIL.Windows.Forms.ClearShare; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] [Category("Archiving")] diff --git a/SIL.Archiving.Tests/SIL.Archiving.Tests.csproj b/SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj similarity index 75% rename from SIL.Archiving.Tests/SIL.Archiving.Tests.csproj rename to SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj index 7e717f625..147b53352 100644 --- a/SIL.Archiving.Tests/SIL.Archiving.Tests.csproj +++ b/SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj @@ -1,9 +1,9 @@ - SIL.Archiving.Tests - SIL.Archiving.Tests - Unit tests for SIL.Archiving + SIL.Windows.Forms.Archiving.Tests + SIL.Windows.Forms.Archiving.Tests + Unit tests for SIL.Windows.Forms.Archiving false true true @@ -17,7 +17,7 @@ - + diff --git a/SIL.Archiving.Tests/SimpleObjectTests.cs b/SIL.Windows.Forms.Archiving.Tests/SimpleObjectTests.cs similarity index 93% rename from SIL.Archiving.Tests/SimpleObjectTests.cs rename to SIL.Windows.Forms.Archiving.Tests/SimpleObjectTests.cs index 8ceca674c..6ab8d0fd3 100644 --- a/SIL.Archiving.Tests/SimpleObjectTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/SimpleObjectTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; -using SIL.Archiving.Generic; +using SIL.Windows.Forms.Archiving.Generic; -namespace SIL.Archiving.Tests +namespace SIL.Windows.Forms.Archiving.Tests { [TestFixture] [Category("Archiving")] diff --git a/SIL.Archiving/ArchivingDlg.Designer.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs old mode 100755 new mode 100644 similarity index 99% rename from SIL.Archiving/ArchivingDlg.Designer.cs rename to SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs index 22d2888de..3195acdd5 --- a/SIL.Archiving/ArchivingDlg.Designer.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs @@ -1,6 +1,6 @@ using SIL.Windows.Forms.Progress; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { partial class ArchivingDlg { @@ -194,7 +194,7 @@ private void InitializeComponent() // // locExtender // - this.locExtender.LocalizationManagerId = "SIL.Archiving"; + this.locExtender.LocalizationManagerId = "SIL.Windows.Forms.Archiving"; this.locExtender.PrefixForNewItems = null; // // _chkMetadataOnly diff --git a/SIL.Archiving/ArchivingDlg.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs similarity index 99% rename from SIL.Archiving/ArchivingDlg.cs rename to SIL.Windows.Forms.Archiving/ArchivingDlg.cs index 5ef1fce1e..7f32e5c8b 100644 --- a/SIL.Archiving/ArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs @@ -5,7 +5,7 @@ using SIL.Windows.Forms.Miscellaneous; using SIL.Windows.Forms.PortableSettingsProvider; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { /// ---------------------------------------------------------------------------------------- public partial class ArchivingDlg : Form diff --git a/SIL.Archiving/ArchivingDlg.resx b/SIL.Windows.Forms.Archiving/ArchivingDlg.resx old mode 100755 new mode 100644 similarity index 100% rename from SIL.Archiving/ArchivingDlg.resx rename to SIL.Windows.Forms.Archiving/ArchivingDlg.resx diff --git a/SIL.Archiving/ArchivingDlgViewModel.cs b/SIL.Windows.Forms.Archiving/ArchivingDlgViewModel.cs similarity index 99% rename from SIL.Archiving/ArchivingDlgViewModel.cs rename to SIL.Windows.Forms.Archiving/ArchivingDlgViewModel.cs index b9a388f03..7385c75de 100644 --- a/SIL.Archiving/ArchivingDlgViewModel.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlgViewModel.cs @@ -8,11 +8,11 @@ using System.Windows.Forms; using JetBrains.Annotations; using L10NSharp; -using SIL.Archiving.Generic; +using SIL.Windows.Forms.Archiving.Generic; using SIL.Code; using SIL.IO; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { /// ------------------------------------------------------------------------------------ public abstract class ArchivingDlgViewModel diff --git a/SIL.Archiving/ArchivingEnumerations.cs b/SIL.Windows.Forms.Archiving/ArchivingEnumerations.cs old mode 100755 new mode 100644 similarity index 99% rename from SIL.Archiving/ArchivingEnumerations.cs rename to SIL.Windows.Forms.Archiving/ArchivingEnumerations.cs index ba5da6715..60fe7c413 --- a/SIL.Archiving/ArchivingEnumerations.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingEnumerations.cs @@ -3,7 +3,7 @@ // ReSharper disable CSharpWarnings::CS1591 // ReSharper disable InconsistentNaming -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { /// /// For use with SetAudience method. Note: Both 'Internal audience' and 'Wider audience' works are expected to be in a diff --git a/SIL.Archiving/ArchivingLanguage.cs b/SIL.Windows.Forms.Archiving/ArchivingLanguage.cs old mode 100755 new mode 100644 similarity index 99% rename from SIL.Archiving/ArchivingLanguage.cs rename to SIL.Windows.Forms.Archiving/ArchivingLanguage.cs index 4ffafd6ae..3d48b59f0 --- a/SIL.Archiving/ArchivingLanguage.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingLanguage.cs @@ -4,7 +4,7 @@ using System.Linq; using SIL.WritingSystems; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { /// public class ArchivingLanguage : IComparable diff --git a/SIL.Archiving/ArchivingPrograms.cs b/SIL.Windows.Forms.Archiving/ArchivingPrograms.cs similarity index 98% rename from SIL.Archiving/ArchivingPrograms.cs rename to SIL.Windows.Forms.Archiving/ArchivingPrograms.cs index fd444bcfa..dd6519037 100644 --- a/SIL.Archiving/ArchivingPrograms.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingPrograms.cs @@ -2,7 +2,7 @@ using System.Linq; using SIL.IO; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { /// public static class ArchivingPrograms diff --git a/SIL.Archiving/Extensions.cs b/SIL.Windows.Forms.Archiving/Extensions.cs old mode 100755 new mode 100644 similarity index 99% rename from SIL.Archiving/Extensions.cs rename to SIL.Windows.Forms.Archiving/Extensions.cs index f0a1e2305..505868677 --- a/SIL.Archiving/Extensions.cs +++ b/SIL.Windows.Forms.Archiving/Extensions.cs @@ -3,7 +3,7 @@ using System.Text; using System.Windows.Forms; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { /// ------------------------------------------------------------------------------------ public static class Extensions diff --git a/SIL.Archiving/Generic/AccessProtocol/AccessProtocolList.cs b/SIL.Windows.Forms.Archiving/Generic/AccessProtocol/AccessProtocolList.cs similarity index 98% rename from SIL.Archiving/Generic/AccessProtocol/AccessProtocolList.cs rename to SIL.Windows.Forms.Archiving/Generic/AccessProtocol/AccessProtocolList.cs index cc1f5778a..3bdbff2b7 100644 --- a/SIL.Archiving/Generic/AccessProtocol/AccessProtocolList.cs +++ b/SIL.Windows.Forms.Archiving/Generic/AccessProtocol/AccessProtocolList.cs @@ -7,9 +7,9 @@ using System.Runtime.Serialization.Json; using System.Text; using JetBrains.Annotations; -using SIL.Archiving.Properties; +using SIL.Windows.Forms.Archiving.Properties; -namespace SIL.Archiving.Generic.AccessProtocol +namespace SIL.Windows.Forms.Archiving.Generic.AccessProtocol { /// This class is used to deserialize the JSON data in %ProgramData%\SIL\Archiving\AccessProtocols.json [CollectionDataContract(ItemName = "AccessProtocol")] diff --git a/SIL.Archiving/Generic/ArchivingAccess.cs b/SIL.Windows.Forms.Archiving/Generic/ArchivingAccess.cs similarity index 84% rename from SIL.Archiving/Generic/ArchivingAccess.cs rename to SIL.Windows.Forms.Archiving/Generic/ArchivingAccess.cs index 00e8e8816..b08f36a73 100644 --- a/SIL.Archiving/Generic/ArchivingAccess.cs +++ b/SIL.Windows.Forms.Archiving/Generic/ArchivingAccess.cs @@ -1,5 +1,5 @@  -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// public class ArchivingAccess diff --git a/SIL.Archiving/Generic/ArchivingActor.cs b/SIL.Windows.Forms.Archiving/Generic/ArchivingActor.cs similarity index 98% rename from SIL.Archiving/Generic/ArchivingActor.cs rename to SIL.Windows.Forms.Archiving/Generic/ArchivingActor.cs index ae4c6fba9..288a472fa 100644 --- a/SIL.Archiving/Generic/ArchivingActor.cs +++ b/SIL.Windows.Forms.Archiving/Generic/ArchivingActor.cs @@ -3,7 +3,7 @@ using System.Linq; using SIL.Extensions; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// An Actor is someone who has contributed to the content as a speaker or writer public class ArchivingActor : IComparable diff --git a/SIL.Archiving/Generic/ArchivingContact.cs b/SIL.Windows.Forms.Archiving/Generic/ArchivingContact.cs similarity index 97% rename from SIL.Archiving/Generic/ArchivingContact.cs rename to SIL.Windows.Forms.Archiving/Generic/ArchivingContact.cs index b377f25b0..abd2bb29e 100644 --- a/SIL.Archiving/Generic/ArchivingContact.cs +++ b/SIL.Windows.Forms.Archiving/Generic/ArchivingContact.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// Information about a contact public class ArchivingContact : IComparable diff --git a/SIL.Archiving/Generic/ArchivingFile.cs b/SIL.Windows.Forms.Archiving/Generic/ArchivingFile.cs similarity index 96% rename from SIL.Archiving/Generic/ArchivingFile.cs rename to SIL.Windows.Forms.Archiving/Generic/ArchivingFile.cs index 7418f6517..e9130511d 100644 --- a/SIL.Archiving/Generic/ArchivingFile.cs +++ b/SIL.Windows.Forms.Archiving/Generic/ArchivingFile.cs @@ -1,8 +1,8 @@ using System; using System.IO; -using SIL.Archiving.Generic.AccessProtocol; +using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// A file to add to the archive public class ArchivingFile diff --git a/SIL.Archiving/Generic/ArchivingFileSystem.cs b/SIL.Windows.Forms.Archiving/Generic/ArchivingFileSystem.cs similarity index 97% rename from SIL.Archiving/Generic/ArchivingFileSystem.cs rename to SIL.Windows.Forms.Archiving/Generic/ArchivingFileSystem.cs index c455dcccf..d2bdb058f 100644 --- a/SIL.Archiving/Generic/ArchivingFileSystem.cs +++ b/SIL.Windows.Forms.Archiving/Generic/ArchivingFileSystem.cs @@ -5,7 +5,7 @@ using System.IO; using SIL.PlatformUtilities; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// public static class ArchivingFileSystem diff --git a/SIL.Archiving/Generic/ArchivingPackage.cs b/SIL.Windows.Forms.Archiving/Generic/ArchivingPackage.cs similarity index 96% rename from SIL.Archiving/Generic/ArchivingPackage.cs rename to SIL.Windows.Forms.Archiving/Generic/ArchivingPackage.cs index dc5db1144..bb522d779 100644 --- a/SIL.Archiving/Generic/ArchivingPackage.cs +++ b/SIL.Windows.Forms.Archiving/Generic/ArchivingPackage.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; -using SIL.Archiving.Generic.AccessProtocol; +using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// public interface IArchivingPackage : IArchivingGenericObject diff --git a/SIL.Archiving/Generic/ArchivingSession.cs b/SIL.Windows.Forms.Archiving/Generic/ArchivingSession.cs similarity index 97% rename from SIL.Archiving/Generic/ArchivingSession.cs rename to SIL.Windows.Forms.Archiving/Generic/ArchivingSession.cs index a711c4f28..d87d7ab1a 100644 --- a/SIL.Archiving/Generic/ArchivingSession.cs +++ b/SIL.Windows.Forms.Archiving/Generic/ArchivingSession.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// Contains the materials being archived, and their metadata public interface IArchivingSession : IArchivingGenericObject diff --git a/SIL.Archiving/Generic/FileMimeType.cs b/SIL.Windows.Forms.Archiving/Generic/FileMimeType.cs similarity index 99% rename from SIL.Archiving/Generic/FileMimeType.cs rename to SIL.Windows.Forms.Archiving/Generic/FileMimeType.cs index d7cf71242..2a5111b40 100644 --- a/SIL.Archiving/Generic/FileMimeType.cs +++ b/SIL.Windows.Forms.Archiving/Generic/FileMimeType.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// public static class FileMimeType diff --git a/SIL.Archiving/Generic/GenericObject.cs b/SIL.Windows.Forms.Archiving/Generic/GenericObject.cs similarity index 86% rename from SIL.Archiving/Generic/GenericObject.cs rename to SIL.Windows.Forms.Archiving/Generic/GenericObject.cs index 405824192..9b50c25c5 100644 --- a/SIL.Archiving/Generic/GenericObject.cs +++ b/SIL.Windows.Forms.Archiving/Generic/GenericObject.cs @@ -1,6 +1,6 @@ -using SIL.Archiving.Generic.AccessProtocol; +using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// Base class for archiving objects public interface IArchivingGenericObject diff --git a/SIL.Archiving/Generic/LanguageString.cs b/SIL.Windows.Forms.Archiving/Generic/LanguageString.cs similarity index 97% rename from SIL.Archiving/Generic/LanguageString.cs rename to SIL.Windows.Forms.Archiving/Generic/LanguageString.cs index c0e3467cb..47619a4bc 100644 --- a/SIL.Archiving/Generic/LanguageString.cs +++ b/SIL.Windows.Forms.Archiving/Generic/LanguageString.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// Class for string values that have a language attribute public class LanguageString : IComparable diff --git a/SIL.Archiving/Generic/SimpleObjects.cs b/SIL.Windows.Forms.Archiving/Generic/SimpleObjects.cs similarity index 94% rename from SIL.Archiving/Generic/SimpleObjects.cs rename to SIL.Windows.Forms.Archiving/Generic/SimpleObjects.cs index 625fa8fe3..2b3304e42 100644 --- a/SIL.Archiving/Generic/SimpleObjects.cs +++ b/SIL.Windows.Forms.Archiving/Generic/SimpleObjects.cs @@ -1,5 +1,5 @@  -namespace SIL.Archiving.Generic +namespace SIL.Windows.Forms.Archiving.Generic { /// Location information for the data in the package public class ArchivingLocation diff --git a/SIL.Archiving/IMDI/IMDIArchivingDlg.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs similarity index 99% rename from SIL.Archiving/IMDI/IMDIArchivingDlg.cs rename to SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs index 8b21e951b..6decc1302 100644 --- a/SIL.Archiving/IMDI/IMDIArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs @@ -6,7 +6,7 @@ using L10NSharp; using SIL.Windows.Forms.PortableSettingsProvider; -namespace SIL.Archiving.IMDI +namespace SIL.Windows.Forms.Archiving.IMDI { /// public class IMDIArchivingDlg : ArchivingDlg diff --git a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlgViewModel.cs similarity index 99% rename from SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs rename to SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlgViewModel.cs index 02740a8a5..67833dc00 100644 --- a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlgViewModel.cs @@ -7,12 +7,12 @@ using System.Text; using System.Threading; using L10NSharp; -using SIL.Archiving.Generic; -using SIL.Archiving.IMDI.Schema; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.IMDI.Schema; using System.Windows.Forms; using SIL.Extensions; -namespace SIL.Archiving.IMDI +namespace SIL.Windows.Forms.Archiving.IMDI { /// Implements archiving for IMDI repositories public class IMDIArchivingDlgViewModel : ArchivingDlgViewModel, ISupportMetadataOnly diff --git a/SIL.Archiving/IMDI/IMDIContributor.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIContributor.cs similarity index 92% rename from SIL.Archiving/IMDI/IMDIContributor.cs rename to SIL.Windows.Forms.Archiving/IMDI/IMDIContributor.cs index 201467342..3545f5211 100644 --- a/SIL.Archiving/IMDI/IMDIContributor.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIContributor.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; -using SIL.Archiving.Generic; +using SIL.Windows.Forms.Archiving.Generic; -namespace SIL.Archiving.IMDI +namespace SIL.Windows.Forms.Archiving.IMDI { public class IMDIContributor : ArchivingActor { diff --git a/SIL.Archiving/IMDI/IMDIFile.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIFile.cs similarity index 96% rename from SIL.Archiving/IMDI/IMDIFile.cs rename to SIL.Windows.Forms.Archiving/IMDI/IMDIFile.cs index 9ed808f2b..6b4ec7ce7 100644 --- a/SIL.Archiving/IMDI/IMDIFile.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIFile.cs @@ -1,9 +1,9 @@ using System.IO; -using SIL.Archiving.Generic; -using SIL.Archiving.IMDI.Lists; -using SIL.Archiving.IMDI.Schema; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.IMDI.Lists; +using SIL.Windows.Forms.Archiving.IMDI.Schema; -namespace SIL.Archiving.IMDI +namespace SIL.Windows.Forms.Archiving.IMDI { /// A file to add to the archive public class IMDIFile : ArchivingFile diff --git a/SIL.Archiving/IMDI/IMDIPackage.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIPackage.cs similarity index 97% rename from SIL.Archiving/IMDI/IMDIPackage.cs rename to SIL.Windows.Forms.Archiving/IMDI/IMDIPackage.cs index 31549bdb2..7c1e2c8c5 100644 --- a/SIL.Archiving/IMDI/IMDIPackage.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIPackage.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using SIL.Archiving.Generic; -using SIL.Archiving.IMDI.Lists; -using SIL.Archiving.IMDI.Schema; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.IMDI.Lists; +using SIL.Windows.Forms.Archiving.IMDI.Schema; using SIL.Extensions; -namespace SIL.Archiving.IMDI +namespace SIL.Windows.Forms.Archiving.IMDI { /// Collects the data and produces an IMDI corpus to upload public class IMDIPackage : ArchivingPackage diff --git a/SIL.Archiving/IMDI/Lists/BooleanEnum.cs b/SIL.Windows.Forms.Archiving/IMDI/Lists/BooleanEnum.cs similarity index 87% rename from SIL.Archiving/IMDI/Lists/BooleanEnum.cs rename to SIL.Windows.Forms.Archiving/IMDI/Lists/BooleanEnum.cs index 77792ce02..979fe5311 100644 --- a/SIL.Archiving/IMDI/Lists/BooleanEnum.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Lists/BooleanEnum.cs @@ -1,5 +1,5 @@  -namespace SIL.Archiving.IMDI.Lists +namespace SIL.Windows.Forms.Archiving.IMDI.Lists { /// In IMDI there are 4 possible values for a boolean public enum BooleanEnum diff --git a/SIL.Archiving/IMDI/Lists/ItemListBase.cs b/SIL.Windows.Forms.Archiving/IMDI/Lists/ItemListBase.cs similarity index 99% rename from SIL.Archiving/IMDI/Lists/ItemListBase.cs rename to SIL.Windows.Forms.Archiving/IMDI/Lists/ItemListBase.cs index 701f46082..19a4479f1 100644 --- a/SIL.Archiving/IMDI/Lists/ItemListBase.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Lists/ItemListBase.cs @@ -5,12 +5,12 @@ using System.Linq; using System.Net; using System.Xml; -using SIL.Archiving.Generic; -using SIL.Archiving.IMDI.Schema; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.IMDI.Schema; using SIL.Extensions; using SIL.WritingSystems; -namespace SIL.Archiving.IMDI.Lists +namespace SIL.Windows.Forms.Archiving.IMDI.Lists { /// Generic class to handle items in the IMDI lists public class IMDIListItem : IComparable diff --git a/SIL.Archiving/IMDI/Lists/LanguageList.cs b/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs similarity index 98% rename from SIL.Archiving/IMDI/Lists/LanguageList.cs rename to SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs index 567d0d275..7f3423cb7 100644 --- a/SIL.Archiving/IMDI/Lists/LanguageList.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs @@ -2,9 +2,9 @@ using System; using System.Linq; using L10NSharp; -using SIL.Archiving.IMDI.Schema; +using SIL.Windows.Forms.Archiving.IMDI.Schema; -namespace SIL.Archiving.IMDI.Lists +namespace SIL.Windows.Forms.Archiving.IMDI.Lists { /// ------------------------------------------------------------------------------------------- public class LanguageItem : IMDIListItem diff --git a/SIL.Archiving/IMDI/Lists/ListConstructor.cs b/SIL.Windows.Forms.Archiving/IMDI/Lists/ListConstructor.cs similarity index 98% rename from SIL.Archiving/IMDI/Lists/ListConstructor.cs rename to SIL.Windows.Forms.Archiving/IMDI/Lists/ListConstructor.cs index 2ab14e2fd..7ded6f1ec 100644 --- a/SIL.Archiving/IMDI/Lists/ListConstructor.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Lists/ListConstructor.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace SIL.Archiving.IMDI.Lists +namespace SIL.Windows.Forms.Archiving.IMDI.Lists { /// /// diff --git a/SIL.Archiving/IMDI/Lists/ListType.cs b/SIL.Windows.Forms.Archiving/IMDI/Lists/ListType.cs similarity index 98% rename from SIL.Archiving/IMDI/Lists/ListType.cs rename to SIL.Windows.Forms.Archiving/IMDI/Lists/ListType.cs index cb08c8a48..5e8c04678 100644 --- a/SIL.Archiving/IMDI/Lists/ListType.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Lists/ListType.cs @@ -1,4 +1,4 @@ -namespace SIL.Archiving.IMDI.Lists +namespace SIL.Windows.Forms.Archiving.IMDI.Lists { /// /// Contains the IMDI list types known at this time. diff --git a/SIL.Archiving/IMDI/Schema/IMDIDescription.cs b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIDescription.cs similarity index 96% rename from SIL.Archiving/IMDI/Schema/IMDIDescription.cs rename to SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIDescription.cs index 53fac9544..6e5c088f4 100644 --- a/SIL.Archiving/IMDI/Schema/IMDIDescription.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIDescription.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Xml.Serialization; -using SIL.Archiving.Generic; +using SIL.Windows.Forms.Archiving.Generic; -namespace SIL.Archiving.IMDI.Schema +namespace SIL.Windows.Forms.Archiving.IMDI.Schema { /// Common description code for multiple IMDI objects public abstract class IMDIDescription diff --git a/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIExtensions.cs similarity index 96% rename from SIL.Archiving/IMDI/Schema/IMDIExtensions.cs rename to SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIExtensions.cs index 70c0f6091..218e7c932 100644 --- a/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIExtensions.cs @@ -1,7 +1,7 @@ -using SIL.Archiving.Generic; -using SIL.Archiving.IMDI.Lists; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.IMDI.Lists; -namespace SIL.Archiving.IMDI.Schema +namespace SIL.Windows.Forms.Archiving.IMDI.Schema { /// Extension methods to simplify access to IMDI objects public static class IMDIExtensions diff --git a/SIL.Archiving/IMDI/Schema/IMDIInterfaces.cs b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIInterfaces.cs similarity index 93% rename from SIL.Archiving/IMDI/Schema/IMDIInterfaces.cs rename to SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIInterfaces.cs index 8a40ed7fd..0b1053e82 100644 --- a/SIL.Archiving/IMDI/Schema/IMDIInterfaces.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIInterfaces.cs @@ -1,5 +1,5 @@  -namespace SIL.Archiving.IMDI.Schema +namespace SIL.Windows.Forms.Archiving.IMDI.Schema { /// Interface to simplify access to session files (media and written) public interface IIMDISessionFile diff --git a/SIL.Archiving/IMDI/Schema/IMDISchemaHelper.cs b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDISchemaHelper.cs similarity index 93% rename from SIL.Archiving/IMDI/Schema/IMDISchemaHelper.cs rename to SIL.Windows.Forms.Archiving/IMDI/Schema/IMDISchemaHelper.cs index 34847e183..bf11b57f7 100644 --- a/SIL.Archiving/IMDI/Schema/IMDISchemaHelper.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDISchemaHelper.cs @@ -1,5 +1,5 @@  -namespace SIL.Archiving.IMDI.Schema +namespace SIL.Windows.Forms.Archiving.IMDI.Schema { /// Functions to simplify access to IMDI objects public static class IMDISchemaHelper diff --git a/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0.cs similarity index 99% rename from SIL.Archiving/IMDI/Schema/IMDI_3_0.cs rename to SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0.cs index 12f392313..b4c02d61e 100644 --- a/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0.cs @@ -8,12 +8,12 @@ using System.Xml.Schema; using System.Xml.Serialization; using System.Diagnostics; -using SIL.Archiving.Generic; -using SIL.Archiving.Generic.AccessProtocol; -using SIL.Archiving.IMDI.Lists; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; +using SIL.Windows.Forms.Archiving.IMDI.Lists; using SIL.Extensions; -namespace SIL.Archiving.IMDI.Schema +namespace SIL.Windows.Forms.Archiving.IMDI.Schema { /// Shared properties and methods public interface IIMDIMajorObject diff --git a/SIL.Archiving/IMDI/Schema/IMDI_3_0_Fix.py b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_Fix.py similarity index 99% rename from SIL.Archiving/IMDI/Schema/IMDI_3_0_Fix.py rename to SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_Fix.py index bdc66d7ac..318336d79 100644 --- a/SIL.Archiving/IMDI/Schema/IMDI_3_0_Fix.py +++ b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_Fix.py @@ -79,7 +79,7 @@ using System.Collections.Generic; using System.Xml.Schema; -namespace SIL.Archiving.IMDI.Schema +namespace SIL.Windows.Forms.Archiving.IMDI.Schema { ''' diff --git a/SIL.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs similarity index 99% rename from SIL.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs rename to SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs index b2080f5b0..1e2446d78 100644 --- a/SIL.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs @@ -1,7 +1,7 @@  // ReSharper disable once EmptyNamespace // ReSharper disable once CheckNamespace -namespace SIL.Archiving.IMDI.Schema.NotUsed +namespace SIL.Windows.Forms.Archiving.IMDI.Schema.NotUsed { ///// //[SerializableAttribute] diff --git a/SIL.Archiving/IMDI/xsd/GenerateClasses.bat b/SIL.Windows.Forms.Archiving/IMDI/xsd/GenerateClasses.bat similarity index 53% rename from SIL.Archiving/IMDI/xsd/GenerateClasses.bat rename to SIL.Windows.Forms.Archiving/IMDI/xsd/GenerateClasses.bat index 529dc7389..c1ddd0e91 100644 --- a/SIL.Archiving/IMDI/xsd/GenerateClasses.bat +++ b/SIL.Windows.Forms.Archiving/IMDI/xsd/GenerateClasses.bat @@ -2,11 +2,11 @@ rem for /f "tokens=2-8 delims=.:/ " %%a in ("%date% %time%") do set DateNtime=%%c-%%a-%%b_%%d-%%e-%%f.%%g for /f "tokens=2-8 delims=.:/ " %%a in ("%date% %time%") do set DateNtime=%%c%%a%%b%%d%%e%%f echo Renaming existing file... -rename "C:\Projects\Palaso\SIL.Archiving\IMDI\Schema\IMDI_3_0.cs" "IMDI_3_0.cs.%DateNtime%.bak" +rename "C:\Projects\Palaso\SIL.Windows.Forms.Archiving\IMDI\Schema\IMDI_3_0.cs" "IMDI_3_0.cs.%DateNtime%.bak" echo. -"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\x64\xsd.exe" -c -l:c# -n:IMDI.Schema "C:\Projects\Palaso\SIL.Archiving\IMDI\xsd\IMDI_3.0.xsd" -o:"C:\Projects\Palaso\SIL.Archiving\IMDI\Schema" +"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\x64\xsd.exe" -c -l:c# -n:IMDI.Schema "C:\Projects\Palaso\SIL.Windows.Forms.Archiving\IMDI\xsd\IMDI_3.0.xsd" -o:"C:\Projects\Palaso\SIL.Windows.Forms.Archiving\IMDI\Schema" echo. echo Fixing output file... -cd C:\Projects\Palaso\SIL.Archiving\IMDI\Schema +cd C:\Projects\Palaso\SIL.Windows.Forms.Archiving\IMDI\Schema c:\python27\python imdi_3_0_fix.py pause \ No newline at end of file diff --git a/SIL.Archiving/IMDI/xsd/imdi-v3.xsd b/SIL.Windows.Forms.Archiving/IMDI/xsd/imdi-v3.xsd similarity index 100% rename from SIL.Archiving/IMDI/xsd/imdi-v3.xsd rename to SIL.Windows.Forms.Archiving/IMDI/xsd/imdi-v3.xsd diff --git a/SIL.Archiving/JSONUtils.cs b/SIL.Windows.Forms.Archiving/JSONUtils.cs old mode 100755 new mode 100644 similarity index 98% rename from SIL.Archiving/JSONUtils.cs rename to SIL.Windows.Forms.Archiving/JSONUtils.cs index da0f0ac2e..60963885f --- a/SIL.Archiving/JSONUtils.cs +++ b/SIL.Windows.Forms.Archiving/JSONUtils.cs @@ -3,7 +3,7 @@ using System.Text; using System.Linq; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { public class JSONUtils { diff --git a/SIL.Archiving/Properties/AssemblyInfo.cs b/SIL.Windows.Forms.Archiving/Properties/AssemblyInfo.cs old mode 100755 new mode 100644 similarity index 91% rename from SIL.Archiving/Properties/AssemblyInfo.cs rename to SIL.Windows.Forms.Archiving/Properties/AssemblyInfo.cs index 7934654cb..f67f16d01 --- a/SIL.Archiving/Properties/AssemblyInfo.cs +++ b/SIL.Windows.Forms.Archiving/Properties/AssemblyInfo.cs @@ -1,7 +1,7 @@ using System.Runtime.CompilerServices; using SIL.Acknowledgements; -[assembly: InternalsVisibleTo("SIL.Archiving.Tests, PublicKey=0024000004800000940000000" + +[assembly: InternalsVisibleTo("SIL.Windows.Forms.Archiving.Tests, PublicKey=0024000004800000940000000" + "6020000002400005253413100040000010001008339b2ae1bf006934f6176dec6ea2a8a7d67383613dcb03d7197" + "5e7b05ad546562c84529a4811e94c889e55f2532d1a90baaf20be9bff39ac6f5365bd605d70b90489840b7ba6d1" + "c231b0e550c4abe4f60553856ef142a40a91e53d56e79f69dc79c4e95817de498aac924ee011f03b4e1c1d772d5" + diff --git a/SIL.Archiving/Properties/Resources.Designer.cs b/SIL.Windows.Forms.Archiving/Properties/Resources.Designer.cs old mode 100755 new mode 100644 similarity index 98% rename from SIL.Archiving/Properties/Resources.Designer.cs rename to SIL.Windows.Forms.Archiving/Properties/Resources.Designer.cs index 6c791efeb..52eff1ab8 --- a/SIL.Archiving/Properties/Resources.Designer.cs +++ b/SIL.Windows.Forms.Archiving/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace SIL.Archiving.Properties { +namespace SIL.Windows.Forms.Archiving.Properties { using System; @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.Archiving.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.Windows.Forms.Archiving.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/SIL.Archiving/Properties/Resources.resx b/SIL.Windows.Forms.Archiving/Properties/Resources.resx old mode 100755 new mode 100644 similarity index 100% rename from SIL.Archiving/Properties/Resources.resx rename to SIL.Windows.Forms.Archiving/Properties/Resources.resx diff --git a/SIL.Archiving/Properties/Settings.Designer.cs b/SIL.Windows.Forms.Archiving/Properties/Settings.Designer.cs old mode 100755 new mode 100644 similarity index 97% rename from SIL.Archiving/Properties/Settings.Designer.cs rename to SIL.Windows.Forms.Archiving/Properties/Settings.Designer.cs index be721f6f8..76e8edeb4 --- a/SIL.Archiving/Properties/Settings.Designer.cs +++ b/SIL.Windows.Forms.Archiving/Properties/Settings.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace SIL.Archiving.Properties { +namespace SIL.Windows.Forms.Archiving.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] diff --git a/SIL.Archiving/Properties/Settings.settings b/SIL.Windows.Forms.Archiving/Properties/Settings.settings old mode 100755 new mode 100644 similarity index 91% rename from SIL.Archiving/Properties/Settings.settings rename to SIL.Windows.Forms.Archiving/Properties/Settings.settings index aedc73300..12e6e1aa6 --- a/SIL.Archiving/Properties/Settings.settings +++ b/SIL.Windows.Forms.Archiving/Properties/Settings.settings @@ -1,5 +1,5 @@  - + diff --git a/SIL.Archiving/RampArchivingDlgViewModel.cs b/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs similarity index 99% rename from SIL.Archiving/RampArchivingDlgViewModel.cs rename to SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs index 861d1150f..a1fbfdd90 100644 --- a/SIL.Archiving/RampArchivingDlgViewModel.cs +++ b/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs @@ -12,15 +12,15 @@ using System.Windows.Forms; using Ionic.Zip; using L10NSharp; -using SIL.Archiving.Generic; -using SIL.Archiving.Properties; +using SIL.Windows.Forms.Archiving.Generic; +using SIL.Windows.Forms.Archiving.Properties; using SIL.Extensions; using SIL.IO; using SIL.PlatformUtilities; using SIL.Windows.Forms.ClearShare; using Timer = System.Threading.Timer; -namespace SIL.Archiving +namespace SIL.Windows.Forms.Archiving { /// ------------------------------------------------------------------------------------ public class RampArchivingDlgViewModel: ArchivingDlgViewModel diff --git a/SIL.Archiving/Resources/AccessProtocols.json b/SIL.Windows.Forms.Archiving/Resources/AccessProtocols.json similarity index 100% rename from SIL.Archiving/Resources/AccessProtocols.json rename to SIL.Windows.Forms.Archiving/Resources/AccessProtocols.json diff --git a/SIL.Archiving/Resources/CustomAccessProtocols.json b/SIL.Windows.Forms.Archiving/Resources/CustomAccessProtocols.json similarity index 100% rename from SIL.Archiving/Resources/CustomAccessProtocols.json rename to SIL.Windows.Forms.Archiving/Resources/CustomAccessProtocols.json diff --git a/SIL.Archiving/Resources/EmptyMets.xml b/SIL.Windows.Forms.Archiving/Resources/EmptyMets.xml old mode 100755 new mode 100644 similarity index 100% rename from SIL.Archiving/Resources/EmptyMets.xml rename to SIL.Windows.Forms.Archiving/Resources/EmptyMets.xml diff --git a/SIL.Archiving/Resources/ailca.html b/SIL.Windows.Forms.Archiving/Resources/ailca.html similarity index 100% rename from SIL.Archiving/Resources/ailca.html rename to SIL.Windows.Forms.Archiving/Resources/ailca.html diff --git a/SIL.Archiving/Resources/ailla.html b/SIL.Windows.Forms.Archiving/Resources/ailla.html similarity index 100% rename from SIL.Archiving/Resources/ailla.html rename to SIL.Windows.Forms.Archiving/Resources/ailla.html diff --git a/SIL.Archiving/Resources/anla.html b/SIL.Windows.Forms.Archiving/Resources/anla.html similarity index 100% rename from SIL.Archiving/Resources/anla.html rename to SIL.Windows.Forms.Archiving/Resources/anla.html diff --git a/SIL.Archiving/Resources/elar.html b/SIL.Windows.Forms.Archiving/Resources/elar.html similarity index 100% rename from SIL.Archiving/Resources/elar.html rename to SIL.Windows.Forms.Archiving/Resources/elar.html diff --git a/SIL.Archiving/Resources/reap.html b/SIL.Windows.Forms.Archiving/Resources/reap.html similarity index 100% rename from SIL.Archiving/Resources/reap.html rename to SIL.Windows.Forms.Archiving/Resources/reap.html diff --git a/SIL.Archiving/Resources/tla.html b/SIL.Windows.Forms.Archiving/Resources/tla.html similarity index 100% rename from SIL.Archiving/Resources/tla.html rename to SIL.Windows.Forms.Archiving/Resources/tla.html diff --git a/SIL.Archiving/SIL.Archiving.csproj b/SIL.Windows.Forms.Archiving/SIL.Windows.Forms.Archiving.csproj similarity index 84% rename from SIL.Archiving/SIL.Archiving.csproj rename to SIL.Windows.Forms.Archiving/SIL.Windows.Forms.Archiving.csproj index 1e913a81c..11a8bd7dc 100644 --- a/SIL.Archiving/SIL.Archiving.csproj +++ b/SIL.Windows.Forms.Archiving/SIL.Windows.Forms.Archiving.csproj @@ -1,9 +1,9 @@  - SIL.Archiving - SIL.Archiving - SIL.Archiving contains Windows Forms UI elements and classes for archiving data to REAP using the RAMP application. + SIL.Windows.Forms.Archiving + SIL.Windows.Forms.Archiving + SIL.Windows.Forms.Archiving contains Windows Forms UI elements and classes for archiving data to REAP using the RAMP application. true diff --git a/SIL.Archiving/app.config b/SIL.Windows.Forms.Archiving/app.config old mode 100755 new mode 100644 similarity index 74% rename from SIL.Archiving/app.config rename to SIL.Windows.Forms.Archiving/app.config index bdd9c96b9..efa8007bc --- a/SIL.Archiving/app.config +++ b/SIL.Windows.Forms.Archiving/app.config @@ -2,11 +2,11 @@ -
+
- + https://gateway.sil.org/display/RH/RAMP+Users%27+Manual @@ -16,7 +16,7 @@ http://www.mpi.nl/imdi/ - + From dd8bfd9ffe12958a77dbfc3b9f2628c0f59f51e4 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Fri, 26 Apr 2024 15:58:47 +0700 Subject: [PATCH 02/15] Reverted rename in changelog and added an entry +semver:major --- CHANGELOG.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fb99bfb6..1fef038eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed + +- [SIL.Windows.Forms.Archiving] Renamed SIL.Archiving to SIL.Windows.Forms.Archiving + ## [14.0.0] - 2024-04-09 ### Changed -- [SIL.Windows.Forms.Archiving] Upgraded to L10nSharp 7.0.0 +- [SIL.Archiving] Upgraded to L10nSharp 7.0.0 - [SIL.Windows.Forms] Upgraded to L10nSharp 7.0.0 - [SIL.Windows.Forms.DblBundle] Upgraded to L10nSharp 7.0.0 - [SIL.Windows.Forms.Keyboarding] Upgraded to L10nSharp 7.0.0 @@ -130,14 +134,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.DblBundle] Attempting to construct a UsxNode based on an invalid XmlNode now throws an exception in the constructor in most cases rather than later when properties are accessed. - [SIL.DblBundle] Accessing UsxChapter.ChapterNumber on a chapter end node returns the chapter number (from the eid attribute) instead of throwing an exception. - [SIL.WritingSystems] Prevent (and clean up) duplicate URLs in LDML files for Fonts, Keyboards, and Spell Check Dictionaries. -- [SIL.Windows.Forms.Archiving] Set UseZip64WhenSaving to Zip64Option.AsNecessary to prevent crash with large archives +- [SIL.Archiving] Set UseZip64WhenSaving to Zip64Option.AsNecessary to prevent crash with large archives ### Changed -- [SIL.Windows.Forms.Archiving] Changed REAP access protocol label from "Insite users" to "REAP users" -- [SIL.Windows.Forms.Archiving] Fixed typo in name of ArchiveAccessProtocol.GetDocumentationUri methods -- [SIL.Windows.Forms.Archiving] Changed ArchiveAccessProtocol.GetDocumentationUri methods -- [SIL.Windows.Forms.Archiving] Changed ArchiveAccessProtocol.SetChoicesFromCsv to thow ArgumentNullException instead of NullReferenceException. Also made it discard duplicate choices if the list contains duplicates. +- [SIL.Archiving] Changed REAP access protocol label from "Insite users" to "REAP users" +- [SIL.Archiving] Fixed typo in name of ArchiveAccessProtocol.GetDocumentationUri methods +- [SIL.Archiving] Changed ArchiveAccessProtocol.GetDocumentationUri methods +- [SIL.Archiving] Changed ArchiveAccessProtocol.SetChoicesFromCsv to thow ArgumentNullException instead of NullReferenceException. Also made it discard duplicate choices if the list contains duplicates. - [SIL.Core] `FileLocationUtilities.GetDirectoryDistributedWithApplication` checks not only in `DistFiles`, `common`, and `src` subdirectories, but also directly in the application or solution directory. - [SIL.Core] Store URLs in Sets instead of Lists in `IKeyboardDefinition` (to prevent duplicates) @@ -193,7 +197,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- [SIL.Windows.Forms.Archiving] Fixed formatting of DateTimes +- [SIL.Archiving] Fixed formatting of DateTimes - [SIL.Core] Fixed SIL.IO.PathUtilities.DeleteToRecycleBin and .GetDefaultFileManager to work in a flatpak environment. - [SIL.Lexicon] Fixed crash caused by incorrect processing of keyboard data - [SIL.Scripture] Fixed SIL.Scripture.MultilingScrBooks.VerseRefRegex to make punctuation more specific From 39927bfda5d68e5d243fd6926da8887d76a48629 Mon Sep 17 00:00:00 2001 From: tombogle Date: Tue, 16 Jul 2024 15:12:39 -0400 Subject: [PATCH 03/15] Improved/added some comments related to LanguageList and its tests This helps clarify some unexpected behavior in SayMore tests. --- Palaso.sln.DotSettings | 1 + .../LanguageListTests.cs | 9 +++++--- .../IMDI/Lists/LanguageList.cs | 22 ++++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Palaso.sln.DotSettings b/Palaso.sln.DotSettings index b55cbf111..6fff68042 100644 --- a/Palaso.sln.DotSettings +++ b/Palaso.sln.DotSettings @@ -65,6 +65,7 @@ True True True + True True True True diff --git a/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs b/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs index 4129205a1..ae11865e5 100644 --- a/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs @@ -11,6 +11,7 @@ public class LanguageListTests { [TestCase("fra", "French")] [TestCase("tru", "Turoyo")] + [TestCase("eng", "English")] public void FindByISO3Code_ExistingLanguageWithNoOtherName_GetsExpectedNameCodeAndId(string iso3Code, string expectedEnglishName) { var result = LanguageList.FindByISO3Code(iso3Code); @@ -33,12 +34,14 @@ public void FindByISO3Code_NoneExistentCode_ResultHasIsoCodeButNoName() } [TestCase("French", "fra")] - [TestCase("français", "fra")] // Not really sure why this works + [TestCase("français", "fra")] // This works because even though "French" is the default (English) name associated with "fra", the Ethnologue data also contains "français" [TestCase("Turoyo", "tru")] - public void FindByEnglishName_ExistingLanguage_GetsExpectedNameCodeAndId(string name, string expectedIso3Code) + [TestCase("English", "eng")] + // [TestCase("Eng", "gss", "Greek Sign Language")] // because these tests use the offline Sldr and there is an outdated langtags.json in our resources, "Eng" does not resolve to gss. + public void FindByEnglishName_ExistingLanguage_GetsExpectedNameCodeAndId(string name, string expectedIso3Code, string defaultName = null) { var result = LanguageList.FindByEnglishName(name); - Assert.AreEqual(name, result.EnglishName); + Assert.AreEqual(defaultName ?? name, result.EnglishName); Assert.AreEqual(expectedIso3Code, result.Iso3Code); Assert.That(result.OtherName, Is.Null.Or.Empty); Assert.AreEqual($"ISO639-3:{expectedIso3Code}", result.Id); diff --git a/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs b/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs index 7f3423cb7..73610aa8b 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs @@ -99,6 +99,15 @@ private static LanguageList GetList() return _instance ?? (_instance = new LanguageList()); } + /// --------------------------------------------------------------------------------------- + /// + /// Gets a language list based on the Ethnologue + /// + /// Even though this ostensibly claims to use the MPI Languages, this file is + /// woefully incomplete (only ~345 languages, less than 5% of the total). A comment inside + /// it even says "When a language name and identifier that you need is not in this list, + /// please look it up under www.ethnologue.com/web.asp.". So we use the information from + /// SIL.WritingSystems, which is based on the complete Ethnologue data. /// --------------------------------------------------------------------------------------- protected LanguageList() : base(ListType.MPILanguages, false) { @@ -152,7 +161,12 @@ public static LanguageItem FindByISO3Code(string iso3Code, bool mustBeInList) } /// ------------------------------------------------------------------------------------------- - /// This finds either English name or localised name + /// + /// Finds information about the language, given its English name (or possibly the localised + /// name or some other variant). + /// + /// Given its actual behavior, this is kind of poorly named. + /// ------------------------------------------------------------------------------------------- public static LanguageItem FindByEnglishName(string englishName) { if (string.IsNullOrEmpty(englishName)) @@ -161,10 +175,8 @@ public static LanguageItem FindByEnglishName(string englishName) var item = GetList().FindByText(englishName); // if not on list, return "und" - if (item == null) - return new LanguageItem(englishName, "ISO639-3:und", englishName); - - return (LanguageItem)(GetList().FindByText(englishName)); + return item == null ? new LanguageItem(englishName, "ISO639-3:und", englishName) + : (LanguageItem)item; } /// ------------------------------------------------------------------------------------------- From b3b018a3e67e908ff76d1ee13d9a0b676a355e52 Mon Sep 17 00:00:00 2001 From: tombogle Date: Wed, 17 Jul 2024 11:15:46 -0400 Subject: [PATCH 04/15] +semver:major Split ClearShare code, moving non-Winforms portions to SIL.Core Added optional parameter to OlacSystem.GetRoles to allow caller to provide its own XML --- CHANGELOG.md | 8 +++ .../ClearShare/ContributionTests.cs | 6 +- SIL.Core.Tests/ClearShare/LicenseTests.cs | 69 +++++++++++++++++++ .../ClearShare/OlacSystemTests.cs | 6 +- .../ClearShare/RoleTests.cs | 6 +- .../ClearShare/Contribution.cs | 4 +- .../ClearShare/ContributionCollection.cs | 4 +- .../ClearShare/License.cs | 40 ++++------- .../ClearShare}/OlacRoles.xml | 0 .../ClearShare/OlacSystem.cs | 67 +++++++++++++----- .../ClearShare/Role.cs | 4 +- .../ClearShare/Work.cs | 4 +- SIL.Core/SIL.Core.csproj | 8 +++ SIL.Media.Tests/SIL.Media.Tests.csproj | 1 + .../RampArchivingDlgViewModelTests.cs | 1 + .../RampArchivingDlgViewModel.cs | 2 +- .../ClearShare/ClearShareUsage.cs | 3 +- .../ContributorsListControlViewModelTests.cs | 1 + .../{LicenseTests.cs => LicenseInfoTests.cs} | 63 +---------------- .../ClearShare/MetaDataDisplayTests.cs | 3 +- .../ClearShare/MetadataEditorControlTests.cs | 1 + .../ClearShare/MetadataTests.cs | 2 +- .../ContributorsListControlViewModel.cs | 1 + .../ClearShare/CreativeCommonsLicense.cs | 8 --- SIL.Windows.Forms/ClearShare/LicenseInfo.cs | 27 +++----- .../ClearShare/LicenseWithLogo.cs | 39 +++++++++++ SIL.Windows.Forms/ClearShare/Metadata.cs | 14 ++-- .../WinFormsUI/ContributorsListControl.cs | 1 + .../WinFormsUI/MetadataDisplayControl.cs | 1 + .../WinFormsUI/MetadataEditorControl.cs | 1 + .../WinFormsUI/MetadataEditorDialog.cs | 1 + .../ImageToolbox/ImageToolboxControl.cs | 1 + .../ImageToolboxDialog.Designer.cs | 3 +- .../ImageToolbox/ImageToolboxDialog.cs | 1 + SIL.Windows.Forms/ImageToolbox/PalasoImage.cs | 1 + .../Properties/Resources.Designer.cs | 21 ------ SIL.Windows.Forms/Properties/Resources.resx | 3 - .../ContributorsForm.cs | 1 + .../SIL.Windows.Forms.TestApp/TestAppForm.cs | 1 + 39 files changed, 244 insertions(+), 184 deletions(-) rename {SIL.Windows.Forms.Tests => SIL.Core.Tests}/ClearShare/ContributionTests.cs (98%) create mode 100644 SIL.Core.Tests/ClearShare/LicenseTests.cs rename {SIL.Windows.Forms.Tests => SIL.Core.Tests}/ClearShare/OlacSystemTests.cs (95%) rename {SIL.Windows.Forms.Tests => SIL.Core.Tests}/ClearShare/RoleTests.cs (96%) rename {SIL.Windows.Forms => SIL.Core}/ClearShare/Contribution.cs (98%) rename {SIL.Windows.Forms => SIL.Core}/ClearShare/ContributionCollection.cs (97%) rename {SIL.Windows.Forms => SIL.Core}/ClearShare/License.cs (69%) rename {SIL.Windows.Forms/Resources => SIL.Core/ClearShare}/OlacRoles.xml (100%) rename {SIL.Windows.Forms => SIL.Core}/ClearShare/OlacSystem.cs (75%) rename {SIL.Windows.Forms => SIL.Core}/ClearShare/Role.cs (97%) rename {SIL.Windows.Forms => SIL.Core}/ClearShare/Work.cs (90%) rename SIL.Windows.Forms.Tests/ClearShare/{LicenseTests.cs => LicenseInfoTests.cs} (63%) create mode 100644 SIL.Windows.Forms/ClearShare/LicenseWithLogo.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index ec0671f09..15acd8764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - [SIL.Windows.Forms.Archiving] Renamed SIL.Archiving to SIL.Windows.Forms.Archiving +- [SIL.Windows.Forms] Split ClearShare code, moving non-Winforms portions to SIL.Core (SIL.Core.ClearShare namespace) +- [SIL.Core] Added optional parameter to OlacSystem.GetRoles to allow caller to provide its own XML with role definitions. +- [SIL.Windows.Forms] Split License into a base class called License and a derived LicenseWithLogo, so that License could be in SIL.Core. + +### Removed + +- [SIL.Windows.Forms] Removed previously deprecated CreativeCommonsLicense.IntergovernmentalOriganizationQualifier + ## [14.1.1] - 2024-05-23 ### Fixed diff --git a/SIL.Windows.Forms.Tests/ClearShare/ContributionTests.cs b/SIL.Core.Tests/ClearShare/ContributionTests.cs similarity index 98% rename from SIL.Windows.Forms.Tests/ClearShare/ContributionTests.cs rename to SIL.Core.Tests/ClearShare/ContributionTests.cs index 9a2d5d989..4bae090f7 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/ContributionTests.cs +++ b/SIL.Core.Tests/ClearShare/ContributionTests.cs @@ -1,8 +1,8 @@ -using System; +using System; using NUnit.Framework; -using SIL.Windows.Forms.ClearShare; +using SIL.Core.ClearShare; -namespace SIL.Windows.Forms.Tests.ClearShare +namespace SIL.Tests.ClearShare { [TestFixture] public class ContributionTests diff --git a/SIL.Core.Tests/ClearShare/LicenseTests.cs b/SIL.Core.Tests/ClearShare/LicenseTests.cs new file mode 100644 index 000000000..14b13c3c9 --- /dev/null +++ b/SIL.Core.Tests/ClearShare/LicenseTests.cs @@ -0,0 +1,69 @@ +using NUnit.Framework; +using SIL.Core.ClearShare; + +namespace SIL.Tests.ClearShare +{ + /// ---------------------------------------------------------------------------------------- + [TestFixture] + public class LicenseTests + { + /// ------------------------------------------------------------------------------------ + [Test] + public void AreContentsEqual_OtherIsNull_ReturnsFalse() + { + var l = License.CreativeCommons_Attribution_ShareAlike; + Assert.IsFalse(l.AreContentsEqual(null)); + } + + /// ------------------------------------------------------------------------------------ + [Test] + public void AreContentsEqual_AreDifferent_ReturnsFalse() + { + var l1 = License.CreativeCommons_Attribution_ShareAlike; + var l2 = License.CreativeCommons_Attribution; + Assert.IsFalse(l1.AreContentsEqual(l2)); + } + + /// ------------------------------------------------------------------------------------ + [Test] + public void AreContentsEqual_AreSame_ReturnsTrue() + { + var l1 = License.CreativeCommons_Attribution_ShareAlike; + var l2 = License.CreativeCommons_Attribution_ShareAlike; + Assert.IsTrue(l1.AreContentsEqual(l2)); + } + + /// ------------------------------------------------------------------------------------ + [Test] + public void Equals_SameInstance_ReturnsTrue() + { + var l = License.CreativeCommons_Attribution_ShareAlike; + Assert.IsTrue(l.Equals(l)); + } + + /// ------------------------------------------------------------------------------------ + [Test] + public void Equals_CompareToNull_ReturnsFalse() + { + var l = License.CreativeCommons_Attribution_ShareAlike; + Assert.IsFalse(l.Equals(null)); + } + + /// ------------------------------------------------------------------------------------ + [Test] + public void Equals_CompareToObjOfDifferentType_ReturnsFalse() + { + var l = License.CreativeCommons_Attribution_ShareAlike; + Assert.IsFalse(l.Equals("junk")); + } + + /// ------------------------------------------------------------------------------------ + [Test] + public void Equals_AreSame_ReturnsTrue() + { + var l1 = License.CreativeCommons_Attribution_ShareAlike; + var l2 = License.CreativeCommons_Attribution_ShareAlike; + Assert.IsTrue(l1.Equals(l2)); + } + } +} diff --git a/SIL.Windows.Forms.Tests/ClearShare/OlacSystemTests.cs b/SIL.Core.Tests/ClearShare/OlacSystemTests.cs similarity index 95% rename from SIL.Windows.Forms.Tests/ClearShare/OlacSystemTests.cs rename to SIL.Core.Tests/ClearShare/OlacSystemTests.cs index 0b3a86c36..5ded293e2 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/OlacSystemTests.cs +++ b/SIL.Core.Tests/ClearShare/OlacSystemTests.cs @@ -1,8 +1,8 @@ -using System; +using System; using NUnit.Framework; -using SIL.Windows.Forms.ClearShare; +using SIL.Core.ClearShare; -namespace SIL.Windows.Forms.Tests.ClearShare +namespace SIL.Tests.ClearShare { [TestFixture] public class OlacSystemTests diff --git a/SIL.Windows.Forms.Tests/ClearShare/RoleTests.cs b/SIL.Core.Tests/ClearShare/RoleTests.cs similarity index 96% rename from SIL.Windows.Forms.Tests/ClearShare/RoleTests.cs rename to SIL.Core.Tests/ClearShare/RoleTests.cs index 5ea4f46cc..079955615 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/RoleTests.cs +++ b/SIL.Core.Tests/ClearShare/RoleTests.cs @@ -1,7 +1,7 @@ -using NUnit.Framework; -using SIL.Windows.Forms.ClearShare; +using NUnit.Framework; +using SIL.Core.ClearShare; -namespace SIL.Windows.Forms.Tests.ClearShare +namespace SIL.Tests.ClearShare { [TestFixture] public class RoleTests diff --git a/SIL.Windows.Forms/ClearShare/Contribution.cs b/SIL.Core/ClearShare/Contribution.cs similarity index 98% rename from SIL.Windows.Forms/ClearShare/Contribution.cs rename to SIL.Core/ClearShare/Contribution.cs index 5ecfa3483..3db329f79 100644 --- a/SIL.Windows.Forms/ClearShare/Contribution.cs +++ b/SIL.Core/ClearShare/Contribution.cs @@ -1,6 +1,6 @@ -using System; +using System; -namespace SIL.Windows.Forms.ClearShare +namespace SIL.Core.ClearShare { /// /// Records a single contribution of a single individual to a single "work". diff --git a/SIL.Windows.Forms/ClearShare/ContributionCollection.cs b/SIL.Core/ClearShare/ContributionCollection.cs similarity index 97% rename from SIL.Windows.Forms/ClearShare/ContributionCollection.cs rename to SIL.Core/ClearShare/ContributionCollection.cs index 7dfb8d52d..4f6f5bfc4 100644 --- a/SIL.Windows.Forms/ClearShare/ContributionCollection.cs +++ b/SIL.Core/ClearShare/ContributionCollection.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Text; -namespace SIL.Windows.Forms.ClearShare +namespace SIL.Core.ClearShare { /// ---------------------------------------------------------------------------------------- public interface IAutoCompleteValueProviderWeird { diff --git a/SIL.Windows.Forms/ClearShare/License.cs b/SIL.Core/ClearShare/License.cs similarity index 69% rename from SIL.Windows.Forms/ClearShare/License.cs rename to SIL.Core/ClearShare/License.cs index 1583a262e..f0fa4c9d9 100644 --- a/SIL.Windows.Forms/ClearShare/License.cs +++ b/SIL.Core/ClearShare/License.cs @@ -1,9 +1,7 @@ -using System.Drawing; - -namespace SIL.Windows.Forms.ClearShare +namespace SIL.Core.ClearShare { /// - /// describes a single license, under which many works can be licensed for use + /// Describes a single license, under which many works can be licensed for use /// public class License { @@ -14,35 +12,23 @@ public class License public string Name { get; private set; } - public Image Logo { get; private set; } - //TODO: support the full six options at http://creativecommons.org/licenses/, plus public domain /// ------------------------------------------------------------------------------------ - public static License CreativeCommons_Attribution_ShareAlike - { - get + public static License CreativeCommons_Attribution_ShareAlike => + new License { - return new License - { - Name = "Creative Commons. Attribution-ShareAlike 3.0", - Url = "http://creativecommons.org/licenses/by-sa/3.0/" - }; - } - } + Name = "Creative Commons. Attribution-ShareAlike 3.0", + Url = "http://creativecommons.org/licenses/by-sa/3.0/" + }; /// ------------------------------------------------------------------------------------ - public static License CreativeCommons_Attribution - { - get + public static License CreativeCommons_Attribution => + new License { - return new License - { - Name = "Creative Commons. Attribution 3.0", - Url = "http://creativecommons.org/licenses/by/3.0/" - }; - } - } + Name = "Creative Commons. Attribution 3.0", + Url = "http://creativecommons.org/licenses/by/3.0/" + }; /// ------------------------------------------------------------------------------------ public override int GetHashCode() @@ -51,7 +37,6 @@ public override int GetHashCode() { int result = (Url != null ? Url.GetHashCode() : 0); result = (result * 397) ^ (Name != null ? Name.GetHashCode() : 0); - result = (result * 397) ^ (Logo != null ? Logo.GetHashCode() : 0); return result; } } @@ -79,7 +64,6 @@ public override bool Equals(object other) /// ------------------------------------------------------------------------------------ public bool AreContentsEqual(License other) { - // TODO: compare logo images. return (other != null && Name.Equals(other.Name) && Url.Equals(other.Url)); } } diff --git a/SIL.Windows.Forms/Resources/OlacRoles.xml b/SIL.Core/ClearShare/OlacRoles.xml similarity index 100% rename from SIL.Windows.Forms/Resources/OlacRoles.xml rename to SIL.Core/ClearShare/OlacRoles.xml diff --git a/SIL.Windows.Forms/ClearShare/OlacSystem.cs b/SIL.Core/ClearShare/OlacSystem.cs similarity index 75% rename from SIL.Windows.Forms/ClearShare/OlacSystem.cs rename to SIL.Core/ClearShare/OlacSystem.cs index 03edb27db..71da83a1c 100644 --- a/SIL.Windows.Forms/ClearShare/OlacSystem.cs +++ b/SIL.Core/ClearShare/OlacSystem.cs @@ -1,14 +1,14 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Xml; using System.Xml.Linq; using SIL.Code; -using SIL.Windows.Forms.Properties; -namespace SIL.Windows.Forms.ClearShare +namespace SIL.Core.ClearShare { ///----------------------------------------------------------------------------------------- /// @@ -18,7 +18,7 @@ namespace SIL.Windows.Forms.ClearShare ///----------------------------------------------------------------------------------------- public class OlacSystem { - private IEnumerable _roles; + private List _roles; private static readonly XNamespace s_nsOlac = "http://www.language-archives.org/OLAC/1.1/"; private static readonly XNamespace s_nsDc = "http://purl.org/dc/elements/1.1/"; @@ -96,23 +96,52 @@ public string GetXmlForWork(Work work) /// Get all the roles in the system's controlled vocabulary /// /// ------------------------------------------------------------------------------------ - public IEnumerable GetRoles() + public IEnumerable GetRoles(string customRolesXmlFilename = null) { + List ReadRoles(Stream stream) + { + List roles; + using (var xmlReader = XmlReader.Create(stream)) + { + var doc = XDocument.Load(xmlReader); + + // This is a bit confusing because the role heading node is at the same level + // (i.e. a sibling of) as all the associated term nodes. Therefore, the first + // thing to do is get the heading nodes that are children of section nodes. + // Then find the one heading node whose content is "Role". Then backup to the + // section containing that heading node and take all "term" child nodes of + // that section (i.e. that are siblings of the role heading node). + roles = doc.Descendants("body").Descendants("section") + .Elements("heading") + .Where(n => n.Value == "Role").Ancestors("section").First() + .Descendants("term") + .Select(n => new Role(n.Element("code").Value, + n.Element("name").Value, n.Element("definition").Value)).ToList(); + xmlReader.Close(); + } + + stream.Close(); + stream.Dispose(); + + return roles; + } + if (_roles == null) { - // TODO: Provide a way for user-specified roles to be read from a roles.xml - // file in a folder somewhere related to the application. - var doc = XDocument.Parse(Resources.OlacRoles); - - // This is a bit confusing because the role heading node is at the same level - // (i.e. a sibling of) as all the associated term nodes. Therefore, the first - // thing to do is get the heading nodes that are children of section nodes. - // Then find the one heading node whose content is "Role". Then backup to the - // section containing that heading node and take all "term" child nodes of - // that section (i.e. that are siblings of the role heading node). - _roles = doc.Descendants("body").Descendants("section").Elements("heading") - .Where(n => n.Value == "Role").Ancestors("section").First().Descendants("term") - .Select(n => new Role(n.Element("code").Value, n.Element("name").Value, n.Element("definition").Value)); + if (customRolesXmlFilename != null) + { + try + { + _roles = ReadRoles(new FileStream(customRolesXmlFilename, FileMode.Open)); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + _roles ??= ReadRoles(Assembly.GetExecutingAssembly() + .GetManifestResourceStream("SIL.Core.ClearShare.OlacRoles.xml")); } return _roles; @@ -140,7 +169,7 @@ public Role GetRoleByCodeOrThrow(string code) if (role == null) { - var msg = string.Format("This version of OLAC does not contain a role with code '{0}'.", code); + var msg = $"This version of OLAC does not contain a role with code '{code}'."; throw new ArgumentOutOfRangeException(msg); } diff --git a/SIL.Windows.Forms/ClearShare/Role.cs b/SIL.Core/ClearShare/Role.cs similarity index 97% rename from SIL.Windows.Forms/ClearShare/Role.cs rename to SIL.Core/ClearShare/Role.cs index 96448e626..347019d97 100644 --- a/SIL.Windows.Forms/ClearShare/Role.cs +++ b/SIL.Core/ClearShare/Role.cs @@ -1,7 +1,7 @@ -using System; +using System; using System.Text; -namespace SIL.Windows.Forms.ClearShare +namespace SIL.Core.ClearShare { public class Role { diff --git a/SIL.Windows.Forms/ClearShare/Work.cs b/SIL.Core/ClearShare/Work.cs similarity index 90% rename from SIL.Windows.Forms/ClearShare/Work.cs rename to SIL.Core/ClearShare/Work.cs index 74533b494..2c49080bc 100644 --- a/SIL.Windows.Forms/ClearShare/Work.cs +++ b/SIL.Core/ClearShare/Work.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace SIL.Windows.Forms.ClearShare +namespace SIL.Core.ClearShare { /// /// The word "work" in isolation doesn't suggest the right sense, here. Think of "derived-work" or "work of fiction". diff --git a/SIL.Core/SIL.Core.csproj b/SIL.Core/SIL.Core.csproj index 5bc772ecd..c9895e467 100644 --- a/SIL.Core/SIL.Core.csproj +++ b/SIL.Core/SIL.Core.csproj @@ -5,6 +5,14 @@ SIL.Core provides general utilities for language software. It is the base library for all Palaso libraries. + + + + + + + + diff --git a/SIL.Media.Tests/SIL.Media.Tests.csproj b/SIL.Media.Tests/SIL.Media.Tests.csproj index 65c2cc5a6..02ac3fc41 100644 --- a/SIL.Media.Tests/SIL.Media.Tests.csproj +++ b/SIL.Media.Tests/SIL.Media.Tests.csproj @@ -18,6 +18,7 @@ + diff --git a/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs b/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs index d1a50d5e9..acdf34df3 100644 --- a/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs +++ b/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs @@ -5,6 +5,7 @@ using System.Text; using Ionic.Zip; using NUnit.Framework; +using SIL.Core.ClearShare; using SIL.IO; using SIL.Reporting; using SIL.TestUtilities; diff --git a/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs b/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs index a1fbfdd90..20ec9ed6d 100644 --- a/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs +++ b/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs @@ -17,8 +17,8 @@ using SIL.Extensions; using SIL.IO; using SIL.PlatformUtilities; -using SIL.Windows.Forms.ClearShare; using Timer = System.Threading.Timer; +using SIL.Core.ClearShare; namespace SIL.Windows.Forms.Archiving { diff --git a/SIL.Windows.Forms.Tests/ClearShare/ClearShareUsage.cs b/SIL.Windows.Forms.Tests/ClearShare/ClearShareUsage.cs index d80351fe1..df376a3ec 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/ClearShareUsage.cs +++ b/SIL.Windows.Forms.Tests/ClearShare/ClearShareUsage.cs @@ -1,6 +1,7 @@ -using System.Linq; +using System.Linq; using System.Xml; using NUnit.Framework; +using SIL.Core.ClearShare; using SIL.IO; using SIL.Windows.Forms.ClearShare; diff --git a/SIL.Windows.Forms.Tests/ClearShare/ContributorsListControlViewModelTests.cs b/SIL.Windows.Forms.Tests/ClearShare/ContributorsListControlViewModelTests.cs index 6a14cab8d..f72edac5e 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/ContributorsListControlViewModelTests.cs +++ b/SIL.Windows.Forms.Tests/ClearShare/ContributorsListControlViewModelTests.cs @@ -1,6 +1,7 @@ using System.Linq; using Moq; using NUnit.Framework; +using SIL.Core.ClearShare; using SIL.Windows.Forms.ClearShare; namespace SIL.Windows.Forms.Tests.ClearShare diff --git a/SIL.Windows.Forms.Tests/ClearShare/LicenseTests.cs b/SIL.Windows.Forms.Tests/ClearShare/LicenseInfoTests.cs similarity index 63% rename from SIL.Windows.Forms.Tests/ClearShare/LicenseTests.cs rename to SIL.Windows.Forms.Tests/ClearShare/LicenseInfoTests.cs index c5f644988..bbde984ee 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/LicenseTests.cs +++ b/SIL.Windows.Forms.Tests/ClearShare/LicenseInfoTests.cs @@ -1,71 +1,12 @@ -using NUnit.Framework; +using NUnit.Framework; using SIL.Windows.Forms.ClearShare; namespace SIL.Windows.Forms.Tests.ClearShare { /// ---------------------------------------------------------------------------------------- [TestFixture] - public class LicenseTests + public class LicenseInfoTests { - /// ------------------------------------------------------------------------------------ - [Test] - public void AreContentsEqual_OtherIsNull_ReturnsFalse() - { - var l = License.CreativeCommons_Attribution_ShareAlike; - Assert.IsFalse(l.AreContentsEqual(null)); - } - - /// ------------------------------------------------------------------------------------ - [Test] - public void AreContentsEqual_AreDifferent_ReturnsFalse() - { - var l1 = License.CreativeCommons_Attribution_ShareAlike; - var l2 = License.CreativeCommons_Attribution; - Assert.IsFalse(l1.AreContentsEqual(l2)); - } - - /// ------------------------------------------------------------------------------------ - [Test] - public void AreContentsEqual_AreSame_ReturnsTrue() - { - var l1 = License.CreativeCommons_Attribution_ShareAlike; - var l2 = License.CreativeCommons_Attribution_ShareAlike; - Assert.IsTrue(l1.AreContentsEqual(l2)); - } - - /// ------------------------------------------------------------------------------------ - [Test] - public void Equals_SameInstance_ReturnsTrue() - { - var l = License.CreativeCommons_Attribution_ShareAlike; - Assert.IsTrue(l.Equals(l)); - } - - /// ------------------------------------------------------------------------------------ - [Test] - public void Equals_CompareToNull_ReturnsFalse() - { - var l = License.CreativeCommons_Attribution_ShareAlike; - Assert.IsFalse(l.Equals(null)); - } - - /// ------------------------------------------------------------------------------------ - [Test] - public void Equals_CompareToObjOfDifferentType_ReturnsFalse() - { - var l = License.CreativeCommons_Attribution_ShareAlike; - Assert.IsFalse(l.Equals("junk")); - } - - /// ------------------------------------------------------------------------------------ - [Test] - public void Equals_AreSame_ReturnsTrue() - { - var l1 = License.CreativeCommons_Attribution_ShareAlike; - var l2 = License.CreativeCommons_Attribution_ShareAlike; - Assert.IsTrue(l1.Equals(l2)); - } - [Test] public void FromToken_CreativeCommons_GiveExpectedAttributes() { diff --git a/SIL.Windows.Forms.Tests/ClearShare/MetaDataDisplayTests.cs b/SIL.Windows.Forms.Tests/ClearShare/MetaDataDisplayTests.cs index 97b0b4a9e..cb675ef87 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/MetaDataDisplayTests.cs +++ b/SIL.Windows.Forms.Tests/ClearShare/MetaDataDisplayTests.cs @@ -1,5 +1,6 @@ -using System.Windows.Forms; +using System.Windows.Forms; using NUnit.Framework; +using SIL.Core.ClearShare; using SIL.Windows.Forms.ClearShare; using SIL.Windows.Forms.ClearShare.WinFormsUI; diff --git a/SIL.Windows.Forms.Tests/ClearShare/MetadataEditorControlTests.cs b/SIL.Windows.Forms.Tests/ClearShare/MetadataEditorControlTests.cs index 3500e2ce0..21464cf20 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/MetadataEditorControlTests.cs +++ b/SIL.Windows.Forms.Tests/ClearShare/MetadataEditorControlTests.cs @@ -1,5 +1,6 @@ using System.Windows.Forms; using NUnit.Framework; +using SIL.Core.ClearShare; using SIL.Windows.Forms.ClearShare; using SIL.Windows.Forms.ClearShare.WinFormsUI; diff --git a/SIL.Windows.Forms.Tests/ClearShare/MetadataTests.cs b/SIL.Windows.Forms.Tests/ClearShare/MetadataTests.cs index 0a66ba658..775abc35c 100644 --- a/SIL.Windows.Forms.Tests/ClearShare/MetadataTests.cs +++ b/SIL.Windows.Forms.Tests/ClearShare/MetadataTests.cs @@ -538,7 +538,7 @@ public void ChangingFromCCLicense_WorksOkay() private void VerifyMetadataUnchangedSavingToTag(Metadata oldMetadata, XmpTag tag, string header) { // XmpTag objects are wretched to work with, so load it into another Metadata object for testing. - // This way we test both SaveInImageTag and LoadProperties for roundtripping. + // This way we test both SaveInImageTag and LoadProperties for round-tripping. oldMetadata.SaveInImageTag(tag); var newMetadata = new Metadata(); Metadata.LoadProperties(tag, newMetadata); diff --git a/SIL.Windows.Forms/ClearShare/ContributorsListControlViewModel.cs b/SIL.Windows.Forms/ClearShare/ContributorsListControlViewModel.cs index 12c94aff7..f556a0422 100644 --- a/SIL.Windows.Forms/ClearShare/ContributorsListControlViewModel.cs +++ b/SIL.Windows.Forms/ClearShare/ContributorsListControlViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Forms; +using SIL.Core.ClearShare; using SIL.Windows.Forms.Widgets.BetterGrid; namespace SIL.Windows.Forms.ClearShare diff --git a/SIL.Windows.Forms/ClearShare/CreativeCommonsLicense.cs b/SIL.Windows.Forms/ClearShare/CreativeCommonsLicense.cs index e80c5ba17..1f47484f2 100644 --- a/SIL.Windows.Forms/ClearShare/CreativeCommonsLicense.cs +++ b/SIL.Windows.Forms/ClearShare/CreativeCommonsLicense.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Drawing; using System.Globalization; -using NDesk.DBus.Introspection; namespace SIL.Windows.Forms.ClearShare { @@ -363,13 +362,6 @@ public string Version private string _qualifier = null; - [Obsolete("Use IntergovernmentalOrganizationQualifier")] - public bool IntergovernmentalOriganizationQualifier - { - get => IntergovernmentalOrganizationQualifier; - set => IntergovernmentalOrganizationQualifier = value; - } - /// /// CC 3.0 licenses were ported to better serve the needs of Intergovernmental Organizations (IGOs). /// CC 4.0 does not include a separate IGO suite (at least 2016-2023); presumably, stock CC 4.0 licenses should serve IGOs well as is. diff --git a/SIL.Windows.Forms/ClearShare/LicenseInfo.cs b/SIL.Windows.Forms/ClearShare/LicenseInfo.cs index 45526c213..4cedfc2ed 100644 --- a/SIL.Windows.Forms/ClearShare/LicenseInfo.cs +++ b/SIL.Windows.Forms/ClearShare/LicenseInfo.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using JetBrains.Annotations; using L10NSharp; namespace SIL.Windows.Forms.ClearShare @@ -10,14 +11,11 @@ public abstract class LicenseInfo { public static LicenseInfo FromXmp(Dictionary properties) { - if(properties.ContainsKey("license") && properties["license"].Contains("creativecommons")) - { + if (properties.ContainsKey("license") && properties["license"].Contains("creativecommons")) return CreativeCommonsLicense.FromMetadata(properties); - } - else if ( properties.ContainsKey("rights (en)")) - { + + if ( properties.ContainsKey("rights (en)")) return CustomLicense.FromMetadata(properties); - } return new NullLicense(); } @@ -57,6 +55,7 @@ public virtual Image GetImage() /// REVIEW: How do we know whether this is a well-known license? Presently, only is always well-known. /// REVIEW (Hasso) 2023.07: This is never used (internally, at least) and all overriding implementations return false, too. /// + [PublicAPI] public virtual bool EditingAllowed => false; public abstract string Url { get; set; } @@ -117,11 +116,9 @@ public override string GetDescription(IEnumerable languagePriorityIds, o return GetBestLicenseTranslation("NullLicense", englishText, comment, languagePriorityIds, out idOfLanguageUsed); } - public override string Token - { + public override string Token => //do not think of changing this, there is data out there that could get messed up - get { return "ask"; } - } + "ask"; public override string GetMinimalFormForCredits(IEnumerable languagePriorityIds, out string idOfLanguageUsed) { @@ -136,7 +133,7 @@ public override string ToString() public override string Url { - get { return ""; } + get => ""; set { } } } @@ -175,17 +172,15 @@ public override string GetDescription(IEnumerable languagePriorityIds, o } //We don't actually have a way of knowing what language this is, so we use "und", from http://www.loc.gov/standards/iso639-2/faq.html#25 - //I hearby coin "Zook's First Law": Eventually any string entered by a user will wish it had been tagged with a language identifier + //I hereby coin "Zook's First Law": Eventually any string entered by a user will wish it had been tagged with a language identifier //"Zook's Second Law" can be: Eventually any string entered by a user will wish it was a multi-string (multiple (language,value) pairs) idOfLanguageUsed = "und"; return RightsStatement; } - public override string Token - { + public override string Token => //do not think of changing this, there is data out there that could get messed up - get { return "custom"; } - } + "custom"; public override Image GetImage() { diff --git a/SIL.Windows.Forms/ClearShare/LicenseWithLogo.cs b/SIL.Windows.Forms/ClearShare/LicenseWithLogo.cs new file mode 100644 index 000000000..c1b020ff9 --- /dev/null +++ b/SIL.Windows.Forms/ClearShare/LicenseWithLogo.cs @@ -0,0 +1,39 @@ +using System.Drawing; +using SIL.Core.ClearShare; + +namespace SIL.Windows.Forms.ClearShare +{ + /// + /// Describes a single license, under which many works can be licensed for use + /// + public class LicenseWithLogo : License + { + public Image Logo { get; private set; } + + /// ------------------------------------------------------------------------------------ + public override int GetHashCode() + { + unchecked + { + int result = base.GetHashCode(); + result = (result * 397) ^ (Logo != null ? Logo.GetHashCode() : 0); + return result; + } + } + + /// ------------------------------------------------------------------------------------ + public override bool Equals(object other) + { + if (other == null) + return false; + + if (ReferenceEquals(this, other)) + return true; + + if (GetType() != other.GetType()) + return false; + + return AreContentsEqual(other as License); + } + } +} diff --git a/SIL.Windows.Forms/ClearShare/Metadata.cs b/SIL.Windows.Forms/ClearShare/Metadata.cs index 25361c16f..90ecc8f71 100644 --- a/SIL.Windows.Forms/ClearShare/Metadata.cs +++ b/SIL.Windows.Forms/ClearShare/Metadata.cs @@ -1,12 +1,13 @@ -// Copyright (c) 2018-2023 SIL International +// Copyright (c) 2018-2024 SIL International // This software is licensed under the MIT License (http://opensource.org/licenses/MIT) + using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System.Text.RegularExpressions; -using L10NSharp; +using JetBrains.Annotations; using SIL.Code; using SIL.Extensions; using SIL.IO; @@ -14,7 +15,6 @@ using TagLib.IFD; using TagLib.Image; using TagLib.Xmp; -using File = System.IO.File; namespace SIL.Windows.Forms.ClearShare { @@ -774,6 +774,7 @@ public static bool HaveStoredExemplar(FileCategory category) /// Deletes the stored exemplar (if it exists). This can be useful if a program /// wants to establish "CC BY" as the default license for a new product. /// + [PublicAPI] public static void DeleteStoredExemplar(FileCategory category) { var path = GetExemplarPath(category); @@ -788,11 +789,12 @@ public static void DeleteStoredExemplar(FileCategory category) /// The summary will be in the first language available. /// /// - public string GetSummaryParagraph(IEnumerable languagePriorityIds, out string idOfLanguageUsed) + [PublicAPI] + public string GetSummaryParagraph(IEnumerable languagePriorityIds, out string idOfLanguageUsed, string localizedCreatorLabel = "Creator") { var b = new StringBuilder(); - string creatorLabel = LocalizationManager.GetString("MetadataDisplay.CreatorLabel", "Creator"); - b.AppendLine(creatorLabel+": " + Creator); + b.Append(localizedCreatorLabel).Append(": ").AppendLine(Creator); + b.AppendLine($"{localizedCreatorLabel}: {Creator}"); b.AppendLine(CopyrightNotice); if(!string.IsNullOrEmpty(CollectionName)) b.AppendLine(CollectionName); diff --git a/SIL.Windows.Forms/ClearShare/WinFormsUI/ContributorsListControl.cs b/SIL.Windows.Forms/ClearShare/WinFormsUI/ContributorsListControl.cs index bc2e95122..4e65e78a7 100644 --- a/SIL.Windows.Forms/ClearShare/WinFormsUI/ContributorsListControl.cs +++ b/SIL.Windows.Forms/ClearShare/WinFormsUI/ContributorsListControl.cs @@ -9,6 +9,7 @@ using JetBrains.Annotations; using L10NSharp.UI; using SIL.Code; +using SIL.Core.ClearShare; using SIL.Windows.Forms.Widgets.BetterGrid; namespace SIL.Windows.Forms.ClearShare.WinFormsUI diff --git a/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataDisplayControl.cs b/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataDisplayControl.cs index 607685342..c23499e24 100644 --- a/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataDisplayControl.cs +++ b/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataDisplayControl.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.Windows.Forms; using L10NSharp; +using SIL.Core.ClearShare; using SIL.Windows.Forms.Widgets; namespace SIL.Windows.Forms.ClearShare.WinFormsUI diff --git a/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorControl.cs b/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorControl.cs index 29cd816a2..4387a0753 100644 --- a/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorControl.cs +++ b/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorControl.cs @@ -3,6 +3,7 @@ using System.Drawing.Drawing2D; using System.Windows.Forms; using L10NSharp; +using SIL.Core.ClearShare; namespace SIL.Windows.Forms.ClearShare.WinFormsUI { diff --git a/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorDialog.cs b/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorDialog.cs index 9c8e915bd..4f3aee307 100644 --- a/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorDialog.cs +++ b/SIL.Windows.Forms/ClearShare/WinFormsUI/MetadataEditorDialog.cs @@ -1,6 +1,7 @@ using System; using System.Windows.Forms; using L10NSharp; +using SIL.Core.ClearShare; namespace SIL.Windows.Forms.ClearShare.WinFormsUI { diff --git a/SIL.Windows.Forms/ImageToolbox/ImageToolboxControl.cs b/SIL.Windows.Forms/ImageToolbox/ImageToolboxControl.cs index 8a9584844..64a6b976f 100644 --- a/SIL.Windows.Forms/ImageToolbox/ImageToolboxControl.cs +++ b/SIL.Windows.Forms/ImageToolbox/ImageToolboxControl.cs @@ -4,6 +4,7 @@ using System.Windows.Forms; using L10NSharp; using SIL.Code; +using SIL.Core.ClearShare; using SIL.PlatformUtilities; using SIL.Reporting; using SIL.Windows.Forms.ClearShare; diff --git a/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.Designer.cs b/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.Designer.cs index e93de8bf0..40d4e8510 100644 --- a/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.Designer.cs +++ b/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.Designer.cs @@ -1,4 +1,5 @@ -using SIL.Windows.Forms.ClearShare; +using SIL.Core.ClearShare; +using SIL.Windows.Forms.ClearShare; namespace SIL.Windows.Forms.ImageToolbox { diff --git a/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.cs b/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.cs index 60aa3fbe7..9c74640b9 100644 --- a/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.cs +++ b/SIL.Windows.Forms/ImageToolbox/ImageToolboxDialog.cs @@ -1,5 +1,6 @@ using System; using System.Windows.Forms; +using SIL.Core.ClearShare; using SIL.Reporting; using SIL.Windows.Forms.ClearShare; diff --git a/SIL.Windows.Forms/ImageToolbox/PalasoImage.cs b/SIL.Windows.Forms/ImageToolbox/PalasoImage.cs index fdc7e3dae..39ccb2f11 100644 --- a/SIL.Windows.Forms/ImageToolbox/PalasoImage.cs +++ b/SIL.Windows.Forms/ImageToolbox/PalasoImage.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using SIL.Code; +using SIL.Core.ClearShare; using SIL.IO; using SIL.Windows.Forms.ClearShare; diff --git a/SIL.Windows.Forms/Properties/Resources.Designer.cs b/SIL.Windows.Forms/Properties/Resources.Designer.cs index 14e679812..b320d2994 100644 --- a/SIL.Windows.Forms/Properties/Resources.Designer.cs +++ b/SIL.Windows.Forms/Properties/Resources.Designer.cs @@ -130,27 +130,6 @@ internal static System.Drawing.Bitmap MenuButtonArrow { } } - /// - /// Looks up a localized string similar to <?xml version="1.0"?> - ///<OLAC_doc> - /// <header> - /// <status code="adopted" type="recommendation"/> - /// <!-- Promoted to Adopted on 2008-12-19 --> - /// <title>OLAC Role Vocabulary</title> - /// <baseName>role</baseName> - /// <issued>20060406</issued> - /// <previousIssued>20031010</previousIssued> - /// <abstract> - /// <p>Role is an attribute of both the Creator and Contributor elements. (Please note that Dublin - /// Core now discourages the use of the Creator element, recommending that all Role information be - /// associated with C [rest of string was truncated]";. - /// - internal static string OlacRoles { - get { - return ResourceManager.GetString("OlacRoles", resourceCulture); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/SIL.Windows.Forms/Properties/Resources.resx b/SIL.Windows.Forms/Properties/Resources.resx index f7f3cd1de..a63ad0f42 100644 --- a/SIL.Windows.Forms/Properties/Resources.resx +++ b/SIL.Windows.Forms/Properties/Resources.resx @@ -124,9 +124,6 @@ ..\Resources\RecycleBin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\OlacRoles.xml;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - ..\Resources\RemoveGridRowNormal.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/TestApps/SIL.Windows.Forms.TestApp/ContributorsForm.cs b/TestApps/SIL.Windows.Forms.TestApp/ContributorsForm.cs index ebe9643f8..414316118 100644 --- a/TestApps/SIL.Windows.Forms.TestApp/ContributorsForm.cs +++ b/TestApps/SIL.Windows.Forms.TestApp/ContributorsForm.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Drawing; using System.Windows.Forms; +using SIL.Core.ClearShare; using SIL.Windows.Forms.ClearShare; using SIL.Windows.Forms.ClearShare.WinFormsUI; using SIL.Windows.Forms.Widgets.BetterGrid; diff --git a/TestApps/SIL.Windows.Forms.TestApp/TestAppForm.cs b/TestApps/SIL.Windows.Forms.TestApp/TestAppForm.cs index 978db2993..a1f6f2216 100644 --- a/TestApps/SIL.Windows.Forms.TestApp/TestAppForm.cs +++ b/TestApps/SIL.Windows.Forms.TestApp/TestAppForm.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using System.Windows.Forms; +using SIL.Core.ClearShare; using SIL.Extensions; using SIL.IO; using SIL.Lexicon; From 0dfeebe3c01551a18fe086509300bd7ed659295b Mon Sep 17 00:00:00 2001 From: tombogle Date: Wed, 31 Jul 2024 23:20:58 -0400 Subject: [PATCH 05/15] +semver:major Split SIL.Archiving, moving Winforms portions to SIL.Windows.Forms.Archiving Included significant refactoring and replacing clunky cancellation of background process (which required calls to Application.DoEvents) with a proper async approach. --- CHANGELOG.md | 49 +- Palaso.sln | 20 +- Palaso.sln.DotSettings | 10 + .../AccessProtocolListTests.cs | 4 +- .../ArchivingFileSystemTests.cs | 4 +- SIL.Archiving.Tests/ArchivingLanguageTests.cs | 27 + .../IMDI30Tests.cs | 13 +- .../IMDIArchivingDlgViewModelTests.cs | 54 +- .../JSONUtilsTests.cs | 2 +- .../LanguageListTests.cs | 4 +- .../RampArchivingDlgViewModelTests.cs | 250 +++---- .../SIL.Archiving.Tests.csproj | 9 +- .../SimpleObjectTests.cs | 8 +- SIL.Archiving.Tests/TestProgress.cs | 23 + SIL.Archiving/App.config | 21 + .../ArchivingDlgViewModel.cs | 363 +++++----- .../ArchivingEnumerations.cs | 8 +- .../ArchivingLanguage.cs | 50 +- .../ArchivingPrograms.cs | 16 +- .../Extensions.cs | 87 +-- .../AccessProtocol/AccessProtocolList.cs | 13 +- .../Generic/ArchivingAccess.cs | 2 +- .../Generic/ArchivingActor.cs | 2 +- .../Generic/ArchivingContact.cs | 2 +- .../Generic/ArchivingFile.cs | 18 +- .../Generic/ArchivingFileSystem.cs | 2 +- .../Generic/ArchivingPackage.cs | 11 +- .../Generic/ArchivingSession.cs | 2 +- .../Generic/FileMimeType.cs | 2 +- .../Generic/GenericObject.cs | 4 +- .../Generic/LanguageString.cs | 2 +- .../Generic/SimpleObjects.cs | 2 +- SIL.Archiving/IArchivingMessageProvider.cs | 16 + .../IMDI/IMDIArchivingDlgViewModel.cs | 446 +++++++++++++ .../IMDI/IMDIContributor.cs | 4 +- .../IMDI/IMDIFile.cs | 8 +- .../IMDI/IMDIPackage.cs | 35 +- .../IMDI/Lists/BooleanEnum.cs | 2 +- .../Lists/InvalidLanguageCodeException.cs | 15 + .../IMDI/Lists/ItemListBase.cs | 8 +- .../IMDI/Lists/LanguageList.cs | 36 +- .../IMDI/Lists/ListConstructor.cs | 11 +- .../IMDI/Lists/ListType.cs | 2 +- .../IMDI/Schema/IMDIDescription.cs | 4 +- .../IMDI/Schema/IMDIExtensions.cs | 6 +- .../IMDI/Schema/IMDIInterfaces.cs | 2 +- .../IMDI/Schema/IMDISchemaHelper.cs | 2 +- .../IMDI/Schema/IMDI_3_0.cs | 8 +- .../IMDI/Schema/IMDI_3_0_Fix.py | 0 .../IMDI/Schema/IMDI_3_0_NotUsed.cs | 2 +- .../IMDI/xsd/GenerateClasses.bat | 0 .../IMDI/xsd/imdi-v3.xsd | 0 .../JSONUtils.cs | 2 +- SIL.Archiving/Properties/AssemblyInfo.cs | 9 + SIL.Archiving/Properties/Settings.Designer.cs | 54 ++ SIL.Archiving/Properties/Settings.settings | 15 + .../RampArchivingDlgViewModel.cs | 562 +++++++--------- .../Resources/AccessProtocols.json | 0 .../Resources/CustomAccessProtocols.json | 0 .../Resources/EmptyMets.xml | 2 +- SIL.Archiving/Resources/Resources.cs | 37 ++ .../Resources/ailca.html | 0 .../Resources/ailla.html | 0 .../Resources/anla.html | 0 .../Resources/elar.html | 0 .../Resources/reap.html | 0 .../Resources/tla.html | 0 SIL.Archiving/SIL.Archiving.csproj | 67 ++ .../SIL.Scripture.Tests.csproj | 1 + .../ArchivingDlg.Designer.cs | 3 +- SIL.Windows.Forms.Archiving/ArchivingDlg.cs | 443 +++++++++++-- .../IMDI/IMDIArchivingDlg.cs | 101 ++- .../IMDI/IMDIArchivingDlgViewModel.cs | 620 ------------------ .../LinkLabelExtensions.cs | 83 +++ .../Properties/Resources.Designer.cs | 236 +------ .../Properties/Resources.resx | 29 +- .../Properties/Settings.settings | 14 +- .../SIL.Windows.Forms.Archiving.csproj | 8 +- SIL.Windows.Forms.Archiving/app.config | 20 +- SIL.Windows.Forms.Scripture.Tests/App.config | 11 + SIL.Windows.Forms.Tests/App.config | 6 + .../App.config | 11 + SIL.WritingSystems/IetfLanguageTag.cs | 1 - 83 files changed, 2167 insertions(+), 1859 deletions(-) rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/AccessProtocolListTests.cs (93%) rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/ArchivingFileSystemTests.cs (90%) create mode 100644 SIL.Archiving.Tests/ArchivingLanguageTests.cs rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/IMDI30Tests.cs (97%) rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/IMDIArchivingDlgViewModelTests.cs (83%) rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/JSONUtilsTests.cs (99%) rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/LanguageListTests.cs (96%) rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/RampArchivingDlgViewModelTests.cs (78%) rename SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj => SIL.Archiving.Tests/SIL.Archiving.Tests.csproj (68%) rename {SIL.Windows.Forms.Archiving.Tests => SIL.Archiving.Tests}/SimpleObjectTests.cs (85%) create mode 100644 SIL.Archiving.Tests/TestProgress.cs create mode 100644 SIL.Archiving/App.config rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/ArchivingDlgViewModel.cs (68%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/ArchivingEnumerations.cs (99%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/ArchivingLanguage.cs (73%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/ArchivingPrograms.cs (89%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Extensions.cs (59%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/AccessProtocol/AccessProtocolList.cs (94%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/ArchivingAccess.cs (84%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/ArchivingActor.cs (98%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/ArchivingContact.cs (97%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/ArchivingFile.cs (88%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/ArchivingFileSystem.cs (97%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/ArchivingPackage.cs (91%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/ArchivingSession.cs (97%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/FileMimeType.cs (99%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/GenericObject.cs (86%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/LanguageString.cs (97%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Generic/SimpleObjects.cs (94%) create mode 100644 SIL.Archiving/IArchivingMessageProvider.cs create mode 100644 SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/IMDIContributor.cs (92%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/IMDIFile.cs (96%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/IMDIPackage.cs (87%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Lists/BooleanEnum.cs (87%) create mode 100644 SIL.Archiving/IMDI/Lists/InvalidLanguageCodeException.cs rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Lists/ItemListBase.cs (98%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Lists/LanguageList.cs (88%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Lists/ListConstructor.cs (95%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Lists/ListType.cs (98%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Schema/IMDIDescription.cs (96%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Schema/IMDIExtensions.cs (96%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Schema/IMDIInterfaces.cs (93%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Schema/IMDISchemaHelper.cs (93%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Schema/IMDI_3_0.cs (99%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Schema/IMDI_3_0_Fix.py (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/Schema/IMDI_3_0_NotUsed.cs (99%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/xsd/GenerateClasses.bat (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/IMDI/xsd/imdi-v3.xsd (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/JSONUtils.cs (98%) create mode 100644 SIL.Archiving/Properties/AssemblyInfo.cs create mode 100644 SIL.Archiving/Properties/Settings.Designer.cs create mode 100644 SIL.Archiving/Properties/Settings.settings rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/RampArchivingDlgViewModel.cs (81%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/AccessProtocols.json (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/CustomAccessProtocols.json (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/EmptyMets.xml (59%) create mode 100644 SIL.Archiving/Resources/Resources.cs rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/ailca.html (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/ailla.html (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/anla.html (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/elar.html (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/reap.html (100%) rename {SIL.Windows.Forms.Archiving => SIL.Archiving}/Resources/tla.html (100%) create mode 100644 SIL.Archiving/SIL.Archiving.csproj delete mode 100644 SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlgViewModel.cs create mode 100644 SIL.Windows.Forms.Archiving/LinkLabelExtensions.cs create mode 100644 SIL.Windows.Forms.Scripture.Tests/App.config create mode 100644 SIL.Windows.Forms.WritingSystems.Tests/App.config diff --git a/CHANGELOG.md b/CHANGELOG.md index 15acd8764..d9edde3c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,17 +19,62 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - [SIL.Core] Added macOS support for `GlobalMutex` +- [SIL.Archiving] Added ArchivingDlgViewModel.Standard and ArchivingDlgViewModel.StringId emumerations. +- [SIL.Archiving] Added public delegate ArchivingDlgViewModel.ExceptionHandler and event ArchivingDlgViewModel.OnExceptionDuringLaunch. +- [SIL.Archiving] Added IArchivingProgressDisplay interface. +- [SIL.Archiving] Added overload of ArchivingDlgViewModel.DisplayMessage to take format parameters. +- [SIL.Archiving] Added public overload of ArchivingDlgViewModel.LaunchArchivingProgram. +- [SIL.Archiving] Added protected methods to ArchivingDlgViewModel: ReportMajorProgressPoint, ReportProgress, CleanUp +- [SIL.Windows.Forms.Archiving] Added protected virtual properties ArchiveTypeForTitleBar and InformativeText to ArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added public virtual method GetMessage to ArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added public virtual property ArchiveTypeName to ArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added protected methods DisplayMessage and Initialize (async) to ArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added protected virtual method PackageCreationComplete to ArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added (public) override of property ArchiveTypeName to IMDIArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added (protected) override of property InformativeText to IMDIArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added (protected) override of method PackageCreationComplete to IMDIArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added (public) override of method GetMessage to IMDIArchivingDlg. +- [SIL.Windows.Forms.Archiving] Added public extensions class LinkLabelExtensions with some methods that were formerly in Extensions class (now in SIL.Archiving). ### Changed -- [SIL.Windows.Forms.Archiving] Renamed SIL.Archiving to SIL.Windows.Forms.Archiving +- [SIL.Windows.Forms.Archiving] Split SIL.Archiving, moving Winforms portions (including dependency on L10nSharp) to SIL.Windows.Forms.Archiving. +- [SIL.Archiving] Required ArchivingDlgViewModel implementations to implement IDisposable. +- [SIL.Archiving] Made protected members in ArchivingDlgViewModel private, adding protected accessors as needed. +- [SIL.Archiving] In ArchivingDlgViewModel, renamed DisplayMessageEventHandler to MessageEventHandler, OnDisplayMessage to OnReportMessage, DisplayErrorEventHandler to ErrorEventHandler, and OnDisplayError to OnError. +- [SIL.Archiving] Changed signature of ArchivingDlgViewModel.OverrideDisplayInitialSummary to include a CancellationToken. +- [SIL.Archiving] Made ArchivingDlgViewModel.ArchiveType property public and changed it from a string to Standard (new enum). +- [SIL.Archiving] Changed signature of setFilesToArchive delegate in ArchivingDlgViewModel's protected constructor. +- [SIL.Archiving] Changed return type of ArchivingDlgViewModel.Initialize (to make it async) and added two parameters. +- [SIL.Archiving] Changed ArchivingDlgViewModel.DisplayMessage from public to protected. +- [SIL.Archiving] Changed the signature of protected methods in ArchivingDlgViewModel: LaunchArchivingProgram, GetFileExcludedMsg. +- [SIL.Archiving] Changed the signature of the public method ArchivingDlgViewModel.CreatePackage. +- [SIL.Archiving] Changed underlying type of public enums VernacularMaterialsType and SilDomain from ulong to long. +- [SIL.Archiving] Replaced protected _keys field (now private) in abstract class ArchivingPackage with protected accessor property Keys. +- [SIL.Archiving] IMDIArchivingDlgViewModel (subclass of ArchivingDlgViewModel) affected by many of the changes to the base class. +- [SIL.Archiving] IMDIArchivingDlgViewModel and RampArchivingDlgViewModel (subclasses of ArchivingDlgViewModel) affected by many of the changes to the base class. +- [SIL.Archiving] IMDIArchivingDlgViewModel constructor signature changed. +- [SIL.Archiving] RampArchivingDlgViewModel constructor signature changed. +- [SIL.Windows.Forms.Archiving] Made ArchivingDlg implement IArchivingProgressDisplay. +- [SIL.Windows.Forms.Archiving] ArchivingDlg constructor signature changed: removed localizationManagerId; added optional archiveInfoHyperlinkText. +- [SIL.Windows.Forms.Archiving] IMDIArchivingDlg constructor signature changed: added appSpecificArchivalProcessInfo. - [SIL.Windows.Forms] Split ClearShare code, moving non-Winforms portions to SIL.Core (SIL.Core.ClearShare namespace) - [SIL.Core] Added optional parameter to OlacSystem.GetRoles to allow caller to provide its own XML with role definitions. - [SIL.Windows.Forms] Split License into a base class called License and a derived LicenseWithLogo, so that License could be in SIL.Core. +### Fixed +- [SIL.Archiving] Fixed typo in RampArchivingDlgViewModel for Ethnomusicology performance collection. +- [SIL.Archiving] Changed URLs that used http: to https: in resource EmptyMets.xml. + ### Removed - [SIL.Windows.Forms] Removed previously deprecated CreativeCommonsLicense.IntergovernmentalOriganizationQualifier +- [SIL.Archiving] Removed abstract properties from ArchivingDlgViewModel: InformativeText and ArchiveInfoHyperlinkText. +- [SIL.Archiving] Removed public method ArchivingDlgViewModel.Cancel. (Now handled via cancellation tokens.) +- [SIL.Archiving] Removed protected methods from ArchivingDlgViewModel: PreparingFilesMsg, GetSavingFilesMsg +- [SIL.Archiving] Removed protected fields (renamed and made private) from ArchivingLanguage: _iso3Code, _englishName +- [SIL.Archiving] Removed protected fields (made private) from ArchivingFile: _fullName, _fileName, _fileSize, _mimeType, _descriptions, _accessProtocol +- [SIL.Archiving] Removed public methods CreateMetsFile and CreateRampPackage from RampArchivingDlgViewModel (made internal). ## [14.1.1] - 2024-05-23 @@ -282,7 +327,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Core, SIL.Windows.Forms] `IErrorReporter` interface added a simpler overload of NotifyUserOfProblem method, which must be implemented by IErrorReporters. (It is acceptable for implementers to just fill some parameters then call the original method) `ConsoleErrorReporter` and `WinFormsErrorReporter` implement `IErrorReporter`'s new interface method -- [SIL.Core] Added override of SerializeToFileWithWriteThrough to simplify error handling. +- [SIL.Core] Added overload of SerializeToFileWithWriteThrough to simplify error handling. - [SIL.Windows.Forms] Added a CheckedComboBox control - [SIL.WritingSystems] Added several methods to IetfLanguageTag class to support getting language names. - [SIL.Windows.Forms.WritingSystems] Added extension method InitializeWithAvailableUILocales diff --git a/Palaso.sln b/Palaso.sln index 0821796fd..4e5e622fd 100755 --- a/Palaso.sln +++ b/Palaso.sln @@ -27,8 +27,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Reporting.TestApp", "TestAp EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Windows.Forms.Archiving", "SIL.Windows.Forms.Archiving\SIL.Windows.Forms.Archiving.csproj", "{BCE1F124-5479-4B23-90B1-B7A4EBE44FA3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Windows.Forms.Archiving.Tests", "SIL.Windows.Forms.Archiving.Tests\SIL.Windows.Forms.Archiving.Tests.csproj", "{892C7F20-FBBB-4AB3-BAC2-E40A135567B6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Scripture", "SIL.Scripture\SIL.Scripture.csproj", "{F71BA7B9-D9DC-4F8C-A307-87B503D0E05B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Scripture.Tests", "SIL.Scripture.Tests\SIL.Scripture.Tests.csproj", "{4528287F-BA86-49D8-AFBB-1250A60CE7EA}" @@ -118,7 +116,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.TestUtilities.Tests", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClipboardTestApp", "TestApps\ClipboardTestApp\ClipboardTestApp.csproj", "{B1E0B522-FEDF-497E-BFCD-A572F67C03C1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLineRunnerTestApp", "TestApps\CommandLineRunnerTestApp\CommandLineRunnerTestApp.csproj", "{6407C2F9-F62D-4568-B694-7A79C72582C9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommandLineRunnerTestApp", "TestApps\CommandLineRunnerTestApp\CommandLineRunnerTestApp.csproj", "{6407C2F9-F62D-4568-B694-7A79C72582C9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving", "SIL.Archiving\SIL.Archiving.csproj", "{01B31D97-63A4-4FC6-940F-D7278F4D0F65}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving.Tests", "SIL.Archiving.Tests\SIL.Archiving.Tests.csproj", "{698FDB66-0ACE-46E0-843C-3AB70DC7B055}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -162,10 +164,6 @@ Global {BCE1F124-5479-4B23-90B1-B7A4EBE44FA3}.Debug|Any CPU.Build.0 = Debug|Any CPU {BCE1F124-5479-4B23-90B1-B7A4EBE44FA3}.Release|Any CPU.ActiveCfg = Release|Any CPU {BCE1F124-5479-4B23-90B1-B7A4EBE44FA3}.Release|Any CPU.Build.0 = Release|Any CPU - {892C7F20-FBBB-4AB3-BAC2-E40A135567B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {892C7F20-FBBB-4AB3-BAC2-E40A135567B6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {892C7F20-FBBB-4AB3-BAC2-E40A135567B6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {892C7F20-FBBB-4AB3-BAC2-E40A135567B6}.Release|Any CPU.Build.0 = Release|Any CPU {F71BA7B9-D9DC-4F8C-A307-87B503D0E05B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F71BA7B9-D9DC-4F8C-A307-87B503D0E05B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F71BA7B9-D9DC-4F8C-A307-87B503D0E05B}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -302,6 +300,14 @@ Global {6407C2F9-F62D-4568-B694-7A79C72582C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {6407C2F9-F62D-4568-B694-7A79C72582C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {6407C2F9-F62D-4568-B694-7A79C72582C9}.Release|Any CPU.Build.0 = Release|Any CPU + {01B31D97-63A4-4FC6-940F-D7278F4D0F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01B31D97-63A4-4FC6-940F-D7278F4D0F65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01B31D97-63A4-4FC6-940F-D7278F4D0F65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01B31D97-63A4-4FC6-940F-D7278F4D0F65}.Release|Any CPU.Build.0 = Release|Any CPU + {698FDB66-0ACE-46E0-843C-3AB70DC7B055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {698FDB66-0ACE-46E0-843C-3AB70DC7B055}.Debug|Any CPU.Build.0 = Debug|Any CPU + {698FDB66-0ACE-46E0-843C-3AB70DC7B055}.Release|Any CPU.ActiveCfg = Release|Any CPU + {698FDB66-0ACE-46E0-843C-3AB70DC7B055}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Palaso.sln.DotSettings b/Palaso.sln.DotSettings index 604948fba..ef9fcff4d 100644 --- a/Palaso.sln.DotSettings +++ b/Palaso.sln.DotSettings @@ -20,6 +20,7 @@ Review (?<=\W|^)(?<TAG>REVIEW)(\W|$)(.*) Normal + True True True True @@ -34,6 +35,7 @@ True True True + True True True True @@ -41,10 +43,12 @@ True True True + True True True True True + True True True True @@ -58,18 +62,22 @@ True True True + True True True True True + True True True + True True True True True True True + True True True True @@ -78,6 +86,7 @@ True True True + True True True True @@ -88,6 +97,7 @@ True True True + True True True True diff --git a/SIL.Windows.Forms.Archiving.Tests/AccessProtocolListTests.cs b/SIL.Archiving.Tests/AccessProtocolListTests.cs similarity index 93% rename from SIL.Windows.Forms.Archiving.Tests/AccessProtocolListTests.cs rename to SIL.Archiving.Tests/AccessProtocolListTests.cs index d5aff3aa9..bcbb325f0 100644 --- a/SIL.Windows.Forms.Archiving.Tests/AccessProtocolListTests.cs +++ b/SIL.Archiving.Tests/AccessProtocolListTests.cs @@ -2,9 +2,9 @@ using System.IO; using System.Linq; using NUnit.Framework; -using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; +using SIL.Archiving.Generic.AccessProtocol; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] [Category("Archiving")] diff --git a/SIL.Windows.Forms.Archiving.Tests/ArchivingFileSystemTests.cs b/SIL.Archiving.Tests/ArchivingFileSystemTests.cs similarity index 90% rename from SIL.Windows.Forms.Archiving.Tests/ArchivingFileSystemTests.cs rename to SIL.Archiving.Tests/ArchivingFileSystemTests.cs index fc9180bf5..f71d16630 100644 --- a/SIL.Windows.Forms.Archiving.Tests/ArchivingFileSystemTests.cs +++ b/SIL.Archiving.Tests/ArchivingFileSystemTests.cs @@ -4,10 +4,10 @@ using System; using System.IO; using NUnit.Framework; -using SIL.Windows.Forms.Archiving.Generic; +using SIL.Archiving.Generic; using SIL.IO; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] public class ArchivingFileSystemTests diff --git a/SIL.Archiving.Tests/ArchivingLanguageTests.cs b/SIL.Archiving.Tests/ArchivingLanguageTests.cs new file mode 100644 index 000000000..fd22f39e3 --- /dev/null +++ b/SIL.Archiving.Tests/ArchivingLanguageTests.cs @@ -0,0 +1,27 @@ +using NUnit.Framework; + +namespace SIL.Archiving.Tests +{ + [TestFixture] + public class ArchivingLanguageTests + { + [Test] + public void Compare_SameCodeAndLanguageName_ReturnsZero() + { + Assert.That(ArchivingLanguage.Compare(new ArchivingLanguage("eng", "English"), + new ArchivingLanguage("ENG", "English")), Is.EqualTo(0)); + } + + [TestCase("eng", "English", "frg", "Froggish", ExpectedResult = false)] + [TestCase("zzz", "Zyzzyvian", "zzz", "Scrabbilian", ExpectedResult = true)] + [TestCase("som", "Some Language", "unk", "Some Language", ExpectedResult = false)] + public bool Compare_DifferentCodeOrLanguageName_ReturnsNonZero(string code1, string name1, + string code2, string name2) + { + var val = ArchivingLanguage.Compare(new ArchivingLanguage(code1, name1), + new ArchivingLanguage(code2, name2)); + Assert.That(val, Is.Not.EqualTo(0)); + return val > 0; + } + } +} diff --git a/SIL.Windows.Forms.Archiving.Tests/IMDI30Tests.cs b/SIL.Archiving.Tests/IMDI30Tests.cs similarity index 97% rename from SIL.Windows.Forms.Archiving.Tests/IMDI30Tests.cs rename to SIL.Archiving.Tests/IMDI30Tests.cs index 42c080313..238f21974 100644 --- a/SIL.Windows.Forms.Archiving.Tests/IMDI30Tests.cs +++ b/SIL.Archiving.Tests/IMDI30Tests.cs @@ -2,13 +2,13 @@ using System.Globalization; using System.Linq; using NUnit.Framework; -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.IMDI; -using SIL.Windows.Forms.Archiving.IMDI.Lists; -using SIL.Windows.Forms.Archiving.IMDI.Schema; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI; +using SIL.Archiving.IMDI.Lists; +using SIL.Archiving.IMDI.Schema; using SIL.TestUtilities; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] [OfflineSldr] @@ -236,7 +236,8 @@ public void SessionAddActor_Anonymized_RemovesActorFiles() [Test] public void FindByISO3Code_InvalidIso3Code_MustBeInList_Throws() { - Assert.Throws(() => LanguageList.FindByISO3Code("xyz", true)); + var code = Assert.Throws(() => LanguageList.FindByISO3Code("xyz", true)).Code; + Assert.That(code, Is.EqualTo("xyz")); } [Test] diff --git a/SIL.Windows.Forms.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs b/SIL.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs similarity index 83% rename from SIL.Windows.Forms.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs rename to SIL.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs index 95fa9b83e..ff294e983 100644 --- a/SIL.Windows.Forms.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs +++ b/SIL.Archiving.Tests/IMDIArchivingDlgViewModelTests.cs @@ -1,11 +1,13 @@ using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; using System.Xml; using NUnit.Framework; -using SIL.Windows.Forms.Archiving.IMDI; +using SIL.Archiving.IMDI; using SIL.Reporting; using SIL.TestUtilities; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] [OfflineSldr] @@ -14,7 +16,7 @@ internal class IMDIArchivingDlgViewModelTests { private class MessageData { - public string MsgText; + public readonly string MsgText; public ArchivingDlgViewModel.MessageType MsgType; public MessageData(string msg, ArchivingDlgViewModel.MessageType type) @@ -25,8 +27,9 @@ public MessageData(string msg, ArchivingDlgViewModel.MessageType type) } private IMDIArchivingDlgViewModel _model; - private TemporaryFolder _tmpFolder; - private List _messages; + private TestProgress m_progress; + private TemporaryFolder m_tmpFolder; + private List m_messages; private const string kAppName = "Tèst App Náme"; private const string kTitle = "Tèst Title"; private const string kArchiveId = "Tèst Corpus Náme"; // include some invalid characters for testing @@ -35,13 +38,17 @@ public MessageData(string msg, ArchivingDlgViewModel.MessageType type) /// ------------------------------------------------------------------------------------ [SetUp] - public void Setup() + public async Task Setup() { ErrorReport.IsOkToInteractWithUser = false; - _tmpFolder = new TemporaryFolder("IMDIArchiveHelperTestFolder"); - _model = new IMDIArchivingDlgViewModel(kAppName, kTitle, kArchiveId, null, true, dummyAction => { }, _tmpFolder.Path); - _messages = new List(); - _model.OnDisplayMessage += (msg, type) => { _messages.Add(new MessageData(msg, type)); }; + m_tmpFolder = new TemporaryFolder("IMDIArchiveHelperTestFolder"); + _model = new IMDIArchivingDlgViewModel(kAppName, kTitle, kArchiveId, true, (no, op) => { }, m_tmpFolder.Path); + m_progress = new TestProgress("IMDI"); + var cancel = new CancellationToken(); + await _model.Initialize(m_progress, cancel); + Assert.That(m_progress.Step, Is.EqualTo(1)); + m_messages = new List(); + _model.OnReportMessage += (msg, type) => { m_messages.Add(new MessageData(msg, type)); }; } /// ------------------------------------------------------------------------------------ @@ -49,7 +56,7 @@ public void Setup() public void TearDown() { _model.CleanUp(); - _tmpFolder.Dispose(); + m_tmpFolder.Dispose(); } #endregion @@ -79,10 +86,10 @@ public void CorpusDirectoryName_ValidNameForNewDirectory() [Test] public void PathIsAccessible_WritablePath_True() { - var dir = _tmpFolder.Path; + var dir = m_tmpFolder.Path; var writable = _model.IsPathWritable(dir); Assert.True(writable); - Assert.IsEmpty(_messages); + Assert.IsEmpty(m_messages); } [Test] @@ -91,9 +98,9 @@ public void PathIsAccessible_NonexistentPath_False() const string dir = "/one/two"; var writable = _model.IsPathWritable(dir); Assert.False(writable); - Assert.AreEqual(1, _messages.Count); - Assert.AreEqual("The path is not writable: /one/two", _messages[0].MsgText); - Assert.AreEqual(ArchivingDlgViewModel.MessageType.Warning, _messages[0].MsgType); + Assert.AreEqual(1, m_messages.Count); + Assert.AreEqual("Test implementation message for PathNotWritable", m_messages[0].MsgText); + Assert.AreEqual(ArchivingDlgViewModel.MessageType.Warning, m_messages[0].MsgType); } [Test] @@ -103,9 +110,9 @@ public void IsPathWritable_WindowsInvalidPath_False() const string dir = ":?"; var writable = _model.IsPathWritable(dir); Assert.False(writable); - Assert.AreEqual(1, _messages.Count); - Assert.AreEqual("The path is not of a legal form.", _messages[0].MsgText); - Assert.AreEqual(ArchivingDlgViewModel.MessageType.Warning, _messages[0].MsgType); + Assert.AreEqual(1, m_messages.Count); + Assert.AreEqual("The path is not of a legal form.", m_messages[0].MsgText); + Assert.AreEqual(ArchivingDlgViewModel.MessageType.Warning, m_messages[0].MsgType); } [Test] @@ -114,9 +121,9 @@ public void IsPathWritable_IllegalCharacterInPath_False() const string dir = "/\0"; var writable = _model.IsPathWritable(dir); Assert.False(writable); - Assert.AreEqual(1, _messages.Count); - Assert.AreEqual("Illegal characters in path.", _messages[0].MsgText); - Assert.AreEqual(ArchivingDlgViewModel.MessageType.Warning, _messages[0].MsgType); + Assert.AreEqual(1, m_messages.Count); + Assert.AreEqual("Illegal characters in path.", m_messages[0].MsgText); + Assert.AreEqual(ArchivingDlgViewModel.MessageType.Warning, m_messages[0].MsgType); } #endregion @@ -158,7 +165,6 @@ public void GetNameOfProgramToLaunch_ExeNameContainsFolderName_ReturnsFolderName [Test] public void SetAbstract_UnspecifiedLanguage_AddsDescriptionToCorpusImdiFile() { - _model.Initialize(); _model.SetAbstract("Story about a frog", string.Empty); XmlDocument doc = new XmlDocument(); doc.LoadXml(_model.GetMetadata()); @@ -190,7 +196,6 @@ public void SetAbstract_UnspecifiedLanguage_AddsDescriptionToCorpusImdiFile() [Test] public void SetAbstract_SingleLanguage_AddsDescriptionToCorpusImdiFile() { - _model.Initialize(); _model.SetAbstract("Story about a frog", "eng"); XmlDocument doc = new XmlDocument(); doc.LoadXml(_model.GetMetadata()); @@ -217,7 +222,6 @@ public void SetAbstract_SingleLanguage_AddsDescriptionToCorpusImdiFile() [Test] public void SetAbstract_MultipleLanguages_AddsDescriptionToCorpusImdiFile() { - _model.Initialize(); Dictionary descriptions = new Dictionary(); descriptions["eng"] = "Story about a frog"; descriptions["deu"] = "Geschichte über einen Frosch"; diff --git a/SIL.Windows.Forms.Archiving.Tests/JSONUtilsTests.cs b/SIL.Archiving.Tests/JSONUtilsTests.cs similarity index 99% rename from SIL.Windows.Forms.Archiving.Tests/JSONUtilsTests.cs rename to SIL.Archiving.Tests/JSONUtilsTests.cs index fd7b9b0fe..f0544ea46 100644 --- a/SIL.Windows.Forms.Archiving.Tests/JSONUtilsTests.cs +++ b/SIL.Archiving.Tests/JSONUtilsTests.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using NUnit.Framework; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] [Category("Archiving")] diff --git a/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs b/SIL.Archiving.Tests/LanguageListTests.cs similarity index 96% rename from SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs rename to SIL.Archiving.Tests/LanguageListTests.cs index ae11865e5..aa7d0d784 100644 --- a/SIL.Windows.Forms.Archiving.Tests/LanguageListTests.cs +++ b/SIL.Archiving.Tests/LanguageListTests.cs @@ -1,8 +1,8 @@ using NUnit.Framework; -using SIL.Windows.Forms.Archiving.IMDI.Lists; +using SIL.Archiving.IMDI.Lists; using SIL.TestUtilities; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] [OfflineSldr] diff --git a/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs b/SIL.Archiving.Tests/RampArchivingDlgViewModelTests.cs similarity index 78% rename from SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs rename to SIL.Archiving.Tests/RampArchivingDlgViewModelTests.cs index acdf34df3..db5ad3f4f 100644 --- a/SIL.Windows.Forms.Archiving.Tests/RampArchivingDlgViewModelTests.cs +++ b/SIL.Archiving.Tests/RampArchivingDlgViewModelTests.cs @@ -3,43 +3,48 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading; +using System.Threading.Tasks; using Ionic.Zip; using NUnit.Framework; using SIL.Core.ClearShare; using SIL.IO; using SIL.Reporting; using SIL.TestUtilities; -using SIL.Windows.Forms.ClearShare; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] [Category("Archiving")] public class RampArchivingDlgViewModelTests { - private RampArchivingDlgViewModel _helper; - private Dictionary, string>> _filesToAdd; - private bool? _isRampInstalled; + private RampArchivingDlgViewModel m_model; + private TestProgress m_progress; + private readonly Dictionary, string>> m_filesToAdd = + new Dictionary, string>>(); + private bool? m_isRampInstalled; /// ------------------------------------------------------------------------------------ [SetUp] - public void Setup() + public async Task Setup() { ErrorReport.IsOkToInteractWithUser = false; - _helper = new RampArchivingDlgViewModel("Test App", "Test Title", "tst", null, + m_model = new RampArchivingDlgViewModel("Test App", "Test Title", "tst", SetFilesToArchive, GetFileDescription); - _helper.AppSpecificFilenameNormalization = CustomFilenameNormalization; - _filesToAdd = new Dictionary, string>>(); + m_progress = new TestProgress("RAMP"); + m_model.AppSpecificFilenameNormalization = CustomFilenameNormalization; + var cancel = new CancellationToken(); + await m_model.Initialize(m_progress, cancel); } /// ------------------------------------------------------------------------------------ [TearDown] public void TearDown() { - _helper.CleanUp(); - - try { File.Delete(_helper.PackagePath); } + m_model.CleanUp(); + m_filesToAdd.Clear(); + try { File.Delete(m_model.PackagePath); } // ReSharper disable once EmptyGeneralCatchClause catch { } } @@ -48,7 +53,7 @@ public void TearDown() [Test] public void CreateMetsFile_CreatesFile() { - var metsPath = _helper.CreateMetsFile(); + var metsPath = m_model.CreateMetsFile(); Assert.IsNotNull(metsPath); Assert.IsTrue(File.Exists(metsPath)); } @@ -56,7 +61,7 @@ public void CreateMetsFile_CreatesFile() /// ------------------------------------------------------------------------------------ [Test] [Category("SkipOnTeamCity")] - public void CreateRampPackageWithSessionArchiveAndMetsFile_CreatesRampPackage() + public async Task CreateRampPackageWithSessionArchiveAndMetsFile_CreatesRampPackage() { TemporaryFolder tmpFolder = new TemporaryFolder("ArchiveHelperTestFolder"); try @@ -64,11 +69,12 @@ public void CreateRampPackageWithSessionArchiveAndMetsFile_CreatesRampPackage() string fileName = Path.Combine(tmpFolder.Path, "ddo.session"); File.CreateText(fileName).Close(); var fileList = new[] { Path.Combine(tmpFolder.Path, "ddo.session") }; - _filesToAdd.Add(string.Empty, new Tuple, string>(fileList, "Message to display.")); - _helper.Initialize(); - _helper.CreateMetsFile(); - Assert.IsTrue(_helper.CreateRampPackage()); - Assert.IsTrue(File.Exists(_helper.PackagePath)); + m_filesToAdd.Add(string.Empty, new Tuple, string>(fileList, "Message to display.")); + var cancel = new CancellationToken(); + await m_model.Initialize(new TestProgress(RampArchivingDlgViewModel.kRampProcessName), cancel); + m_model.CreateMetsFile(); + Assert.IsTrue(m_model.CreateRampPackage(new CancellationToken()).Result); + Assert.IsTrue(File.Exists(m_model.PackagePath)); } finally { @@ -80,14 +86,14 @@ public void CreateRampPackageWithSessionArchiveAndMetsFile_CreatesRampPackage() [Test] public void GetMode_NullList_ReturnsNull() { - Assert.IsNull(_helper.GetMode(null)); + Assert.IsNull(m_model.GetMode(null)); } /// ------------------------------------------------------------------------------------ [Test] public void GetMode_EmptyList_ReturnsNull() { - Assert.IsNull(_helper.GetMode(new string[0])); + Assert.IsNull(m_model.GetMode(Array.Empty())); } /// ------------------------------------------------------------------------------------ @@ -95,14 +101,14 @@ public void GetMode_EmptyList_ReturnsNull() public void GetMode_SingleTypeInList_ReturnsCorrectMetsList() { Assert.AreEqual("\"" + RampArchivingDlgViewModel.kFileTypeModeList + "\":[\"" + - RampArchivingDlgViewModel.kModeVideo + "\"]", _helper.GetMode(new[] { "blah.mpg" })); + RampArchivingDlgViewModel.kModeVideo + "\"]", m_model.GetMode(new[] { "blah.mpg" })); } /// ------------------------------------------------------------------------------------ [Test] public void GetMode_MultipleTypesInList_ReturnsCorrectMetsList() { - var mode = _helper.GetMode(new[] { "blah.mp3", "blah.doc", "blah.mov" }); + var mode = m_model.GetMode(new[] { "blah.mp3", "blah.doc", "blah.mov" }); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kFileTypeModeList + "\":[\"" + RampArchivingDlgViewModel.kModeSpeech + "\",\"" + RampArchivingDlgViewModel.kModeText + "\",\"" + @@ -121,7 +127,7 @@ public void GetMode_ZipFileWithMultipleTypesInList_ReturnsCorrectMetsList() try { zipFile.Save(tempFile.Path); - var mode = _helper.GetMode(new[] { zipFile.Name }); + var mode = m_model.GetMode(new[] { zipFile.Name }); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kFileTypeModeList + "\":[\"" + RampArchivingDlgViewModel.kModeSpeech + "\",\"" + RampArchivingDlgViewModel.kModeText + "\",\"" + @@ -136,7 +142,7 @@ public void GetMode_ZipFileWithMultipleTypesInList_ReturnsCorrectMetsList() /// ------------------------------------------------------------------------------------ [Test] - public void GetMode_FwbackupFileWithMultipleTypesInList_ReturnsCorrectMetsList() + public void GetMode_FwBackupFileWithMultipleTypesInList_ReturnsCorrectMetsList() { ZipFile zipFile = new ZipFile(); zipFile.AddEntry("blah.fwdata", "whatever"); @@ -146,7 +152,7 @@ public void GetMode_FwbackupFileWithMultipleTypesInList_ReturnsCorrectMetsList() try { zipFile.Save(tempFile.Path); - var mode = _helper.GetMode(new[] { zipFile.Name }); + var mode = m_model.GetMode(new[] { zipFile.Name }); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kFileTypeModeList + "\":[\"" + RampArchivingDlgViewModel.kModeText + "\",\"" + RampArchivingDlgViewModel.kModeDataset + "\",\"" + @@ -164,7 +170,7 @@ public void GetMode_FwbackupFileWithMultipleTypesInList_ReturnsCorrectMetsList() [Test] public void GetMode_ListContainsMultiplesOfOneType_ReturnsOnlyOneTypeInList() { - var mode = _helper.GetMode(new[] { "blah.mp3", "blah.wma", "blah.wav" }); + var mode = m_model.GetMode(new[] { "blah.mp3", "blah.wma", "blah.wav" }); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kFileTypeModeList + "\":[\"" + RampArchivingDlgViewModel.kModeSpeech + "\"]", mode); } @@ -174,81 +180,100 @@ public void GetMode_ListContainsMultiplesOfOneType_ReturnsOnlyOneTypeInList() [Test] public void GetSourceFilesForMetsData_ListContainsOnlySessionMetaFile_ReturnsCorrectMetsData() { - var fileLists = new Dictionary, string>>(); - fileLists[string.Empty] = new Tuple, string>(new[] { "blah.session" }, "Message to display."); + var fileLists = new Dictionary, string>> + { + [string.Empty] = new Tuple, string>( + new[] { "blah.session" }, "Message to display.") + }; var expected = "\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"blah.session\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileDescription + "\":\"MyApp Session Metadata (XML)\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\""; - Assert.AreEqual(expected, _helper.GetSourceFilesForMetsData(fileLists).ElementAt(0)); + Assert.AreEqual(expected, m_model.GetSourceFilesForMetsData(fileLists).ElementAt(0)); } /// ------------------------------------------------------------------------------------ [Test] public void GetSourceFilesForMetsData_ListContainsOnlyPersonMetaFile_ReturnsCorrectMetsData() { - var fileLists = new Dictionary, string>>(); - fileLists[string.Empty] = new Tuple, string>(new[] { "blah.person" }, "Message to display."); + var fileLists = new Dictionary, string>> + { + [string.Empty] = new Tuple, string>( + new[] { "blah.person" }, "Message to display.") + }; var expected = "\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"blah.person\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileDescription + "\":\"MyApp Contributor Metadata (XML)\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\""; - Assert.AreEqual(expected, _helper.GetSourceFilesForMetsData(fileLists).ElementAt(0)); + Assert.AreEqual(expected, m_model.GetSourceFilesForMetsData(fileLists).ElementAt(0)); } /// ------------------------------------------------------------------------------------ [Test] public void GetSourceFilesForMetsData_ListContainsOnlyMetaFile_ReturnsCorrectMetsData() { - var fileLists = new Dictionary, string>>(); - fileLists[string.Empty] = new Tuple, string>(new[] { "blah.meta" }, "Message to display."); + var fileLists = new Dictionary, string>> + { + [string.Empty] = new Tuple, string>( + new[] { "blah.meta" }, "Message to display.") + }; var expected = "\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"blah.meta\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileDescription + "\":\"MyApp File Metadata (XML)\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\""; - Assert.AreEqual(expected, _helper.GetSourceFilesForMetsData(fileLists).ElementAt(0)); + Assert.AreEqual(expected, m_model.GetSourceFilesForMetsData(fileLists).ElementAt(0)); } /// ------------------------------------------------------------------------------------ [Test] public void GetSourceFilesForMetsData_ListContainsGenericSessionFile_ReturnsCorrectMetsData() { - var fileLists = new Dictionary, string>>(); - fileLists[string.Empty] = new Tuple, string>(new[] { "blah.wav" }, "Message to display."); + var fileLists = new Dictionary, string>> + { + [string.Empty] = new Tuple, string>( + new[] { "blah.wav" }, "Message to display.") + }; var expected = "\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"blah.wav\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileDescription + "\":\"MyApp Session File\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\""; - Assert.AreEqual(expected, _helper.GetSourceFilesForMetsData(fileLists).ElementAt(0)); + Assert.AreEqual(expected, m_model.GetSourceFilesForMetsData(fileLists).ElementAt(0)); } /// ------------------------------------------------------------------------------------ [Test] public void GetSourceFilesForMetsData_ListContainsGenericPersonFile_ReturnsCorrectMetsData() { - var fileLists = new Dictionary, string>>(); - fileLists["Carmen"] = new Tuple, string>(new[] { "Carmen_blah.wav" }, "Message to display."); + var fileLists = new Dictionary, string>> + { + ["Carmen"] = new Tuple, string>( + new[] { "Carmen_blah.wav" }, "Message to display.") + }; var expected = "\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"__AppSpecific__Carmen_blah.wav\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileDescription + "\":\"MyApp Contributor File\"" + RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\""; - Assert.AreEqual(expected, _helper.GetSourceFilesForMetsData(fileLists).ElementAt(0)); + Assert.AreEqual(expected, m_model.GetSourceFilesForMetsData(fileLists).ElementAt(0)); } /// ------------------------------------------------------------------------------------ [Test] public void GetSourceFilesForMetsData_ListMultipleFiles_ReturnsCorrectMetsData() { - var fileLists = new Dictionary, string>>(); - fileLists[string.Empty] = new Tuple, string>(new[] { "blah.session", "really cool.wav" }, "Message to display."); - fileLists["person id"] = new Tuple, string>(new[] { "person id_blah.person", "person id_baa.mpg", "person id_baa.mpg.meta" }, "Message to display."); + var fileLists = new Dictionary, string>> + { + [string.Empty] = new Tuple, string>( + new[] { "blah.session", "really cool.wav" }, "Message to display."), + ["person id"] = new Tuple, string>( + new[] { "person id_blah.person", "person id_baa.mpg", "person id_baa.mpg.meta" }, "Message to display.") + }; Assert.AreEqual("\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"blah.session\"" + RampArchivingDlgViewModel.kSeparator + "\"" + @@ -256,7 +281,7 @@ public void GetSourceFilesForMetsData_ListMultipleFiles_ReturnsCorrectMetsData() RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\"", - _helper.GetSourceFilesForMetsData(fileLists).ElementAt(0)); + m_model.GetSourceFilesForMetsData(fileLists).ElementAt(0)); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"really-cool.wav\"" + RampArchivingDlgViewModel.kSeparator + "\"" + @@ -264,7 +289,7 @@ public void GetSourceFilesForMetsData_ListMultipleFiles_ReturnsCorrectMetsData() RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\"", - _helper.GetSourceFilesForMetsData(fileLists).ElementAt(1)); + m_model.GetSourceFilesForMetsData(fileLists).ElementAt(1)); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"__AppSpecific__person-id_blah.person\"" + RampArchivingDlgViewModel.kSeparator + "\"" + @@ -272,7 +297,7 @@ public void GetSourceFilesForMetsData_ListMultipleFiles_ReturnsCorrectMetsData() RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\"", - _helper.GetSourceFilesForMetsData(fileLists).ElementAt(2)); + m_model.GetSourceFilesForMetsData(fileLists).ElementAt(2)); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"__AppSpecific__person-id_baa.mpg\"" + RampArchivingDlgViewModel.kSeparator + "\"" + @@ -280,7 +305,7 @@ public void GetSourceFilesForMetsData_ListMultipleFiles_ReturnsCorrectMetsData() RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\"", - _helper.GetSourceFilesForMetsData(fileLists).ElementAt(3)); + m_model.GetSourceFilesForMetsData(fileLists).ElementAt(3)); Assert.AreEqual("\"" + RampArchivingDlgViewModel.kDefaultKey + "\":\"__AppSpecific__person-id_baa.mpg.meta\"" + RampArchivingDlgViewModel.kSeparator + "\"" + @@ -288,7 +313,7 @@ public void GetSourceFilesForMetsData_ListMultipleFiles_ReturnsCorrectMetsData() RampArchivingDlgViewModel.kSeparator + "\"" + RampArchivingDlgViewModel.kFileRelationship + "\":\"" + RampArchivingDlgViewModel.kRelationshipSource + "\"", - _helper.GetSourceFilesForMetsData(fileLists).ElementAt(4)); + m_model.GetSourceFilesForMetsData(fileLists).ElementAt(4)); } #endregion @@ -297,9 +322,9 @@ public void GetSourceFilesForMetsData_ListMultipleFiles_ReturnsCorrectMetsData() [Test] public void SetAudience_ChangeAudience_ThrowsInvalidOperationException() { - _helper.SetAudience(AudienceType.Vernacular); + m_model.SetAudience(AudienceType.Vernacular); Assert.Throws( - () => _helper.SetAudience(AudienceType.Training) + () => m_model.SetAudience(AudienceType.Training) ); } #endregion @@ -309,9 +334,9 @@ public void SetAudience_ChangeAudience_ThrowsInvalidOperationException() [Test] public void SetVernacularMaterialsAndContentType_IncompatibleWithAudience_ThrowsInvalidOperationException() { - _helper.SetAudience(AudienceType.Training); + m_model.SetAudience(AudienceType.Training); Assert.Throws( - () => _helper.SetVernacularMaterialsAndContentType(VernacularMaterialsType.BibleBackground) + () => m_model.SetVernacularMaterialsAndContentType(VernacularMaterialsType.BibleBackground) ); } @@ -319,9 +344,9 @@ public void SetVernacularMaterialsAndContentType_IncompatibleWithAudience_Throws [Test] public void SetVernacularMaterialsAndContentType_CompatibleWithAudience_IncludedInMetsData() { - _helper.SetAudience(AudienceType.Vernacular); - _helper.SetVernacularMaterialsAndContentType(VernacularMaterialsType.LiteracyEducation_Riddles); - var data = _helper.GetMetadata(); + m_model.SetAudience(AudienceType.Vernacular); + m_model.SetVernacularMaterialsAndContentType(VernacularMaterialsType.LiteracyEducation_Riddles); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kAudience + "\":\"" + RampArchivingDlgViewModel.kAudienceVernacular + "\",\"" + RampArchivingDlgViewModel.kVernacularMaterialsType + "\":\"" + RampArchivingDlgViewModel.kVernacularMaterialGeneral + "\",\"" + @@ -334,7 +359,7 @@ public void SetVernacularMaterialsAndContentType_CompatibleWithAudience_Included public void SetVernacularMaterialsAndContentType_MixOfScriptureAndOther_ThrowsArgumentException() { Assert.Throws( - () => _helper.SetVernacularMaterialsAndContentType(VernacularMaterialsType.BibleStory | VernacularMaterialsType.CommunityAndCulture_Calendar) + () => m_model.SetVernacularMaterialsAndContentType(VernacularMaterialsType.BibleStory | VernacularMaterialsType.CommunityAndCulture_Calendar) ); } #endregion @@ -344,8 +369,8 @@ public void SetVernacularMaterialsAndContentType_MixOfScriptureAndOther_ThrowsAr [Test] public void SetAbstract_SetSingleAbstractWithoutLanguage_IncludedInMetsData() { - _helper.SetAbstract("SayMore doesn't let the user specify the language explicitly.", string.Empty); - var data = _helper.GetMetadata(); + m_model.SetAbstract("SayMore doesn't let the user specify the language explicitly.", string.Empty); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\"," + "\"description.abstract.has\":\"Y\",\"dc.description.abstract\":{" + "\"0\":{\" \":\"SayMore doesn't let the user specify the language explicitly.\"}}}", @@ -361,12 +386,12 @@ public void SetAbstract_SetSingleAbstractWithoutLanguage_IncludedInMetsData() [Test] public void SetAbstract_SetTwice_ThrowsInvalidOperationException() { - _helper.SetAbstract("This is pretty abstract", "eng"); + m_model.SetAbstract("This is pretty abstract", "eng"); Dictionary foreignLanguageAbstracts = new Dictionary(); foreignLanguageAbstracts["fra"] = "C'est assez abstrait"; foreignLanguageAbstracts["spa"] = "Esto es bastante abstracto"; Assert.Throws( - () => _helper.SetAbstract(foreignLanguageAbstracts) + () => m_model.SetAbstract(foreignLanguageAbstracts) ); } @@ -374,7 +399,7 @@ public void SetAbstract_SetTwice_ThrowsInvalidOperationException() [Test] public void SetAbstract_Null_ThrowsArgumentNullException() { - Assert.Throws(() => _helper.SetAbstract(null)); + Assert.Throws(() => m_model.SetAbstract(null)); } /// ------------------------------------------------------------------------------------ @@ -385,8 +410,8 @@ public void SetAbstract_ThreeLanguages_IncludedInMetsData() abstracts["eng"] = "This is pretty abstract"; abstracts["fra"] = "C'est assez abstrait"; abstracts["spa"] = "Esto es bastante abstracto"; - _helper.SetAbstract(abstracts); - var data = _helper.GetMetadata(); + m_model.SetAbstract(abstracts); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\"," + "\"description.abstract.has\":\"Y\",\"dc.description.abstract\":{" + "\"0\":{\" \":\"This is pretty abstract\",\"lang\":\"eng\"}," + @@ -401,8 +426,8 @@ public void SetAbstract_ThreeLanguages_IncludedInMetsData() [Test] public void SetAudioVideoExtent_FreeFormString_IncludedInMetsData() { - _helper.SetAudioVideoExtent("6 and a half seconds"); - var data = _helper.GetMetadata(); + m_model.SetAudioVideoExtent("6 and a half seconds"); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kRecordingExtent + "\":\"6 and a half seconds\"}", data); @@ -413,8 +438,8 @@ public void SetAudioVideoExtent_FreeFormString_IncludedInMetsData() public void SetAudioVideoExtent_ValidTimeSpan_IncludedInMetsData() { TimeSpan duration = new TimeSpan(0, 2, 3, 4); - _helper.SetAudioVideoExtent(duration); - var data = _helper.GetMetadata(); + m_model.SetAudioVideoExtent(duration); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kRecordingExtent + "\":\"02:03:04\"}", data); @@ -424,9 +449,9 @@ public void SetAudioVideoExtent_ValidTimeSpan_IncludedInMetsData() [Test] public void SetAudioVideoExtent_SetTwice_ThrowsInvalidOperationException() { - _helper.SetAudioVideoExtent("twelve years or more"); + m_model.SetAudioVideoExtent("twelve years or more"); TimeSpan duration = new TimeSpan(0, 2, 3, 4); - Assert.Throws(() => _helper.SetAudioVideoExtent(duration)); + Assert.Throws(() => m_model.SetAudioVideoExtent(duration)); } #endregion @@ -441,8 +466,8 @@ public void SetContentLanguages_TwoLanguages_IncludedInMetsData() Assert.Ignore("This test is no longer valid because RAMP 3.0 does not have a languages file"); - _helper.SetContentLanguages("eng", "fra"); - var data = _helper.GetMetadata(); + m_model.SetContentLanguages("eng", "fra"); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kContentLanguages + "\":{\"0\":{\" \":\"eng:English\"},\"1\":{\" \":\"fra:French\"}}}", data); @@ -456,8 +481,8 @@ public void SetContentLanguages_SetTwice_ThrowsInvalidOperationException() { IgnoreTestIfRampIsNotInstalled(); - _helper.SetContentLanguages("eng", "fra"); - Assert.Throws(() => _helper.SetContentLanguages("spa", "fra")); + m_model.SetContentLanguages("eng", "fra"); + Assert.Throws(() => m_model.SetContentLanguages("spa", "fra")); } #endregion @@ -466,17 +491,17 @@ public void SetContentLanguages_SetTwice_ThrowsInvalidOperationException() [Test] public void SetContributors_Null_ThrowsArgumentNullException() { - Assert.Throws(() => _helper.SetContributors(null)); + Assert.Throws(() => m_model.SetContributors(null)); } /// ------------------------------------------------------------------------------------ [Test] public void SetContributors_Empty_NoChangeToMetsData() { - var dataBefore = _helper.GetMetadata(); + var dataBefore = m_model.GetMetadata(); var empty = new ContributionCollection(); - _helper.SetContributors(empty); - var dataAfter = _helper.GetMetadata(); + m_model.SetContributors(empty); + var dataAfter = m_model.GetMetadata(); Assert.AreEqual(dataBefore, dataAfter); } @@ -488,8 +513,8 @@ public void SetContributors_TwoContributors_IncludedInMetsData() OlacSystem olacSystem = new OlacSystem(); contributors.Add(new Contribution("Erkel", olacSystem.GetRoleByCodeOrThrow("author"))); contributors.Add(new Contribution("Sungfu", olacSystem.GetRoleByCodeOrThrow("recorder"))); - _helper.SetContributors(contributors); - var data = _helper.GetMetadata(); + m_model.SetContributors(contributors); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kContributor + "\":{\"0\":{\" \":\"Erkel\",\"role\":\"author\"},\"1\":{\" \":\"Sungfu\",\"role\":\"recorder\"}}}", data); @@ -504,8 +529,8 @@ public void SetContributors_SetTwice_ThrowsInvalidOperationException() Role role = olacSystem.GetRoleByCodeOrThrow("author"); var contrib = new Contribution("Erkel", role); contributors.Add(contrib); - _helper.SetContributors(contributors); - Assert.Throws(() => _helper.SetContributors(contributors)); + m_model.SetContributors(contributors); + Assert.Throws(() => m_model.SetContributors(contributors)); } #endregion @@ -514,8 +539,8 @@ public void SetContributors_SetTwice_ThrowsInvalidOperationException() [Test] public void SetCreationDate_FreeFormString_IncludedInMetsData() { - _helper.SetCreationDate("four years ago"); - var data = _helper.GetMetadata(); + m_model.SetCreationDate("four years ago"); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kDateCreated + "\":\"four years ago\"}", data); @@ -526,8 +551,8 @@ public void SetCreationDate_FreeFormString_IncludedInMetsData() public void SetCreationDate_ValidTimeSpan_IncludedInMetsData() { DateTime creationDate = new DateTime(2012, 4, 13); - _helper.SetCreationDate(creationDate); - var data = _helper.GetMetadata(); + m_model.SetCreationDate(creationDate); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kDateCreated + "\":\"2012-04-13\"}", data); @@ -537,8 +562,8 @@ public void SetCreationDate_ValidTimeSpan_IncludedInMetsData() [Test] public void SetCreationDate_SetTwice_ThrowsInvalidOperationException() { - _helper.SetCreationDate("tomorrow"); - Assert.Throws(() => _helper.SetCreationDate(new DateTime(2012, 4, 13))); + m_model.SetCreationDate("tomorrow"); + Assert.Throws(() => m_model.SetCreationDate(new DateTime(2012, 4, 13))); } #endregion @@ -547,8 +572,8 @@ public void SetCreationDate_SetTwice_ThrowsInvalidOperationException() [Test] public void SetDatasetExtent_FreeFormString_IncludedInMetsData() { - _helper.SetDatasetExtent("6 voice records and maybe an odd text file or two"); - var data = _helper.GetMetadata(); + m_model.SetDatasetExtent("6 voice records and maybe an odd text file or two"); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kDatasetExtent + "\":\"6 voice records and maybe an odd text file or two\"}", data); @@ -558,8 +583,8 @@ public void SetDatasetExtent_FreeFormString_IncludedInMetsData() [Test] public void SetDatasetExtent_SetTwice_ThrowsInvalidOperationException() { - _helper.SetDatasetExtent("practically nothing"); - Assert.Throws(() => _helper.SetDatasetExtent("lots of data")); + m_model.SetDatasetExtent("practically nothing"); + Assert.Throws(() => m_model.SetDatasetExtent("lots of data")); } #endregion @@ -568,16 +593,16 @@ public void SetDatasetExtent_SetTwice_ThrowsInvalidOperationException() [Test] public void SetDescription_Null_ThrowsArgumentNullException() { - Assert.Throws(() => _helper.SetDescription(null)); + Assert.Throws(() => m_model.SetDescription(null)); } /// ------------------------------------------------------------------------------------ [Test] public void SetDescription_Empty_NoChangeToMetsData() { - var dataBefore = _helper.GetMetadata(); - _helper.SetDescription(new Dictionary()); - var dataAfter = _helper.GetMetadata(); + var dataBefore = m_model.GetMetadata(); + m_model.SetDescription(new Dictionary()); + var dataAfter = m_model.GetMetadata(); Assert.AreEqual(dataBefore, dataAfter); } @@ -588,8 +613,8 @@ public void SetDescription_TwoLanguages_IncludedInMetsData() var descriptions = new Dictionary(); descriptions["eng"] = "General data"; descriptions["spa"] = "Datos generales"; - _helper.SetDescription(descriptions); - var data = _helper.GetMetadata(); + m_model.SetDescription(descriptions); + var data = m_model.GetMetadata(); Assert.AreEqual("{\"dc.title\":\"Test Title\",\"" + RampArchivingDlgViewModel.kFlagHasGeneralDescription + "\":\"Y\",\"" + RampArchivingDlgViewModel.kGeneralDescription + "\":{\"0\":{\" \":\"General data\",\"lang\":\"eng\"},\"1\":{\" \":\"Datos generales\",\"lang\":\"spa\"}}}", data); @@ -601,8 +626,8 @@ public void SetDescription_SetTwice_ThrowsInvalidOperationException() { var descriptions = new Dictionary(); descriptions["eng"] = "General data"; - _helper.SetDescription(descriptions); - Assert.Throws(() => _helper.SetDescription(descriptions)); + m_model.SetDescription(descriptions); + Assert.Throws(() => m_model.SetDescription(descriptions)); } #endregion @@ -627,7 +652,7 @@ public void GetLanguageName_English_ReturnsEnglish() Assert.Ignore("This test is no longer valid because RAMP 3.0 does not have a languages file"); - var langName = _helper.GetLanguageName("eng"); + var langName = m_model.GetLanguageName("eng"); Assert.AreEqual(langName, "English"); } @@ -639,7 +664,7 @@ public void GetLanguageName_Gibberish_ReturnsNull() { IgnoreTestIfRampIsNotInstalled(); - var langName = _helper.GetLanguageName("z23"); + var langName = m_model.GetLanguageName("z23"); Assert.IsNull(langName); } @@ -655,8 +680,8 @@ public void GetLanguageName_ArchivingLanguage_ReturnsCorrectName() // FieldWorks associates the name "Chinese" with the ISO3 Code "cmn" ArchivingLanguage lang = new ArchivingLanguage("cmn", "Chinese"); - // RAMP reqires the name "Chinese, Mandarin" - Assert.AreEqual("Chinese, Mandarin", _helper.GetLanguageName(lang.Iso3Code)); + // RAMP requires the name "Chinese, Mandarin" + Assert.AreEqual("Chinese, Mandarin", m_model.GetLanguageName(lang.Iso3Code)); } /// ------------------------------------------------------------------------------------ @@ -673,9 +698,9 @@ public void GetRAMPFileLocation_RAMPInstalled_ReturnsFileLocation() #region Private helper methods /// ------------------------------------------------------------------------------------ - private void SetFilesToArchive(ArchivingDlgViewModel model) + private void SetFilesToArchive(ArchivingDlgViewModel model, CancellationToken cancellationToken) { - foreach (var kvp in _filesToAdd) + foreach (var kvp in m_filesToAdd) model.AddFileGroup(kvp.Key, kvp.Value.Item1, kvp.Value.Item2); } @@ -703,14 +728,11 @@ private void CustomFilenameNormalization(string key, string file, StringBuilder private void IgnoreTestIfRampIsNotInstalled() { - if (!_isRampInstalled.HasValue) - { - // we remember the value so that we check only once. This won't change within - // a test run. - _isRampInstalled = !string.IsNullOrEmpty(RampArchivingDlgViewModel.GetExeFileLocation()); - } + // we remember the value so that we check only once. This won't change within + // a test run. + m_isRampInstalled ??= !string.IsNullOrEmpty(RampArchivingDlgViewModel.GetExeFileLocation()); - if (!_isRampInstalled.Value) + if (!m_isRampInstalled.Value) Assert.Ignore("This test requires RAMP"); } #endregion diff --git a/SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj b/SIL.Archiving.Tests/SIL.Archiving.Tests.csproj similarity index 68% rename from SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj rename to SIL.Archiving.Tests/SIL.Archiving.Tests.csproj index 147b53352..625bf04e9 100644 --- a/SIL.Windows.Forms.Archiving.Tests/SIL.Windows.Forms.Archiving.Tests.csproj +++ b/SIL.Archiving.Tests/SIL.Archiving.Tests.csproj @@ -1,9 +1,9 @@ - SIL.Windows.Forms.Archiving.Tests - SIL.Windows.Forms.Archiving.Tests - Unit tests for SIL.Windows.Forms.Archiving + SIL.Archiving.Tests + SIL.Archiving.Tests + Unit tests for SIL.Archiving false true true @@ -17,11 +17,10 @@ - + - \ No newline at end of file diff --git a/SIL.Windows.Forms.Archiving.Tests/SimpleObjectTests.cs b/SIL.Archiving.Tests/SimpleObjectTests.cs similarity index 85% rename from SIL.Windows.Forms.Archiving.Tests/SimpleObjectTests.cs rename to SIL.Archiving.Tests/SimpleObjectTests.cs index 6ab8d0fd3..bb9082c86 100644 --- a/SIL.Windows.Forms.Archiving.Tests/SimpleObjectTests.cs +++ b/SIL.Archiving.Tests/SimpleObjectTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; -using SIL.Windows.Forms.Archiving.Generic; +using SIL.Archiving.Generic; -namespace SIL.Windows.Forms.Archiving.Tests +namespace SIL.Archiving.Tests { [TestFixture] [Category("Archiving")] @@ -35,8 +35,8 @@ public void LanguageStringComparer_CorrectlyComparesLanguageStrings() [Test] public void ToLatinOnly_MultiplePeriod_OnePeriod() { - var result = "Langauge.wav.meta".ToLatinOnly("_", "+", "."); - Assert.AreEqual("Langauge_wav.meta", result); + var result = "Language.wav.meta".ToLatinOnly("_", "+", "."); + Assert.AreEqual("Language_wav.meta", result); } } } diff --git a/SIL.Archiving.Tests/TestProgress.cs b/SIL.Archiving.Tests/TestProgress.cs new file mode 100644 index 000000000..d94d32ffb --- /dev/null +++ b/SIL.Archiving.Tests/TestProgress.cs @@ -0,0 +1,23 @@ +namespace SIL.Archiving.Tests +{ + internal class TestProgress : IArchivingProgressDisplay + { + public int Step { get; private set; } = 0; + public string ArchiveTypeName { get; } + + internal TestProgress(string type) + { + ArchiveTypeName = $"{type} (Test)"; + } + + public void IncrementProgress() + { + Step++; + } + + public string GetMessage(ArchivingDlgViewModel.StringId msgId) + { + return $"Test implementation message for {msgId}"; + } + } +} diff --git a/SIL.Archiving/App.config b/SIL.Archiving/App.config new file mode 100644 index 000000000..4bfe07ada --- /dev/null +++ b/SIL.Archiving/App.config @@ -0,0 +1,21 @@ + + + + +
+ + + + + + http://www.mpi.nl/imdi/ + + + https://gateway.sil.org/display/RH/RAMP+Users%27+Manual + + + author;compiler;consultant;developer;editor;facilitator;illustrator;interviewer;photographer;recorder;researcher;signer;speaker;transcriber;translator + + + + \ No newline at end of file diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlgViewModel.cs b/SIL.Archiving/ArchivingDlgViewModel.cs similarity index 68% rename from SIL.Windows.Forms.Archiving/ArchivingDlgViewModel.cs rename to SIL.Archiving/ArchivingDlgViewModel.cs index 7385c75de..580cb360c 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlgViewModel.cs +++ b/SIL.Archiving/ArchivingDlgViewModel.cs @@ -1,22 +1,32 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; -using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; using JetBrains.Annotations; -using L10NSharp; -using SIL.Windows.Forms.Archiving.Generic; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI.Lists; using SIL.Code; +using SIL.EventsAndDelegates; using SIL.IO; +using static System.String; +// ReSharper disable InconsistentNaming -namespace SIL.Windows.Forms.Archiving +namespace SIL.Archiving { /// ------------------------------------------------------------------------------------ - public abstract class ArchivingDlgViewModel + public abstract class ArchivingDlgViewModel : IDisposable { + public enum Standard + { + REAP, + IMDI, + Other, + } + [Flags] protected enum MetadataProperties { @@ -41,14 +51,12 @@ protected enum MetadataProperties } #region Data members - protected readonly string _id; // ID/Name of the top-level element being archived (can be either a session or a project) - protected readonly string _appSpecificArchivalProcessInfo; - protected readonly Dictionary _titles = new Dictionary(); //Titles of elements being archived (keyed by element id) + private readonly string _id; // ID/Name of the top-level element being archived (can be either a session or a project) + private readonly Dictionary _titles = new Dictionary(); //Titles of elements being archived (keyed by element id) private readonly Dictionary _propertiesSet = new Dictionary(); // Metadata properties that have been set (keyed by element id) - private readonly Action _setFilesToArchive; + private readonly Action _setFilesToArchive; + private readonly Dictionary, string>> _fileLists = new Dictionary, string>>(); - protected bool _cancelProcess; - protected readonly Dictionary _progressMessages = new Dictionary(); /// /// Keyed and grouped according to whatever logical grouping makes sense in the /// calling application. The key for each group will be supplied back to the calling app @@ -56,11 +64,30 @@ protected enum MetadataProperties /// enumerable list of files to include, and Item2 contains a progress message to be /// displayed when that group of files is being processed. /// - protected IDictionary, string>> _fileLists = new Dictionary, string>>(); - protected BackgroundWorker _worker; + protected IDictionary, string>> FileLists => _fileLists; #endregion #region Delegates and Events + /// ------------------------------------------------------------------------------------ + public enum StringId + { + PreArchivingStatus, + SearchingForArchiveUploadingProgram, + ArchiveUploadingProgramNotFound, + ErrorStartingArchivalProgram, + PreparingFiles, + SavingFilesInPackage, + FileExcludedFromPackage, + PathNotWritable, + ReadyToCallRampMsg, + ErrorCreatingArchive, + IMDIActorsGroup, + CopyingFiles, + FailedToMakePackage, + ErrorCreatingMetsFile, + RampPackageRemoved + } + /// ------------------------------------------------------------------------------------ public enum MessageType { @@ -84,40 +111,48 @@ public enum MessageType Volatile, } - /// Delegate for OnDisplayMessage event + /// Delegate for event /// Message to display - /// Type of message (which handler can use to determine appropriate color, style, indentation, etc. - public delegate void DisplayMessageEventHandler(string msg, MessageType type); + /// Type of message (which handler can use to determine appropriate + /// presentation formatting to use). + public delegate void MessageEventHandler(string msg, MessageType type); /// - /// Notifiers subscribers of a message to display. + /// Notifies subscribers of a message to display. /// - public event DisplayMessageEventHandler OnDisplayMessage; + public event MessageEventHandler OnReportMessage; - /// Delegate for DisplayError event - /// Message to display + /// Delegate for event + /// Error message to display /// Title of package being created /// Exception (can be null) - public delegate void DisplayErrorEventHandler(string msg, string packageTitle, Exception e); + public delegate void ErrorEventHandler(string msg, string packageTitle, Exception e); /// /// Notifiers subscribers of an error message to report. /// - public event DisplayErrorEventHandler OnDisplayError; + public event ErrorEventHandler OnError; + + /// Delegate for event + /// Event args that hold the exception that occurred + public delegate void ExceptionHandler(EventArgs args); + + /// + /// Notifies subscribers of an exception thrown during launch of archive uploader program. + /// + public event ExceptionHandler OnExceptionDuringLaunch; - /// Action raised when progress happens - public Action IncrementProgressBarAction { protected get; set; } + protected IArchivingProgressDisplay Progress { get; private set; } #endregion #region properties + protected string PackageId => _id; + protected string PackageTitle => _titles[_id]; + /// ------------------------------------------------------------------------------------ - /// - /// Short name/description of the archiving program or standard used for this type of - /// archiving. (Should fit in the frame "Archive using ___".) - /// - /// ------------------------------------------------------------------------------------ - internal abstract string ArchiveType { get; } + public abstract Standard ArchiveType { get; } + /// ------------------------------------------------------------------------------------ /// /// Short name of the archiving program to launch once package is created. @@ -125,16 +160,6 @@ public enum MessageType /// ------------------------------------------------------------------------------------ public abstract string NameOfProgramToLaunch { get; } - /// ------------------------------------------------------------------------------------ - public abstract string InformativeText { get; } - - /// ------------------------------------------------------------------------------------ - /// - /// Implement ArchiveInfoHyperlinkText to define text (first occurrence only) in the - /// InformativeText that will be marked as a hyperlink to ArchiveInfoUrl. - /// - /// ------------------------------------------------------------------------------------ - public abstract string ArchiveInfoHyperlinkText { get; } /// ------------------------------------------------------------------------------------ public abstract string ArchiveInfoUrl { get; } @@ -145,11 +170,12 @@ public enum MessageType /// ------------------------------------------------------------------------------------ /// Path to the generated package + /// This is also returned by CreatePackage if successful. /// ------------------------------------------------------------------------------------ public string PackagePath { get; protected set; } /// ------------------------------------------------------------------------------------ - public string AppName { get; private set; } + public string AppName { get; } /// ------------------------------------------------------------------------------------ public bool IsBusy { get; protected set; } @@ -188,7 +214,7 @@ public enum MessageType /// the application implements this, then the default summary display will be suppressed. /// /// ------------------------------------------------------------------------------------ - public Action, string>>> OverrideDisplayInitialSummary { private get; set; } + public Action, string>>, CancellationToken> OverrideDisplayInitialSummary { private get; set; } #endregion #region construction and initialization @@ -197,54 +223,40 @@ public enum MessageType /// The application name /// Title of the submission /// Identifier (used as filename) for the package being created - /// Application can use this to pass - /// additional information that will be displayed to the user in the dialog to explain - /// any application-specific details about the archival process. /// Delegate to request client to call methods to set /// which files should be archived (this is deferred to allow display of progress message) /// ------------------------------------------------------------------------------------ protected ArchivingDlgViewModel(string appName, string title, string id, - string appSpecificArchivalProcessInfo, Action setFilesToArchive) + Action setFilesToArchive) { - if (appName == null) - throw new ArgumentNullException("appName"); - AppName = appName; - if (title == null) - throw new ArgumentNullException("title"); - if (id == null) - throw new ArgumentNullException("id"); - _id = id; - _appSpecificArchivalProcessInfo = appSpecificArchivalProcessInfo; + AppName = appName ?? throw new ArgumentNullException(nameof(appName)); + _id = id ?? throw new ArgumentNullException(nameof(id)); _setFilesToArchive = setFilesToArchive; - _titles[id] = title; + _titles[id] = title ?? throw new ArgumentNullException(nameof(title)); _propertiesSet[id] = MetadataProperties.Title; AdditionalMessages = new Dictionary(); } /// ------------------------------------------------------------------------------------ - public bool Initialize() + public async Task Initialize(IArchivingProgressDisplay progress, CancellationToken cancellationToken) { - IsBusy = true; + Progress = progress ?? throw new ArgumentNullException(nameof(progress)); + + if (!DoArchiveSpecificInitialization()) + return false; - try - { - if (!DoArchiveSpecificInitialization()) - return false; + await SetFilesToArchive(cancellationToken); + DisplayInitialSummary(cancellationToken); - _setFilesToArchive(this); - foreach (var fileList in _fileLists.Where(fileList => fileList.Value.Item1.Any())) - { - string normalizedName = NormalizeFilename(fileList.Key, Path.GetFileName(fileList.Value.Item1.First())); - _progressMessages[normalizedName] = fileList.Value.Item2; - } - DisplayInitialSummary(); + return true; + } - return true; - } - finally + private async Task SetFilesToArchive(CancellationToken cancellationToken) + { + await Task.Run(() => { - IsBusy = false; - } + _setFilesToArchive(this, cancellationToken); + }); } /// ------------------------------------------------------------------------------------ @@ -257,29 +269,31 @@ public bool Initialize() public virtual void AddFileGroup(string groupId, IEnumerable files, string progressMessage) { Guard.AgainstNull(groupId, nameof(groupId)); - if (_fileLists.ContainsKey(groupId)) + if (FileLists.ContainsKey(groupId)) throw new ArgumentException("Duplicate file group ID: " + groupId, nameof(groupId)); - _fileLists[groupId] = Tuple.Create(files, progressMessage); + FileLists[groupId] = Tuple.Create(files, progressMessage); } /// ------------------------------------------------------------------------------------ - private void DisplayInitialSummary() + private void DisplayInitialSummary(CancellationToken cancellationToken) { if (OverrideDisplayInitialSummary != null) - OverrideDisplayInitialSummary(_fileLists); - else if (OnDisplayMessage != null) + OverrideDisplayInitialSummary(FileLists, cancellationToken); + else { - OnDisplayMessage(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.PrearchivingStatusMsg", - "The following files will be added to the archive:"), MessageType.Normal); + ReportProgress(Progress.GetMessage(StringId.PreArchivingStatus), MessageType.Normal, cancellationToken); - foreach (var kvp in _fileLists) + if (OnReportMessage != null) { - string msg = FileGroupDisplayMessage(kvp.Key); - if (msg != string.Empty) - OnDisplayMessage(msg, MessageType.Indented); + foreach (var kvp in FileLists) + { + string msg = FileGroupDisplayMessage(kvp.Key); + if (msg != Empty) + OnReportMessage(msg, MessageType.Indented); - foreach (var file in kvp.Value.Item1) - OnDisplayMessage(Path.GetFileName(file), MessageType.Bullet); + foreach (var file in kvp.Value.Item1) + OnReportMessage(Path.GetFileName(file), MessageType.Bullet); + } } } } @@ -318,7 +332,7 @@ protected void PreventDuplicateMetadataProperty(string elementId, MetadataProper if (_propertiesSet.TryGetValue(elementId, out var propertiesSet)) { if (propertiesSet.HasFlag(property)) - throw new InvalidOperationException(string.Format("{0} has already been set", property.ToString())); + throw new InvalidOperationException($"{property} has already been set"); _propertiesSet[elementId] |= property; } else @@ -400,15 +414,16 @@ public void SetAbstract(string description, string language) public void SetAbstract(IDictionary descriptions) { if (descriptions == null) - throw new ArgumentNullException("descriptions"); + throw new ArgumentNullException(nameof(descriptions)); if (descriptions.Count == 0) return; if (descriptions.Count > 1) { - if (descriptions.Keys.Any(k => k.Length != 3)) - throw new ArgumentException(); + var invalidLanguageCode = descriptions.Keys.FirstOrDefault(k => k.Length != 3); + if (invalidLanguageCode != null) + throw new InvalidLanguageCodeException(invalidLanguageCode); } PreventDuplicateMetadataProperty(MetadataProperties.AbstractDescription); SetAbstract_Impl(descriptions); @@ -423,49 +438,107 @@ public void SetAbstract(IDictionary descriptions) #endregion /// ------------------------------------------------------------------------------------ - public void DisplayMessage(string msg, MessageType type) + protected void DisplayMessage(StringId msgId, MessageType type, params object[] fmtParams) { - if (OnDisplayMessage != null) - OnDisplayMessage(msg, type); + if (OnReportMessage != null) + { + var msg = Progress.GetMessage(msgId); + if (fmtParams?.Length > 0) + msg = Format(msg, fmtParams); + if (msg != null) + OnReportMessage(msg, type); + } } /// ------------------------------------------------------------------------------------ - [PublicAPI] - public abstract string GetMetadata(); + protected void DisplayMessage(string msg, MessageType type) + { + OnReportMessage?.Invoke(msg, type); + } /// ------------------------------------------------------------------------------------ - internal abstract void LaunchArchivingProgram(); + [PublicAPI] + public abstract string GetMetadata(); /// ------------------------------------------------------------------------------------ - protected void LaunchArchivingProgram(Action HandleInvalidOperation) + public virtual void LaunchArchivingProgram() { - if (string.IsNullOrEmpty(PathToProgramToLaunch) || !File.Exists(PathToProgramToLaunch)) + if (IsNullOrEmpty(PathToProgramToLaunch) || !File.Exists(PathToProgramToLaunch)) return; + var prs = new Process(); + prs.StartInfo.FileName = PathToProgramToLaunch; + if (!IsNullOrEmpty(PackagePath)) + prs.StartInfo.Arguments = "\"" + PackagePath + "\""; + LaunchArchivingProgram(prs); + } + + /// ------------------------------------------------------------------------------------ + protected void LaunchArchivingProgram(Process prs) + { try { - var prs = new Process(); - prs.StartInfo.FileName = PathToProgramToLaunch; - if (!string.IsNullOrEmpty(PackagePath)) - prs.StartInfo.Arguments = "\"" + PackagePath + "\""; prs.Start(); } catch (Exception e) { - if (e is InvalidOperationException && HandleInvalidOperation != null) - HandleInvalidOperation(); - else - { - ReportError(e, string.Format(LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.StartingRampErrorMsg", - "There was an error attempting to open the archive package in {0}."), - PathToProgramToLaunch)); - } + OnExceptionDuringLaunch?.Invoke(new EventArgs(e)); + + ReportError(e, Progress.GetMessage(StringId.ErrorStartingArchivalProgram)); + } + } + + /// ------------------------------------------------------------------------------------ + /// Creates the archiving package asynchronously + /// A task, which when completed, provides the "result" (typically a file path); + /// or null if package creation failed. + /// + /// ------------------------------------------------------------------------------------ + public abstract Task CreatePackage(CancellationToken cancellationToken); + + /// ------------------------------------------------------------------------------------ + /// Report archiving progress at a major (success) point and check to see if + /// user has requested cancellation + /// ------------------------------------------------------------------------------------ + protected void ReportMajorProgressPoint(StringId id, CancellationToken cancellationToken, + bool isAtCancelablePoint = true) + { + ReportProgress(Progress.GetMessage(id), MessageType.Success, cancellationToken, + isAtCancelablePoint); + } + + /// ------------------------------------------------------------------------------------ + /// Report archiving progress and check to see if user has requested + /// cancellation + /// ------------------------------------------------------------------------------------ + protected void ReportProgress(string message, MessageType type, + CancellationToken cancellationToken, bool isAtCancelablePoint = true) + { + if (cancellationToken.IsCancellationRequested) + { + if (!isAtCancelablePoint) + return; + CleanUp(); + throw new OperationCanceledException(); } + + DisplayMessage(message, type); + Progress.IncrementProgress(); + } + + public virtual void Dispose() + { + CleanUp(); } /// ------------------------------------------------------------------------------------ - public abstract bool CreatePackage(); + /// Performs any needed clean-up after creating a package or when creation is + /// canceled + /// ------------------------------------------------------------------------------------ + protected internal virtual void CleanUp() + { + // delete temp files, etc. + } /// ------------------------------------------------------------------------------------ protected virtual StringBuilder DoArchiveSpecificFilenameNormalization(string key, string fileName) @@ -483,7 +556,7 @@ public virtual string NormalizeFilename(string key, string fileName) } /// ------------------------------------------------------------------------------------ - const int CopyBufferSize = 64 * 1024; + private const int kCopyBufferSize = 64 * 1024; /// ------------------------------------------------------------------------------------ protected static void CopyFile(string src, string dest) { @@ -491,9 +564,9 @@ protected static void CopyFile(string src, string dest) { using (var inputFile = File.OpenRead(src)) { - var buffer = new byte[CopyBufferSize]; + var buffer = new byte[kCopyBufferSize]; int bytesRead; - while ((bytesRead = inputFile.Read(buffer, 0, CopyBufferSize)) != 0) + while ((bytesRead = inputFile.Read(buffer, 0, kCopyBufferSize)) != 0) { outputFile.Write(buffer, 0, bytesRead); } @@ -501,55 +574,19 @@ protected static void CopyFile(string src, string dest) } } - /// ------------------------------------------------------------------------------------ - public virtual void Cancel() - { - if (_cancelProcess) - return; - - _cancelProcess = true; - - if (_worker != null) - { - DisplayMessage(Environment.NewLine + LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.CancellingMsg", "Canceling..."), MessageType.Error); - - _worker.CancelAsync(); - while (_worker.IsBusy) - Application.DoEvents(); - } - } - /// ------------------------------------------------------------------------------------ protected void ReportError(Exception e, string msg) { - if (OnDisplayError != null) - OnDisplayError(msg, _titles[_id], e); + if (OnError != null) + OnError(msg, _titles[_id], e); else if (e != null) throw e; - if (HandleNonFatalError != null) - HandleNonFatalError(e, msg); + HandleNonFatalError?.Invoke(e, msg); } - protected string PreparingFilesMsg => LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.PreparingFilesMsg", "Analyzing component files"); - - protected string GetSavingFilesMsg(string type) - { - return string.Format(LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.SavingFilesInPackageMsg", - "Saving files in {0} package", - "Parameter is the type of archive (e.g., RAMP/IMDI)"), type); - } - - protected string GetFileExcludedMsg(string type, string file) - { - return string.Format(LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.FileExcludedFromPackage", - "File excluded from {0} package: ", - "Parameter is the type of archive (e.g., RAMP/IMDI)"), type) + file; - } + protected string GetFileExcludedMsg(string file) => + Progress.GetMessage(StringId.FileExcludedFromPackage) + file; /// ------------------------------------------------------------------------------------ /// @@ -568,7 +605,7 @@ protected string GetFileExcludedMsg(string type, string file) public abstract IArchivingPackage ArchivingPackage { get; } /// - public Dictionary AdditionalMessages { get; private set; } + public Dictionary AdditionalMessages { get; } public bool IsPathWritable(string directory) { @@ -579,15 +616,11 @@ public bool IsPathWritable(string directory) } catch (Exception e) { - DisplayMessage(e.Message, MessageType.Warning); + OnReportMessage?.Invoke(e.Message, MessageType.Warning); return false; } - var msg = LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.PathNotWritableMsg", - "The path is not writable: {0}"); - - DisplayMessage(string.Format(msg, directory), MessageType.Warning); + DisplayMessage(StringId.PathNotWritable, MessageType.Warning, directory); return false; } diff --git a/SIL.Windows.Forms.Archiving/ArchivingEnumerations.cs b/SIL.Archiving/ArchivingEnumerations.cs similarity index 99% rename from SIL.Windows.Forms.Archiving/ArchivingEnumerations.cs rename to SIL.Archiving/ArchivingEnumerations.cs index 60fe7c413..948fa25e6 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingEnumerations.cs +++ b/SIL.Archiving/ArchivingEnumerations.cs @@ -1,9 +1,9 @@ -using System; +using System; // ReSharper disable CSharpWarnings::CS1591 // ReSharper disable InconsistentNaming -namespace SIL.Windows.Forms.Archiving +namespace SIL.Archiving { /// /// For use with SetAudience method. Note: Both 'Internal audience' and 'Wider audience' works are expected to be in a @@ -48,7 +48,7 @@ public enum AudienceType /// the Scripture Part (specific testaments/books included). /// [Flags] - public enum VernacularMaterialsType : ulong + public enum VernacularMaterialsType : long { // First two bits determine the overall vernacular materials type. Only one of these may be set. Remaining // bits indicate specific content. @@ -225,7 +225,7 @@ public enum ScholarlyWorkType /// Domains to which a resource relates http://purl.org/net/sword-types/SIL/metadata/dc/subject/silDomain /// [Flags] - public enum SilDomain : ulong + public enum SilDomain : long { // Academic domains diff --git a/SIL.Windows.Forms.Archiving/ArchivingLanguage.cs b/SIL.Archiving/ArchivingLanguage.cs similarity index 73% rename from SIL.Windows.Forms.Archiving/ArchivingLanguage.cs rename to SIL.Archiving/ArchivingLanguage.cs index 3d48b59f0..f51780029 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingLanguage.cs +++ b/SIL.Archiving/ArchivingLanguage.cs @@ -2,15 +2,16 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using JetBrains.Annotations; using SIL.WritingSystems; -namespace SIL.Windows.Forms.Archiving +namespace SIL.Archiving { /// public class ArchivingLanguage : IComparable { - protected string _iso3Code; // ex. "eng" - protected string _englishName; // ex. "English" + private string m_iso3Code; // ex. "eng" + private string m_englishName; // ex. "English" /// public ArchivingLanguage(string iso3Code) @@ -26,6 +27,7 @@ public ArchivingLanguage(string iso3Code, string languageName) } /// + [PublicAPI] public ArchivingLanguage(string iso3Code, string languageName, string englishName) { LanguageName = languageName; @@ -39,8 +41,8 @@ public ArchivingLanguage(string iso3Code, string languageName, string englishNam /// public string Iso3Code { - get { return _iso3Code; } - set { _iso3Code = value.ToLower(); } + get => m_iso3Code; + set => m_iso3Code = value.ToLower(); } /// @@ -48,13 +50,13 @@ public string EnglishName { get { - if (string.IsNullOrEmpty(_englishName)) + if (string.IsNullOrEmpty(m_englishName)) { var returnVal = string.Empty; // look for the language name in culture info var culture = CultureInfo.GetCultures(CultureTypes.AllCultures).FirstOrDefault( - c => c.ThreeLetterISOLanguageName == _iso3Code); + c => c.ThreeLetterISOLanguageName == m_iso3Code); if (culture != null) { @@ -62,7 +64,7 @@ public string EnglishName // The name returned first might be something like "English (United States)," so // search the parent cultures for the base culture which will return "English." - while ((culture.Parent.ThreeLetterISOLanguageName == _iso3Code) + while ((culture.Parent.ThreeLetterISOLanguageName == m_iso3Code) && (culture.Parent.ThreeLetterISOLanguageName != "ivl")) { culture = culture.Parent; @@ -70,26 +72,30 @@ public string EnglishName } } - _englishName = returnVal; + m_englishName = returnVal; } - if (string.IsNullOrEmpty(_englishName)) + if (string.IsNullOrEmpty(m_englishName)) { // Not very efficient, but this is not very performance-critical. // And it's undesirable to crash if someone uses a language that's not windows-standard. // It's not guaranteed that DesiredName is an English name, but it's the best we can do AFAIK. var lookup = new LanguageLookup(); - var lang = lookup.GetLanguageFromCode(_iso3Code); - _englishName = lang?.DesiredName; + var lang = lookup.GetLanguageFromCode(m_iso3Code); + m_englishName = lang?.DesiredName; } // throw an exception if no name is found - if (string.IsNullOrEmpty(_englishName)) - throw new CultureNotFoundException(string.Format("Could not determine the language for ISO3 code \"{0}.\" Perhaps you need to set the EnglishName value explicitly.", _iso3Code)); + if (string.IsNullOrEmpty(m_englishName)) + { + throw new CultureNotFoundException( + $"Could not determine the language for ISO3 code \"{m_iso3Code}.\" " + + $"Perhaps you need to set the {nameof(EnglishName)} value explicitly."); + } - return _englishName; + return m_englishName; } - set { _englishName = value; } + set => m_englishName = value; } /// The script used for the Subject Language. Ex. "Latn:Latin" @@ -98,26 +104,26 @@ public string EnglishName /// The dialect used for the language. Ex. "03035:Standard; deu" public string Dialect { get; set; } - /// Compare 2 ArchivingLanguage objects. They are identical if they have the same Iso3Code and LanguageName + /// Compare an ArchivingLanguage to an object. They are identical if the object + /// is an ArchivingLanguage with the same Iso3Code and LanguageName public int CompareTo(object obj) { if (obj == null) return 1; - ArchivingLanguage other = obj as ArchivingLanguage; - - if (other == null) + if (!(obj is ArchivingLanguage other)) throw new ArgumentException(); // first compare the Iso3Code - int result = String.Compare(Iso3Code, other.Iso3Code, StringComparison.Ordinal); + int result = string.Compare(Iso3Code, other.Iso3Code, StringComparison.Ordinal); if (result != 0) return result; // if the same Iso3Code, compare the LanguageName return String.Compare(LanguageName, other.LanguageName, StringComparison.Ordinal); } - /// Compare 2 LanguageString objects. They are identical if they have the same Iso3LanguageId + /// Compare 2 ArchivingLanguage objects. They are identical if they have the same + /// Iso3Code and LanguageName public static int Compare(ArchivingLanguage langA, ArchivingLanguage langB) { return langA.CompareTo(langB); diff --git a/SIL.Windows.Forms.Archiving/ArchivingPrograms.cs b/SIL.Archiving/ArchivingPrograms.cs similarity index 89% rename from SIL.Windows.Forms.Archiving/ArchivingPrograms.cs rename to SIL.Archiving/ArchivingPrograms.cs index dd6519037..5e6b60089 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingPrograms.cs +++ b/SIL.Archiving/ArchivingPrograms.cs @@ -1,22 +1,25 @@ -using System.IO; +using System.IO; using System.Linq; +using JetBrains.Annotations; using SIL.IO; -namespace SIL.Windows.Forms.Archiving +namespace SIL.Archiving { /// public static class ArchivingPrograms { /// Is RAMP installed on this computer + [PublicAPI] public static bool RampIsInstalled() { - return (GetRampExeFileLocation() != null); + return GetRampExeFileLocation() != null; } /// Is Arbil installed on this computer + [PublicAPI] public static bool ArbilIsInstalled() { - return (GetArbilExeFileLocation() != null); + return GetArbilExeFileLocation() != null; } /// Get the path and file name of the RAMP executable file @@ -74,9 +77,6 @@ private static string FindArbilJarFileMono() } /// Command line parameters use to launch Arbil in Linux - public static string ArbilCommandLineArgs - { - get { return "-Xms256m -Xmx1024m -jar \"{0}\""; } - } + public static string ArbilCommandLineArgs => "-Xms256m -Xmx1024m -jar \"{0}\""; } } diff --git a/SIL.Windows.Forms.Archiving/Extensions.cs b/SIL.Archiving/Extensions.cs similarity index 59% rename from SIL.Windows.Forms.Archiving/Extensions.cs rename to SIL.Archiving/Extensions.cs index 505868677..ae4b86775 100644 --- a/SIL.Windows.Forms.Archiving/Extensions.cs +++ b/SIL.Archiving/Extensions.cs @@ -1,88 +1,15 @@ using System; using System.Globalization; using System.Text; -using System.Windows.Forms; -namespace SIL.Windows.Forms.Archiving +namespace SIL.Archiving { /// ------------------------------------------------------------------------------------ public static class Extensions { /// ------------------------------------------------------------------------------------ /// - /// Used to size a link label in mono because it is not working at all - /// - /// - /// ------------------------------------------------------------------------------------ - public static void SizeToContents(this LinkLabel linkLabel) - { - var w = linkLabel.ClientSize.Width; - - using (var g = linkLabel.CreateGraphics()) - { - - if (ArchivingDlgViewModel.IsMono) - { - // split at the existing like breaks - var segments = linkLabel.Text.Replace("\r", "").Split(new[] {'\n'}, StringSplitOptions.None); - var newText = new StringBuilder(); - - foreach (var segment in segments) - { - var thisSegment = segment.Trim(); - - while (MeasureText(linkLabel, g, thisSegment, linkLabel.Font).Width > w) - { - var line = string.Empty; - var lastSpace = 0; - - for (var i = 0; i < thisSegment.Length; i++) - { - if (char.IsWhiteSpace(thisSegment[i])) - { - if (MeasureText(linkLabel, g, line, linkLabel.Font).Width > w) - { - newText.AppendLine(thisSegment.Substring(0, lastSpace)); - thisSegment = thisSegment.Substring(lastSpace + 1); - break; - } - - lastSpace = i; - } - line += thisSegment[i]; - } - } - - // check for left-overs - if (thisSegment.Length > 0) - newText.AppendLine(thisSegment); - } - - linkLabel.Text = newText.ToString(); - } - - var size = MeasureText(linkLabel, g, linkLabel.Text, linkLabel.Font, new System.Drawing.Size(w, Int32.MaxValue)); - linkLabel.Height = size.Height; - } - } - private static System.Drawing.Size MeasureText(this LinkLabel linkLabel, System.Drawing.Graphics g, string text, System.Drawing.Font font) - { - if (linkLabel.UseCompatibleTextRendering) - return g.MeasureString(text, font).ToSize(); - else - return TextRenderer.MeasureText(g, text, font); - } - private static System.Drawing.Size MeasureText(this LinkLabel linkLabel, System.Drawing.Graphics g, string text, System.Drawing.Font font, System.Drawing.Size proposedSize) - { - if (linkLabel.UseCompatibleTextRendering) - return g.MeasureString(text, font, proposedSize.Width).ToSize(); - else - return TextRenderer.MeasureText(g, text, font, proposedSize, TextFormatFlags.WordBreak); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Combines the functionality fo StringBuilder.AppendFormat and + /// Combines the functionality of StringBuilder.AppendFormat and /// StringBuilder.AppendLine. Also allows for the delimiter to be specified. If the /// delimiter is null, Environment.NewLine will be used. /// @@ -93,8 +20,9 @@ private static System.Drawing.Size MeasureText(this LinkLabel linkLabel, System. /// ------------------------------------------------------------------------------------ public static void AppendLineFormat(this StringBuilder sb, string format, object[] args, string delimiter) { - if (delimiter == null) delimiter = Environment.NewLine; - if (sb.Length != 0) sb.Append(delimiter); + delimiter ??= Environment.NewLine; + if (sb.Length != 0) + sb.Append(delimiter); sb.AppendFormat(format, args); } @@ -108,8 +36,9 @@ public static void AppendLineFormat(this StringBuilder sb, string format, object /// ------------------------------------------------------------------------------------ public static void AppendDelimiter(this StringBuilder sb, string value, string delimiter) { - if (delimiter == null) delimiter = Environment.NewLine; - if (sb.Length != 0) sb.Append(delimiter); + delimiter ??= Environment.NewLine; + if (sb.Length != 0) + sb.Append(delimiter); sb.Append(value); } diff --git a/SIL.Windows.Forms.Archiving/Generic/AccessProtocol/AccessProtocolList.cs b/SIL.Archiving/Generic/AccessProtocol/AccessProtocolList.cs similarity index 94% rename from SIL.Windows.Forms.Archiving/Generic/AccessProtocol/AccessProtocolList.cs rename to SIL.Archiving/Generic/AccessProtocol/AccessProtocolList.cs index 3bdbff2b7..3ed2fb3a8 100644 --- a/SIL.Windows.Forms.Archiving/Generic/AccessProtocol/AccessProtocolList.cs +++ b/SIL.Archiving/Generic/AccessProtocol/AccessProtocolList.cs @@ -1,4 +1,3 @@ - using System; using System.Collections.Generic; using System.IO; @@ -7,9 +6,9 @@ using System.Runtime.Serialization.Json; using System.Text; using JetBrains.Annotations; -using SIL.Windows.Forms.Archiving.Properties; +using static SIL.Archiving.Resources.Resources; -namespace SIL.Windows.Forms.Archiving.Generic.AccessProtocol +namespace SIL.Archiving.Generic.AccessProtocol { /// This class is used to deserialize the JSON data in %ProgramData%\SIL\Archiving\AccessProtocols.json [CollectionDataContract(ItemName = "AccessProtocol")] @@ -35,13 +34,13 @@ protected AccessProtocols(IEnumerable items) /// public static AccessProtocols Load(string programDirectory) => - _instance ??= LoadFromFile(kProtocolFileName, Resources.AccessProtocols, programDirectory); + _instance ??= LoadFromFile(kProtocolFileName, GetResource(Name.AccessProtocols_json), programDirectory); /// public static AccessProtocols LoadCustom() { return _customInstance ??= - LoadFromFile(kCustomProtocolFileName, Resources.CustomAccessProtocols, null); + LoadFromFile(kCustomProtocolFileName, GetResource(Name.CustomAccessProtocols_json), null); } private static AccessProtocols LoadFromFile(string protocolFileName, string resourceName, string programDirectory) @@ -206,8 +205,8 @@ public string GetDocumentationUri(string programDirectory) if (!File.Exists(fileName)) { var pos = DocumentationFile.LastIndexOf('.'); - var resourceName = (pos > -1) ? DocumentationFile.Substring(0, pos) : DocumentationFile; - var resourceString = Resources.ResourceManager.GetString(resourceName); + var resourceName = pos > -1 ? DocumentationFile.Substring(0, pos) : DocumentationFile; + var resourceString = GetResource(resourceName); if (!string.IsNullOrEmpty(resourceString)) File.WriteAllText(fileName, resourceString); } diff --git a/SIL.Windows.Forms.Archiving/Generic/ArchivingAccess.cs b/SIL.Archiving/Generic/ArchivingAccess.cs similarity index 84% rename from SIL.Windows.Forms.Archiving/Generic/ArchivingAccess.cs rename to SIL.Archiving/Generic/ArchivingAccess.cs index b08f36a73..00e8e8816 100644 --- a/SIL.Windows.Forms.Archiving/Generic/ArchivingAccess.cs +++ b/SIL.Archiving/Generic/ArchivingAccess.cs @@ -1,5 +1,5 @@  -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// public class ArchivingAccess diff --git a/SIL.Windows.Forms.Archiving/Generic/ArchivingActor.cs b/SIL.Archiving/Generic/ArchivingActor.cs similarity index 98% rename from SIL.Windows.Forms.Archiving/Generic/ArchivingActor.cs rename to SIL.Archiving/Generic/ArchivingActor.cs index 288a472fa..ae4c6fba9 100644 --- a/SIL.Windows.Forms.Archiving/Generic/ArchivingActor.cs +++ b/SIL.Archiving/Generic/ArchivingActor.cs @@ -3,7 +3,7 @@ using System.Linq; using SIL.Extensions; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// An Actor is someone who has contributed to the content as a speaker or writer public class ArchivingActor : IComparable diff --git a/SIL.Windows.Forms.Archiving/Generic/ArchivingContact.cs b/SIL.Archiving/Generic/ArchivingContact.cs similarity index 97% rename from SIL.Windows.Forms.Archiving/Generic/ArchivingContact.cs rename to SIL.Archiving/Generic/ArchivingContact.cs index abd2bb29e..b377f25b0 100644 --- a/SIL.Windows.Forms.Archiving/Generic/ArchivingContact.cs +++ b/SIL.Archiving/Generic/ArchivingContact.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// Information about a contact public class ArchivingContact : IComparable diff --git a/SIL.Windows.Forms.Archiving/Generic/ArchivingFile.cs b/SIL.Archiving/Generic/ArchivingFile.cs similarity index 88% rename from SIL.Windows.Forms.Archiving/Generic/ArchivingFile.cs rename to SIL.Archiving/Generic/ArchivingFile.cs index e9130511d..b98017a04 100644 --- a/SIL.Windows.Forms.Archiving/Generic/ArchivingFile.cs +++ b/SIL.Archiving/Generic/ArchivingFile.cs @@ -1,18 +1,18 @@ -using System; +using System; using System.IO; -using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; +using SIL.Archiving.Generic.AccessProtocol; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// A file to add to the archive public class ArchivingFile { - protected readonly string _fullName; - protected string _fileName; - protected string _fileSize; // in KB - protected string _mimeType; - protected LanguageStringCollection _descriptions; - protected ArchiveAccessProtocol _accessProtocol; + private readonly string _fullName; + private string _fileName; + private string _fileSize; // in KB + private string _mimeType; + private LanguageStringCollection _descriptions; + private ArchiveAccessProtocol _accessProtocol; /// If this file contains information about another file, put the name of the other file here public string DescribesAnotherFile; diff --git a/SIL.Windows.Forms.Archiving/Generic/ArchivingFileSystem.cs b/SIL.Archiving/Generic/ArchivingFileSystem.cs similarity index 97% rename from SIL.Windows.Forms.Archiving/Generic/ArchivingFileSystem.cs rename to SIL.Archiving/Generic/ArchivingFileSystem.cs index d2bdb058f..c455dcccf 100644 --- a/SIL.Windows.Forms.Archiving/Generic/ArchivingFileSystem.cs +++ b/SIL.Archiving/Generic/ArchivingFileSystem.cs @@ -5,7 +5,7 @@ using System.IO; using SIL.PlatformUtilities; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// public static class ArchivingFileSystem diff --git a/SIL.Windows.Forms.Archiving/Generic/ArchivingPackage.cs b/SIL.Archiving/Generic/ArchivingPackage.cs similarity index 91% rename from SIL.Windows.Forms.Archiving/Generic/ArchivingPackage.cs rename to SIL.Archiving/Generic/ArchivingPackage.cs index bb522d779..684d5be95 100644 --- a/SIL.Windows.Forms.Archiving/Generic/ArchivingPackage.cs +++ b/SIL.Archiving/Generic/ArchivingPackage.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; -using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; +using System.Runtime.CompilerServices; +using SIL.Archiving.Generic.AccessProtocol; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// public interface IArchivingPackage : IArchivingGenericObject @@ -47,7 +48,7 @@ public interface IArchivingPackage : IArchivingGenericObject /// Collects the data needed to produce an archive package to upload public abstract class ArchivingPackage : IArchivingPackage { - protected readonly List> _keys; + private readonly List> _keys; public ArchivingLanguageCollection MetadataIso3Languages { get; set; } @@ -71,6 +72,8 @@ protected ArchivingPackage() } + protected IEnumerable> Keys => _keys; + /// public string Title { get; set; } diff --git a/SIL.Windows.Forms.Archiving/Generic/ArchivingSession.cs b/SIL.Archiving/Generic/ArchivingSession.cs similarity index 97% rename from SIL.Windows.Forms.Archiving/Generic/ArchivingSession.cs rename to SIL.Archiving/Generic/ArchivingSession.cs index d87d7ab1a..a711c4f28 100644 --- a/SIL.Windows.Forms.Archiving/Generic/ArchivingSession.cs +++ b/SIL.Archiving/Generic/ArchivingSession.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// Contains the materials being archived, and their metadata public interface IArchivingSession : IArchivingGenericObject diff --git a/SIL.Windows.Forms.Archiving/Generic/FileMimeType.cs b/SIL.Archiving/Generic/FileMimeType.cs similarity index 99% rename from SIL.Windows.Forms.Archiving/Generic/FileMimeType.cs rename to SIL.Archiving/Generic/FileMimeType.cs index 2a5111b40..d7cf71242 100644 --- a/SIL.Windows.Forms.Archiving/Generic/FileMimeType.cs +++ b/SIL.Archiving/Generic/FileMimeType.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// public static class FileMimeType diff --git a/SIL.Windows.Forms.Archiving/Generic/GenericObject.cs b/SIL.Archiving/Generic/GenericObject.cs similarity index 86% rename from SIL.Windows.Forms.Archiving/Generic/GenericObject.cs rename to SIL.Archiving/Generic/GenericObject.cs index 9b50c25c5..405824192 100644 --- a/SIL.Windows.Forms.Archiving/Generic/GenericObject.cs +++ b/SIL.Archiving/Generic/GenericObject.cs @@ -1,6 +1,6 @@ -using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; +using SIL.Archiving.Generic.AccessProtocol; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// Base class for archiving objects public interface IArchivingGenericObject diff --git a/SIL.Windows.Forms.Archiving/Generic/LanguageString.cs b/SIL.Archiving/Generic/LanguageString.cs similarity index 97% rename from SIL.Windows.Forms.Archiving/Generic/LanguageString.cs rename to SIL.Archiving/Generic/LanguageString.cs index 47619a4bc..c0e3467cb 100644 --- a/SIL.Windows.Forms.Archiving/Generic/LanguageString.cs +++ b/SIL.Archiving/Generic/LanguageString.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// Class for string values that have a language attribute public class LanguageString : IComparable diff --git a/SIL.Windows.Forms.Archiving/Generic/SimpleObjects.cs b/SIL.Archiving/Generic/SimpleObjects.cs similarity index 94% rename from SIL.Windows.Forms.Archiving/Generic/SimpleObjects.cs rename to SIL.Archiving/Generic/SimpleObjects.cs index 2b3304e42..625fa8fe3 100644 --- a/SIL.Windows.Forms.Archiving/Generic/SimpleObjects.cs +++ b/SIL.Archiving/Generic/SimpleObjects.cs @@ -1,5 +1,5 @@  -namespace SIL.Windows.Forms.Archiving.Generic +namespace SIL.Archiving.Generic { /// Location information for the data in the package public class ArchivingLocation diff --git a/SIL.Archiving/IArchivingMessageProvider.cs b/SIL.Archiving/IArchivingMessageProvider.cs new file mode 100644 index 000000000..49d94de08 --- /dev/null +++ b/SIL.Archiving/IArchivingMessageProvider.cs @@ -0,0 +1,16 @@ +namespace SIL.Archiving +{ + public interface IArchivingProgressDisplay + { + void IncrementProgress(); + string GetMessage(ArchivingDlgViewModel.StringId msgId); + /// ------------------------------------------------------------------------------------ + /// + /// Short name/description of the archiving program or standard used for this type of + /// archiving. (Should fit in the frame "Archive using ___".) Typically not localized, + /// but can potentially be. + /// + /// ------------------------------------------------------------------------------------ + string ArchiveTypeName { get; } + } +} diff --git a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs new file mode 100644 index 000000000..c24634198 --- /dev/null +++ b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs @@ -0,0 +1,446 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI.Schema; +using SIL.Extensions; +using SIL.WritingSystems; +using static System.String; + +namespace SIL.Archiving.IMDI +{ + /// Implements archiving for IMDI repositories + public class IMDIArchivingDlgViewModel : ArchivingDlgViewModel, ISupportMetadataOnly + { + private readonly IMDIPackage _imdiData; + private string _corpusDirectoryName; + private string _programPreset; + private string _otherProgramPath; + private readonly string _configFileName = Path.Combine(ArchivingFileSystem.SilCommonArchivingDataFolder, "IMDIProgram.config"); + private string _outputFolder; + + #region Properties + + public override Standard ArchiveType => Standard.IMDI; + + public override string NameOfProgramToLaunch + { + get + { + // DO NOT SHOW THE LAUNCH OPTION AT THIS TIME + return null; + + //if (string.IsNullOrEmpty(PathToProgramToLaunch)) + // return null; + + //// Arbil + //if (PathToProgramToLaunch.ToLower().Contains("arbil")) return "Arbil"; + + + //// if not one of the presets, just return the exe name + //string exe = Path.GetFileNameWithoutExtension(PathToProgramToLaunch); + //string dir = Path.GetDirectoryName(PathToProgramToLaunch); + //if (!string.IsNullOrEmpty(dir)) + //{ + // dir = Path.GetFileNameWithoutExtension(dir); + // if (dir.Length > 0 && exe.ToLowerInvariant().Contains(dir.ToLowerInvariant())) + // return dir; + //} + //return exe; + } + } + + /// ------------------------------------------------------------------------------------ + public override string ArchiveInfoUrl => Properties.Settings.Default.IMDIWebSite; + + public bool MetadataOnly { get; set; } + #endregion + + /// ------------------------------------------------------------------------------------ + /// Constructor + /// The application name + /// Title of the submission. + /// Identifier for the package being created. Used as the CORPUS name. + /// Indicates whether this is for an entire project corpus or a + /// single session + /// Delegate to request client to call methods to set + /// which files should be archived (this is deferred to allow display of progress message) + /// Base folder where IMDI file structure is to be created + /// ------------------------------------------------------------------------------------ + public IMDIArchivingDlgViewModel(string appName, string title, string id, bool corpus, + Action setFilesToArchive, string outputFolder) + : base(appName, title, id, setFilesToArchive) + { + OutputFolder = outputFolder; + + _imdiData = new IMDIPackage(corpus, PackagePath) + { + Title = PackageTitle, + Name = PackageId + }; + } + + /// ------------------------------------------------------------------------------------ + protected override bool DoArchiveSpecificInitialization() + { + // no-op + return true; + } + + /// ------------------------------------------------------------------------------------ + public override int CalculateMaxProgressBarValue() + { + // One for processing each list and one for copying each file + return FileLists.Count + FileLists.SelectMany(kvp => kvp.Value.Item1).Count(); + } + + /// ------------------------------------------------------------------------------------ + protected override string FileGroupDisplayMessage(string groupKey) + { + if (groupKey == Empty) + Progress.GetMessage(StringId.IMDIActorsGroup); + return base.FileGroupDisplayMessage(groupKey); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Sets a description for the specified session in a single language + /// + /// + /// The abstract description + /// ISO 639-3 3-letter language code + /// ------------------------------------------------------------------------------------ + [PublicAPI] + public void SetSessionDescription(string sessionId, string description, string iso3LanguageCode) + { + if (description == null) + throw new ArgumentNullException(nameof(description)); + // This will throw an appropriate exception if the language code is not valid: + IetfLanguageTag.Create(iso3LanguageCode, null, null, null); + + _imdiData.AddDescription(sessionId, new LanguageString { Value = description, Iso3LanguageId = iso3LanguageCode }); + } + + /// ------------------------------------------------------------------------------------ + protected override void SetAbstract_Impl(IDictionary descriptions) + { + foreach (var desc in descriptions) + _imdiData.AddDescription(new LanguageString(desc.Value, desc.Key)); + } + + + /// ------------------------------------------------------------------------------------ + public override string GetMetadata() + { + return _imdiData.BaseImdiFile.ToString(); + } + + /// ------------------------------------------------------------------------------------ + /// Launch Arbil or Lamus or whatever + /// Need custom launcher here because Arbil is a java program, with no + /// executable on linux + /// ------------------------------------------------------------------------------------ + public override void LaunchArchivingProgram() + { + if (IsNullOrEmpty(PathToProgramToLaunch) || !File.Exists(PathToProgramToLaunch)) + return; + + // if it is a .jar file, open with java + var exePath = PathToProgramToLaunch.EndsWith(".jar") ? "java" : PathToProgramToLaunch; + var args = Empty; + if (exePath == "java") + { + // are there additional command line parameters for this program? + args = PathToProgramToLaunch.ToLower().Contains("arbil") ? + Format(ArchivingPrograms.ArbilCommandLineArgs, PathToProgramToLaunch) : + PathToProgramToLaunch; + } + + var prs = new Process { StartInfo = { FileName = exePath, Arguments = args } }; + + LaunchArchivingProgram(prs); + } + +#region Create IMDI package asynchronously + + /// ------------------------------------------------------------------------------------ + public override async Task CreatePackage(CancellationToken cancellationToken) + { + // check for missing data that is required by Arbil + var success = _imdiData.SetMissingInformation(); + + // write the xml files + if (success) + success = _imdiData.CreateIMDIPackage(); // REVIEW: Should this also be awaited? + + // copy the content files + if (success && !MetadataOnly) + success = await CreateIMDIPackageAsync(cancellationToken); + + CleanUp(); + + return success ? _imdiData.MainExportFile : null; + } + + /// ------------------------------------------------------------------------------------ + private Task CreateIMDIPackageAsync(CancellationToken cancellationToken) + { + try + { + var outputDirectory = Path.Combine(_imdiData.PackagePath, NormalizeDirectoryName(_imdiData.Name)); + + ReportMajorProgressPoint(StringId.PreparingFiles, cancellationToken); + + var filesToCopy = new Dictionary(); + + // get files from each session + foreach (var session in _imdiData.Sessions.OfType()) + { + ReportProgress(session.Name, MessageType.Detail, cancellationToken); + + // get files to copy + foreach (var file in session.Resources.MediaFile) + { + // create sub directory + var fullSessionDirName = Path.Combine(outputDirectory, NormalizeDirectoryName(file.OutputDirectory)); + Directory.CreateDirectory(fullSessionDirName); + + var newFileName = NormalizeFilename(Empty, Path.GetFileName(file.FullPathAndFileName)); + filesToCopy[file.FullPathAndFileName] = Path.Combine(fullSessionDirName, newFileName); + } + + foreach (var file in session.Resources.WrittenResource) + { + // create sub directory + var fullSessionDirName = Path.Combine(outputDirectory, NormalizeDirectoryName(file.OutputDirectory)); + Directory.CreateDirectory(fullSessionDirName); + + var newFileName = NormalizeFilename(Empty, Path.GetFileName(file.FullPathAndFileName)); + filesToCopy[file.FullPathAndFileName] = Path.Combine(fullSessionDirName, newFileName); + } + } + + ReportMajorProgressPoint(StringId.CopyingFiles, cancellationToken); + + // copy the files now + foreach (var fileToCopy in filesToCopy) + { + ReportProgress(Path.GetFileName(fileToCopy.Key), MessageType.Detail, cancellationToken); + if (FileCopyOverride != null) + { + try + { + if (FileCopyOverride(this, fileToCopy.Key, fileToCopy.Value)) + { + if (!File.Exists(fileToCopy.Value)) + throw new FileNotFoundException("Calling application claimed to copy file but didn't", fileToCopy.Value); + continue; + } + } + catch (Exception error) + { + var msg = GetFileExcludedMsg(fileToCopy.Value); + ReportError(error, msg); + } + } + // Don't use File.Copy because it's asynchronous. + CopyFile(fileToCopy.Key, fileToCopy.Value); + } + + ReportMajorProgressPoint(StringId.SavingFilesInPackage, cancellationToken, false); + + return Task.FromResult(true); + } + catch (OperationCanceledException) + { + return Task.FromResult(false); + } + catch (Exception exception) + { + ReportError(exception, Progress.GetMessage(StringId.ErrorCreatingArchive)); + return Task.FromResult(false); + } + } + +#endregion + + /// Only Latin characters, URL compatible + protected override StringBuilder DoArchiveSpecificFilenameNormalization(string key, string fileName) + { + return new StringBuilder(NormalizeFileName(fileName)); + } + + /// Only Latin characters, URL compatible + internal static string NormalizeFileName(string fileName) + { + return fileName.ToLatinOnly("_", "+", "."); + } + + /// Only Latin characters, URL compatible + internal static string NormalizeDirectoryName(string dirName) + { + return dirName.ToLatinOnly("_", "_", ".-"); + } + + /// Returns the normalized name to use for the output corpus folder. A sub-directory of OutputFolder + public string CorpusDirectoryName + { + get + { + // create the output base directory if it doesn't already exist + Directory.CreateDirectory(OutputFolder); + + if (IsNullOrEmpty(_corpusDirectoryName)) + { + var baseName = NormalizeDirectoryName(PackageTitle + " " + DateTime.Today.ToISO8601TimeFormatDateOnlyString()); + var test = baseName; + var i = 1; + + while (Directory.Exists(Path.Combine(OutputFolder, test))) + { + test = NormalizeDirectoryName(baseName + " " + i.ToString("000")); + i++; + } + _corpusDirectoryName = test; + } + return _corpusDirectoryName; + } + } + + /// Adds a new session and returns it + /// + public override IArchivingSession AddSession(string sessionId) + { + // look for existing session + var session = _imdiData.Sessions.FirstOrDefault(s => s.Name == sessionId); + + if (session != null) + return session; + + // if not found, add a new session + session = new Session {Name = sessionId}; + + _imdiData.Sessions.Add(session); + + return session; + } + + public override IArchivingPackage ArchivingPackage => _imdiData; + + /// + public new string PathToProgramToLaunch + { + get + { + switch (ProgramPreset) + { + case "Arbil": + return ArchivingPrograms.GetArbilExeFileLocation(); + + default: + return OtherProgramPath; + } + } + set => _otherProgramPath = value; // this is just for compatibility + } + + /// + public string ProgramPreset + { + get + { + if (IsNullOrEmpty(_programPreset)) + GetSavedValues(); + + return _programPreset; + } + set + { + _programPreset = value; + SaveProgramValues(); + } + } + + /// + public string OtherProgramPath + { + get + { + if (IsNullOrEmpty(_programPreset)) + GetSavedValues(); + + return _otherProgramPath; + } + set + { + _otherProgramPath = value; + SaveProgramValues(); + } + } + + public void GetSavedValues() + { + + if (File.Exists(_configFileName)) + { + var lines = File.ReadAllLines(_configFileName); + + foreach (var line in lines) + { + var kvp = line.Split(new[] { '=' }, 2); + if (kvp.Length == 2) + { + switch (kvp[0]) + { + case "ProgramPreset": + _programPreset = kvp[1]; + break; + + case "OtherProgramPath": + _otherProgramPath = kvp[1]; + break; + } + } + } + } + + // default to Arbil + if (IsNullOrEmpty(_programPreset)) + _programPreset = "Arbil"; + + _otherProgramPath ??= Empty; + } + + private void SaveProgramValues() + { + List lines = new List + { + "ProgramPreset=" + ProgramPreset, + "OtherProgramPath=" + OtherProgramPath + }; + + File.WriteAllLines(_configFileName, lines); + } + + /// + public string OutputFolder + { + get => _outputFolder; + set + { + _outputFolder = value; + PackagePath = !IsNullOrEmpty(value)? + Path.Combine(value, CorpusDirectoryName): + CorpusDirectoryName; + if (_imdiData != null) + _imdiData.PackagePath = PackagePath; + } + } + } +} diff --git a/SIL.Windows.Forms.Archiving/IMDI/IMDIContributor.cs b/SIL.Archiving/IMDI/IMDIContributor.cs similarity index 92% rename from SIL.Windows.Forms.Archiving/IMDI/IMDIContributor.cs rename to SIL.Archiving/IMDI/IMDIContributor.cs index 3545f5211..201467342 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/IMDIContributor.cs +++ b/SIL.Archiving/IMDI/IMDIContributor.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; -using SIL.Windows.Forms.Archiving.Generic; +using SIL.Archiving.Generic; -namespace SIL.Windows.Forms.Archiving.IMDI +namespace SIL.Archiving.IMDI { public class IMDIContributor : ArchivingActor { diff --git a/SIL.Windows.Forms.Archiving/IMDI/IMDIFile.cs b/SIL.Archiving/IMDI/IMDIFile.cs similarity index 96% rename from SIL.Windows.Forms.Archiving/IMDI/IMDIFile.cs rename to SIL.Archiving/IMDI/IMDIFile.cs index 6b4ec7ce7..9ed808f2b 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/IMDIFile.cs +++ b/SIL.Archiving/IMDI/IMDIFile.cs @@ -1,9 +1,9 @@ using System.IO; -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.IMDI.Lists; -using SIL.Windows.Forms.Archiving.IMDI.Schema; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI.Lists; +using SIL.Archiving.IMDI.Schema; -namespace SIL.Windows.Forms.Archiving.IMDI +namespace SIL.Archiving.IMDI { /// A file to add to the archive public class IMDIFile : ArchivingFile diff --git a/SIL.Windows.Forms.Archiving/IMDI/IMDIPackage.cs b/SIL.Archiving/IMDI/IMDIPackage.cs similarity index 87% rename from SIL.Windows.Forms.Archiving/IMDI/IMDIPackage.cs rename to SIL.Archiving/IMDI/IMDIPackage.cs index 7c1e2c8c5..8b4205c3b 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/IMDIPackage.cs +++ b/SIL.Archiving/IMDI/IMDIPackage.cs @@ -3,18 +3,18 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.IMDI.Lists; -using SIL.Windows.Forms.Archiving.IMDI.Schema; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI.Lists; +using SIL.Archiving.IMDI.Schema; using SIL.Extensions; -namespace SIL.Windows.Forms.Archiving.IMDI +namespace SIL.Archiving.IMDI { /// Collects the data and produces an IMDI corpus to upload public class IMDIPackage : ArchivingPackage { /// - public MetaTranscript BaseImdiFile { get; private set; } + public MetaTranscript BaseImdiFile { get; } /// The file to import into Arbil public string MainExportFile { get; private set; } @@ -40,15 +40,12 @@ public IMDIPackage(bool corpus, string packagePath) } #region Properties - private IIMDIMajorObject BaseMajorObject - { - get { return (IIMDIMajorObject)BaseImdiFile.Items[0]; } - } + private IIMDIMajorObject BaseMajorObject => (IIMDIMajorObject)BaseImdiFile.Items[0]; /// The path where the corpus imdi file and corpus directory will be created public string PackagePath { - get { return _packagePath; } + get => _packagePath; set { if (_creationStarted) @@ -65,7 +62,7 @@ public string PackagePath // Test_Corpus\Test_Corpus_Catalog.imdi (catalogue of information) // Test_Corpus\Test_Session (directory) // Test_Corpus\Test_Session.imdi (session meta data file) - // Test_Corpus\Test_Session\Contributors (directory - contains files pertaining to contributers/actors) + // Test_Corpus\Test_Session\Contributors (directory - contains files pertaining to contributors/actors) // Test_Corpus\Test_Session\Files*.* (session files) // Test_Corpus\Contributors\Files*.* (contributor/actor files) @@ -82,8 +79,11 @@ public bool CreateIMDIPackage() // ReSharper disable once LoopCanBeConvertedToQuery foreach (var session in Sessions) { - var sessImdi = new MetaTranscript { Items = new object[] { session }, Type = MetatranscriptValueType.SESSION }; - sessionFiles.Add(sessImdi.WriteImdiFile(PackagePath, Name)); + var sessionImdi = new MetaTranscript { + Items = new object[] { session }, + Type = MetatranscriptValueType.SESSION + }; + sessionFiles.Add(sessionImdi.WriteImdiFile(PackagePath, Name)); } if (!_corpus) @@ -159,7 +159,7 @@ private string CreateCorpusCatalogue() catalogue.Publisher.Add(Publisher); // keys - foreach (var kvp in _keys) + foreach (var kvp in Keys) catalogue.Keys.Key.Add(new KeyType { Name = kvp.Key, Value = kvp.Value }); // access @@ -195,7 +195,8 @@ private string CreateCorpusCatalogue() foreach (var itm in BaseMajorObject.Description) { if (itm.LanguageId == description.Iso3LanguageId) - throw new InvalidOperationException(string.Format("A description for language {0} has already been set", itm.LanguageId)); + throw new InvalidOperationException( + $"A description for language {itm.LanguageId} has already been set"); } BaseMajorObject.Description.Add(description); @@ -209,9 +210,9 @@ public void AddDescription(string sessionId, LanguageString description) // prevent duplicate description if (_corpus) { - foreach (var sess in Sessions.Where(sess => sess.Name == sessionId)) + foreach (var session in Sessions.Where(sess => sess.Name == sessionId)) { - sess.AddDescription(description); + session.AddDescription(description); } } else diff --git a/SIL.Windows.Forms.Archiving/IMDI/Lists/BooleanEnum.cs b/SIL.Archiving/IMDI/Lists/BooleanEnum.cs similarity index 87% rename from SIL.Windows.Forms.Archiving/IMDI/Lists/BooleanEnum.cs rename to SIL.Archiving/IMDI/Lists/BooleanEnum.cs index 979fe5311..77792ce02 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Lists/BooleanEnum.cs +++ b/SIL.Archiving/IMDI/Lists/BooleanEnum.cs @@ -1,5 +1,5 @@  -namespace SIL.Windows.Forms.Archiving.IMDI.Lists +namespace SIL.Archiving.IMDI.Lists { /// In IMDI there are 4 possible values for a boolean public enum BooleanEnum diff --git a/SIL.Archiving/IMDI/Lists/InvalidLanguageCodeException.cs b/SIL.Archiving/IMDI/Lists/InvalidLanguageCodeException.cs new file mode 100644 index 000000000..7101a26f6 --- /dev/null +++ b/SIL.Archiving/IMDI/Lists/InvalidLanguageCodeException.cs @@ -0,0 +1,15 @@ +using System; + +namespace SIL.Archiving.IMDI.Lists +{ + public class InvalidLanguageCodeException : ArgumentException + { + public string Code { get; } + + public InvalidLanguageCodeException(string code, string paramName = null, Exception innerException = null) : + base ("Invalid language code", paramName, innerException) + { + Code = code; + } + } +} diff --git a/SIL.Windows.Forms.Archiving/IMDI/Lists/ItemListBase.cs b/SIL.Archiving/IMDI/Lists/ItemListBase.cs similarity index 98% rename from SIL.Windows.Forms.Archiving/IMDI/Lists/ItemListBase.cs rename to SIL.Archiving/IMDI/Lists/ItemListBase.cs index 19a4479f1..5c670dbb7 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Lists/ItemListBase.cs +++ b/SIL.Archiving/IMDI/Lists/ItemListBase.cs @@ -5,12 +5,12 @@ using System.Linq; using System.Net; using System.Xml; -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.IMDI.Schema; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI.Schema; using SIL.Extensions; using SIL.WritingSystems; -namespace SIL.Windows.Forms.Archiving.IMDI.Lists +namespace SIL.Archiving.IMDI.Lists { /// Generic class to handle items in the IMDI lists public class IMDIListItem : IComparable @@ -19,7 +19,7 @@ public class IMDIListItem : IComparable public string Text { get; protected set; } /// Value suitable for storing in metadata files - public string Value { get; private set; } + public string Value { get; } /// Description to the user (often the same as the text) public string Definition { get; private set; } diff --git a/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs b/SIL.Archiving/IMDI/Lists/LanguageList.cs similarity index 88% rename from SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs rename to SIL.Archiving/IMDI/Lists/LanguageList.cs index 73610aa8b..11365d0eb 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Lists/LanguageList.cs +++ b/SIL.Archiving/IMDI/Lists/LanguageList.cs @@ -1,10 +1,9 @@ - using System; using System.Linq; -using L10NSharp; -using SIL.Windows.Forms.Archiving.IMDI.Schema; +using JetBrains.Annotations; +using SIL.Archiving.IMDI.Schema; -namespace SIL.Windows.Forms.Archiving.IMDI.Lists +namespace SIL.Archiving.IMDI.Lists { /// ------------------------------------------------------------------------------------------- public class LanguageItem : IMDIListItem @@ -23,19 +22,14 @@ internal LanguageItem(string englishName, string imdiCode, string otherName) : t } /// This is provided because the XSD uses the term "LanguageId" - public string Id { get { return Value; } } + public string Id => Value; /// public string OtherName { get; set; } /// - public string DisplayName - { - get - { - return string.IsNullOrEmpty(OtherName) ? EnglishName : OtherName; - } - } + [PublicAPI] + public string DisplayName => string.IsNullOrEmpty(OtherName) ? EnglishName : OtherName; /// Convert to a LanguageType object public LanguageType ToLanguageType() @@ -43,7 +37,7 @@ public LanguageType ToLanguageType() var langName = Text; // check for "und" code - if ((Id.EndsWith("und")) && (!string.IsNullOrEmpty(OtherName))) + if (Id.EndsWith("und") && !string.IsNullOrEmpty(OtherName)) langName = OtherName; return new LanguageType @@ -76,15 +70,12 @@ public SubjectLanguageType ToSubjectLanguageType() /// public string EnglishName { - get { return Text; } - set { Text = value; } + get => Text; + set => Text = value; } /// - public string Iso3Code - { - get { return Value.Substring(Value.Length - 3); } - } + public string Iso3Code => Value.Substring(Value.Length - 3); } /// ------------------------------------------------------------------------------------------- @@ -96,7 +87,7 @@ public class LanguageList : IMDIItemList /// private static LanguageList GetList() { - return _instance ?? (_instance = new LanguageList()); + return _instance ??= new LanguageList(); } /// --------------------------------------------------------------------------------------- @@ -154,10 +145,7 @@ public static LanguageItem FindByISO3Code(string iso3Code, bool mustBeInList) // if not found, and not limited to list, just return the code passed in if (!mustBeInList) return new LanguageItem(string.Empty, "ISO639-3:" + iso3Code.ToLower()); - // if not found, throw exception - var msg = LocalizationManager.GetString("DialogBoxes.ArchivingDlg.InvalidLanguageCode", - "Invalid ISO 639-3 code: {0}"); - throw new ArgumentException(string.Format(msg, iso3Code), "iso3Code"); + throw new InvalidLanguageCodeException(iso3Code, nameof(iso3Code)); } /// ------------------------------------------------------------------------------------------- diff --git a/SIL.Windows.Forms.Archiving/IMDI/Lists/ListConstructor.cs b/SIL.Archiving/IMDI/Lists/ListConstructor.cs similarity index 95% rename from SIL.Windows.Forms.Archiving/IMDI/Lists/ListConstructor.cs rename to SIL.Archiving/IMDI/Lists/ListConstructor.cs index 7ded6f1ec..4f1724769 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Lists/ListConstructor.cs +++ b/SIL.Archiving/IMDI/Lists/ListConstructor.cs @@ -1,7 +1,7 @@ -using System; +using System; using System.Collections.Generic; -namespace SIL.Windows.Forms.Archiving.IMDI.Lists +namespace SIL.Archiving.IMDI.Lists { /// /// @@ -34,7 +34,8 @@ public enum RemoveUnknown /// Delegate to use for getting localized versions of the Text and /// Definition of list items. The parameters are: 1) the list name; 2) list item value; /// 3) "Definition" or "Text"; 4) default (English) value. - public static IMDIItemList GetList(string listName, bool uppercaseFirstCharacter, Func localize) + public static IMDIItemList GetList(string listName, bool uppercaseFirstCharacter, + Func localize) { return GetList(listName, uppercaseFirstCharacter, localize, RemoveUnknown.RemoveNone); } @@ -57,9 +58,7 @@ public static IMDIItemList GetList(string listName, bool uppercaseFirstCharacter listName = ListNameWithXmlExtension(listName); var listKey = listName + removeUnknown; - IMDIItemList list; - - if (!_loadedLists.TryGetValue(listKey, out list)) + if (!_loadedLists.TryGetValue(listKey, out var list)) { list = new IMDIItemList(listName, uppercaseFirstCharacter, removeUnknown); diff --git a/SIL.Windows.Forms.Archiving/IMDI/Lists/ListType.cs b/SIL.Archiving/IMDI/Lists/ListType.cs similarity index 98% rename from SIL.Windows.Forms.Archiving/IMDI/Lists/ListType.cs rename to SIL.Archiving/IMDI/Lists/ListType.cs index 5e8c04678..cb08c8a48 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Lists/ListType.cs +++ b/SIL.Archiving/IMDI/Lists/ListType.cs @@ -1,4 +1,4 @@ -namespace SIL.Windows.Forms.Archiving.IMDI.Lists +namespace SIL.Archiving.IMDI.Lists { /// /// Contains the IMDI list types known at this time. diff --git a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIDescription.cs b/SIL.Archiving/IMDI/Schema/IMDIDescription.cs similarity index 96% rename from SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIDescription.cs rename to SIL.Archiving/IMDI/Schema/IMDIDescription.cs index 6e5c088f4..53fac9544 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIDescription.cs +++ b/SIL.Archiving/IMDI/Schema/IMDIDescription.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Xml.Serialization; -using SIL.Windows.Forms.Archiving.Generic; +using SIL.Archiving.Generic; -namespace SIL.Windows.Forms.Archiving.IMDI.Schema +namespace SIL.Archiving.IMDI.Schema { /// Common description code for multiple IMDI objects public abstract class IMDIDescription diff --git a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIExtensions.cs b/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs similarity index 96% rename from SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIExtensions.cs rename to SIL.Archiving/IMDI/Schema/IMDIExtensions.cs index 218e7c932..70c0f6091 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIExtensions.cs +++ b/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs @@ -1,7 +1,7 @@ -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.IMDI.Lists; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI.Lists; -namespace SIL.Windows.Forms.Archiving.IMDI.Schema +namespace SIL.Archiving.IMDI.Schema { /// Extension methods to simplify access to IMDI objects public static class IMDIExtensions diff --git a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIInterfaces.cs b/SIL.Archiving/IMDI/Schema/IMDIInterfaces.cs similarity index 93% rename from SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIInterfaces.cs rename to SIL.Archiving/IMDI/Schema/IMDIInterfaces.cs index 0b1053e82..8a40ed7fd 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDIInterfaces.cs +++ b/SIL.Archiving/IMDI/Schema/IMDIInterfaces.cs @@ -1,5 +1,5 @@  -namespace SIL.Windows.Forms.Archiving.IMDI.Schema +namespace SIL.Archiving.IMDI.Schema { /// Interface to simplify access to session files (media and written) public interface IIMDISessionFile diff --git a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDISchemaHelper.cs b/SIL.Archiving/IMDI/Schema/IMDISchemaHelper.cs similarity index 93% rename from SIL.Windows.Forms.Archiving/IMDI/Schema/IMDISchemaHelper.cs rename to SIL.Archiving/IMDI/Schema/IMDISchemaHelper.cs index bf11b57f7..34847e183 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDISchemaHelper.cs +++ b/SIL.Archiving/IMDI/Schema/IMDISchemaHelper.cs @@ -1,5 +1,5 @@  -namespace SIL.Windows.Forms.Archiving.IMDI.Schema +namespace SIL.Archiving.IMDI.Schema { /// Functions to simplify access to IMDI objects public static class IMDISchemaHelper diff --git a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0.cs b/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs similarity index 99% rename from SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0.cs rename to SIL.Archiving/IMDI/Schema/IMDI_3_0.cs index b4c02d61e..12f392313 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0.cs +++ b/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs @@ -8,12 +8,12 @@ using System.Xml.Schema; using System.Xml.Serialization; using System.Diagnostics; -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.Generic.AccessProtocol; -using SIL.Windows.Forms.Archiving.IMDI.Lists; +using SIL.Archiving.Generic; +using SIL.Archiving.Generic.AccessProtocol; +using SIL.Archiving.IMDI.Lists; using SIL.Extensions; -namespace SIL.Windows.Forms.Archiving.IMDI.Schema +namespace SIL.Archiving.IMDI.Schema { /// Shared properties and methods public interface IIMDIMajorObject diff --git a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_Fix.py b/SIL.Archiving/IMDI/Schema/IMDI_3_0_Fix.py similarity index 100% rename from SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_Fix.py rename to SIL.Archiving/IMDI/Schema/IMDI_3_0_Fix.py diff --git a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs b/SIL.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs similarity index 99% rename from SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs rename to SIL.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs index 1e2446d78..b2080f5b0 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs +++ b/SIL.Archiving/IMDI/Schema/IMDI_3_0_NotUsed.cs @@ -1,7 +1,7 @@  // ReSharper disable once EmptyNamespace // ReSharper disable once CheckNamespace -namespace SIL.Windows.Forms.Archiving.IMDI.Schema.NotUsed +namespace SIL.Archiving.IMDI.Schema.NotUsed { ///// //[SerializableAttribute] diff --git a/SIL.Windows.Forms.Archiving/IMDI/xsd/GenerateClasses.bat b/SIL.Archiving/IMDI/xsd/GenerateClasses.bat similarity index 100% rename from SIL.Windows.Forms.Archiving/IMDI/xsd/GenerateClasses.bat rename to SIL.Archiving/IMDI/xsd/GenerateClasses.bat diff --git a/SIL.Windows.Forms.Archiving/IMDI/xsd/imdi-v3.xsd b/SIL.Archiving/IMDI/xsd/imdi-v3.xsd similarity index 100% rename from SIL.Windows.Forms.Archiving/IMDI/xsd/imdi-v3.xsd rename to SIL.Archiving/IMDI/xsd/imdi-v3.xsd diff --git a/SIL.Windows.Forms.Archiving/JSONUtils.cs b/SIL.Archiving/JSONUtils.cs similarity index 98% rename from SIL.Windows.Forms.Archiving/JSONUtils.cs rename to SIL.Archiving/JSONUtils.cs index 60963885f..da0f0ac2e 100644 --- a/SIL.Windows.Forms.Archiving/JSONUtils.cs +++ b/SIL.Archiving/JSONUtils.cs @@ -3,7 +3,7 @@ using System.Text; using System.Linq; -namespace SIL.Windows.Forms.Archiving +namespace SIL.Archiving { public class JSONUtils { diff --git a/SIL.Archiving/Properties/AssemblyInfo.cs b/SIL.Archiving/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..25ad05caa --- /dev/null +++ b/SIL.Archiving/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +// Copyright (c) 2016-2024 SIL International +// This software is licensed under the MIT License (http://opensource.org/licenses/MIT) + +using System; +using System.Runtime.CompilerServices; + +[assembly: CLSCompliant(true)] + +[assembly: InternalsVisibleTo("SIL.Archiving.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001008339b2ae1bf006934f6176dec6ea2a8a7d67383613dcb03d71975e7b05ad546562c84529a4811e94c889e55f2532d1a90baaf20be9bff39ac6f5365bd605d70b90489840b7ba6d1c231b0e550c4abe4f60553856ef142a40a91e53d56e79f69dc79c4e95817de498aac924ee011f03b4e1c1d772d51c4946c1185e3bfb621bc6")] diff --git a/SIL.Archiving/Properties/Settings.Designer.cs b/SIL.Archiving/Properties/Settings.Designer.cs new file mode 100644 index 000000000..1505ac2ae --- /dev/null +++ b/SIL.Archiving/Properties/Settings.Designer.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SIL.Archiving.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("http://www.mpi.nl/imdi/")] + public string IMDIWebSite { + get { + return ((string)(this["IMDIWebSite"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://gateway.sil.org/display/RH/RAMP+Users%27+Manual")] + public string RampWebSite { + get { + return ((string)(this["RampWebSite"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("author;compiler;consultant;developer;editor;facilitator;illustrator;interviewer;p" + + "hotographer;recorder;researcher;signer;speaker;transcriber;translator")] + public string RampContributorRoles { + get { + return ((string)(this["RampContributorRoles"])); + } + } + } +} diff --git a/SIL.Archiving/Properties/Settings.settings b/SIL.Archiving/Properties/Settings.settings new file mode 100644 index 000000000..4748efedb --- /dev/null +++ b/SIL.Archiving/Properties/Settings.settings @@ -0,0 +1,15 @@ + + + + + + http://www.mpi.nl/imdi/ + + + https://gateway.sil.org/display/RH/RAMP+Users%27+Manual + + + author;compiler;consultant;developer;editor;facilitator;illustrator;interviewer;photographer;recorder;researcher;signer;speaker;transcriber;translator + + + \ No newline at end of file diff --git a/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs b/SIL.Archiving/RampArchivingDlgViewModel.cs similarity index 81% rename from SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs rename to SIL.Archiving/RampArchivingDlgViewModel.cs index 20ec9ed6d..0e39fec33 100644 --- a/SIL.Windows.Forms.Archiving/RampArchivingDlgViewModel.cs +++ b/SIL.Archiving/RampArchivingDlgViewModel.cs @@ -1,48 +1,28 @@ using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; -using System.Windows.Forms; +using System.Threading.Tasks; using Ionic.Zip; -using L10NSharp; -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.Properties; +using JetBrains.Annotations; +using SIL.Archiving.Generic; +using SIL.Core.ClearShare; using SIL.Extensions; using SIL.IO; using SIL.PlatformUtilities; using Timer = System.Threading.Timer; -using SIL.Core.ClearShare; +using static System.String; +using static SIL.Archiving.Resources.Resources; -namespace SIL.Windows.Forms.Archiving +namespace SIL.Archiving { /// ------------------------------------------------------------------------------------ public class RampArchivingDlgViewModel: ArchivingDlgViewModel { - [DllImport("user32.dll", EntryPoint = "SetWindowPos")] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool SetWindowPosWindows(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); - - private static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, - int cy, uint uFlags) - { - // on Linux simply return true - return !Platform.IsWindows || SetWindowPosWindows(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); - } - // ReSharper disable InconsistentNaming - private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); // brings window to top and makes it "always on top" - private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); // brings window to top but not "always on top" - private const UInt32 SWP_NOSIZE = 0x0001; - private const UInt32 SWP_NOMOVE = 0x0002; - private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE; - // ReSharper restore InconsistentNaming - #region RAMP and METS constants // ReSharper disable CSharpWarnings::CS1591 @@ -158,14 +138,16 @@ private static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int #endregion #region Data members + private readonly Dictionary _progressMessages = new Dictionary(); private readonly List _metsPairs; private AudienceType _metsAudienceType; private string _metsFilePath; private string _tempFolder; private Timer _timer; - private bool _workerException; private Dictionary _languageList; - private readonly Func _getFileDescription; // first param is filelist key, second param is filename + private readonly Func _getFileDescription; // first param is file list key, second param is filename + private readonly Action _setFilesToArchive; + private int _imageCount = -1; private int _audioCount = -1; private int _videoCount = -1; @@ -174,32 +156,11 @@ private static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int #region properties /// ------------------------------------------------------------------------------------ - internal override string ArchiveType => LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.RAMPArchiveType", "RAMP (SIL Only)"); + public override Standard ArchiveType => Standard.REAP; /// ------------------------------------------------------------------------------------ public override string NameOfProgramToLaunch => kRampProcessName; - /// ------------------------------------------------------------------------------------ - public override string InformativeText - { - get - { - return string.Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.RAMPOverviewText", - "{0} is a utility for entering metadata and uploading submissions to SIL's internal archive, " + - "REAP. If you have access to this archive, this tool will help you use {0} to archive your " + - "{1} data. {2} When the {0} package has been created, you can launch {0} and enter any " + - "additional information before doing the actual submission.", - "Parameter 0 is the word 'RAMP' (the first one will be turned into a hyperlink); " + - "Parameter 1 is the name of the calling (host) program (SayMore, FLEx, etc.); " + - "Parameter 2 is additional app-specific information."), NameOfProgramToLaunch, AppName, - _appSpecificArchivalProcessInfo); - } - } - - /// ------------------------------------------------------------------------------------ - public override string ArchiveInfoHyperlinkText => NameOfProgramToLaunch; - /// ------------------------------------------------------------------------------------ public override string ArchiveInfoUrl => Properties.Settings.Default.RampWebSite; @@ -227,29 +188,31 @@ public int ImageCount { get { - if (_fileLists != null && _imageCount < 0) + if (FileLists != null && _imageCount < 0) ExtractInformationFromFiles(); return _imageCount; } } /// ------------------------------------------------------------------------------------ + [PublicAPI] public int AudioCount { get { - if (_fileLists != null && _audioCount < 0) + if (FileLists != null && _audioCount < 0) ExtractInformationFromFiles(); return _audioCount; } } /// ------------------------------------------------------------------------------------ + [PublicAPI] public int VideoCount { get { - if (_fileLists != null && _videoCount < 0) + if (FileLists != null && _videoCount < 0) ExtractInformationFromFiles(); return _videoCount; } @@ -263,7 +226,7 @@ public int VideoCount /// ------------------------------------------------------------------------------------ private void ExtractInformationFromFiles() { - ExtractInformationFromFiles(_fileLists.SelectMany(f => f.Value.Item1)); + ExtractInformationFromFiles(FileLists.SelectMany(f => f.Value.Item1)); } /// ------------------------------------------------------------------------------------ @@ -329,27 +292,23 @@ private void AddModesToSet(IEnumerable files) /// The application name /// Title of the submission /// Identifier (used as filename) for the package being created - /// Application can use this to pass - /// additional information that will be displayed to the user in the dialog to explain - /// any application-specific details about the archival process. /// Delegate to request client to call methods to set /// which files should be archived (this is deferred to allow display of progress message) /// Callback function to get a file description based /// on the file-list key (param 1) and the filename (param 2) /// ------------------------------------------------------------------------------------ public RampArchivingDlgViewModel(string appName, string title, string id, - string appSpecificArchivalProcessInfo, Action setFilesToArchive, + Action setFilesToArchive, Func getFileDescription) : base(appName, title, id, - appSpecificArchivalProcessInfo, setFilesToArchive) + (m, c) => { ((RampArchivingDlgViewModel)m).SetFilesToArchive(c); }) { - if (getFileDescription == null) - throw new ArgumentNullException("getFileDescription"); - _getFileDescription = getFileDescription; + _getFileDescription = getFileDescription ?? throw new ArgumentNullException(nameof(getFileDescription)); + _setFilesToArchive = setFilesToArchive; ShowRecordingCountNotLength = false; ImagesArePhotographs = true; - _metsPairs = new List(new [] {JSONUtils.MakeKeyValuePair(kPackageTitle, _titles[_id])}); + _metsPairs = new List(new [] {JSONUtils.MakeKeyValuePair(kPackageTitle, PackageTitle)}); foreach (var orphanedRampPackage in Directory.GetFiles(Path.GetTempPath(), "*" + kRampFileExtension)) { @@ -359,19 +318,31 @@ public RampArchivingDlgViewModel(string appName, string title, string id, } } + private void SetFilesToArchive(CancellationToken cancellationToken) + { + _setFilesToArchive(this, cancellationToken); + if (cancellationToken.IsCancellationRequested) + throw new OperationCanceledException(); + foreach (var fileList in FileLists.Where(fileList => fileList.Value.Item1.Any())) + { + var normalizedName = NormalizeFilename(fileList.Key, + Path.GetFileName(fileList.Value.Item1.First())); + _progressMessages[normalizedName] = fileList.Value.Item2; + } + } + /// ------------------------------------------------------------------------------------ protected override bool DoArchiveSpecificInitialization() { - DisplayMessage(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.SearchingForRampMsg", - "Searching for the RAMP program..."), MessageType.Volatile); + DisplayMessage(Progress.GetMessage(StringId.SearchingForArchiveUploadingProgram), + MessageType.Volatile); - Application.DoEvents(); PathToProgramToLaunch = GetExeFileLocation(); if (PathToProgramToLaunch == null) { - DisplayMessage(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.RampNotFoundMsg", - "The RAMP program cannot be found!"), MessageType.Error); + DisplayMessage(Progress.GetMessage(StringId.ArchiveUploadingProgramNotFound), + MessageType.Error); return false; } @@ -383,24 +354,29 @@ public override int CalculateMaxProgressBarValue() { // One for analyzing each list, one for copying each file, one for adding each file // to the zip file and one for the mets.xml file. - return _fileLists.Count + 2 * _fileLists.SelectMany(kvp => kvp.Value.Item1).Count() + 1; + return FileLists.Count + 2 * FileLists.SelectMany(kvp => kvp.Value.Item1).Count() + 1; } #endregion #region Methods to add app-specific METS pairs + /// ------------------------------------------------------------------------------------ /// /// Sets the "Broad Type", the audience for which the resource being archived is /// primarily intended. This is set automatically as a side-effect of setting the /// stage or type. /// + /// Audience has already been set and + /// cannot be changed to a different value. + /// The audience type is not one that is + /// currently handled. /// ------------------------------------------------------------------------------------ public void SetAudience(AudienceType audienceType) { if (IsMetadataPropertySet(MetadataProperties.Audience)) { if (_metsAudienceType != audienceType) - throw new InvalidOperationException(string.Format("Audience has already been set and cannot be changed to a different value.")); + throw new InvalidOperationException("Audience has already been set and cannot be changed to a different value."); return; // Already added } @@ -577,7 +553,10 @@ public void SetVernacularMaterialsAndContentType(VernacularMaterialsType vernacu /// (for published textbooks call SetScholarlyWorkType instead as these are generally for /// a wider audience). /// + /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetTrainingResourceType(TrainingResourceType trainingResourceType) { SetAudience(AudienceType.Training); @@ -605,6 +584,7 @@ public void SetTrainingResourceType(TrainingResourceType trainingResourceType) /// a wider audience). /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetInternalWorkType(InternalWorkType internalWorkType) { SetAudience(AudienceType.Internal); @@ -629,7 +609,10 @@ public void SetInternalWorkType(InternalWorkType internalWorkType) /// /// Sets the bibliographic type of the resource being archived (for a "wider audience") /// + /// The scholarlyWorkType value is one that is + /// not currently handled. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetScholarlyWorkType(ScholarlyWorkType scholarlyWorkType) { SetAudience(AudienceType.Wider); @@ -659,6 +642,7 @@ public void SetScholarlyWorkType(ScholarlyWorkType scholarlyWorkType) /// pay attention to the comments for each work stage to avoid pairing it with an /// invalid audience type. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetStage(WorkStage stage) { PreventDuplicateMetadataProperty(MetadataProperties.Stage); @@ -710,7 +694,7 @@ private void PreventInvalidAudienceTypeForWorkStage(Enum invalidAudience, WorkSt { if ((invalidAudience != null) && (invalidAudience.HasFlag(_metsAudienceType))) { - throw new InvalidOperationException(string.Format( + throw new InvalidOperationException(Format( "Resources with an audience of \"{0}\" cannot have a work stage of {1}", _metsAudienceType, stage)); } @@ -731,6 +715,7 @@ private void SetStage(string stage) /// necessary to OR the sub-domains with their corresponding domains, since the /// subdomains already have the correct domain bits set. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetDomains(SilDomain domains) { PreventDuplicateMetadataProperty(MetadataProperties.Domains); @@ -759,7 +744,7 @@ public void SetDomains(SilDomain domains) if (domains.HasFlag(SilDomain.Emus_ArtisticCommunicationProfile)) AddSubDomain(kEthnomusicologyAbbrev, "artistic communication profile"); if (domains.HasFlag(SilDomain.Emus_PerformanceCollection)) - AddSubDomain(kEthnomusicologyAbbrev, "aperformance collection"); + AddSubDomain(kEthnomusicologyAbbrev, "performance collection"); if (domains.HasFlag(SilDomain.Emus_SongCollection)) AddSubDomain(kEthnomusicologyAbbrev, "song collection"); if (domains.HasFlag(SilDomain.Emus_SummaryArtisticEventFormAnalysis)) @@ -895,15 +880,16 @@ private void AddDomain(string domainAbbrev, string domainName) { // if a mets pair already exists for domains, add this domain to the existing list. var existingValue = _metsPairs.Find(s => s.Contains(kSilDomain)); - if (!string.IsNullOrEmpty(existingValue)) + if (!IsNullOrEmpty(existingValue)) { int pos = existingValue.IndexOf(']'); - string newValue = existingValue.Insert(pos, string.Format(",\"{0}:{1}\"", domainAbbrev, domainName)); + string newValue = existingValue.Insert(pos, $",\"{domainAbbrev}:{domainName}\""); _metsPairs[_metsPairs.IndexOf(existingValue)] = newValue; } else { - _metsPairs.Add(JSONUtils.MakeKeyValuePair(kSilDomain, string.Format("{0}:{1}", domainAbbrev, domainName), true)); + _metsPairs.Add(JSONUtils.MakeKeyValuePair(kSilDomain, + $"{domainAbbrev}:{domainName}", true)); } } @@ -916,19 +902,19 @@ private void AddDomain(string domainAbbrev, string domainName) /// ------------------------------------------------------------------------------------ private void AddSubDomain(string domainAbbrev, string subDomain) { - // if a mets pair already exists for this domain, add this subdomain to the existing list. - var key = string.Format(kFmtDomainSubtype, domainAbbrev); + // if a mets pair already exists for this domain, add this sub-domain to the existing list. + var key = Format(kFmtDomainSubtype, domainAbbrev); var existingValue = _metsPairs.Find(s => s.Contains(key)); - if (!string.IsNullOrEmpty(existingValue)) + if (!IsNullOrEmpty(existingValue)) { int pos = existingValue.IndexOf(']'); - string newValue = existingValue.Insert(pos, string.Format(",\"{0} ({1})\"", subDomain, domainAbbrev)); + string newValue = existingValue.Insert(pos, $",\"{subDomain} ({domainAbbrev})\""); _metsPairs[_metsPairs.IndexOf(existingValue)] = newValue; } else { _metsPairs.Add(JSONUtils.MakeKeyValuePair(key, - string.Format("{0} ({1})", subDomain, domainAbbrev), true)); + $"{subDomain} ({domainAbbrev})", true)); } } @@ -937,6 +923,7 @@ private void AddSubDomain(string domainAbbrev, string subDomain) /// Adds a METS pair for the Date this resource was initially created /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetCreationDate(DateTime date) { SetCreationDate(date.ToISO8601TimeFormatDateOnlyString()); @@ -948,6 +935,7 @@ public void SetCreationDate(DateTime date) /// was collected or work was being done on this resource /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetCreationDate(int startYear, int endYear) { if (endYear < startYear) @@ -960,7 +948,7 @@ public void SetCreationDate(int startYear, int endYear) if (startYear < 0) endYr += (endYear < 0) ? " BCE" : " CE"; - SetCreationDate(string.Format("{0}-{1}", startYr, endYr)); + SetCreationDate($"{startYr}-{endYr}"); } /// ------------------------------------------------------------------------------------ @@ -969,10 +957,11 @@ public void SetCreationDate(int startYear, int endYear) /// was collected or work was being done on this resource /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetCreationDate(string date) { - if (string.IsNullOrEmpty(date)) - throw new ArgumentNullException("date"); + if (IsNullOrEmpty(date)) + throw new ArgumentNullException(nameof(date)); PreventDuplicateMetadataProperty(MetadataProperties.CreationDate); @@ -984,6 +973,7 @@ public void SetCreationDate(string date) /// Adds a METS pair for the Date this resource was last updated /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetModifiedDate(DateTime date) { PreventDuplicateMetadataProperty(MetadataProperties.ModifiedDate); @@ -999,6 +989,7 @@ public void SetModifiedDate(DateTime date) /// The 3-letter ISO 639-2 code for the language /// The English name of the language /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetSubjectLanguage(string iso3Code, string languageName) { PreventDuplicateMetadataProperty(MetadataProperties.SubjectLanguage); @@ -1012,7 +1003,7 @@ public void SetSubjectLanguage(string iso3Code, string languageName) /// /// Sets the given METS flag (typically appears as a checkbox in RAMP) to true/yes ("Y") /// - /// One of the kFlag... contants + /// One of the kFlag... constants /// ------------------------------------------------------------------------------------ private void SetFlag(string flagKey) { @@ -1027,6 +1018,7 @@ private void SetFlag(string flagKey) /// Be as specific a possible, indicating version number(s) /// where appropriate /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetSoftwareRequirements(params string[] requirements) { SetSoftwareRequirements((IEnumerable)requirements); @@ -1040,12 +1032,12 @@ public void SetSoftwareRequirements(params string[] requirements) /// Be as specific a possible, indicating version number(s) /// where appropriate /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetSoftwareRequirements(IEnumerable requirements) { - requirements = requirements.Where(r => !string.IsNullOrEmpty(r)); + requirements = requirements.Where(r => !IsNullOrEmpty(r)).ToList(); - HashSet softwareKeyValuePairs = new HashSet(); -// ReSharper disable PossibleMultipleEnumeration + var softwareKeyValuePairs = new HashSet(); if (requirements.Any()) { PreventDuplicateMetadataProperty(MetadataProperties.SoftwareRequirements); @@ -1057,7 +1049,6 @@ public void SetSoftwareRequirements(IEnumerable requirements) _metsPairs.Add(JSONUtils.MakeArrayFromValues(kSoftwareOrFontRequirements, softwareKeyValuePairs)); } -// ReSharper restore PossibleMultipleEnumeration } /// ------------------------------------------------------------------------------------ @@ -1070,13 +1061,14 @@ public void SetSoftwareRequirements(IEnumerable requirements) /// /// The 3-letter ISO 639-2 codes for the languages /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetContentLanguages(params string[] iso3Codes) { var languages = new List(); foreach (var iso3Code in iso3Codes) { - if (!string.IsNullOrEmpty(iso3Code)) + if (!IsNullOrEmpty(iso3Code)) languages.Add(new ArchivingLanguage(iso3Code)); } @@ -1094,20 +1086,22 @@ public void SetContentLanguages(params string[] iso3Codes) /// The 3-letter ISO 639-2 codes for the languages, as well as /// the English name, dialect and writing system script /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetContentLanguages(IEnumerable languages) { var languageValues = new HashSet(); var scripts = new HashSet(); - foreach (var lang in languages.Where(r => !string.IsNullOrEmpty(r.Iso3Code))) + foreach (var lang in languages.Where(r => !IsNullOrEmpty(r.Iso3Code))) { - var langPair = JSONUtils.MakeKeyValuePair(kDefaultKey, string.Format("{0}:{1}", lang.Iso3Code, GetLanguageName(lang.Iso3Code))); - if (!string.IsNullOrEmpty(lang.Dialect)) + var langPair = JSONUtils.MakeKeyValuePair(kDefaultKey, + $"{lang.Iso3Code}:{GetLanguageName(lang.Iso3Code)}"); + if (!IsNullOrEmpty(lang.Dialect)) langPair += "," + JSONUtils.MakeKeyValuePair("dialect", lang.Dialect); languageValues.Add(langPair); - if (!string.IsNullOrEmpty(lang.Script)) + if (!IsNullOrEmpty(lang.Script)) scripts.Add(JSONUtils.MakeKeyValuePair(kDefaultKey, lang.Script)); } @@ -1120,18 +1114,17 @@ public void SetContentLanguages(IEnumerable languages) if (scripts.Any()) _metsPairs.Add(JSONUtils.MakeArrayFromValues(kContentLanguageScripts, scripts)); } - - } /// ------------------------------------------------------------------------------------ /// /// Sets the schema(s) to which this resource -- or the file(s) it contains -- conforms. /// - /// Known schema name (typically, but not nescessarily, + /// Known schema name (typically, but not necessarily, /// for XML files). RAMP doesn't say what to do if the resource contains files conforming to /// multiple standards, but I would say just make a comma-separated list. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetSchemaConformance(string schemaDescriptor) { PreventDuplicateMetadataProperty(MetadataProperties.SchemaConformance); @@ -1145,10 +1138,11 @@ public void SetSchemaConformance(string schemaDescriptor) /// /// For example, "2505 entries" /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetDatasetExtent(string extent) { - if (string.IsNullOrEmpty(extent)) - throw new ArgumentNullException("extent"); + if (IsNullOrEmpty(extent)) + throw new ArgumentNullException(nameof(extent)); PreventDuplicateMetadataProperty(MetadataProperties.DatasetExtent); @@ -1160,6 +1154,7 @@ public void SetDatasetExtent(string extent) /// Sets the total duration of all audio and/or video recording in this resource. /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetAudioVideoExtent(TimeSpan totalDuration) { SetAudioVideoExtent(totalDuration.ToString()); @@ -1170,6 +1165,7 @@ public void SetAudioVideoExtent(TimeSpan totalDuration) /// Sets the total duration of all audio and/or video recording in this resource. ///
/// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetAudioVideoExtent(string totalDuration) { PreventDuplicateMetadataProperty(MetadataProperties.RecordingExtent); @@ -1182,10 +1178,11 @@ public void SetAudioVideoExtent(string totalDuration) /// Sets the collection of contributors (and their roles) to this resource. ///
/// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetContributors(ContributionCollection contributions) { if (contributions == null) - throw new ArgumentNullException("contributions"); + throw new ArgumentNullException(nameof(contributions)); if (contributions.Count == 0) return; @@ -1197,11 +1194,11 @@ public void SetContributors(ContributionCollection contributions) } /// ------------------------------------------------------------------------------------ - private string GetContributorsMetsPairs(Contribution contribution) + private static string GetContributorsMetsPairs(Contribution contribution) { - var roleCode = (contribution.Role != null && + var roleCode = contribution.Role != null && Properties.Settings.Default.RampContributorRoles.Contains(contribution.Role.Code) ? - contribution.Role.Code : string.Empty); + contribution.Role.Code : Empty; return JSONUtils.MakeKeyValuePair(kDefaultKey, contribution.ContributorName) + kSeparator + JSONUtils.MakeKeyValuePair(kRole, roleCode); @@ -1216,6 +1213,7 @@ private string GetContributorsMetsPairs(Contribution contribution) /// 20 major LWCs. Not sure what happens if an unrecognized code gets passed to this. /// Feel free to try it and find out. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetDescription(string description, string language) { SetGeneralDescription(new[] { GetKvpsForLanguageSpecificString(language, description) }); @@ -1230,10 +1228,11 @@ public void SetDescription(string description, string language) /// what happens if an unrecognized code gets passed to this. Feel free to try it and /// find out. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetDescription(IDictionary descriptions) { if (descriptions == null) - throw new ArgumentNullException("descriptions"); + throw new ArgumentNullException(nameof(descriptions)); if (descriptions.Count == 0) return; @@ -1274,7 +1273,7 @@ protected override void SetAbstract_Impl(IDictionary description IEnumerable metsDescriptions; - if (descriptions.Count == 1 && string.IsNullOrEmpty(descriptions.Keys.ElementAt(0))) + if (descriptions.Count == 1 && IsNullOrEmpty(descriptions.Keys.ElementAt(0))) metsDescriptions = new [] {JSONUtils.MakeKeyValuePair(kDefaultKey, descriptions.Values.ElementAt(0))}; else metsDescriptions = descriptions.Select(desc => GetKvpsForLanguageSpecificString(desc.Key, desc.Value)); @@ -1291,6 +1290,7 @@ protected override void SetAbstract_Impl(IDictionary description /// 20 major LWCs. Not sure what happens if an unrecognized code gets passed to this. /// Feel free to try it and find out. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetPromotion(string text, string language) { SetPromotion(new[] { GetKvpsForLanguageSpecificString(language, text) }); @@ -1305,10 +1305,11 @@ public void SetPromotion(string text, string language) /// happens if an unrecognized code gets passed to this. Feel free to try it and find /// out. /// ------------------------------------------------------------------------------------ + [PublicAPI] public void SetPromotion(IDictionary descriptions) { if (descriptions == null) - throw new ArgumentNullException("descriptions"); + throw new ArgumentNullException(nameof(descriptions)); if (descriptions.Count == 0) return; @@ -1353,75 +1354,28 @@ private string GetKvpsForLanguageSpecificString(string lang, string s) #region RAMP calling methods /// ------------------------------------------------------------------------------------ - internal override void LaunchArchivingProgram() + public override void LaunchArchivingProgram() { if (!File.Exists(PackagePath)) { - ReportError(null, string.Format("RAMP package prematurely removed: {0}", PackagePath)); + ReportError(null, Progress.GetMessage(StringId.RampPackageRemoved)); return; } - LaunchArchivingProgram(EnsureRampHasFocusAndWaitForPackageToUnlock); - } - - /// ------------------------------------------------------------------------------------ - private void EnsureRampHasFocusAndWaitForPackageToUnlock() - { - if (IsMono) + try { - BringToFrontMono(); + base.LaunchArchivingProgram(); } - else + catch (InvalidOperationException) { - BringToFrontWindows(); + // Every 4 seconds we'll check to see if the RAMP package is locked. When + // it gets unlocked by RAMP, then we'll delete it. + _timer = new Timer(CheckIfPackageFileIsLocked, PackagePath, 2000, 4000); } - - // Every 4 seconds we'll check to see if the RAMP package is locked. When - // it gets unlocked by RAMP, then we'll delete it. - _timer = new Timer(CheckIfPackageFileIsLocked, PackagePath, 2000, 4000); - } - - private static void BringToFrontWindows() - { - var processes = Process.GetProcessesByName(kRampProcessName); - if (processes.Length < 1) return; - - // First, make the window topmost: this puts it in front of all other windows - // and sets it as "always on top." - SetWindowPos(processes[0].MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); - - // Second, make the window notopmost: this removes the "always on top" behavior - // and positions the window on top of all other "not always on top" windows. - SetWindowPos(processes[0].MainWindowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); - } - - private static void BringToFrontMono() - { - // On mono this requires xdotool or wmctrl - string args = null; - if (!string.IsNullOrEmpty(FileLocationUtilities.LocateInProgramFiles("xdotool", true))) /* try to find xdotool first */ - args = "-c \"for pid in `xdotool search --name RAMP`; do xdotool windowactivate $pid; done\""; - else if (!string.IsNullOrEmpty(FileLocationUtilities.LocateInProgramFiles("wmctrl", true))) /* if xdotool is not installed, look for wmctrl */ - args = "-c \"wmctrl -a RAMP\""; - - if (string.IsNullOrEmpty(args)) return; - - var prs = new Process - { - StartInfo = - { - FileName = "bash", - Arguments = args, - UseShellExecute = false, - RedirectStandardError = true - } - }; - - prs.Start(); } /// ------------------------------------------------------------------------------------ - private void CheckIfPackageFileIsLocked(Object packageFile) + private void CheckIfPackageFileIsLocked(object packageFile) { if (!FileHelper.IsLocked(packageFile as string)) CleanUpTempRampPackage(); @@ -1432,25 +1386,22 @@ private void CheckIfPackageFileIsLocked(Object packageFile) /// ------------------------------------------------------------------------------------ /// Public to facilitate testing /// ------------------------------------------------------------------------------------ - public override bool CreatePackage() + public override async Task CreatePackage(CancellationToken cancellationToken) { IsBusy = true; var success = CreateMetsFile() != null; if (success) - success = CreateRampPackage(); + success = await CreateRampPackage(cancellationToken); - CleanUp(); + DeleteTempFolder(); if (success) - { - DisplayMessage(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.ReadyToCallRampMsg", - "Ready to hand the package to RAMP"), MessageType.Success); - } + DisplayMessage(StringId.ReadyToCallRampMsg, MessageType.Success); IsBusy = false; - return success; + return success? PackagePath : null; } /// ------------------------------------------------------------------------------------ @@ -1475,33 +1426,34 @@ public override string GetMetadata() foreach (var value in _metsPairs) bldr.AppendFormat("{0},", value); - return string.Format("{{{0}}}", bldr.ToString().TrimEnd(',')); + return $"{{{bldr.ToString().TrimEnd(',')}}}"; } /// ------------------------------------------------------------------------------------ - public string CreateMetsFile() + internal string CreateMetsFile() { try { - var metsData = Resources.EmptyMets.Replace("", "" + JSONUtils.EncodeData(GetMetadata())); - _tempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(_tempFolder); - _metsFilePath = Path.Combine(_tempFolder, "mets.xml"); - File.WriteAllText(_metsFilePath, metsData); + var metsData = GetResource(Name.EmptyMets_xml).Replace("", + "" + JSONUtils.EncodeData(GetMetadata())); + _tempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(_tempFolder); + _metsFilePath = Path.Combine(_tempFolder, "mets.xml"); + File.WriteAllText(_metsFilePath, metsData); } catch (Exception e) { - if ((e is IOException) || (e is UnauthorizedAccessException) || (e is SecurityException)) + if (e is IOException || e is UnauthorizedAccessException || + e is SecurityException) { - ReportError(e, LocalizationManager.GetString("DialogBoxes.ArchivingDlg.CreatingInternalReapMetsFileErrorMsg", - "There was an error attempting to create the RAMP/REAP mets file.")); + ReportError(e, Progress.GetMessage(StringId.ErrorCreatingMetsFile)); return null; } + throw; } - if (IncrementProgressBarAction != null) - IncrementProgressBarAction(); + Progress.IncrementProgress(); return _metsFilePath; } @@ -1509,7 +1461,7 @@ public string CreateMetsFile() /// ------------------------------------------------------------------------------------ private void SetMetsPairsForFiles() { - if (_fileLists.Any()) + if (FileLists.Any()) { string value = GetMode(); if (value != null) @@ -1519,12 +1471,12 @@ private void SetMetsPairsForFiles() { // Return JSON array of files with their descriptions. _metsPairs.Add(JSONUtils.MakeArrayFromValues(kSourceFilesForMets, - GetSourceFilesForMetsData(_fileLists))); + GetSourceFilesForMetsData(FileLists))); MarkMetadataPropertyAsSet(MetadataProperties.Files); } if (ImageCount > 0) - _metsPairs.Add(JSONUtils.MakeKeyValuePair(kImageExtent, string.Format("{0} image{1}.", + _metsPairs.Add(JSONUtils.MakeKeyValuePair(kImageExtent, Format("{0} image{1}.", _imageCount.ToString(CultureInfo.InvariantCulture), (_imageCount == 1) ? "" : "s"))); @@ -1599,7 +1551,7 @@ public IEnumerable GetSourceFilesForMetsData(IDictionary CreateRampPackage(CancellationToken cancellationToken) { + bool result = false; try { - PackagePath = Path.Combine(Path.GetTempPath(), _id + kRampFileExtension); + PackagePath = Path.Combine(Path.GetTempPath(), PackageId + kRampFileExtension); - using (_worker = new BackgroundWorker()) - { - _cancelProcess = false; - _workerException = false; - _worker.ProgressChanged += HandleBackgroundWorkerProgressChanged; - _worker.WorkerReportsProgress = true; - _worker.WorkerSupportsCancellation = true; - _worker.DoWork += CreateZipFileInWorkerThread; - _worker.RunWorkerAsync(); - - while (_worker.IsBusy) - Application.DoEvents(); - } - } - catch (Exception e) - { - ReportError(e, LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.CreatingZipFileErrorMsg", - "There was a problem starting process to create zip file.")); + CreateZipFile(cancellationToken); - return false; + if (!File.Exists(PackagePath)) + ReportError(null, Progress.GetMessage(StringId.FailedToMakePackage)); + else + result = true; } - finally + catch (OperationCanceledException) { - _worker = null; } - - if (!File.Exists(PackagePath)) + catch (Exception exception) { - ReportError(null, string.Format("Failed to make the RAMP package: {0}", PackagePath)); - return false; + ReportError(exception, Progress.GetMessage(StringId.ErrorCreatingArchive)); } - return !_cancelProcess && !_workerException; + return Task.FromResult(result); } /// ------------------------------------------------------------------------------------ - private void CreateZipFileInWorkerThread(object sender, DoWorkEventArgs e) + private void CreateZipFile(CancellationToken cancellationToken) { - try - { - if (Thread.CurrentThread.Name == null) - Thread.CurrentThread.Name = "CreateZipFileInWorkerThread"; + // Before adding the files to the RAMP (zip) file, we need to copy all the + // files to a temp folder, flattening out the directory structure and renaming + // the files as needed to comply with REAP guidelines. + // REVIEW: Are multiple periods and/or non-Roman script really a problem? - // Before adding the files to the RAMP (zip) file, we need to copy all the - // files to a temp folder, flattening out the directory structure and renaming - // the files as needed to comply with REAP guidelines. - // REVIEW: Are multiple periods and/or non-Roman script really a problem? + ReportProgress(Progress.GetMessage(StringId.PreparingFiles), MessageType.Success, + cancellationToken); - _worker.ReportProgress(0, PreparingFilesMsg); - - var filesToCopyAndZip = new Dictionary(); - foreach (var list in _fileLists) + var filesToCopyAndZip = new Dictionary(); + foreach (var list in FileLists) + { + ReportProgress(IsNullOrEmpty(list.Key) ? PackageId : list.Key, MessageType.Detail, + cancellationToken); + foreach (var file in list.Value.Item1) { - _worker.ReportProgress(1 /* actual value ignored, progress just increments */, - string.IsNullOrEmpty(list.Key) ? _id: list.Key); - foreach (var file in list.Value.Item1) - { - string newFileName = Path.GetFileName(file); - newFileName = NormalizeFilename(list.Key, newFileName); - filesToCopyAndZip[file] = Path.Combine(_tempFolder, newFileName); - } - if (_cancelProcess) - return; + string newFileName = Path.GetFileName(file); + newFileName = NormalizeFilename(list.Key, newFileName); + filesToCopyAndZip[file] = Path.Combine(_tempFolder, newFileName); } + } - _worker.ReportProgress(0, LocalizationManager.GetString("DialogBoxes.ArchivingDlg.CopyingFilesMsg", - "Copying files")); + ReportProgress(Progress.GetMessage(StringId.CopyingFiles), MessageType.Success, + cancellationToken); - foreach (var fileToCopy in filesToCopyAndZip) + foreach (var fileToCopy in filesToCopyAndZip) + { + ReportProgress(Path.GetFileName(fileToCopy.Key), MessageType.Detail, + cancellationToken); + if (FileCopyOverride != null) { - if (_cancelProcess) - return; - _worker.ReportProgress(1 /* actual value ignored, progress just increments */, - Path.GetFileName(fileToCopy.Key)); - if (FileCopyOverride != null) + try { - try + if (FileCopyOverride(this, fileToCopy.Key, fileToCopy.Value)) { - if (FileCopyOverride(this, fileToCopy.Key, fileToCopy.Value)) - { - if (!File.Exists(fileToCopy.Value)) - throw new FileNotFoundException("Calling application claimed to copy file but didn't", fileToCopy.Value); - continue; - } - } - catch (Exception error) - { - var msg = GetFileExcludedMsg(NameOfProgramToLaunch, fileToCopy.Value); - ReportError(error, msg); + if (!File.Exists(fileToCopy.Value)) + throw new FileNotFoundException( + "Calling application claimed to copy file but didn't", + fileToCopy.Value); + continue; } } - // Don't use File.Copy because it's asynchronous. - CopyFile(fileToCopy.Key, fileToCopy.Value); + catch (Exception error) + { + var msg = GetFileExcludedMsg(fileToCopy.Value); + ReportError(error, msg); + } } - _worker.ReportProgress(0, GetSavingFilesMsg(NameOfProgramToLaunch)); - - using (var zip = new ZipFile()) - { - // RAMP packages must not be compressed or RAMP can't read them. - zip.UseZip64WhenSaving = Zip64Option.AsNecessary; // See SP-2291 - zip.CompressionLevel = Ionic.Zlib.CompressionLevel.None; - zip.AddFiles(filesToCopyAndZip.Values, @"\"); - zip.AddFile(_metsFilePath, string.Empty); - zip.SaveProgress += HandleZipSaveProgress; - zip.Save(PackagePath); - - if (!_cancelProcess && IncrementProgressBarAction != null) - Thread.Sleep(800); - } + // Don't use File.Copy because it's asynchronous. + CopyFile(fileToCopy.Key, fileToCopy.Value); } - catch (Exception exception) + + ReportMajorProgressPoint(StringId.SavingFilesInPackage, cancellationToken); + + using (var zip = new ZipFile()) { - _worker.ReportProgress(0, new KeyValuePair(exception, - LocalizationManager.GetString("DialogBoxes.ArchivingDlg.CreatingRAMPFileErrorMsg", - "There was an error attempting to create the RAMP file."))); + // RAMP packages must not be compressed or RAMP can't read them. + zip.UseZip64WhenSaving = Zip64Option.AsNecessary; // See SP-2291 + zip.CompressionLevel = Ionic.Zlib.CompressionLevel.None; + zip.AddFiles(filesToCopyAndZip.Values, @"\"); + zip.AddFile(_metsFilePath, Empty); + zip.SaveProgress += delegate(object sender, SaveProgressEventArgs args) + { + HandleZipSaveProgress(args, cancellationToken); + }; + zip.Save(PackagePath); - _workerException = true; + if (!cancellationToken.IsCancellationRequested) + Thread.Sleep(800); } } @@ -1748,44 +1672,16 @@ private void CreateZipFileInWorkerThread(object sender, DoWorkEventArgs e) /// saved to the disk. ///
/// ------------------------------------------------------------------------------------ - private void HandleZipSaveProgress(object s, SaveProgressEventArgs e) + private void HandleZipSaveProgress(SaveProgressEventArgs e, + CancellationToken cancellationToken) { - if (_cancelProcess || e.EventType != ZipProgressEventType.Saving_BeforeWriteEntry) + if (e.EventType != ZipProgressEventType.Saving_BeforeWriteEntry) return; - string msg; - if (_progressMessages.TryGetValue(e.CurrentEntry.FileName, out msg)) + if (_progressMessages.TryGetValue(e.CurrentEntry.FileName, out var msg)) DisplayMessage(msg, MessageType.Progress); - _worker.ReportProgress(e.EntriesSaved + 1, Path.GetFileName(e.CurrentEntry.FileName)); - } - - /// ------------------------------------------------------------------------------------ - void HandleBackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e) - { - if (e.UserState == null || _cancelProcess) - return; - - if (e.UserState is KeyValuePair) - { - var kvp = (KeyValuePair)e.UserState; - ReportError(kvp.Key, kvp.Value); - return; - } - - if (!string.IsNullOrEmpty(e.UserState as string)) - { - if (e.ProgressPercentage == 0) - { - DisplayMessage(e.UserState.ToString(), MessageType.Success); - return; - } - - DisplayMessage(e.UserState.ToString(), MessageType.Detail); - } - - if (IncrementProgressBarAction != null) - IncrementProgressBarAction(); + ReportProgress(Path.GetFileName(e.CurrentEntry.FileName), MessageType.Detail, cancellationToken); } #endregion @@ -1813,7 +1709,7 @@ private static string GetLanguageFileLocation() //Ramp 3.0 Package doesn't have languages.yaml if (!Directory.Exists(Path.Combine(dir, "data"))) { - return string.Empty; + return Empty; } } // on Linux the exe and data directory are not in the same directory @@ -1829,24 +1725,24 @@ private static string GetLanguageFileLocation() //Ramp 3.0 Package doesn't have languages.yaml if (!Directory.Exists(Path.Combine(dir, "data"))) { - return string.Empty; + return Empty; } } // get the data directory dir = Path.Combine(dir, "data"); if (!Directory.Exists(dir)) - throw new DirectoryNotFoundException(string.Format("The path {0} is not valid.", dir)); + throw new DirectoryNotFoundException(Format("The path {0} is not valid.", dir)); // get the options directory dir = Path.Combine(dir, "options"); if (!Directory.Exists(dir)) - throw new DirectoryNotFoundException(string.Format("The path {0} is not valid.", dir)); + throw new DirectoryNotFoundException(Format("The path {0} is not valid.", dir)); // get the languages.yaml file var langFile = Path.Combine(dir, "languages.yaml"); if (!File.Exists(langFile)) - throw new FileNotFoundException(string.Format("The file {0} was not found.", langFile)); + throw new FileNotFoundException(Format("The file {0} was not found.", langFile), langFile); return langFile; } @@ -1901,31 +1797,28 @@ public string GetLanguageName(string iso3Code) } #endregion - /// ------------------------------------------------------------------------------------ - public override void Cancel() - { - base.Cancel(); - - CleanUp(); - CleanUpTempRampPackage(); - } - /// ------------------------------------------------------------------------------------ public override IArchivingSession AddSession(string sessionId) { throw new NotImplementedException(); } - public override IArchivingPackage ArchivingPackage - { - get { throw new NotImplementedException(); } - } + public override IArchivingPackage ArchivingPackage => throw new NotImplementedException(); #region Clean-up methods /// ------------------------------------------------------------------------------------ - public void CleanUp() + protected internal override void CleanUp() + { + base.CleanUp(); + DeleteTempFolder(); + CleanUpTempRampPackage(); + } + + private void DeleteTempFolder() { - try { Directory.Delete(_tempFolder, true); } + try { + Directory.Delete(_tempFolder, true); + } // ReSharper disable once EmptyGeneralCatchClause catch { } } @@ -1933,6 +1826,7 @@ public void CleanUp() /// ------------------------------------------------------------------------------------ public void CleanUpTempRampPackage() { + // REVIEW: How long is this test supposed to last? // Comment out as a test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //try { File.Delete(RampPackagePath); } //catch { } diff --git a/SIL.Windows.Forms.Archiving/Resources/AccessProtocols.json b/SIL.Archiving/Resources/AccessProtocols.json similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/AccessProtocols.json rename to SIL.Archiving/Resources/AccessProtocols.json diff --git a/SIL.Windows.Forms.Archiving/Resources/CustomAccessProtocols.json b/SIL.Archiving/Resources/CustomAccessProtocols.json similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/CustomAccessProtocols.json rename to SIL.Archiving/Resources/CustomAccessProtocols.json diff --git a/SIL.Windows.Forms.Archiving/Resources/EmptyMets.xml b/SIL.Archiving/Resources/EmptyMets.xml similarity index 59% rename from SIL.Windows.Forms.Archiving/Resources/EmptyMets.xml rename to SIL.Archiving/Resources/EmptyMets.xml index 8a99cd22b..0eaceafec 100644 --- a/SIL.Windows.Forms.Archiving/Resources/EmptyMets.xml +++ b/SIL.Archiving/Resources/EmptyMets.xml @@ -1,4 +1,4 @@ - + diff --git a/SIL.Archiving/Resources/Resources.cs b/SIL.Archiving/Resources/Resources.cs new file mode 100644 index 000000000..8b627c66d --- /dev/null +++ b/SIL.Archiving/Resources/Resources.cs @@ -0,0 +1,37 @@ +using System.IO; +using System.Reflection; +using System.Resources; + +namespace SIL.Archiving.Resources +{ + internal static class Resources + { + public enum Name + { + AccessProtocols_json, + CustomAccessProtocols_json, + EmptyMets_xml, + } + + public static string GetResource(Name namedResource) + { + return GetResource(namedResource.ToString().Replace("_", ".")); + } + + public static string GetResource(string filename) + { + using (var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream($"SIL.Archiving.Resources.{filename}")) + { + if (stream == null) + { + throw new MissingManifestResourceException( + $"{filename} resource not found"); + } + + var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } + } + } +} diff --git a/SIL.Windows.Forms.Archiving/Resources/ailca.html b/SIL.Archiving/Resources/ailca.html similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/ailca.html rename to SIL.Archiving/Resources/ailca.html diff --git a/SIL.Windows.Forms.Archiving/Resources/ailla.html b/SIL.Archiving/Resources/ailla.html similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/ailla.html rename to SIL.Archiving/Resources/ailla.html diff --git a/SIL.Windows.Forms.Archiving/Resources/anla.html b/SIL.Archiving/Resources/anla.html similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/anla.html rename to SIL.Archiving/Resources/anla.html diff --git a/SIL.Windows.Forms.Archiving/Resources/elar.html b/SIL.Archiving/Resources/elar.html similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/elar.html rename to SIL.Archiving/Resources/elar.html diff --git a/SIL.Windows.Forms.Archiving/Resources/reap.html b/SIL.Archiving/Resources/reap.html similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/reap.html rename to SIL.Archiving/Resources/reap.html diff --git a/SIL.Windows.Forms.Archiving/Resources/tla.html b/SIL.Archiving/Resources/tla.html similarity index 100% rename from SIL.Windows.Forms.Archiving/Resources/tla.html rename to SIL.Archiving/Resources/tla.html diff --git a/SIL.Archiving/SIL.Archiving.csproj b/SIL.Archiving/SIL.Archiving.csproj new file mode 100644 index 000000000..14048bbed --- /dev/null +++ b/SIL.Archiving/SIL.Archiving.csproj @@ -0,0 +1,67 @@ + + + + SIL.Archiving + SIL.Archiving + SIL.Archiving contains classes for archiving data to REAP and IMDI. + + + + + + + + + + + + + + + + + + + All + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Settings.settings + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + \ No newline at end of file diff --git a/SIL.Scripture.Tests/SIL.Scripture.Tests.csproj b/SIL.Scripture.Tests/SIL.Scripture.Tests.csproj index 41605e9f3..03e90300d 100644 --- a/SIL.Scripture.Tests/SIL.Scripture.Tests.csproj +++ b/SIL.Scripture.Tests/SIL.Scripture.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs index 3195acdd5..b45d5e81d 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs @@ -1,4 +1,4 @@ -using SIL.Windows.Forms.Progress; +using SIL.Windows.Forms.Progress; namespace SIL.Windows.Forms.Archiving { @@ -178,6 +178,7 @@ private void InitializeComponent() this._buttonCancel.TabIndex = 2; this._buttonCancel.Text = "Cancel"; this._buttonCancel.UseVisualStyleBackColor = true; + this._buttonCancel.Click += new System.EventHandler(this.HandleButtonCancelClick); // // _flowLayoutExtra // diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs index 7f32e5c8b..c26d1adaa 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs @@ -1,75 +1,118 @@ using System; +using System.Diagnostics; using System.Drawing; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; -using SIL.Windows.Forms; +using L10NSharp; +using SIL.Archiving; +using SIL.EventsAndDelegates; +using SIL.IO; +using SIL.PlatformUtilities; +using SIL.Reporting; using SIL.Windows.Forms.Miscellaneous; using SIL.Windows.Forms.PortableSettingsProvider; +using static System.Environment; +using static System.String; +using static SIL.Archiving.ArchivingDlgViewModel.StringId; + +// ReSharper disable InconsistentNaming namespace SIL.Windows.Forms.Archiving { /// ---------------------------------------------------------------------------------------- - public partial class ArchivingDlg : Form + public partial class ArchivingDlg : Form, IArchivingProgressDisplay { + [DllImport("user32.dll", EntryPoint = "SetWindowPos")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool SetWindowPosWindows(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); + + // ReSharper disable InconsistentNaming + // ReSharper disable IdentifierTypo + private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); // brings window to top and makes it "always on top" + private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); // brings window to top but not "always on top" + private const UInt32 SWP_NOSIZE = 0x0001; + private const UInt32 SWP_NOMOVE = 0x0002; + private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE; + // ReSharper restore InconsistentNaming + // ReSharper restore IdentifierTypo + private readonly FormSettings _settings; protected readonly ArchivingDlgViewModel _viewModel; protected readonly string _launchButtonTextFormat; + protected readonly string _appSpecificArchivalProcessInfo; + protected readonly string _archiveInfoHyperlinkText; + private Exception _exceptionToNotReport; + + private CancellationTokenSource _cts; + + protected virtual string ArchiveTypeForTitleBar => + _viewModel?.ArchiveType == ArchivingDlgViewModel.Standard.REAP ? + LocalizationManager.GetString("DialogBoxes.ArchivingDlg.RAMPArchiveType", + "RAMP (SIL Only)") : null; + + protected virtual string InformativeText => + _viewModel?.ArchiveType == ArchivingDlgViewModel.Standard.REAP ? + Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.RAMPOverviewText", + "{0} is a utility for entering metadata and uploading submissions to SIL's internal archive, " + + "REAP. If you have access to this archive, this tool will help you use {0} to archive your " + + "{1} data. {2} When the {0} package has been created, you can launch {0} and enter any " + + "additional information before doing the actual submission.", + "Parameter 0 is the word 'RAMP' (the first one will be turned into a hyperlink); " + + "Parameter 1 is the name of the calling (host) program (SayMore, FLEx, etc.); " + + "Parameter 2 is additional app-specific information."), _viewModel.NameOfProgramToLaunch, _viewModel.AppName, + _appSpecificArchivalProcessInfo) : _appSpecificArchivalProcessInfo; /// ------------------------------------------------------------------------------------ /// Caller can use this to retrieve and persist form settings (typically /// after form is closed). /// ------------------------------------------------------------------------------------ - public FormSettings FormSettings - { - get { return _settings; } - } + public FormSettings FormSettings => _settings; /// ------------------------------------------------------------------------------------ /// View model + /// Application can use this to pass + /// additional information that will be displayed to the user in the dialog to explain + /// any application-specific details about the archival process. For archive systems + /// ( that this "generic" archiving dialog box + /// does not specifically know what to show as informative text, the value passed in + /// to this parameter will be displayed. /// The ID of the localization manager for the /// calling application. /// Application can set this to ensure a consistent look /// in the UI (especially useful for when a localization requires a particular font). /// Location, size, and state where the client would like the /// dialog box to appear (can be null) + /// Text in the InformativeText that will be + /// marked as a hyperlink to ArchiveInfoUrl (first occurrence only). Defaults to + /// > /// ------------------------------------------------------------------------------------ - public ArchivingDlg(ArchivingDlgViewModel model, string localizationManagerId, - Font programDialogFont, FormSettings settings) + public ArchivingDlg(ArchivingDlgViewModel model, string appSpecificArchivalProcessInfo, + string localizationManagerId, Font programDialogFont, FormSettings settings, + string archiveInfoHyperlinkText = null) { _settings = settings ?? FormSettings.Create(this); _viewModel = model; + _appSpecificArchivalProcessInfo = appSpecificArchivalProcessInfo; + _archiveInfoHyperlinkText = archiveInfoHyperlinkText ?? + _viewModel.NameOfProgramToLaunch; InitializeComponent(); - if (!string.IsNullOrEmpty(localizationManagerId)) + if (!IsNullOrEmpty(localizationManagerId)) locExtender.LocalizationManagerId = localizationManagerId; - Text = string.Format(Text, model.AppName, model.ArchiveType); - _progressBar.Visible = false; - - // remember this because we will need it later in a derived class _launchButtonTextFormat = _buttonLaunchRamp.Text; - - UpdateLaunchButtonText(); - _buttonLaunchRamp.Enabled = false; //!string.IsNullOrEmpty(model.PathToProgramToLaunch); + _progressBar.Visible = false; _chkMetadataOnly.Visible = _viewModel is ISupportMetadataOnly; - _linkOverview.Text = model.InformativeText; - _linkOverview.Links.Clear(); - - if (!string.IsNullOrEmpty(model.ArchiveInfoUrl) && !string.IsNullOrEmpty(model.ArchiveInfoHyperlinkText)) - { - int i = _linkOverview.Text.IndexOf(model.ArchiveInfoHyperlinkText, StringComparison.InvariantCulture); - if (i >= 0) - _linkOverview.Links.Add(i, model.ArchiveInfoHyperlinkText.Length, model.ArchiveInfoUrl); - } - - // this is for a display problem in mono - _linkOverview.SizeToContents(); _logBox.Tag = false; - model.OnDisplayMessage += DisplayMessage; - model.OnDisplayError += new ArchivingDlgViewModel.DisplayErrorEventHandler(model_DisplayError); + model.OnReportMessage += DisplayMessage; + model.OnError += DisplayError; + model.OnExceptionDuringLaunch += HandleLaunchException; if (programDialogFont != null) { @@ -85,21 +128,96 @@ public ArchivingDlg(ArchivingDlgViewModel model, string localizationManagerId, _buttonCancel.MouseLeave += delegate { - if (model.IsBusy) + if (_cts != null) WaitCursor.Show(); }; _buttonCancel.MouseEnter += delegate { - if (model.IsBusy) + if (_cts != null) WaitCursor.Hide(); }; - _buttonCancel.Click += delegate + } + + private void HandleButtonCancelClick(object sender, EventArgs args) + { + try { - model.Cancel(); - WaitCursor.Hide(); + _cts?.Cancel(); + // British spelling for the ID. American spelling for the string :-) + DisplayMessage(NewLine + LocalizationManager.GetString("DialogBoxes.ArchivingDlg.CancellingMsg", "Canceling..."), ArchivingDlgViewModel.MessageType.Error); + } + catch (Exception e) + { + // Probably a race condition - process just ended. + Console.WriteLine(e); + } + } + + private void HandleLaunchException(EventArgs args) + { + if (_viewModel.ArchiveType == ArchivingDlgViewModel.Standard.REAP && + args.Item is InvalidOperationException) + { + _exceptionToNotReport = args.Item; + EnsureRampHasFocusAndWaitForPackageToUnlock(); + } + } + + /// ------------------------------------------------------------------------------------ + private void EnsureRampHasFocusAndWaitForPackageToUnlock() + { + if (ArchivingDlgViewModel.IsMono) + BringToFrontMono(); + else + BringToFrontWindows(); + } + + private static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, + int cy, uint uFlags) + { + // on Linux simply return true + return !Platform.IsWindows || SetWindowPosWindows(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); + } + + private static void BringToFrontWindows() + { + var processes = Process.GetProcessesByName(RampArchivingDlgViewModel.kRampProcessName); + if (processes.Length < 1) return; + + // First, make the window topmost: this puts it in front of all other windows + // and sets it as "always on top." + SetWindowPos(processes[0].MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); + + // Second, make the window not top-most: this removes the "always on top" behavior + // and positions the window on top of all other "not always on top" windows. + SetWindowPos(processes[0].MainWindowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); + } + + private static void BringToFrontMono() + { + // On mono this requires xdotool or wmctrl + string args = null; + if (!IsNullOrEmpty(FileLocationUtilities.LocateInProgramFiles("xdotool", true))) /* try to find xdotool first */ + args = "-c \"for pid in `xdotool search --name RAMP`; do xdotool windowactivate $pid; done\""; + else if (!IsNullOrEmpty(FileLocationUtilities.LocateInProgramFiles("wmctrl", true))) /* if xdotool is not installed, look for wmctrl */ + args = "-c \"wmctrl -a RAMP\""; + + if (IsNullOrEmpty(args)) return; + + var prs = new Process + { + StartInfo = + { + FileName = "bash", + Arguments = args, + UseShellExecute = false, + RedirectStandardError = true + } }; + + prs.Start(); } private void CreatePackage(object sender, EventArgs eventArgs) @@ -109,9 +227,63 @@ private void CreatePackage(object sender, EventArgs eventArgs) _progressBar.Visible = true; WaitCursor.Show(); _logBox.Clear(); - _buttonLaunchRamp.Enabled = _viewModel.CreatePackage(); - _progressBar.Visible = false; - WaitCursor.Hide(); + + Task.Run(async () => await CreatePackageAsync()); + } + + private async Task CreatePackageAsync() + { + _cts = new CancellationTokenSource(); + + try + { + var result = await _viewModel.CreatePackage(_cts.Token); + + if (result != null) + PackageCreationComplete(result); + } + catch (OperationCanceledException) + { + CompleteCancellation(); + } + catch (Exception ex) + { + // Handle any other exceptions + DisplayMessage(GetMessage(ErrorCreatingArchive) + + NewLine + ex.Message, ArchivingDlgViewModel.MessageType.Error); + } + finally + { + _progressBar.Visible = false; + WaitCursor.Hide(); + + try + { + _cts.Dispose(); + } + catch (Exception e) + { + Logger.WriteError(e); + } + _cts = null; + } + } + + private void CompleteCancellation() + { + // American spelling for the ID. British spelling for the string :-) + DisplayMessage(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.CanceledMsg", "Cancelled..."), + ArchivingDlgViewModel.MessageType.Error); + + Thread.Sleep(500); + DialogResult = DialogResult.Cancel; + Close(); + } + + protected virtual void PackageCreationComplete(string result) + { + _buttonLaunchRamp.Enabled = true; } protected virtual void DisableControlsDuringPackageCreation() @@ -123,17 +295,123 @@ protected virtual void DisableControlsDuringPackageCreation() /// ------------------------------------------------------------------------------------ protected void UpdateLaunchButtonText() { - _buttonLaunchRamp.Text = string.Format(_launchButtonTextFormat, _viewModel.NameOfProgramToLaunch); + _buttonLaunchRamp.Text = Format(_launchButtonTextFormat, _viewModel.NameOfProgramToLaunch); } /// ------------------------------------------------------------------------------------ protected void UpdateOverviewText() { - _linkOverview.Text = _viewModel.InformativeText; + _linkOverview.Text = InformativeText; + } + + #region Implementation of IArchivingProgressDisplay + + public void IncrementProgress() + { + _progressBar.Increment(1); + } + + /// ------------------------------------------------------------------------------------ + public virtual string GetMessage(ArchivingDlgViewModel.StringId msgId) + { + switch (msgId) + { + case PreArchivingStatus: + return LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.PrearchivingStatusMsg", + "The following files will be added to the archive:"); + case SearchingForArchiveUploadingProgram: + return Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.SearchingForRampMsg", + "Searching for the {0} program...", + "Parameter is the path to the auxiliary archive upload program (RAMP, etc.)."), + _viewModel.PathToProgramToLaunch); + case ArchiveUploadingProgramNotFound: + return Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.RampNotFoundMsg", + "The {0} program cannot be found!", + "Parameter is the path to the auxiliary archive upload program (RAMP, etc.)."), + _viewModel.PathToProgramToLaunch); + case ErrorStartingArchivalProgram: + return Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.StartingRampErrorMsg", + "There was an error attempting to open the archive package in {0}.", + "Parameter is the path to the auxiliary archive upload program (RAMP, etc.)."), + _viewModel.PathToProgramToLaunch); + case PreparingFiles: + return LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.PreparingFilesMsg", + "Analyzing component files"); + case SavingFilesInPackage: + return Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.SavingFilesInPackageMsg", + "Saving files in {0} package", + "Parameter is the type of archive (e.g., RAMP/IMDI)"), ArchiveTypeName); + case FileExcludedFromPackage: + return Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.FileExcludedFromPackage", + "File excluded from {0} package: ", + "Parameter is the type of archive (e.g., RAMP/IMDI)"), ArchiveTypeName); + case PathNotWritable: + return LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.PathNotWritableMsg", + "The path is not writable: {0}"); + case ReadyToCallRampMsg: + return LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.ReadyToCallRampMsg", + "Ready to hand the package to RAMP"); + case CopyingFiles: + return LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.CopyingFilesMsg", + "Copying files"); + case FailedToMakePackage: + return Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.FailedToMakePackage", + "Failed to make the {0} package: {1}", + "Param 0: The type of archive (e.g., RAMP); " + + "Param 1: Path to the package that was supposed to get created"), + ArchiveTypeName, _viewModel.PackagePath); + case ErrorCreatingMetsFile: + return Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.CreatingInternalReapMetsFileErrorMsg", + "There was an error attempting to create the {0}/{1} {2} file.", + "Param 0: \"RAMP\" (program for uploading to REAP)" + + "Param 1: \"REAP\" (SIL's corporate archive repository)" + + "Param 2: \"METS\" (Acronym for the Metadata Encoding & Transmission Standard used by the U.S. Library of Congress)"), + RampArchivingDlgViewModel.kRampProcessName, "REAP", "METS"); + case RampPackageRemoved: + return Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.", + "{0} package prematurely removed: {1}", + "Param 0: \"RAMP\" (program for uploading to REAP)" + + "Param 1: Path to the missing package"), + _viewModel.PackagePath); + case ErrorCreatingArchive: + return Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.CreatingArchiveErrorMsg", + "There was an error attempting to create the {0} package: {1}", + "Parameter is the type of archive (e.g., RAMP/IMDI)"), + ArchiveTypeName, _viewModel.PackagePath); + default: + throw new ArgumentOutOfRangeException(nameof(msgId), msgId, null); + } + } + + public virtual string ArchiveTypeName => + _viewModel?.ArchiveType == ArchivingDlgViewModel.Standard.REAP + ? RampArchivingDlgViewModel.kRampProcessName : + _viewModel?.ArchiveType.ToString() ?? "Other"; + + #endregion + + /// ------------------------------------------------------------------------------------ + protected void DisplayMessage(string msg, ArchivingDlgViewModel.MessageType type) + { + if (InvokeRequired) + Invoke(new Action(() => { DisplayMessageOnUIThread(msg, type); })); + + DisplayMessageOnUIThread(msg, type); } /// ------------------------------------------------------------------------------------ - void DisplayMessage(string msg, ArchivingDlgViewModel.MessageType type) + private void DisplayMessageOnUIThread(string msg, ArchivingDlgViewModel.MessageType type) { if ((bool) _logBox.Tag) { @@ -146,7 +424,7 @@ void DisplayMessage(string msg, ArchivingDlgViewModel.MessageType type) _logBox.WriteMessage(msg); break; case ArchivingDlgViewModel.MessageType.Indented: - _logBox.WriteMessage(Environment.NewLine + " " + msg); + _logBox.WriteMessage(NewLine + " " + msg); break; case ArchivingDlgViewModel.MessageType.Detail: _logBox.WriteMessageWithFontStyle(FontStyle.Regular, "\t" + msg); @@ -155,16 +433,16 @@ void DisplayMessage(string msg, ArchivingDlgViewModel.MessageType type) _logBox.WriteMessageWithFontStyle(FontStyle.Regular, " \u00B7 {0}", msg); break; case ArchivingDlgViewModel.MessageType.Progress: - _logBox.WriteMessage(Environment.NewLine + msg); + _logBox.WriteMessage(NewLine + msg); break; case ArchivingDlgViewModel.MessageType.Warning: _logBox.WriteWarning(msg); break; case ArchivingDlgViewModel.MessageType.Error: - _logBox.WriteMessageWithColor("Red", msg + Environment.NewLine); + _logBox.WriteMessageWithColor("Red", msg + NewLine); break; case ArchivingDlgViewModel.MessageType.Success: - _logBox.WriteMessageWithColor(Color.DarkGreen, Environment.NewLine + msg); + _logBox.WriteMessageWithColor(Color.DarkGreen, NewLine + msg); break; case ArchivingDlgViewModel.MessageType.Volatile: _logBox.WriteMessage(msg); @@ -174,7 +452,22 @@ void DisplayMessage(string msg, ArchivingDlgViewModel.MessageType type) } /// ------------------------------------------------------------------------------------ - void model_DisplayError(string msg, string packageTitle, Exception e) + private void DisplayError(string msg, string packageTitle, Exception e) + { + if (e == _exceptionToNotReport) + { + _exceptionToNotReport = null; + return; + } + + if (InvokeRequired) + Invoke(new Action(() => { DisplayErrorOnUIThread(msg, packageTitle, e); })); + + DisplayErrorOnUIThread(msg, packageTitle, e); + } + + /// ------------------------------------------------------------------------------------ + private void DisplayErrorOnUIThread(string msg, string packageTitle, Exception e) { if (_logBox.IsHandleCreated) { @@ -183,7 +476,6 @@ void model_DisplayError(string msg, string packageTitle, Exception e) if (e != null) _logBox.WriteException(e); } - } /// ------------------------------------------------------------------------------------ @@ -191,26 +483,69 @@ protected override void OnLoad(EventArgs e) { _settings.InitializeForm(this); base.OnLoad(e); + + Text = Format(Text, _viewModel.AppName, ArchiveTypeForTitleBar ?? ArchiveTypeName); + + UpdateLaunchButtonText(); + _buttonLaunchRamp.Enabled = false; //!string.IsNullOrEmpty(model.PathToProgramToLaunch); + + _linkOverview.Text = InformativeText; + _linkOverview.Links.Clear(); + + if (!IsNullOrEmpty(_viewModel.ArchiveInfoUrl) && !IsNullOrEmpty(_archiveInfoHyperlinkText)) + { + int i = _linkOverview.Text.IndexOf(_archiveInfoHyperlinkText, StringComparison.InvariantCulture); + if (i >= 0) + _linkOverview.Links.Add(i, _archiveInfoHyperlinkText.Length, _viewModel.ArchiveInfoUrl); + } + + // this is for a display problem in mono + _linkOverview.SizeToContents(); } /// ------------------------------------------------------------------------------------ protected override void OnShown(EventArgs e) { base.OnShown(e); + Initialize(); + WaitCursor.Show(); + _buttonCreatePackage.Enabled = false; + } + + /// ------------------------------------------------------------------------------------ + protected async void Initialize() + { + _cts = new CancellationTokenSource(); try { - WaitCursor.Show(); - _viewModel.IncrementProgressBarAction = () => _progressBar.Increment(1); - _buttonCreatePackage.Enabled = _viewModel.Initialize(); + _buttonCreatePackage.Enabled = await _viewModel.Initialize(this, _cts.Token); _logBox.ScrollToTop(); _progressBar.Maximum = _viewModel.CalculateMaxProgressBarValue(); - WaitCursor.Hide(); + _buttonCreatePackage.Enabled = true; + } + catch (OperationCanceledException) + { + CompleteCancellation(); + } + catch (Exception ex) + { + ErrorReport.ReportNonFatalException(ex); + Close(); } - catch + finally { WaitCursor.Hide(); - throw; + + try + { + _cts.Dispose(); + } + catch (Exception e) + { + Logger.WriteError(e); + } + _cts = null; } } @@ -219,7 +554,7 @@ private void HandleRampLinkClicked(object sender, LinkLabelLinkClickedEventArgs { var tgt = e.Link.LinkData as string; - if (!string.IsNullOrEmpty(tgt)) + if (!IsNullOrEmpty(tgt)) System.Diagnostics.Process.Start(tgt); } diff --git a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs index 6decc1302..8b316583d 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs @@ -3,12 +3,17 @@ using System.IO; using System.Linq; using System.Windows.Forms; +using JetBrains.Annotations; using L10NSharp; +using SIL.Archiving; +using SIL.Archiving.IMDI; using SIL.Windows.Forms.PortableSettingsProvider; +// ReSharper disable InconsistentNaming namespace SIL.Windows.Forms.Archiving.IMDI { /// + [PublicAPI] public class IMDIArchivingDlg : ArchivingDlg { private TableLayoutPanel _destinationFolderTable; @@ -19,9 +24,25 @@ public class IMDIArchivingDlg : ArchivingDlg private LinkLabel _browseIMDIProgram; private ComboBox _selectIMDIPreset; - /// - public IMDIArchivingDlg(ArchivingDlgViewModel model, string localizationManagerId, Font programDialogFont, FormSettings settings) - : base(model, localizationManagerId, programDialogFont, settings) + /// ------------------------------------------------------------------------------------ + /// View model + /// Application can use this to pass + /// additional information that will be displayed to the user in the dialog to explain + /// any application-specific details about the archival process. + /// The ID of the localization manager for the + /// calling application. + /// Application can set this to ensure a consistent look + /// in the UI (especially useful for when a localization requires a particular font). + /// Location, size, and state where the client would like the + /// dialog box to appear (can be null) + /// ------------------------------------------------------------------------------------ + public IMDIArchivingDlg(IMDIArchivingDlgViewModel model, + string appSpecificArchivalProcessInfo, string localizationManagerId, + Font programDialogFont, FormSettings settings) + : base(model, appSpecificArchivalProcessInfo, localizationManagerId, + programDialogFont, settings, LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.IsleMetadataInitiative", "Isle Metadata Initiative", + "Typically this probably does not need to be localized.")) { // DO NOT SHOW THE LAUNCH OPTION AT THIS TIME model.PathToProgramToLaunch = null; @@ -29,7 +50,7 @@ public IMDIArchivingDlg(ArchivingDlgViewModel model, string localizationManagerI InitializeNewControls(); // get the saved IMDI program value - GetSavedValues(); + model.GetSavedValues(); // set control properties SetControlProperties(); @@ -80,12 +101,84 @@ private void AddDestinationFolder() _flowLayoutExtra.Controls.Add(_destinationFolderTable); } + public override string ArchiveTypeName => + LocalizationManager.GetString("DialogBoxes.ArchivingDlg.IMDIArchiveType", "IMDI", + "This is the abbreviation for Isle Metadata Initiative (https://www.mpi.nl/imdi/). " + + "Typically this probably does not need to be localized."); + + /// ------------------------------------------------------------------------------------ + protected override string InformativeText + { + get + { + string programInfo = string.IsNullOrEmpty(_viewModel.NameOfProgramToLaunch) ? + string.Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.NoIMDIProgramInfoText", + "The {0} package will be created in {1}.", + "Parameter 0 is 'IMDI'; " + + "Parameter 1 is the path where the package is created."), + _viewModel.ArchiveType, _viewModel.PackagePath) + : + string.Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.IMDIProgramInfoText", + "This tool will help you use {0} to archive your {1} data. When the {1} package has been " + + "created, you can launch {0} and enter any additional information before doing the actual submission.", + "Parameter 0 is the name of the program that will be launched to further prepare the IMDI data for submission; " + + "Parameter 1 is the name of the calling (host) program (SayMore, FLEx, etc.)"), + _viewModel.NameOfProgramToLaunch, _viewModel.AppName); + return string.Format(LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.IMDIOverviewText", + "{0} ({1}) is a metadata standard to describe multi-media and multi-modal language " + + "resources. The standard provides interoperability for browsable and searchable " + + "corpus structures and resource descriptions.", + "Parameter 0 is 'Isle Metadata Initiative' (the first occurrence will be turned into a hyperlink); " + + "Parameter 1 is 'IMDI'"), + _archiveInfoHyperlinkText, _viewModel.ArchiveType) + + " " + _appSpecificArchivalProcessInfo + + " " + programInfo; + } + } + protected override void DisableControlsDuringPackageCreation() { base.DisableControlsDuringPackageCreation(); _destinationFolderTable.Visible = false; } + protected override void PackageCreationComplete(string result) + { + base.PackageCreationComplete(result); + + var mainExportFile = result; + + if (mainExportFile != null) + { + // copy the path to the imdi file to the clipboard + + // SP-818: Crash in IMDI export when dialog tries to put string on clipboard + // 18 FEB 2014, Phil Hopper: I found this possible solution using retries on StackOverflow + // https://stackoverflow.com/questions/5707990/requested-clipboard-operation-did-not-succeed + //Clipboard.SetData(DataFormats.Text, _imdiData.MainExportFile); + Clipboard.SetDataObject(mainExportFile, true, 3, 500); + + var successMsg = LocalizationManager.GetString("DialogBoxes.ArchivingDlg.ReadyToCallIMDIMsg", + "Exported to {0}. This path is now on your clipboard. If you are using Arbil, go to File, Import, then paste this path in."); + DisplayMessage(string.Format(successMsg, mainExportFile), ArchivingDlgViewModel.MessageType.Success); + } + } + + public override string GetMessage(ArchivingDlgViewModel.StringId msgId) + { + switch (msgId) + { + case ArchivingDlgViewModel.StringId.IMDIActorsGroup: + return LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.IMDIActorsGroup", "Actors", + "This is the heading displayed in the Archive Using IMDI dialog box for the files for the actors/participants"); + default: return base.GetMessage(msgId); + } + } + void SetDestinationLabelText() { var labelText = ((IMDIArchivingDlgViewModel)_viewModel).OutputFolder; diff --git a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlgViewModel.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlgViewModel.cs deleted file mode 100644 index 67833dc00..000000000 --- a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlgViewModel.cs +++ /dev/null @@ -1,620 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using L10NSharp; -using SIL.Windows.Forms.Archiving.Generic; -using SIL.Windows.Forms.Archiving.IMDI.Schema; -using System.Windows.Forms; -using SIL.Extensions; - -namespace SIL.Windows.Forms.Archiving.IMDI -{ - /// Implements archiving for IMDI repositories - public class IMDIArchivingDlgViewModel : ArchivingDlgViewModel, ISupportMetadataOnly - { - private readonly IMDIPackage _imdiData; - private string _corpusDirectoryName; - private bool _workerException; - private string _programPreset; - private string _otherProgramPath; - private readonly string _configFileName = Path.Combine(ArchivingFileSystem.SilCommonArchivingDataFolder, "IMDIProgram.config"); - private string _outputFolder; - - #region Properties - internal override string ArchiveType - { - get - { - return LocalizationManager.GetString("DialogBoxes.ArchivingDlg.IMDIArchiveType", "IMDI", - "This is the abbreviation for Isle Metadata Initiative (https://www.mpi.nl/imdi/). " + - "Typically this probably does not need to be localized."); - } - } - - public override string NameOfProgramToLaunch - { - get - { - // DO NOT SHOW THE LAUNCH OPTION AT THIS TIME - return null; - - //if (string.IsNullOrEmpty(PathToProgramToLaunch)) - // return null; - - //// Arbil - //if (PathToProgramToLaunch.ToLower().Contains("arbil")) return "Arbil"; - - - //// if not one of the presets, just return the exe name - //string exe = Path.GetFileNameWithoutExtension(PathToProgramToLaunch); - //string dir = Path.GetDirectoryName(PathToProgramToLaunch); - //if (!string.IsNullOrEmpty(dir)) - //{ - // dir = Path.GetFileNameWithoutExtension(dir); - // if (dir.Length > 0 && exe.ToLowerInvariant().Contains(dir.ToLowerInvariant())) - // return dir; - //} - //return exe; - } - } - - /// ------------------------------------------------------------------------------------ - public override string InformativeText - { - get - { - string programInfo = string.IsNullOrEmpty(NameOfProgramToLaunch) ? - string.Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.NoIMDIProgramInfoText", - "The {0} package will be created in {1}.", - "Parameter 0 is 'IMDI'; " + - "Parameter 1 is the path where the package is created."), - ArchiveType, PackagePath) - : - string.Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.IMDIProgramInfoText", - "This tool will help you use {0} to archive your {1} data. When the {1} package has been " + - "created, you can launch {0} and enter any additional information before doing the actual submission.", - "Parameter 0 is the name of the program that will be launched to further prepare the IMDI data for submission; " + - "Parameter 1 is the name of the calling (host) program (SayMore, FLEx, etc.)"), NameOfProgramToLaunch, AppName); - return string.Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.IMDIOverviewText", - "{0} ({1}) is a metadata standard to describe multi-media and multi-modal language " + - "resources. The standard provides interoperability for browsable and searchable " + - "corpus structures and resource descriptions.", - "Parameter 0 is 'Isle Metadata Initiative' (the first occurrence will be turned into a hyperlink); " + - "Parameter 1 is 'IMDI'"), - ArchiveInfoHyperlinkText, ArchiveType) + - " " + _appSpecificArchivalProcessInfo + - " " + programInfo; - } - } - - /// - public override string ArchiveInfoHyperlinkText - { - get { return LocalizationManager.GetString("DialogBoxes.ArchivingDlg.IsleMetadataInitiative", - "Isle Metadata Initiative", "Typically this probably does not need to be localized."); } - } - - /// ------------------------------------------------------------------------------------ - public override string ArchiveInfoUrl => Properties.Settings.Default.IMDIWebSite; - - public bool MetadataOnly { get; set; } - #endregion - - /// ------------------------------------------------------------------------------------ - /// Constructor - /// The application name - /// Title of the submission. - /// Identifier for the package being created. Used as the CORPUS name. - /// Application can use this to pass - /// additional information that will be displayed to the user in the dialog to explain - /// any application-specific details about the archival process. - /// Indicates whether this is for an entire project corpus or a - /// single session - /// Delegate to request client to call methods to set - /// which files should be archived (this is deferred to allow display of progress message) - /// Base folder where IMDI file structure is to be created - /// ------------------------------------------------------------------------------------ - public IMDIArchivingDlgViewModel(string appName, string title, string id, - string appSpecificArchivalProcessInfo, bool corpus, - Action setFilesToArchive, string outputFolder) - : base(appName, title, id, appSpecificArchivalProcessInfo, setFilesToArchive) - { - OutputFolder = outputFolder; - - _imdiData = new IMDIPackage(corpus, PackagePath) - { - Title = _titles[_id], - Name = _id - }; - } - - /// ------------------------------------------------------------------------------------ - protected override bool DoArchiveSpecificInitialization() - { - // no-op - return true; - } - - /// ------------------------------------------------------------------------------------ - public override int CalculateMaxProgressBarValue() - { - // One for processing each list and one for copying each file - return _fileLists.Count + _fileLists.SelectMany(kvp => kvp.Value.Item1).Count(); - } - - /// ------------------------------------------------------------------------------------ - protected override string FileGroupDisplayMessage(string groupKey) - { - if (groupKey == string.Empty) - return LocalizationManager.GetString("DialogBoxes.ArchivingDlg.IMDIActorsGroup", "Actors", - "This is the heading displayed in the Archive Using IMDI dialog box for the files for the actors/participants"); - return base.FileGroupDisplayMessage(groupKey); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Sets a description for the specified session in a single language - /// - /// - /// The abstract description - /// ISO 639-3 3-letter language code - /// ------------------------------------------------------------------------------------ - public void SetSessionDescription(string sessionId, string description, string iso3LanguageCode) - { - if (description == null) - throw new ArgumentNullException("description"); - if (iso3LanguageCode == null) - throw new ArgumentNullException("iso3LanguageCode"); - if (iso3LanguageCode.Length != 3) - { - var msg = LocalizationManager.GetString("DialogBoxes.ArchivingDlg.ISO3CodeRequired", - "ISO 639-3 3-letter language code required.", - "Message displayed when an invalid language code is given."); - throw new ArgumentException(msg, "iso3LanguageCode"); - } - - _imdiData.AddDescription(sessionId, new LanguageString { Value = description, Iso3LanguageId = iso3LanguageCode }); - } - - /// - /// - protected override void SetAbstract_Impl(IDictionary descriptions) - { - foreach (var desc in descriptions) - _imdiData.AddDescription(new LanguageString(desc.Value, desc.Key)); - } - - /// - /// - public override string GetMetadata() - { - return _imdiData.BaseImdiFile.ToString(); - } - - /// ------------------------------------------------------------------------------------ - /// Launch Arbil or Lamus or whatever - /// need custom launcher here because Arbil is a java program, with no executable on linux - /// ------------------------------------------------------------------------------------ - internal override void LaunchArchivingProgram() - { - if (string.IsNullOrEmpty(PathToProgramToLaunch) || !File.Exists(PathToProgramToLaunch)) - return; - - // if it is a .jar file, open with java - var exePath = (PathToProgramToLaunch.EndsWith(".jar")) ? "java" : PathToProgramToLaunch; - var args = string.Empty; - if (exePath == "java") - { - // are there additional command line parameters for this program? - if (PathToProgramToLaunch.ToLower().Contains("arbil")) - args = string.Format(ArchivingPrograms.ArbilCommandLineArgs, PathToProgramToLaunch); - else - args = PathToProgramToLaunch; - } - - try - { - var prs = new Process { StartInfo = { FileName = exePath, Arguments = args } }; - prs.Start(); - } - catch (Exception e) - { - ReportError(e, string.Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.StartingIMDIErrorMsg", - "There was an error attempting to open the archive package in {0}."), PathToProgramToLaunch)); - } - } - -#region Create IMDI package in worker thread - - /// - public override bool CreatePackage() - { - IsBusy = true; - - // check for missing data that is required by Arbil - var success = _imdiData.SetMissingInformation(); - - // write the xml files - if (success) - success = _imdiData.CreateIMDIPackage(); - - // copy the content files - if (success && !MetadataOnly) - success = CreateIMDIPackage(); - - CleanUp(); - - if (success) - { - // copy the path to the imdi file to the clipboard - - // SP-818: Crash in IMDI export when dialog tries to put string on clipboard - // 18 FEB 2014, Phil Hopper: I found this possible solution using retries on StackOverflow - // https://stackoverflow.com/questions/5707990/requested-clipboard-operation-did-not-succeed - //Clipboard.SetData(DataFormats.Text, _imdiData.MainExportFile); - Clipboard.SetDataObject(_imdiData.MainExportFile, true, 3, 500); - - var successMsg = LocalizationManager.GetString("DialogBoxes.ArchivingDlg.ReadyToCallIMDIMsg", - "Exported to {0}. This path is now on your clipboard. If you are using Arbil, go to File, Import, then paste this path in."); - DisplayMessage(string.Format(successMsg, _imdiData.MainExportFile), MessageType.Success); - } - - IsBusy = false; - return success; - } - - /// - public bool CreateIMDIPackage() - { - try - { - using (_worker = new BackgroundWorker()) - { - _cancelProcess = false; - _workerException = false; - _worker.ProgressChanged += HandleBackgroundWorkerProgressChanged; - _worker.WorkerReportsProgress = true; - _worker.WorkerSupportsCancellation = true; - _worker.DoWork += CreateIMDIPackageInWorkerThread; - _worker.RunWorkerAsync(); - - while (_worker.IsBusy) - Application.DoEvents(); - } - } - catch (Exception e) - { - ReportError(e, LocalizationManager.GetString( - "DialogBoxes.ArchivingDlg.CreatingIMDIPackageErrorMsg", - "There was a problem starting process to create IMDI package.")); - - return false; - } - finally - { - _worker = null; - } - - return !_cancelProcess && !_workerException; - } - - public override void Cancel() - { - base.Cancel(); - - CleanUp(); - } - - /// - void HandleBackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e) - { - if (e.UserState == null || _cancelProcess) - return; - - if (e.UserState is KeyValuePair) - { - var kvp = (KeyValuePair)e.UserState; - ReportError(kvp.Key, kvp.Value); - return; - } - - if (!string.IsNullOrEmpty(e.UserState as string)) - { - if (e.ProgressPercentage == 0) - { - DisplayMessage(e.UserState.ToString(), MessageType.Success); - return; - } - - DisplayMessage(e.UserState.ToString(), MessageType.Detail); - } - - if (IncrementProgressBarAction != null) - IncrementProgressBarAction(); - } - - private void CreateIMDIPackageInWorkerThread(object sender, DoWorkEventArgs e) - { - try - { - var outputDirectory = Path.Combine(_imdiData.PackagePath, NormalizeDirectoryName(_imdiData.Name)); - - if (Thread.CurrentThread.Name == null) - Thread.CurrentThread.Name = "CreateIMDIPackageInWorkerThread"; - - _worker.ReportProgress(0, PreparingFilesMsg); - - var filesToCopy = new Dictionary(); - - // get files from each session - foreach (var sess in _imdiData.Sessions) - { - Session session = (Session) sess; - - _worker.ReportProgress(1 /* actual value ignored, progress just increments */, - session.Name); - - // get files to copy - foreach (var file in session.Resources.MediaFile) - { - // create sub directory - var fullSessionDirName = Path.Combine(outputDirectory, NormalizeDirectoryName(file.OutputDirectory)); - Directory.CreateDirectory(fullSessionDirName); - - var newFileName = NormalizeFilename(string.Empty, Path.GetFileName(file.FullPathAndFileName)); - filesToCopy[file.FullPathAndFileName] = Path.Combine(fullSessionDirName, newFileName); - } - - foreach (var file in session.Resources.WrittenResource) - { - // create sub directory - var fullSessionDirName = Path.Combine(outputDirectory, NormalizeDirectoryName(file.OutputDirectory)); - Directory.CreateDirectory(fullSessionDirName); - - var newFileName = NormalizeFilename(string.Empty, Path.GetFileName(file.FullPathAndFileName)); - filesToCopy[file.FullPathAndFileName] = Path.Combine(fullSessionDirName, newFileName); - } - - if (_cancelProcess) - return; - } - - _worker.ReportProgress(0, LocalizationManager.GetString("DialogBoxes.ArchivingDlg.CopyingFilesMsg", - "Copying files")); - - // copy the files now - foreach (var fileToCopy in filesToCopy) - { - if (_cancelProcess) - return; - _worker.ReportProgress(1 /* actual value ignored, progress just increments */, - Path.GetFileName(fileToCopy.Key)); - if (FileCopyOverride != null) - { - try - { - if (FileCopyOverride(this, fileToCopy.Key, fileToCopy.Value)) - { - if (!File.Exists(fileToCopy.Value)) - throw new FileNotFoundException("Calling application claimed to copy file but didn't", fileToCopy.Value); - continue; - } - } - catch (Exception error) - { - var msg = GetFileExcludedMsg(ArchiveType, fileToCopy.Value); - ReportError(error, msg); - } - } - // Don't use File.Copy because it's asynchronous. - CopyFile(fileToCopy.Key, fileToCopy.Value); - } - - _worker.ReportProgress(0, GetSavingFilesMsg(ArchiveType)); - } - catch (Exception exception) - { - _worker.ReportProgress(0, new KeyValuePair(exception, - string.Format(LocalizationManager.GetString("DialogBoxes.ArchivingDlg.CreatingArchiveErrorMsg", - "There was an error attempting to create the {0} package.", "Parameter is the type of archive (e.g., IMDI)"), ArchiveType))); - - _workerException = true; - } - } - -#endregion - - /// Only Latin characters, URL compatible - protected override StringBuilder DoArchiveSpecificFilenameNormalization(string key, string fileName) - { - return new StringBuilder(NormalizeFileName(fileName)); - } - - /// Only Latin characters, URL compatible - internal static string NormalizeFileName(string fileName) - { - return fileName.ToLatinOnly("_", "+", "."); - } - - /// Only Latin characters, URL compatible - internal static string NormalizeDirectoryName(string dirName) - { - return dirName.ToLatinOnly("_", "_", ".-"); - } - - /// Performs clean-up for the class - public void CleanUp() - { - // delete temp files, etc - } - - /// Returns the normalized name to use for the output corpus folder. A sub-directory of OutputFolder - public string CorpusDirectoryName - { - get - { - // create the output base directory if it doesn't already exist - if (!Directory.Exists(OutputFolder)) - { - Directory.CreateDirectory(OutputFolder); - - if (!Directory.Exists(OutputFolder)) - throw new DirectoryNotFoundException(string.Format("The path {0} was not found.", OutputFolder)); - } - - if (string.IsNullOrEmpty(_corpusDirectoryName)) - { - var baseName = NormalizeDirectoryName(_titles[_id] + " " + DateTime.Today.ToISO8601TimeFormatDateOnlyString()); - var test = baseName; - var i = 1; - - while (Directory.Exists(Path.Combine(OutputFolder, test))) - { - test = NormalizeDirectoryName(baseName + " " + i.ToString("000")); - i++; - } - _corpusDirectoryName = test; - } - return _corpusDirectoryName; - } - } - - /// Adds a new session and returns it - /// - public override IArchivingSession AddSession(string sessionId) - { - // look for existing session - foreach (var sess in _imdiData.Sessions.Where(sess => sess.Name == sessionId)) - return sess; - - // if not found, add a new session - Session session = new Session {Name = sessionId}; - - _imdiData.Sessions.Add(session); - - return session; - } - - public override IArchivingPackage ArchivingPackage { get { return _imdiData; } } - - /// - public new string PathToProgramToLaunch - { - get - { - switch (ProgramPreset) - { - case "Arbil": - return ArchivingPrograms.GetArbilExeFileLocation(); - - default: - return OtherProgramPath; - } - } - set - { - // this is just for compatibility - _otherProgramPath = value; - } - } - - /// - public string ProgramPreset - { - get - { - if (string.IsNullOrEmpty(_programPreset)) - GetSavedValues(); - - return _programPreset; - } - set - { - _programPreset = value; - SaveProgramValues(); - } - } - - /// - public string OtherProgramPath - { - get - { - if (string.IsNullOrEmpty(_programPreset)) - GetSavedValues(); - - return _otherProgramPath; - } - set - { - _otherProgramPath = value; - SaveProgramValues(); - } - } - - private void GetSavedValues() - { - - if (File.Exists(_configFileName)) - { - var lines = File.ReadAllLines(_configFileName); - - foreach (var line in lines) - { - var kvp = line.Split(new[] { '=' }, 2); - if (kvp.Length == 2) - { - switch (kvp[0]) - { - case "ProgramPreset": - _programPreset = kvp[1]; - break; - - case "OtherProgramPath": - _otherProgramPath = kvp[1]; - break; - } - } - } - } - - // default to Arbil - if (string.IsNullOrEmpty(_programPreset)) - _programPreset = "Arbil"; - - if (_otherProgramPath == null) - _otherProgramPath = string.Empty; - } - - private void SaveProgramValues() - { - List lines = new List - { - "ProgramPreset=" + ProgramPreset, - "OtherProgramPath=" + OtherProgramPath - }; - - File.WriteAllLines(_configFileName, lines); - } - - /// - public string OutputFolder - { - get { return _outputFolder; } - set - { - _outputFolder = value; - PackagePath = !string.IsNullOrEmpty(value)? - Path.Combine(value, CorpusDirectoryName): - CorpusDirectoryName; - if (_imdiData != null) - _imdiData.PackagePath = PackagePath; - } - } - } -} diff --git a/SIL.Windows.Forms.Archiving/LinkLabelExtensions.cs b/SIL.Windows.Forms.Archiving/LinkLabelExtensions.cs new file mode 100644 index 000000000..5594b55b1 --- /dev/null +++ b/SIL.Windows.Forms.Archiving/LinkLabelExtensions.cs @@ -0,0 +1,83 @@ +using System; +using System.Text; +using System.Windows.Forms; +using SIL.Archiving; + +namespace SIL.Windows.Forms.Archiving +{ + /// ------------------------------------------------------------------------------------ + public static class LinkLabelExtensions + { + /// ------------------------------------------------------------------------------------ + /// + /// Used to size a link label in mono because it is not working at all + /// + /// + /// ------------------------------------------------------------------------------------ + public static void SizeToContents(this LinkLabel linkLabel) + { + var w = linkLabel.ClientSize.Width; + + using (var g = linkLabel.CreateGraphics()) + { + + if (ArchivingDlgViewModel.IsMono) + { + // split at the existing like breaks + var segments = linkLabel.Text.Replace("\r", "").Split(new[] {'\n'}, StringSplitOptions.None); + var newText = new StringBuilder(); + + foreach (var segment in segments) + { + var thisSegment = segment.Trim(); + + while (MeasureText(linkLabel, g, thisSegment, linkLabel.Font).Width > w) + { + var line = string.Empty; + var lastSpace = 0; + + for (var i = 0; i < thisSegment.Length; i++) + { + if (char.IsWhiteSpace(thisSegment[i])) + { + if (MeasureText(linkLabel, g, line, linkLabel.Font).Width > w) + { + newText.AppendLine(thisSegment.Substring(0, lastSpace)); + thisSegment = thisSegment.Substring(lastSpace + 1); + break; + } + + lastSpace = i; + } + line += thisSegment[i]; + } + } + + // check for left-overs + if (thisSegment.Length > 0) + newText.AppendLine(thisSegment); + } + + linkLabel.Text = newText.ToString(); + } + + var size = MeasureText(linkLabel, g, linkLabel.Text, linkLabel.Font, new System.Drawing.Size(w, Int32.MaxValue)); + linkLabel.Height = size.Height; + } + } + private static System.Drawing.Size MeasureText(this LinkLabel linkLabel, System.Drawing.Graphics g, string text, System.Drawing.Font font) + { + if (linkLabel.UseCompatibleTextRendering) + return g.MeasureString(text, font).ToSize(); + else + return TextRenderer.MeasureText(g, text, font); + } + private static System.Drawing.Size MeasureText(this LinkLabel linkLabel, System.Drawing.Graphics g, string text, System.Drawing.Font font, System.Drawing.Size proposedSize) + { + if (linkLabel.UseCompatibleTextRendering) + return g.MeasureString(text, font, proposedSize.Width).ToSize(); + else + return TextRenderer.MeasureText(g, text, font, proposedSize, TextFormatFlags.WordBreak); + } + } +} diff --git a/SIL.Windows.Forms.Archiving/Properties/Resources.Designer.cs b/SIL.Windows.Forms.Archiving/Properties/Resources.Designer.cs index 52eff1ab8..f4ff45ed2 100644 --- a/SIL.Windows.Forms.Archiving/Properties/Resources.Designer.cs +++ b/SIL.Windows.Forms.Archiving/Properties/Resources.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -59,239 +59,5 @@ internal Resources() { resourceCulture = value; } } - - /// - /// Looks up a localized string similar to [ - ///{"protocol":"AILCA","documentation":"ailca.html","choices":[ - /// {"label":"F","description":"access is Free to all"}, - /// {"label":"U","description":"all Users can access (requires registration)"}, - /// {"label":"RC","description":"Researchers and Community members are allowed access"}, - /// {"label":"C","description":"only Community members are allowed access (normally requires application to Depositor)"}, - /// {"label":"S","description":"only Subscribers are allowed access (requires application to Depositor)"}, - /// { [rest of string was truncated]";. - /// - internal static string AccessProtocols { - get { - return ResourceManager.GetString("AccessProtocols", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <html> - /// <head></head> - /// <style> - /// body { - /// margin: 0; - /// } - /// body, table { - /// font-size: 12px; - /// font-family: 'Segoe UI', 'Tahoma', 'Arial', 'Helvetica', sans-serif; - /// } - /// td { - /// vertical-align: top; - /// } - /// .bold { - /// font-weight: 700; - /// } - /// .space-before { - /// padding-top: 10px; - /// } - /// .fixed { - /// font-family: 'Consolas', 'DejaVu Sans Mono', monospace; - /// } - /// </style> - /// <body style="background-color: rgb(230, 150, 100)"> - /// <table> - /// <tr> - /// <td colspan="3" class="bold">Name:</td> - /// [rest of string was truncated]";. - /// - internal static string ailca { - get { - return ResourceManager.GetString("ailca", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <html> - /// <head></head> - /// <style> - /// body { - /// margin: 0; - /// } - /// body, table { - /// font-size: 12px; - /// font-family: 'Segoe UI', 'Tahoma', 'Arial', 'Helvetica', sans-serif; - /// } - /// td { - /// vertical-align: top; - /// } - /// .bold { - /// font-weight: 700; - /// } - /// .space-before { - /// padding-top: 10px; - /// } - /// .fixed { - /// font-family: 'Consolas', 'DejaVu Sans Mono', monospace; - /// } - /// .nowrap { white-space: nowrap; } - /// </style> - /// <body style="background-color: rgb(230, 150, 100)"> - /// <table> - /// <tr> - /// <td col [rest of string was truncated]";. - /// - internal static string ailla { - get { - return ResourceManager.GetString("ailla", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <html> - /// <head></head> - /// <style> - /// body { - /// margin: 0; - /// } - /// body, table { - /// font-size: 12px; - /// font-family: 'Segoe UI', 'Tahoma', 'Arial', 'Helvetica', sans-serif; - /// } - /// td { - /// vertical-align: top; - /// } - /// .bold { - /// font-weight: 700; - /// } - /// .space-before { - /// padding-top: 10px; - /// } - /// .fixed { - /// font-family: 'Consolas', 'DejaVu Sans Mono', monospace; - /// } - /// .nowrap { white-space: nowrap; } - /// </style> - /// <body style="background-color: rgb(230, 150, 100)"> - /// <table> - /// <tr> - /// <td col [rest of string was truncated]";. - /// - internal static string anla { - get { - return ResourceManager.GetString("anla", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to [ - ///{"protocol":"Custom","documentation":"","choices":[ - /// {"label":"","description":""}]}, - ///]. - /// - internal static string CustomAccessProtocols { - get { - return ResourceManager.GetString("CustomAccessProtocols", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <html> - /// <head></head> - /// <style> - /// body { - /// margin: 0; - /// } - /// body, table { - /// font-size: 12px; - /// font-family: 'Segoe UI', 'Tahoma', 'Arial', 'Helvetica', sans-serif; - /// } - /// td { - /// vertical-align: top; - /// } - /// .bold { - /// font-weight: 700; - /// } - /// .space-before { - /// padding-top: 10px; - /// } - /// .fixed { - /// font-family: 'Consolas', 'DejaVu Sans Mono', monospace; - /// } - /// </style> - /// <body style="background-color: rgb(230, 150, 100)"> - /// <table> - /// <tr> - /// <td colspan="3" class="bold">Name:</td> - /// [rest of string was truncated]";. - /// - internal static string elar { - get { - return ResourceManager.GetString("elar", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" ?><mets ID="sort-mets_mets" OBJID="sword-mets" LABEL="DSpace SWORD Item" PROFILE="DSpace SIL SIP Profile 1.0" xmlns="http://www.loc.gov/METS/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/METS/ http://www.loc.gov/standards/mets/mets.xsd"> - /// <metsHdr/> - /// <dmdSec ID="ramp-mets-dmd-2" GROUPID="ramp-mets-dmd-2_group-1"> - /// <mdWrap LABEL="RAMP Metadata" MDTYPE="OTHER" OTHERMDTYPE="SIL. [rest of string was truncated]";. - /// - internal static string EmptyMets { - get { - return ResourceManager.GetString("EmptyMets", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <html> - /// <head></head> - /// <body> - /// - /// </body> - ///</html>. - /// - internal static string reap { - get { - return ResourceManager.GetString("reap", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <html> - /// <head></head> - /// <style> - /// body { - /// margin: 0; - /// } - /// body, table { - /// font-size: 12px; - /// font-family: 'Segoe UI', 'Tahoma', 'Arial', 'Helvetica', sans-serif; - /// } - /// td { - /// vertical-align: top; - /// } - /// .bold { - /// font-weight: 700; - /// } - /// .space-before { - /// padding-top: 10px; - /// } - /// .fixed { - /// font-family: 'Consolas', 'DejaVu Sans Mono', monospace; - /// } - /// .nowrap { white-space: nowrap; } - /// </style> - /// <body style="background-color: rgb(230, 150, 100)"> - /// <table> - /// <tr> - /// <td col [rest of string was truncated]";. - /// - internal static string tla { - get { - return ResourceManager.GetString("tla", resourceCulture); - } - } } } diff --git a/SIL.Windows.Forms.Archiving/Properties/Resources.resx b/SIL.Windows.Forms.Archiving/Properties/Resources.resx index 3b5dad038..267ed3e43 100644 --- a/SIL.Windows.Forms.Archiving/Properties/Resources.resx +++ b/SIL.Windows.Forms.Archiving/Properties/Resources.resx @@ -1,4 +1,4 @@ - + - -
- + +
+
- - - + + + @@ -27,9 +27,11 @@ - - - - + + + + + + - + \ No newline at end of file diff --git a/SIL.Windows.Forms.WritingSystems.Tests/App.config b/SIL.Windows.Forms.WritingSystems.Tests/App.config index 6e62a852b..e6c577f71 100644 --- a/SIL.Windows.Forms.WritingSystems.Tests/App.config +++ b/SIL.Windows.Forms.WritingSystems.Tests/App.config @@ -3,9 +3,11 @@ - - - - + + + + + + \ No newline at end of file From defcf716679ce963eeb1f3219dcfc46604a41993 Mon Sep 17 00:00:00 2001 From: tombogle Date: Fri, 2 Aug 2024 18:00:59 -0400 Subject: [PATCH 07/15] [WIP] Started adding a test app for the archiving stuff --- ArchivingTestApp/ArchivingTestApp.csproj | 24 +++ ArchivingTestApp/MainForm.Designer.cs | 168 ++++++++++++++++++ ArchivingTestApp/MainForm.cs | 75 ++++++++ ArchivingTestApp/MainForm.resx | 120 +++++++++++++ ArchivingTestApp/Program.cs | 32 ++++ CHANGELOG.md | 2 +- Palaso.sln | 7 + SIL.Archiving/ArchivingDlgViewModel.cs | 4 +- .../IMDI/IMDIArchivingDlgViewModel.cs | 9 +- SIL.Archiving/RampArchivingDlgViewModel.cs | 3 +- SIL.Windows.Forms.Archiving/ArchivingDlg.cs | 13 +- 11 files changed, 448 insertions(+), 9 deletions(-) create mode 100644 ArchivingTestApp/ArchivingTestApp.csproj create mode 100644 ArchivingTestApp/MainForm.Designer.cs create mode 100644 ArchivingTestApp/MainForm.cs create mode 100644 ArchivingTestApp/MainForm.resx create mode 100644 ArchivingTestApp/Program.cs diff --git a/ArchivingTestApp/ArchivingTestApp.csproj b/ArchivingTestApp/ArchivingTestApp.csproj new file mode 100644 index 000000000..7fd3012c8 --- /dev/null +++ b/ArchivingTestApp/ArchivingTestApp.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net8.0-windows + enable + true + enable + net8.0-windows + latest + ArchivingTestApp.Program + + + + + + + + + + + + + \ No newline at end of file diff --git a/ArchivingTestApp/MainForm.Designer.cs b/ArchivingTestApp/MainForm.Designer.cs new file mode 100644 index 000000000..21a61e201 --- /dev/null +++ b/ArchivingTestApp/MainForm.Designer.cs @@ -0,0 +1,168 @@ +namespace ArchivingTestApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + m_btnIMDI = new Button(); + m_tableLayoutPanelMain = new TableLayoutPanel(); + m_btnRamp = new Button(); + m_lblTitle = new SIL.Windows.Forms.Widgets.BetterLabel(); + m_txtTitle = new TextBox(); + m_btnAddFiles = new Button(); + m_listFiles = new ListView(); + m_tableLayoutPanelMain.SuspendLayout(); + SuspendLayout(); + // + // m_btnIMDI + // + m_btnIMDI.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + m_btnIMDI.AutoSize = true; + m_btnIMDI.Enabled = false; + m_btnIMDI.Location = new Point(812, 469); + m_btnIMDI.Margin = new Padding(4, 3, 4, 3); + m_btnIMDI.Name = "m_btnIMDI"; + m_btnIMDI.Size = new Size(99, 29); + m_btnIMDI.TabIndex = 0; + m_btnIMDI.Text = "IMDI Archive"; + m_btnIMDI.UseVisualStyleBackColor = true; + // + // m_tableLayoutPanelMain + // + m_tableLayoutPanelMain.ColumnCount = 3; + m_tableLayoutPanelMain.ColumnStyles.Add(new ColumnStyle()); + m_tableLayoutPanelMain.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); + m_tableLayoutPanelMain.ColumnStyles.Add(new ColumnStyle()); + m_tableLayoutPanelMain.Controls.Add(m_btnIMDI, 2, 2); + m_tableLayoutPanelMain.Controls.Add(m_btnRamp, 1, 2); + m_tableLayoutPanelMain.Controls.Add(m_lblTitle, 0, 0); + m_tableLayoutPanelMain.Controls.Add(m_txtTitle, 1, 0); + m_tableLayoutPanelMain.Controls.Add(m_btnAddFiles, 0, 1); + m_tableLayoutPanelMain.Controls.Add(m_listFiles, 1, 1); + m_tableLayoutPanelMain.Dock = DockStyle.Fill; + m_tableLayoutPanelMain.Location = new Point(9, 9); + m_tableLayoutPanelMain.Margin = new Padding(4, 3, 4, 3); + m_tableLayoutPanelMain.Name = "m_tableLayoutPanelMain"; + m_tableLayoutPanelMain.RowCount = 3; + m_tableLayoutPanelMain.RowStyles.Add(new RowStyle()); + m_tableLayoutPanelMain.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); + m_tableLayoutPanelMain.RowStyles.Add(new RowStyle()); + m_tableLayoutPanelMain.Size = new Size(915, 501); + m_tableLayoutPanelMain.TabIndex = 1; + // + // m_btnRamp + // + m_btnRamp.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + m_btnRamp.AutoSize = true; + m_btnRamp.Enabled = false; + m_btnRamp.Location = new Point(702, 471); + m_btnRamp.Margin = new Padding(4, 3, 4, 3); + m_btnRamp.Name = "m_btnRamp"; + m_btnRamp.Padding = new Padding(0, 0, 9, 0); + m_btnRamp.Size = new Size(102, 27); + m_btnRamp.TabIndex = 1; + m_btnRamp.Text = "RAMP Archive"; + m_btnRamp.UseVisualStyleBackColor = true; + m_btnRamp.Click += m_btnRamp_Click; + // + // m_lblTitle + // + m_lblTitle.BorderStyle = BorderStyle.None; + m_lblTitle.Enabled = false; + m_lblTitle.ForeColor = SystemColors.ControlText; + m_lblTitle.IsTextSelectable = false; + m_lblTitle.Location = new Point(4, 3); + m_lblTitle.Margin = new Padding(4, 3, 4, 3); + m_lblTitle.Multiline = true; + m_lblTitle.Name = "m_lblTitle"; + m_lblTitle.ReadOnly = true; + m_lblTitle.Size = new Size(117, 15); + m_lblTitle.TabIndex = 2; + m_lblTitle.TabStop = false; + m_lblTitle.Text = "Title of Submission:"; + // + // m_txtTitle + // + m_txtTitle.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + m_txtTitle.Location = new Point(129, 3); + m_txtTitle.Margin = new Padding(4, 3, 4, 3); + m_txtTitle.Name = "m_txtTitle"; + m_txtTitle.Size = new Size(675, 23); + m_txtTitle.TabIndex = 3; + // + // m_btnAddFiles + // + m_btnAddFiles.Anchor = AnchorStyles.Top; + m_btnAddFiles.AutoSize = true; + m_btnAddFiles.Location = new Point(25, 32); + m_btnAddFiles.Name = "m_btnAddFiles"; + m_btnAddFiles.Size = new Size(75, 25); + m_btnAddFiles.TabIndex = 4; + m_btnAddFiles.Text = "Add Files"; + m_btnAddFiles.UseVisualStyleBackColor = true; + m_btnAddFiles.Click += HandleAddFilesClick; + // + // m_listFiles + // + m_listFiles.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + m_listFiles.HeaderStyle = ColumnHeaderStyle.Nonclickable; + m_listFiles.HideSelection = true; + m_listFiles.LabelWrap = false; + m_listFiles.Location = new Point(128, 32); + m_listFiles.MultiSelect = false; + m_listFiles.Name = "m_listFiles"; + m_listFiles.Size = new Size(677, 431); + m_listFiles.TabIndex = 5; + m_listFiles.UseCompatibleStateImageBehavior = false; + m_listFiles.View = View.List; + // + // MainForm + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(933, 519); + Controls.Add(m_tableLayoutPanelMain); + Margin = new Padding(4, 3, 4, 3); + Name = "MainForm"; + Padding = new Padding(9); + Text = "Archiving Dialog Test app"; + m_tableLayoutPanelMain.ResumeLayout(false); + m_tableLayoutPanelMain.PerformLayout(); + ResumeLayout(false); + } + + #endregion + + private Button m_btnIMDI; + private TableLayoutPanel m_tableLayoutPanelMain; + private Button m_btnRamp; + private SIL.Windows.Forms.Widgets.BetterLabel m_lblTitle; + private TextBox m_txtTitle; + private Button m_btnAddFiles; + private ListView m_listFiles; + } +} diff --git a/ArchivingTestApp/MainForm.cs b/ArchivingTestApp/MainForm.cs new file mode 100644 index 000000000..b91c03002 --- /dev/null +++ b/ArchivingTestApp/MainForm.cs @@ -0,0 +1,75 @@ +using L10NSharp; +using SIL.Archiving; +using SIL.Windows.Forms.Archiving; +using static System.IO.Path; +using static System.String; + +namespace ArchivingTestApp +{ + public partial class MainForm : Form + { + private const string kAppName = "Archiving Test App"; + public MainForm() + { + InitializeComponent(); + } + + private void m_btnRamp_Click(object sender, EventArgs e) + { + var title = m_txtTitle.Text; + if (title.Length == 0) + title = "Arbitrary title"; + var model = new RampArchivingDlgViewModel(kAppName, title, + title.ToLatinOnly("~", "_", ""), SetFilesToArchive, GetFileDescription); + using (var rampArchiveDlg = new ArchivingDlg(model, LocalizationManager.GetString( + "ArchivingTestApp.MainForm.AdditionalArchiveProcessInfo", "This is just a test."))) + { + rampArchiveDlg.ShowDialog(this); + } + } + + private void SetFilesToArchive(ArchivingDlgViewModel model, CancellationToken cancellationToken) + { + foreach (ListViewGroup group in m_listFiles.Groups) + { + var files = (from ListViewItem item in @group.Items select item.Text).ToList(); + model.AddFileGroup(group.Header, files, Format(LocalizationManager.GetString( + "ArchivingTestApp.MainForm.AddingFileGroupProgressMsg", + "Adding {0}", "Param is group name (directory)"), group.Header)); + } + } + + private static string GetFileDescription(string key, string filename) + { + return $"{key} - {filename}"; + } + + private void HandleAddFilesClick(object sender, EventArgs e) + { + using (var dlg = new OpenFileDialog()) + { + dlg.CheckFileExists = true; + dlg.Multiselect = true; + dlg.Title = Format(LocalizationManager.GetString( + "ArchivingTestApp.MainForm.AddingFileGroupProgressMsg", + "{0} - Select files to archive", "Param is app name"), kAppName); + if (dlg.ShowDialog(this) == DialogResult.OK && dlg.FileNames.Any()) + { + var group = new ListViewGroup(GetDirectoryName(dlg.FileNames[0]) ?? "root"); + + foreach (var file in dlg.FileNames) + { + var item = new ListViewItem(file) { Group = group }; + m_listFiles.Items.Add(item); + } + + m_listFiles.Groups.Add(group); + m_listFiles.Refresh(); + + m_btnRamp.Enabled = true; + m_btnIMDI.Enabled = true; + } + } + } + } +} diff --git a/ArchivingTestApp/MainForm.resx b/ArchivingTestApp/MainForm.resx new file mode 100644 index 000000000..af32865ec --- /dev/null +++ b/ArchivingTestApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ArchivingTestApp/Program.cs b/ArchivingTestApp/Program.cs new file mode 100644 index 000000000..6bd17d30a --- /dev/null +++ b/ArchivingTestApp/Program.cs @@ -0,0 +1,32 @@ +using L10NSharp; +using SIL.IO; + +namespace ArchivingTestApp +{ + internal static class Program + { + internal static ILocalizationManager? PrimaryL10NManager; + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main(string[] args) + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + //ApplicationConfiguration.Initialize(); + + var preferredUILocale = "en"; + if (args.Length > 0) + preferredUILocale = args[0].ToLowerInvariant(); + + var localizationFolder = Path.GetDirectoryName( + FileLocationUtilities.GetFileDistributedWithApplication($"Palaso.{preferredUILocale}.xlf")); + PrimaryL10NManager = LocalizationManager.Create(preferredUILocale, "Palaso", "Palaso", + "1.0.0", localizationFolder, "SIL/Palaso", null, "testapp@sil.org", new [] {"SIL."}); + + Application.Run(new MainForm()); + } + } +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b2c4c4b2..bb5d7a994 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,7 +56,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Archiving] IMDIArchivingDlgViewModel constructor signature changed. - [SIL.Archiving] RampArchivingDlgViewModel constructor signature changed. - [SIL.Windows.Forms.Archiving] Made ArchivingDlg implement IArchivingProgressDisplay. -- [SIL.Windows.Forms.Archiving] ArchivingDlg constructor signature changed: removed localizationManagerId; added optional archiveInfoHyperlinkText. +- [SIL.Windows.Forms.Archiving] ArchivingDlg constructor signature changed: removed localizationManagerId; added optional archiveInfoHyperlinkText; made some other parameters optional. - [SIL.Windows.Forms.Archiving] IMDIArchivingDlg constructor signature changed: added appSpecificArchivalProcessInfo. - [SIL.Windows.Forms] Split ClearShare code, moving non-Winforms portions to SIL.Core (SIL.Core.ClearShare namespace) - [SIL.Core] Added optional parameter to OlacSystem.GetRoles to allow caller to provide its own XML with role definitions. diff --git a/Palaso.sln b/Palaso.sln index 4e5e622fd..0085644f8 100755 --- a/Palaso.sln +++ b/Palaso.sln @@ -122,6 +122,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving", "SIL.Archiv EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving.Tests", "SIL.Archiving.Tests\SIL.Archiving.Tests.csproj", "{698FDB66-0ACE-46E0-843C-3AB70DC7B055}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchivingTestApp", "ArchivingTestApp\ArchivingTestApp.csproj", "{321BB622-8185-4173-8770-742CD620BC18}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -308,6 +310,10 @@ Global {698FDB66-0ACE-46E0-843C-3AB70DC7B055}.Debug|Any CPU.Build.0 = Debug|Any CPU {698FDB66-0ACE-46E0-843C-3AB70DC7B055}.Release|Any CPU.ActiveCfg = Release|Any CPU {698FDB66-0ACE-46E0-843C-3AB70DC7B055}.Release|Any CPU.Build.0 = Release|Any CPU + {321BB622-8185-4173-8770-742CD620BC18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {321BB622-8185-4173-8770-742CD620BC18}.Debug|Any CPU.Build.0 = Debug|Any CPU + {321BB622-8185-4173-8770-742CD620BC18}.Release|Any CPU.ActiveCfg = Release|Any CPU + {321BB622-8185-4173-8770-742CD620BC18}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -320,6 +326,7 @@ Global {CA8F3657-3D85-4C97-81A6-5C212627B2F6} = {3C695301-9C39-4715-8EDD-817C63EF81E7} {B1E0B522-FEDF-497E-BFCD-A572F67C03C1} = {3C695301-9C39-4715-8EDD-817C63EF81E7} {6407C2F9-F62D-4568-B694-7A79C72582C9} = {3C695301-9C39-4715-8EDD-817C63EF81E7} + {321BB622-8185-4173-8770-742CD620BC18} = {3C695301-9C39-4715-8EDD-817C63EF81E7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0915B762-D4AE-4892-BF4F-AC428A687B02} diff --git a/SIL.Archiving/ArchivingDlgViewModel.cs b/SIL.Archiving/ArchivingDlgViewModel.cs index 580cb360c..930debf2c 100644 --- a/SIL.Archiving/ArchivingDlgViewModel.cs +++ b/SIL.Archiving/ArchivingDlgViewModel.cs @@ -224,7 +224,9 @@ public enum MessageType /// Title of the submission /// Identifier (used as filename) for the package being created /// Delegate to request client to call methods to set - /// which files should be archived (this is deferred to allow display of progress message) + /// which files should be archived (this is deferred to allow display of progress + /// message). Clients will normally do this by calling AddFileGroup one or more times. + /// /// ------------------------------------------------------------------------------------ protected ArchivingDlgViewModel(string appName, string title, string id, Action setFilesToArchive) diff --git a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs index c24634198..bcffc068a 100644 --- a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs +++ b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs @@ -66,12 +66,15 @@ public override string NameOfProgramToLaunch /// Constructor /// The application name /// Title of the submission. - /// Identifier for the package being created. Used as the CORPUS name. + /// Identifier for the package being created. Used as the CORPUS name. + /// /// Indicates whether this is for an entire project corpus or a /// single session /// Delegate to request client to call methods to set - /// which files should be archived (this is deferred to allow display of progress message) - /// Base folder where IMDI file structure is to be created + /// which files should be archived (this is deferred to allow display of progress message). + /// Clients will normally do this by calling AddFileGroup one or more times. + /// Base folder where IMDI file structure is to be created + /// /// ------------------------------------------------------------------------------------ public IMDIArchivingDlgViewModel(string appName, string title, string id, bool corpus, Action setFilesToArchive, string outputFolder) diff --git a/SIL.Archiving/RampArchivingDlgViewModel.cs b/SIL.Archiving/RampArchivingDlgViewModel.cs index 0e39fec33..0d224df7a 100644 --- a/SIL.Archiving/RampArchivingDlgViewModel.cs +++ b/SIL.Archiving/RampArchivingDlgViewModel.cs @@ -293,7 +293,8 @@ private void AddModesToSet(IEnumerable files) /// Title of the submission /// Identifier (used as filename) for the package being created /// Delegate to request client to call methods to set - /// which files should be archived (this is deferred to allow display of progress message) + /// which files should be archived (this is deferred to allow display of progress message). + /// Clients will normally do this by calling AddFileGroup one or more times. /// Callback function to get a file description based /// on the file-list key (param 1) and the filename (param 2) /// ------------------------------------------------------------------------------------ diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs index c26d1adaa..d727da43d 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs @@ -89,8 +89,8 @@ public partial class ArchivingDlg : Form, IArchivingProgressDisplay /// > /// ------------------------------------------------------------------------------------ public ArchivingDlg(ArchivingDlgViewModel model, string appSpecificArchivalProcessInfo, - string localizationManagerId, Font programDialogFont, FormSettings settings, - string archiveInfoHyperlinkText = null) + string localizationManagerId = null, Font programDialogFont = null, + FormSettings settings = null, string archiveInfoHyperlinkText = null) { _settings = settings ?? FormSettings.Create(this); @@ -555,7 +555,14 @@ private void HandleRampLinkClicked(object sender, LinkLabelLinkClickedEventArgs var tgt = e.Link.LinkData as string; if (!IsNullOrEmpty(tgt)) - System.Diagnostics.Process.Start(tgt); + { + var ps = new ProcessStartInfo(tgt) + { + UseShellExecute = true, + Verb = "open" + }; + Process.Start(ps); + } } /// ------------------------------------------------------------------------------------ From 445b557557266aa244c69797a6a1c51117c0b761 Mon Sep 17 00:00:00 2001 From: tombogle Date: Mon, 5 Aug 2024 17:24:57 -0400 Subject: [PATCH 08/15] Got archiving test app to work correctly for both RAMP and IMDI archives. Improved documentation and did code cleanup for some of the IMDI stuff. Closed some loopholes to make it easier for clients to create valid packages --- ArchivingTestApp/MainForm.Designer.cs | 1 + ArchivingTestApp/MainForm.cs | 63 +- CHANGELOG.md | 3 + Palaso.sln.DotSettings | 5 + SIL.Archiving/ArchivingDlgViewModel.cs | 11 +- SIL.Archiving/Generic/ArchivingPackage.cs | 1 - SIL.Archiving/Generic/ArchivingSession.cs | 22 +- .../IMDI/IMDIArchivingDlgViewModel.cs | 10 +- SIL.Archiving/IMDI/IMDIPackage.cs | 10 +- SIL.Archiving/IMDI/Schema/IMDIExtensions.cs | 5 +- SIL.Archiving/IMDI/Schema/IMDI_3_0.cs | 683 ++++++++---------- .../ArchivingDlg.Designer.cs | 413 +++++------ SIL.Windows.Forms.Archiving/ArchivingDlg.cs | 36 +- SIL.Windows.Forms.Archiving/ArchivingDlg.resx | 3 - .../IMDI/IMDIArchivingDlg.cs | 36 +- 15 files changed, 693 insertions(+), 609 deletions(-) diff --git a/ArchivingTestApp/MainForm.Designer.cs b/ArchivingTestApp/MainForm.Designer.cs index 21a61e201..e2ffae0d3 100644 --- a/ArchivingTestApp/MainForm.Designer.cs +++ b/ArchivingTestApp/MainForm.Designer.cs @@ -50,6 +50,7 @@ private void InitializeComponent() m_btnIMDI.TabIndex = 0; m_btnIMDI.Text = "IMDI Archive"; m_btnIMDI.UseVisualStyleBackColor = true; + m_btnIMDI.Click += m_btnIMDI_Click; // // m_tableLayoutPanelMain // diff --git a/ArchivingTestApp/MainForm.cs b/ArchivingTestApp/MainForm.cs index b91c03002..f8bcff64c 100644 --- a/ArchivingTestApp/MainForm.cs +++ b/ArchivingTestApp/MainForm.cs @@ -1,6 +1,10 @@ using L10NSharp; using SIL.Archiving; +using SIL.Archiving.Generic; +using SIL.Archiving.IMDI; +using SIL.IO; using SIL.Windows.Forms.Archiving; +using SIL.Windows.Forms.Archiving.IMDI; using static System.IO.Path; using static System.String; @@ -9,6 +13,15 @@ namespace ArchivingTestApp public partial class MainForm : Form { private const string kAppName = "Archiving Test App"; + + private string GetTitle() + { + var title = m_txtTitle.Text; + if (title.Length == 0) + title = "Arbitrary title"; + return title; + } + public MainForm() { InitializeComponent(); @@ -16,9 +29,7 @@ public MainForm() private void m_btnRamp_Click(object sender, EventArgs e) { - var title = m_txtTitle.Text; - if (title.Length == 0) - title = "Arbitrary title"; + var title = GetTitle(); var model = new RampArchivingDlgViewModel(kAppName, title, title.ToLatinOnly("~", "_", ""), SetFilesToArchive, GetFileDescription); using (var rampArchiveDlg = new ArchivingDlg(model, LocalizationManager.GetString( @@ -28,6 +39,50 @@ private void m_btnRamp_Click(object sender, EventArgs e) } } + private void m_btnIMDI_Click(object sender, EventArgs e) + { + var title = GetTitle(); + TempFile.NamePrefix = kAppName.Replace(" ", "_"); + var folder = new TempFile().Path; + RobustFile.Delete(folder); + Directory.CreateDirectory(folder); + var model = new IMDIArchivingDlgViewModel(kAppName, title, + title.ToLatinOnly("~", "_", ""), false, SetFilesToArchive, folder); + + model.ArchivingPackage.AccessCode = "internal"; + model.ArchivingPackage.Access.DateAvailable = "3 March 2029"; + model.ArchivingPackage.Access.Owner = "Fred"; + model.ArchivingPackage.Publisher = "SIL Elbonia"; + model.ArchivingPackage.Location = new ArchivingLocation + { + Address = "1234 Shoulder St.; Armstrong", + Country = "Elbonia" + }; + model.ArchivingPackage.Author = "Test Dude"; + model.ArchivingPackage.Owner = "Mike"; + + foreach (ListViewGroup group in m_listFiles.Groups) + { + var session = model.AddSession(group.Header); + foreach (var file in (from ListViewItem item in @group.Items select item.Text)) + { + session.AddFile(new ArchivingFile(file)); + session.AddFileAccess(file, (ArchivingPackage)model.ArchivingPackage); + } + + session.Genre = "Dance"; + session.SubGenre = "Entertainment"; + session.PlanningType = "Spontaneous"; + } + + + using (var imdiArchiveDlg = new IMDIArchivingDlg(model, LocalizationManager.GetString( + "ArchivingTestApp.MainForm.AdditionalImdiArchiveProcessInfo", "This is a test of IMDI archival."))) + { + imdiArchiveDlg.ShowDialog(this); + } + } + private void SetFilesToArchive(ArchivingDlgViewModel model, CancellationToken cancellationToken) { foreach (ListViewGroup group in m_listFiles.Groups) @@ -41,7 +96,7 @@ private void SetFilesToArchive(ArchivingDlgViewModel model, CancellationToken ca private static string GetFileDescription(string key, string filename) { - return $"{key} - {filename}"; + return filename.Replace("\\", "_"); } private void HandleAddFilesClick(object sender, EventArgs e) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb5d7a994..b27fe3f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Windows.Forms.Archiving] Added (protected) override of method PackageCreationComplete to IMDIArchivingDlg. - [SIL.Windows.Forms.Archiving] Added (public) override of method GetMessage to IMDIArchivingDlg. - [SIL.Windows.Forms.Archiving] Added public extensions class LinkLabelExtensions with some methods that were formerly in Extensions class (now in SIL.Archiving). +- [SIL.Archiving] Added public property isValid to IMDIPackage. +- [SIL.Archiving] Added public event InitializationFailed to IMDIArchivingDlgViewModel. ### Changed @@ -61,6 +63,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Windows.Forms] Split ClearShare code, moving non-Winforms portions to SIL.Core (SIL.Core.ClearShare namespace) - [SIL.Core] Added optional parameter to OlacSystem.GetRoles to allow caller to provide its own XML with role definitions. - [SIL.Windows.Forms] Split License into a base class called License and a derived LicenseWithLogo, so that License could be in SIL.Core. +- [SIL.Archiving] Changed IArchivingSession.Files (and Session.Files) into an IReadonlyList. ### Fixed - [SIL.Archiving] Fixed typo in RampArchivingDlgViewModel for Ethnomusicology performance collection. diff --git a/Palaso.sln.DotSettings b/Palaso.sln.DotSettings index ef9fcff4d..53e0bb3f5 100644 --- a/Palaso.sln.DotSettings +++ b/Palaso.sln.DotSettings @@ -25,6 +25,9 @@ True True True + True + True + True True True True @@ -77,11 +80,13 @@ True True True + True True True True True True + True True True True diff --git a/SIL.Archiving/ArchivingDlgViewModel.cs b/SIL.Archiving/ArchivingDlgViewModel.cs index 930debf2c..0de1c4c6a 100644 --- a/SIL.Archiving/ArchivingDlgViewModel.cs +++ b/SIL.Archiving/ArchivingDlgViewModel.cs @@ -74,6 +74,7 @@ public enum StringId PreArchivingStatus, SearchingForArchiveUploadingProgram, ArchiveUploadingProgramNotFound, + IMDIPackageInvalid, ErrorStartingArchivalProgram, PreparingFiles, SavingFilesInPackage, @@ -597,8 +598,14 @@ protected string GetFileExcludedMsg(string file) => /// ------------------------------------------------------------------------------------ public static bool IsMono => (Type.GetType("Mono.Runtime") != null); - /// - /// + /// ------------------------------------------------------------------------------------ + /// Adds a "session" or "resource bundle". This usually corresponds to a + /// meaningful unit of analysis, e.g., to a piece of data having the same overall + /// content, the same set of actors, and the same location and time (e.g., one + /// elicitation session on topic X, or one folktale, or one ‘matching game’, or one + /// conversation between several speakers). + /// Unique Identifier for this session. + /// ------------------------------------------------------------------------------------ [PublicAPI] public abstract IArchivingSession AddSession(string sessionId); diff --git a/SIL.Archiving/Generic/ArchivingPackage.cs b/SIL.Archiving/Generic/ArchivingPackage.cs index 684d5be95..56a2611da 100644 --- a/SIL.Archiving/Generic/ArchivingPackage.cs +++ b/SIL.Archiving/Generic/ArchivingPackage.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using SIL.Archiving.Generic.AccessProtocol; namespace SIL.Archiving.Generic diff --git a/SIL.Archiving/Generic/ArchivingSession.cs b/SIL.Archiving/Generic/ArchivingSession.cs index a711c4f28..7c215c277 100644 --- a/SIL.Archiving/Generic/ArchivingSession.cs +++ b/SIL.Archiving/Generic/ArchivingSession.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using JetBrains.Annotations; namespace SIL.Archiving.Generic { @@ -10,10 +11,11 @@ public interface IArchivingSession : IArchivingGenericObject void AddFile(ArchivingFile file); /// + [PublicAPI] void AddFileAccess(string fullFileName, ArchivingPackage package); - /// - List Files { get; } + /// The paths of all resource files in the session. + IReadOnlyList Files { get; } /// Set session date with DateTime object void SetDate(DateTime date); @@ -25,36 +27,47 @@ public interface IArchivingSession : IArchivingGenericObject void SetDate(int year); /// + [PublicAPI] void AddContentLanguage(ArchivingLanguage language, LanguageString description); /// + [PublicAPI] void AddActor(ArchivingActor actor); /// + [PublicAPI] void AddGroupKeyValuePair(string key, string value); /// + [PublicAPI] void AddContentKeyValuePair(string key, string value); /// + [PublicAPI] void AddFileKeyValuePair(string fullFileName, string key, string value); /// + [PublicAPI] void AddContentDescription(LanguageString description); /// + [PublicAPI] void AddActorDescription(ArchivingActor actor, LanguageString description); /// + [PublicAPI] void AddFileDescription(string fullFileName, LanguageString description); /// + [PublicAPI] void AddActorContact(ArchivingActor actor, ArchivingContact contact); /// + [PublicAPI] void AddMediaFileTimes(string fullFileName, string start, string stop); /// + [PublicAPI] void AddProject(ArchivingPackage package); /// @@ -66,10 +79,11 @@ public interface IArchivingSession : IArchivingGenericObject /// string Interactivity { get; set; } - /// + /// Indicates in how far the researcher was involved in the linguistic event + [PublicAPI] string Involvement { get; set; } - /// + /// Degree of planning of the event string PlanningType { get; set; } /// diff --git a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs index bcffc068a..6d695228e 100644 --- a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs +++ b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs @@ -25,6 +25,8 @@ public class IMDIArchivingDlgViewModel : ArchivingDlgViewModel, ISupportMetadata private readonly string _configFileName = Path.Combine(ArchivingFileSystem.SilCommonArchivingDataFolder, "IMDIProgram.config"); private string _outputFolder; + public event EventHandler InitializationFailed; + #region Properties public override Standard ArchiveType => Standard.IMDI; @@ -92,8 +94,12 @@ public IMDIArchivingDlgViewModel(string appName, string title, string id, bool c /// ------------------------------------------------------------------------------------ protected override bool DoArchiveSpecificInitialization() { - // no-op - return true; + if (_imdiData.IsValid) + return true; + + DisplayMessage(Progress.GetMessage(StringId.IMDIPackageInvalid), MessageType.Error); + InitializationFailed?.Invoke(this, EventArgs.Empty); + return false; } /// ------------------------------------------------------------------------------------ diff --git a/SIL.Archiving/IMDI/IMDIPackage.cs b/SIL.Archiving/IMDI/IMDIPackage.cs index 8b4205c3b..c45ccaa98 100644 --- a/SIL.Archiving/IMDI/IMDIPackage.cs +++ b/SIL.Archiving/IMDI/IMDIPackage.cs @@ -1,4 +1,3 @@ - using System; using System.Collections.Generic; using System.IO; @@ -53,6 +52,12 @@ public string PackagePath _packagePath = value; } } + + /// Generally an IMDI package should have at least one session. (This is not + /// strictly required for a corpus package, though it would be strange to want to + /// archive a corpus with no sessions.) + public bool IsValid => _corpus || Sessions.Any(); + #endregion // **** Corpus Layout **** @@ -70,6 +75,9 @@ public string PackagePath /// public bool CreateIMDIPackage() { + if (!IsValid) + return false; + _creationStarted = true; // list of session files for the corpus diff --git a/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs b/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs index 70c0f6091..f656fc3c3 100644 --- a/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs +++ b/SIL.Archiving/IMDI/Schema/IMDIExtensions.cs @@ -1,4 +1,4 @@ -using SIL.Archiving.Generic; +using SIL.Archiving.Generic; using SIL.Archiving.IMDI.Lists; namespace SIL.Archiving.IMDI.Schema @@ -15,8 +15,7 @@ public static void SetValue(this VocabularyType vocabularyType, string value, bo { if (value == null) return; - if (vocabularyType == null) - vocabularyType = new VocabularyType(); + vocabularyType ??= new VocabularyType(); vocabularyType.Value = value; vocabularyType.Type = isClosedVocabulary diff --git a/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs b/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs index 12f392313..a9d84ee75 100644 --- a/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs +++ b/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs @@ -8,10 +8,12 @@ using System.Xml.Schema; using System.Xml.Serialization; using System.Diagnostics; +using JetBrains.Annotations; using SIL.Archiving.Generic; using SIL.Archiving.Generic.AccessProtocol; using SIL.Archiving.IMDI.Lists; using SIL.Extensions; +using static SIL.Archiving.IMDI.Lists.ListType; namespace SIL.Archiving.IMDI.Schema { @@ -29,10 +31,10 @@ public interface IIMDIMajorObject } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlType(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] - [XmlRootAttribute("METATRANSCRIPT", Namespace="http://www.mpi.nl/IMDI/Schema/IMDI", IsNullable=false)] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] + [XmlRoot("METATRANSCRIPT", Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd", IsNullable=false)] public class MetaTranscript { /// @@ -73,9 +75,9 @@ public MetaTranscript(MetatranscriptValueType type) public string SchemaLocation { get; set; } /// - [XmlElementAttribute("Catalogue", typeof(Catalogue))] - [XmlElementAttribute("Corpus", typeof(Corpus))] - [XmlElementAttribute("Session", typeof(Session))] + [XmlElement("Catalogue", typeof(Catalogue))] + [XmlElement("Corpus", typeof(Corpus))] + [XmlElement("Session", typeof(Session))] public object[] Items { get; set; } /// @@ -95,7 +97,7 @@ public MetaTranscript(MetatranscriptValueType type) public string FormatId { get; set; } /// - [XmlAttributeAttribute] + [XmlAttribute] public MetatranscriptValueType Type { get; set; } /// @@ -120,7 +122,6 @@ public override string ToString() var serializer = new XmlSerializer(GetType()); serializer.Serialize(xmlWriter, this); - //return strWriter.ToString(); return Encoding.UTF8.GetString(memStream.ToArray()); } } @@ -255,48 +256,41 @@ private void ArbilCheckSession(Session session) foreach (var actor in session.MDGroup.Actors.Actor) { - if (actor.Role == null) - actor.Role = string.Empty.ToVocabularyType(false, ListType.Link(ListType.ActorRole)); + actor.Role ??= string.Empty.ToVocabularyType(false, Link(ActorRole)); - if (actor.FamilySocialRole == null) - actor.FamilySocialRole = string.Empty.ToVocabularyType(false, ListType.Link(ListType.ActorFamilySocialRole)); + actor.FamilySocialRole ??= string.Empty.ToVocabularyType(false, + Link(ActorFamilySocialRole)); - if (actor.Anonymized == null) - actor.Anonymized = new BooleanType { Link = ListType.Link(ListType.Boolean) }; + actor.Anonymized ??= new BooleanType { Link = Link(ListType.Boolean) }; - if (actor.Sex == null) - actor.Sex = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ActorSex) }; + actor.Sex ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ActorSex) }; } foreach (var file in session.Resources.WrittenResource) { - if (file.SubType == null) - file.SubType = new VocabularyType { Link = ListType.Link(ListType.WrittenResourceSubType) }; + file.SubType ??= new VocabularyType { Link = Link(WrittenResourceSubType) }; - if (file.Validation == null) - file.Validation = new ValidationType - { - Type = new VocabularyType{ Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ValidationType) }, - Methodology = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ValidationMethodology) }, - Level = new IntegerType { Value = "Unspecified" }, - Description = new DescriptionTypeCollection { new LanguageString() } - }; + file.Validation ??= new ValidationType + { + Type = new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ListType.ValidationType) }, + Methodology = new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ValidationMethodology) }, + Level = new IntegerType { Value = "Unspecified" }, + Description = new DescriptionTypeCollection { new LanguageString() } + }; - if (file.Derivation == null) - file.Derivation = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.WrittenResourceDerivation) }; + file.Derivation ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(WrittenResourceDerivation) }; - if (file.Anonymized == null) - file.Anonymized = new BooleanType { Link = ListType.Link(ListType.Boolean) }; + file.Anonymized ??= new BooleanType { Link = Link(ListType.Boolean) }; - if (file.Access == null) - file.Access = new AccessType(); + file.Access ??= new AccessType(); } foreach (var file in session.Resources.MediaFile) - { - if (file.Access == null) - file.Access = new AccessType(); - } + file.Access ??= new AccessType(); } /// Set the access code on session files if not set already. @@ -306,8 +300,7 @@ private void SetFileAccessCode(Session session) foreach (var file in session.Resources.MediaFile) { - if (file.Access == null) - file.Access = new AccessType(); + file.Access ??= new AccessType(); if (string.IsNullOrEmpty(file.Access.Availability)) file.Access.Availability = session.AccessCode; @@ -315,8 +308,7 @@ private void SetFileAccessCode(Session session) foreach (var file in session.Resources.WrittenResource) { - if (file.Access == null) - file.Access = new AccessType(); + file.Access ??= new AccessType(); if (string.IsNullOrEmpty(file.Access.Availability)) file.Access.Availability = session.AccessCode; @@ -325,9 +317,9 @@ private void SetFileAccessCode(Session session) } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class CommaSeparatedStringType { /// @@ -336,10 +328,10 @@ public class CommaSeparatedStringType } /// - [XmlIncludeAttribute(typeof(SubjectLanguageType))] - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [XmlInclude(typeof(SubjectLanguageType))] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class SimpleLanguageType { /// @@ -350,19 +342,19 @@ public class SimpleLanguageType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class LanguageNameType : VocabularyType { } /// - [XmlIncludeAttribute(typeof(LanguageNameType))] - [XmlIncludeAttribute(typeof(KeyType))] - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [XmlInclude(typeof(LanguageNameType))] + [XmlInclude(typeof(KeyType))] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class VocabularyType { /// @@ -388,27 +380,27 @@ public VocabularyType() { } /// - [SerializableAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public enum VocabularyTypeValueType { /// ClosedVocabulary, - /// + [PublicAPI] ClosedVocabularyList, /// OpenVocabulary, - /// + [PublicAPI] OpenVocabularyList, } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class KeyType { /// @@ -421,35 +413,43 @@ public class KeyType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class SubjectLanguageType : SimpleLanguageType { private DescriptionTypeCollection _descriptionField; - /// + /// + /// Is it the most frequently used language in the document. Only applicable if used in the context of the resource's language + /// + [PublicAPI] public BooleanType Dominant { get; set; } - /// + /// + /// Source language of translation. Only applicable in case it is the context of a lexicon resource + /// public BooleanType SourceLanguage { get; set; } - /// + /// + /// Target language of translation. Only applicable in case it is the context of a lexicon resource + /// + [PublicAPI] public BooleanType TargetLanguage { get; set; } /// - [XmlElementAttribute("Description")] + [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return _descriptionField ?? (_descriptionField = new DescriptionTypeCollection()); } - set { _descriptionField = value; } + get => _descriptionField ??= new DescriptionTypeCollection(); + set => _descriptionField = value; } } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class BooleanType { /// @@ -475,9 +475,9 @@ public BooleanType() { } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public partial class DescriptionType { /// @@ -502,9 +502,9 @@ public partial class DescriptionType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class Catalogue : IIMDIMajorObject { /// @@ -617,17 +617,17 @@ public Catalogue() } /// - /// I think this is the DocumentLanguages subelement of a Catalogue element - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType=true, Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + /// I think this is the DocumentLanguages sub-element of a Catalogue element + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType=true, Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class CatalogueDocumentLanguages : IMDIDescription { [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return DescriptionInternal; } - set { DescriptionInternal = value; } + get => DescriptionInternal; + set => DescriptionInternal = value; } /// @@ -642,16 +642,16 @@ public CatalogueDocumentLanguages() } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType=true, Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType=true, Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class CatalogueSubjectLanguages : IMDIDescription { [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return DescriptionInternal; } - set { DescriptionInternal = value; } + get => DescriptionInternal; + set => DescriptionInternal = value; } /// @@ -666,16 +666,16 @@ public CatalogueSubjectLanguages() } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class LocationType { /// public LocationType() { - Continent = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.Continents) }; - Country = new VocabularyType { Link = ListType.Link(ListType.Countries) }; + Continent = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(Continents) }; + Country = new VocabularyType { Link = Link(Countries) }; Region = new List(); } @@ -701,8 +701,8 @@ public LocationType(ArchivingLocation location) : this() /// Closed vocabulary public void SetContinent(string continent) { - var continentList = ListConstructor.GetClosedList(ListType.Continents, false, ListConstructor.RemoveUnknown.RemoveNone); - Continent = continentList.FindByValue(continent).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.Continents)); + var continentList = ListConstructor.GetClosedList(Continents, false, ListConstructor.RemoveUnknown.RemoveNone); + Continent = continentList.FindByValue(continent).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(Continents)); } /// Open vocabulary @@ -711,11 +711,11 @@ public void SetContinent(string continent) /// public void SetCountry(string country) { - Country = IMDISchemaHelper.SetVocabulary(country, false, ListType.Link(ListType.Countries)); + Country = IMDISchemaHelper.SetVocabulary(country, false, Link(Countries)); } /// - [XmlElementAttribute("Region")] + [XmlElement("Region")] public List Region { get; set; } /// @@ -741,9 +741,9 @@ public ArchivingLocation ToArchivingLocation() } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType=true, Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType=true, Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class CatalogueFormat { /// @@ -760,9 +760,9 @@ public class CatalogueFormat } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType=true, Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType=true, Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class CatalogueQuality { /// @@ -779,9 +779,9 @@ public class CatalogueQuality } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class Project : IIMDIMajorObject { /// @@ -842,9 +842,9 @@ public Project(IMDIPackage package) } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ContactType { /// @@ -861,9 +861,9 @@ public class ContactType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class AccessType : IMDIDescription { /// initialize for Arbil @@ -908,15 +908,15 @@ public AccessType(IArchivingPackage package) [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return DescriptionInternal; } - set { DescriptionInternal = value; } + get => DescriptionInternal; + set => DescriptionInternal = value; } } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class KeysType { private List _keyField; @@ -925,15 +925,15 @@ public class KeysType [XmlElement("Key")] public List Key { - get { return _keyField ?? (_keyField = new List()); } - set { _keyField = value; } + get => _keyField ??= new List(); + set => _keyField = value; } } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class Corpus : IIMDIMajorObject { /// @@ -982,9 +982,9 @@ public Corpus() } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class MDGroupType { /// @@ -1015,9 +1015,9 @@ public MDGroupType() } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ContentType { /// @@ -1079,87 +1079,82 @@ public void AddLanguage(ArchivingLanguage language, BooleanEnum dominantLanguage /// public void SetInteractivity(string interactivity) { - IMDIItemList list = ListConstructor.GetClosedList(ListType.ContentInteractivity); - CommunicationContext.Interactivity = list.FindByValue(interactivity).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.ContentInteractivity)); + IMDIItemList list = ListConstructor.GetClosedList(ContentInteractivity); + CommunicationContext.Interactivity = list.FindByValue(interactivity).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(ContentInteractivity)); } /// public void SetPlanningType(string planningType) { - IMDIItemList list = ListConstructor.GetClosedList(ListType.ContentPlanningType, DontRequireUppercaseFirstCharacter); - CommunicationContext.PlanningType = list.FindByValue(planningType).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.ContentPlanningType)); + IMDIItemList list = ListConstructor.GetClosedList(ContentPlanningType, DontRequireUppercaseFirstCharacter); + CommunicationContext.PlanningType = list.FindByValue(planningType).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(ContentPlanningType)); } /// public void SetInvolvement(string involvement) { - IMDIItemList list = ListConstructor.GetClosedList(ListType.ContentInvolvement, DontRequireUppercaseFirstCharacter); - CommunicationContext.Involvement = list.FindByValue(involvement).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.ContentInvolvement)); + IMDIItemList list = ListConstructor.GetClosedList(ContentInvolvement, DontRequireUppercaseFirstCharacter); + CommunicationContext.Involvement = list.FindByValue(involvement).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(ContentInvolvement)); } /// public void SetSocialContext(string socialContext) { - IMDIItemList list = ListConstructor.GetClosedList(ListType.ContentSocialContext); - CommunicationContext.SocialContext = list.FindByValue(socialContext).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.ContentSocialContext)); + IMDIItemList list = ListConstructor.GetClosedList(ContentSocialContext); + CommunicationContext.SocialContext = list.FindByValue(socialContext).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(ContentSocialContext)); } /// public void SetEventStructure(string eventStructure) { - IMDIItemList list = ListConstructor.GetClosedList(ListType.ContentEventStructure); - CommunicationContext.EventStructure = list.FindByValue(eventStructure).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.ContentEventStructure)); + IMDIItemList list = ListConstructor.GetClosedList(ContentEventStructure); + CommunicationContext.EventStructure = list.FindByValue(eventStructure).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(ContentEventStructure)); } /// public void SetChannel(string channel) { - IMDIItemList list = ListConstructor.GetClosedList(ListType.ContentChannel); - CommunicationContext.Channel = list.FindByValue(channel).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.ContentChannel)); + IMDIItemList list = ListConstructor.GetClosedList(ContentChannel); + CommunicationContext.Channel = list.FindByValue(channel).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(ContentChannel)); } /// public void CheckRequiredFields() { - if (Genre == null) - Genre = new VocabularyType { Link = ListType.Link(ListType.ContentGenre) }; + Genre ??= new VocabularyType { Link = Link(ContentGenre) }; - if (SubGenre == null) - SubGenre = new VocabularyType { Link = ListType.Link(ListType.ContentSubGenre) }; + SubGenre ??= new VocabularyType { Link = Link(ContentSubGenre) }; - if (Task == null) - Task = new VocabularyType { Link = ListType.Link(ListType.ContentTask) }; + Task ??= new VocabularyType { Link = Link(ContentTask) }; - if (Modalities == null) - Modalities = new VocabularyType { Link = ListType.Link(ListType.ContentModalities) }; + Modalities ??= new VocabularyType { Link = Link(ContentModalities) }; - if (Subject == null) - Subject = new ContentTypeSubject { Link = ListType.Link(ListType.ContentSubject) }; + Subject ??= new ContentTypeSubject { Link = Link(ContentSubject) }; - if (CommunicationContext.Interactivity == null) - CommunicationContext.Interactivity = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ContentInteractivity) }; + CommunicationContext.Interactivity ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ContentInteractivity) }; - if (CommunicationContext.PlanningType == null) - CommunicationContext.PlanningType = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ContentPlanningType) }; + CommunicationContext.PlanningType ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ContentPlanningType) }; - if (CommunicationContext.Involvement == null) - CommunicationContext.Involvement = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ContentInvolvement) }; + CommunicationContext.Involvement ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ContentInvolvement) }; - if (CommunicationContext.SocialContext == null) - CommunicationContext.SocialContext = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ContentSocialContext) }; + CommunicationContext.SocialContext ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ContentSocialContext) }; - if (CommunicationContext.EventStructure == null) - CommunicationContext.EventStructure = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ContentEventStructure) }; + CommunicationContext.EventStructure ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ContentEventStructure) }; - if (CommunicationContext.Channel == null) - CommunicationContext.Channel = new VocabularyType { Type = VocabularyTypeValueType.ClosedVocabulary, Link = ListType.Link(ListType.ContentChannel) }; + CommunicationContext.Channel ??= new VocabularyType + { Type = VocabularyTypeValueType.ClosedVocabulary, Link = Link(ContentChannel) }; } } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType = true, Namespace = "https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ContentTypeCommunicationContext { /// Closed vocabulary, Content-Interactivity.xml @@ -1182,9 +1177,9 @@ public class ContentTypeCommunicationContext } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType=true, Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType=true, Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ContentTypeSubject : VocabularyType { /// @@ -1193,9 +1188,9 @@ public class ContentTypeSubject : VocabularyType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class LanguagesType : IMDIDescription { private List _languageField; @@ -1208,10 +1203,10 @@ public DescriptionTypeCollection Description } /// - [XmlElementAttribute("Language")] + [XmlElement("Language")] public List Language { - get { return _languageField ?? (_languageField = new List()); } - set { _languageField = value; } + get => _languageField ??= new List(); + set => _languageField = value; } /// @@ -1223,9 +1218,9 @@ public static LanguageType GetLanguage(string iso3CodeOrEnglishName) } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class LanguageType : IMDIDescription { /// @@ -1253,8 +1248,8 @@ public class LanguageType : IMDIDescription [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return DescriptionInternal; } - set { DescriptionInternal = value; } + get => DescriptionInternal; + set => DescriptionInternal = value; } /// @@ -1263,9 +1258,9 @@ public DescriptionTypeCollection Description } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ActorsType : IMDIDescription { private List _actorField; @@ -1273,22 +1268,22 @@ public class ActorsType : IMDIDescription [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return DescriptionInternal; } - set { DescriptionInternal = value; } + get => DescriptionInternal; + set => DescriptionInternal = value; } /// - [XmlElementAttribute("Actor")] + [XmlElement("Actor")] public List Actor { - get { return _actorField ?? (_actorField = new List()); } - set { _actorField = value; } + get => _actorField ??= new List(); + set => _actorField = value; } } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ActorType { private LanguagesType _languagesField; @@ -1352,7 +1347,7 @@ public ActorType(ArchivingActor actor) : this() // Role if (!string.IsNullOrEmpty(actor.Role)) - Role = actor.Role.ToVocabularyType(false, ListType.Link(ListType.ActorRole)); ; + Role = actor.Role.ToVocabularyType(false, Link(ActorRole)); ; // Occupation if (!string.IsNullOrEmpty(actor.Occupation)) @@ -1371,7 +1366,7 @@ public ActorType(ArchivingActor actor) : this() public VocabularyType Role { get; set; } /// - [XmlElementAttribute("Name")] + [XmlElement("Name")] public string[] Name { get; set; } /// @@ -1387,8 +1382,8 @@ public ActorType(ArchivingActor actor) : this() [XmlElement("Languages")] public LanguagesType Languages { - get { return _languagesField ?? (_languagesField = new LanguagesType()); } - set { _languagesField = value; } + get => _languagesField ??= new LanguagesType(); + set => _languagesField = value; } /// @@ -1418,8 +1413,8 @@ public void SetBirthDate(string birthDate) /// public void SetSex(string gender) { - IMDIItemList genderList = ListConstructor.GetClosedList(ListType.ActorSex); - Sex = genderList.FindByValue(gender).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, ListType.Link(ListType.ActorSex)); + IMDIItemList genderList = ListConstructor.GetClosedList(ActorSex); + Sex = genderList.FindByValue(gender).ToVocabularyType(VocabularyTypeValueType.ClosedVocabulary, Link(ActorSex)); } /// @@ -1435,11 +1430,11 @@ public void AddLanguage(ArchivingLanguage language, BooleanEnum primaryLanguage, if (primaryLanguage == BooleanEnum.Unspecified) imdiLanguage.PrimaryLanguage = null; else - imdiLanguage.PrimaryLanguage = new BooleanType { Value = primaryLanguage, Link = ListType.Link(ListType.Boolean) }; + imdiLanguage.PrimaryLanguage = new BooleanType { Value = primaryLanguage, Link = Link(ListType.Boolean) }; if (motherTongue == BooleanEnum.Unspecified) imdiLanguage.MotherTongue = null; else - imdiLanguage.MotherTongue = new BooleanType { Value = motherTongue, Link = ListType.Link(ListType.Boolean) }; + imdiLanguage.MotherTongue = new BooleanType { Value = motherTongue, Link = Link(ListType.Boolean) }; Languages.Language.Add(imdiLanguage); } @@ -1458,14 +1453,14 @@ public void AddLanguage(ArchivingLanguage language, BooleanEnum primaryLanguage, public DescriptionTypeCollection Description { get; set; } /// - [XmlAttributeAttribute] + [XmlAttribute] public string ResourceRef { get; set; } // TODO: Do we need this method? /// public ArchivingActor ToArchivingActor() { - ArchivingActor actr = new ArchivingActor + ArchivingActor actor = new ArchivingActor { Age = Age, Education = Education, @@ -1473,38 +1468,38 @@ public ArchivingActor ToArchivingActor() }; if (Sex != null) - actr.Gender = Sex.Value; + actor.Gender = Sex.Value; if (Name.Length > 0) - actr.Name = Name[0]; + actor.Name = Name[0]; if (!string.IsNullOrEmpty(Role.Value)) - actr.Role = Role.Value; + actor.Role = Role.Value; if (!string.IsNullOrEmpty(BirthDate)) - actr.BirthDate = BirthDate; + actor.BirthDate = BirthDate; foreach (LanguageType lang in Languages.Language) { var iso3 = lang.Id.Substring(lang.Id.Length - 3); var archLanguage = new ArchivingLanguage(iso3, lang.Name[0].Value); - actr.Iso3Languages.Add(archLanguage); + actor.Iso3Languages.Add(archLanguage); if (lang.PrimaryLanguage.Value == BooleanEnum.@true) - actr.PrimaryLanguage = archLanguage; + actor.PrimaryLanguage = archLanguage; if (lang.MotherTongue.Value == BooleanEnum.@true) - actr.MotherTongueLanguage = archLanguage; + actor.MotherTongueLanguage = archLanguage; } - return actr; + return actor; } } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class CorpusLinkType : ResourceLinkType { /// @@ -1513,10 +1508,10 @@ public class CorpusLinkType : ResourceLinkType } /// - [XmlIncludeAttribute(typeof(CorpusLinkType))] - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [XmlInclude(typeof(CorpusLinkType))] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ResourceLinkType { /// @@ -1528,13 +1523,16 @@ public class ResourceLinkType public string Value { get; set; } } - /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + /// Groups data about name conversions for persons who are anonymised> + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class AnonymsType { - /// + /// + /// URL to information to convert pseudo named to real-names + /// + [PublicAPI] public ResourceLinkType ResourceLink { get; set; } /// @@ -1542,9 +1540,9 @@ public class AnonymsType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class CounterPositionType { /// @@ -1555,9 +1553,9 @@ public class CounterPositionType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class IntegerType { /// @@ -1566,9 +1564,9 @@ public class IntegerType } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class SourceType : IMDIDescription { /// @@ -1580,7 +1578,10 @@ public class SourceType : IMDIDescription /// public QualityType Quality { get; set; } - /// + /// + /// Position (start (+end) ) on a old fashioned tape without time indication + /// + [PublicAPI] public CounterPositionType CounterPosition { get; set; } /// @@ -1589,8 +1590,8 @@ public class SourceType : IMDIDescription [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return DescriptionInternal; } - set { DescriptionInternal = value; } + get => DescriptionInternal; + set => DescriptionInternal = value; } /// @@ -1602,9 +1603,9 @@ public DescriptionTypeCollection Description } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class QualityType { /// @@ -1624,9 +1625,9 @@ public QualityType() {} } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class ValidationType { /// @@ -1650,9 +1651,9 @@ public ValidationType() } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class WrittenResourceType : IIMDISessionFile { /// @@ -1735,9 +1736,9 @@ public void AddDescription(LanguageString description) } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class MediaFileType : IIMDISessionFile { /// @@ -1799,10 +1800,15 @@ public void AddDescription(LanguageString description) public string OutputDirectory { get; set; } } - /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + /// + /// A "session" (aka, "resource bundle") usually corresponds to a meaningful unit of analysis, + /// e.g., to a piece of data having the same overall content, the same set of actors, and the + /// same location and time (e.g., one elicitation session on topic X, or one folktale, or one + /// ‘matching game’, or one conversation between several speakers). + /// + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class Session : IIMDIMajorObject, IArchivingSession { private static int _anonymizedCounter = 1; @@ -1816,7 +1822,7 @@ public Session() References = new SessionTypeReferences(); } - /// Name of object + /// Name of session [XmlElement("Name")] public string Name { get; set; } @@ -1863,7 +1869,7 @@ public void SetDate(int year) [XmlIgnore] public ArchivingLocation Location { - get { return MDGroup.Location.ToArchivingLocation(); } + get => MDGroup.Location.ToArchivingLocation(); set { var loc = MDGroup.Location; @@ -1904,8 +1910,7 @@ public void AddProject(ArchivingPackage package) } }; var imdiPackage = package as IMDIPackage; - var corpus = imdiPackage?.BaseImdiFile?.Items?.FirstOrDefault() as Corpus; - if (corpus != null) + if (imdiPackage?.BaseImdiFile?.Items?.FirstOrDefault() is Corpus corpus) project.Description.Add(corpus.Description.FirstOrDefault()); MDGroup.Project = new List{ project }; } @@ -1985,27 +1990,23 @@ public void AddContentKeyValuePair(string key, string value) public void AddFileKeyValuePair(string fullFileName, string key, string value) { var sessionFile = GetFile(fullFileName); - if (sessionFile == null) return; - if (sessionFile is MediaFileType) - { - var audioOrVisualFile = sessionFile as MediaFileType; + if (sessionFile == null) + return; + if (sessionFile is MediaFileType audioOrVisualFile) audioOrVisualFile.Keys.Key.Add(new KeyType { Name = key, Value = value }); - } - else if (sessionFile is WrittenResourceType) - { - var writtenResourceFile = sessionFile as WrittenResourceType; + else if (sessionFile is WrittenResourceType writtenResourceFile) writtenResourceFile.Keys.Key.Add(new KeyType { Name = key, Value = value }); - } } public void AddFileDescription(string fullFileName, LanguageString description) { var sessionFile = GetFile(fullFileName); - if (sessionFile == null) return; + if (sessionFile == null) + return; // IMDIFile.cs line 160 adds a default value which will block the adding of the first entry if (sessionFile.Description.Count == 1 && - sessionFile.Description.FirstOrDefault().Value == null) + sessionFile.Description.FirstOrDefault()?.Value == null) sessionFile.Description.Remove(sessionFile.Description.FirstOrDefault()); sessionFile.Description.Add(description); @@ -2014,7 +2015,8 @@ public void AddFileDescription(string fullFileName, LanguageString description) public void AddActorContact(ArchivingActor actor, ArchivingContact contact) { var actorType = GetActor(actor.FullName); - if (actorType == null) return; + if (actorType == null) + return; actorType.Contact = new ContactType { Name = contact.Name, @@ -2027,8 +2029,8 @@ public void AddActorContact(ArchivingActor actor, ArchivingContact contact) public void AddMediaFileTimes(string fullFileName, string start, string stop) { var sessionFile = GetFile(fullFileName); - if (!(sessionFile is MediaFileType)) return; - var audioOrVisualFile = sessionFile as MediaFileType; + if (!(sessionFile is MediaFileType audioOrVisualFile)) + return; audioOrVisualFile.TimePosition.Start = start; audioOrVisualFile.TimePosition.End = stop; } @@ -2068,22 +2070,13 @@ private ActorType GetActor(string fullName) /// private IIMDISessionFile GetFile(string fileName) { - foreach (var fileType in Resources.MediaFile) - { - if (fileType.FullPathAndFileName == fileName) - return fileType; - } - foreach (var writtenResourceType in Resources.WrittenResource) - { - if (writtenResourceType.FullPathAndFileName == fileName) - return writtenResourceType; - } - return null; + return Resources.MediaFile.FirstOrDefault(fileType => fileType.FullPathAndFileName == fileName) as IIMDISessionFile ?? + Resources.WrittenResource.FirstOrDefault(writtenResourceType => writtenResourceType.FullPathAndFileName == fileName); } /// [XmlIgnore] - public List Files + public IReadOnlyList Files { get { @@ -2099,126 +2092,85 @@ public List Files [XmlIgnore] public string Genre { - get - { - return MDGroup.Content.Genre == null ? null : MDGroup.Content.Genre.Value; - } - set - { - MDGroup.Content.Genre = value?.Replace("<","")?.Replace(">","").ToVocabularyType(false, ListType.Link(ListType.ContentGenre)); - } + get => MDGroup.Content.Genre?.Value; + set => MDGroup.Content.Genre = value?.Replace("<","")?.Replace(">","") + .ToVocabularyType(false, Link(ContentGenre)); } /// [XmlIgnore] public string SubGenre { - get - { - return MDGroup.Content.SubGenre == null ? null : MDGroup.Content.SubGenre.Value; - } - set - { - MDGroup.Content.SubGenre = value.ToVocabularyType(false, ListType.Link(ListType.ContentSubGenre)); - } + get => MDGroup.Content.SubGenre?.Value; + set => MDGroup.Content.SubGenre = value.ToVocabularyType(false, Link(ContentSubGenre)); } /// [XmlIgnore] public string Interactivity { - get - { - return MDGroup.Content.CommunicationContext.Interactivity == null ? null : MDGroup.Content.CommunicationContext.Interactivity.Value; - } - set - { - MDGroup.Content.SetInteractivity(value); - } + get => MDGroup.Content.CommunicationContext.Interactivity?.Value; + set => MDGroup.Content.SetInteractivity(value); } /// [XmlIgnore] public string Involvement { - get - { - return MDGroup.Content.CommunicationContext.Involvement == null ? null : MDGroup.Content.CommunicationContext.Involvement.Value; - } - set - { - MDGroup.Content.SetInvolvement(value); - } + get => MDGroup.Content.CommunicationContext.Involvement?.Value; + set => MDGroup.Content.SetInvolvement(value); } /// [XmlIgnore] public string PlanningType { - get - { - return MDGroup.Content.CommunicationContext.PlanningType == null ? null : MDGroup.Content.CommunicationContext.PlanningType.Value; - } - set - { - MDGroup.Content.SetPlanningType(value); - } + get => MDGroup.Content.CommunicationContext.PlanningType?.Value; + set => MDGroup.Content.SetPlanningType(value); } /// [XmlIgnore] public string SocialContext { - get - { - return MDGroup.Content.CommunicationContext.SocialContext == null ? null : MDGroup.Content.CommunicationContext.SocialContext.Value; - } - set - { - MDGroup.Content.SetSocialContext(value); - } + get => MDGroup.Content.CommunicationContext.SocialContext?.Value; + set => MDGroup.Content.SetSocialContext(value); } /// [XmlIgnore] public string Task { - get - { - return MDGroup.Content.Task == null ? null : MDGroup.Content.Task.Value; - } - set - { - MDGroup.Content.Task = value.ToVocabularyType(false, ListType.Link(ListType.ContentTask)); - } + get => MDGroup.Content.Task?.Value; + set => MDGroup.Content.Task = value.ToVocabularyType(false, Link(ContentTask)); } } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType=true, Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType=true, Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class SessionResources { private List _mediaFileField; private List _writtenResourceField; /// - [XmlElementAttribute("MediaFile")] + [XmlElement("MediaFile")] public List MediaFile { - get { return _mediaFileField ?? (_mediaFileField = new List()); } - set { _mediaFileField = value; } + get => _mediaFileField ??= new List(); + set => _mediaFileField = value; } /// - [XmlElementAttribute("WrittenResource")] + [XmlElement("WrittenResource")] public List WrittenResource { - get { return _writtenResourceField ?? (_writtenResourceField = new List()); } - set { _writtenResourceField = value; } + get { return _writtenResourceField ??= new List(); } + set => _writtenResourceField = value; } /// - [XmlElementAttribute("Source")] + [XmlElement("Source")] public SourceType[] Source { get; set; } /// @@ -2226,22 +2178,22 @@ public List WrittenResource { } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType=true, Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType=true, Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class SessionReferences : IMDIDescription { [XmlElement("Description")] public DescriptionTypeCollection Description { - get { return DescriptionInternal; } - set { DescriptionInternal = value; } + get => DescriptionInternal; + set => DescriptionInternal = value; } } /// - [SerializableAttribute] - [XmlTypeAttribute(Namespace="http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [XmlType(Namespace="https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public enum MetatranscriptValueType { // ReSharper disable InconsistentNaming @@ -2249,36 +2201,37 @@ public enum MetatranscriptValueType SESSION, /// - [XmlEnumAttribute("SESSION.Profile")] + [XmlEnum("SESSION.Profile")] SESSIONProfile, /// + [PublicAPI] LEXICON_RESOURCE_BUNDLE, /// - [XmlEnumAttribute("LEXICON_RESOURCE_BUNDLE.Profile")] + [XmlEnum("LEXICON_RESOURCE_BUNDLE.Profile")] LEXICON_RESOURCE_BUNDLEProfile, /// CATALOGUE, /// - [XmlEnumAttribute("CATALOGUE.Profile")] + [XmlEnum("CATALOGUE.Profile")] CATALOGUEProfile, /// CORPUS, /// - [XmlEnumAttribute("CORPUS.Profile")] + [XmlEnum("CORPUS.Profile")] CORPUSProfile, // ReSharper restore InconsistentNaming } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(Namespace = "http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(Namespace = "https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class TimePositionRangeType { /// @@ -2296,9 +2249,9 @@ public TimePositionRangeType() } /// - [SerializableAttribute] - [DebuggerStepThroughAttribute] - [XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.mpi.nl/IMDI/Schema/IMDI")] + [Serializable] + [DebuggerStepThrough] + [XmlType(AnonymousType = true, Namespace = "https://www.mpi.nl/IMDI/Schema/IMDI_3.0.xsd")] public class SessionTypeReferences { /// diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs index b45d5e81d..6ae64e05a 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.Designer.cs @@ -30,215 +30,218 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this._tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); - this._buttonCreatePackage = new System.Windows.Forms.Button(); - this._linkOverview = new System.Windows.Forms.LinkLabel(); - this._progressBar = new System.Windows.Forms.ProgressBar(); - this._logBox = new SIL.Windows.Forms.Progress.LogBox(); - this._buttonLaunchRamp = new System.Windows.Forms.Button(); - this._buttonCancel = new System.Windows.Forms.Button(); - this._flowLayoutExtra = new System.Windows.Forms.FlowLayoutPanel(); - this.locExtender = new L10NSharp.UI.L10NSharpExtender(this.components); - this._chkMetadataOnly = new System.Windows.Forms.CheckBox(); - this._tableLayoutPanel.SuspendLayout(); - this._flowLayoutExtra.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.locExtender)).BeginInit(); - this.SuspendLayout(); - // - // _tableLayoutPanel - // - this._tableLayoutPanel.ColumnCount = 3; - this._tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this._tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this._tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this._tableLayoutPanel.Controls.Add(this._buttonCreatePackage, 0, 4); - this._tableLayoutPanel.Controls.Add(this._linkOverview, 0, 0); - this._tableLayoutPanel.Controls.Add(this._progressBar, 0, 2); - this._tableLayoutPanel.Controls.Add(this._logBox, 0, 1); - this._tableLayoutPanel.Controls.Add(this._buttonLaunchRamp, 1, 4); - this._tableLayoutPanel.Controls.Add(this._buttonCancel, 2, 4); - this._tableLayoutPanel.Controls.Add(this._flowLayoutExtra, 0, 3); - this._tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; - this._tableLayoutPanel.Location = new System.Drawing.Point(12, 12); - this._tableLayoutPanel.Name = "_tableLayoutPanel"; - this._tableLayoutPanel.RowCount = 5; - this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this._tableLayoutPanel.Size = new System.Drawing.Size(355, 408); - this._tableLayoutPanel.TabIndex = 0; - // - // _buttonCreatePackage - // - this._buttonCreatePackage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this._buttonCreatePackage.AutoSize = true; - this.locExtender.SetLocalizableToolTip(this._buttonCreatePackage, null); - this.locExtender.SetLocalizationComment(this._buttonCreatePackage, null); - this.locExtender.SetLocalizingId(this._buttonCreatePackage, "DialogBoxes.ArchivingDlg._buttonCreatePackage"); - this._buttonCreatePackage.Location = new System.Drawing.Point(58, 382); - this._buttonCreatePackage.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); - this._buttonCreatePackage.Name = "_buttonCreatePackage"; - this._buttonCreatePackage.Size = new System.Drawing.Size(106, 26); - this._buttonCreatePackage.TabIndex = 0; - this._buttonCreatePackage.Text = "&1) Create Package"; - this._buttonCreatePackage.UseVisualStyleBackColor = true; - this._buttonCreatePackage.Click += new System.EventHandler(this.CreatePackage); - - // - // _linkOverview - // - this._linkOverview.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.components = new System.ComponentModel.Container(); + this._tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); + this._buttonCreatePackage = new System.Windows.Forms.Button(); + this._linkOverview = new System.Windows.Forms.LinkLabel(); + this._progressBar = new System.Windows.Forms.ProgressBar(); + this._logBox = new SIL.Windows.Forms.Progress.LogBox(); + this._buttonLaunchRamp = new System.Windows.Forms.Button(); + this._buttonCancel = new System.Windows.Forms.Button(); + this._flowLayoutExtra = new System.Windows.Forms.FlowLayoutPanel(); + this._chkMetadataOnly = new System.Windows.Forms.CheckBox(); + this.locExtender = new L10NSharp.UI.L10NSharpExtender(this.components); + this._tableLayoutPanel.SuspendLayout(); + this._flowLayoutExtra.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.locExtender)).BeginInit(); + this.SuspendLayout(); + // + // _tableLayoutPanel + // + this._tableLayoutPanel.ColumnCount = 3; + this._tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanel.Controls.Add(this._buttonCreatePackage, 0, 4); + this._tableLayoutPanel.Controls.Add(this._linkOverview, 0, 0); + this._tableLayoutPanel.Controls.Add(this._progressBar, 0, 2); + this._tableLayoutPanel.Controls.Add(this._logBox, 0, 1); + this._tableLayoutPanel.Controls.Add(this._buttonLaunchRamp, 1, 4); + this._tableLayoutPanel.Controls.Add(this._buttonCancel, 2, 4); + this._tableLayoutPanel.Controls.Add(this._flowLayoutExtra, 0, 3); + this._tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this._tableLayoutPanel.Location = new System.Drawing.Point(12, 12); + this._tableLayoutPanel.Name = "_tableLayoutPanel"; + this._tableLayoutPanel.RowCount = 5; + this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this._tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this._tableLayoutPanel.Size = new System.Drawing.Size(355, 408); + this._tableLayoutPanel.TabIndex = 0; + // + // _buttonCreatePackage + // + this._buttonCreatePackage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCreatePackage.AutoSize = true; + this._buttonCreatePackage.Enabled = false; + this.locExtender.SetLocalizableToolTip(this._buttonCreatePackage, null); + this.locExtender.SetLocalizationComment(this._buttonCreatePackage, null); + this.locExtender.SetLocalizingId(this._buttonCreatePackage, "DialogBoxes.ArchivingDlg._buttonCreatePackage"); + this._buttonCreatePackage.Location = new System.Drawing.Point(58, 382); + this._buttonCreatePackage.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); + this._buttonCreatePackage.Name = "_buttonCreatePackage"; + this._buttonCreatePackage.Size = new System.Drawing.Size(106, 26); + this._buttonCreatePackage.TabIndex = 0; + this._buttonCreatePackage.Text = "&1) Create Package"; + this._buttonCreatePackage.UseVisualStyleBackColor = true; + this._buttonCreatePackage.Click += new System.EventHandler(this.CreatePackage); + // + // _linkOverview + // + this._linkOverview.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this._linkOverview.AutoSize = true; - this._tableLayoutPanel.SetColumnSpan(this._linkOverview, 3); - this._linkOverview.LinkArea = new System.Windows.Forms.LinkArea(0, 0); - this.locExtender.SetLocalizableToolTip(this._linkOverview, null); - this.locExtender.SetLocalizationComment(this._linkOverview, ""); - this.locExtender.SetLocalizationPriority(this._linkOverview, L10NSharp.LocalizationPriority.NotLocalizable); - this.locExtender.SetLocalizingId(this._linkOverview, "DialogBoxes.ArchivingDlg.OverviewText"); - this._linkOverview.Location = new System.Drawing.Point(3, 0); - this._linkOverview.Name = "_linkOverview"; - this._linkOverview.Size = new System.Drawing.Size(349, 13); - this._linkOverview.TabIndex = 3; - this._linkOverview.Text = "#"; - this._linkOverview.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.HandleRampLinkClicked); - // - // _progressBar - // - this._progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this._linkOverview.AutoSize = true; + this._tableLayoutPanel.SetColumnSpan(this._linkOverview, 3); + this._linkOverview.LinkArea = new System.Windows.Forms.LinkArea(0, 0); + this.locExtender.SetLocalizableToolTip(this._linkOverview, null); + this.locExtender.SetLocalizationComment(this._linkOverview, ""); + this.locExtender.SetLocalizationPriority(this._linkOverview, L10NSharp.LocalizationPriority.NotLocalizable); + this.locExtender.SetLocalizingId(this._linkOverview, "DialogBoxes.ArchivingDlg.OverviewText"); + this._linkOverview.Location = new System.Drawing.Point(3, 0); + this._linkOverview.Name = "_linkOverview"; + this._linkOverview.Size = new System.Drawing.Size(349, 13); + this._linkOverview.TabIndex = 3; + this._linkOverview.Text = "#"; + this._linkOverview.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.HandleRampLinkClicked); + // + // _progressBar + // + this._progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this._tableLayoutPanel.SetColumnSpan(this._progressBar, 3); - this._progressBar.Location = new System.Drawing.Point(0, 326); - this._progressBar.Margin = new System.Windows.Forms.Padding(0, 0, 0, 12); - this._progressBar.Name = "_progressBar"; - this._progressBar.Size = new System.Drawing.Size(355, 15); - this._progressBar.TabIndex = 4; - // - // _logBox - // - this._logBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this._tableLayoutPanel.SetColumnSpan(this._progressBar, 3); + this._progressBar.Location = new System.Drawing.Point(0, 326); + this._progressBar.Margin = new System.Windows.Forms.Padding(0, 0, 0, 12); + this._progressBar.Name = "_progressBar"; + this._progressBar.Size = new System.Drawing.Size(355, 15); + this._progressBar.TabIndex = 4; + // + // _logBox + // + this._logBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this._logBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this._logBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(173)))), ((int)(((byte)(179))))); - this._logBox.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this._logBox.CancelRequested = false; - this._tableLayoutPanel.SetColumnSpan(this._logBox, 3); - this._logBox.ErrorEncountered = false; - this._logBox.Font = new System.Drawing.Font("Segoe UI", 9F); - this._logBox.GetDiagnosticsMethod = null; - this.locExtender.SetLocalizableToolTip(this._logBox, null); - this.locExtender.SetLocalizationComment(this._logBox, null); - this.locExtender.SetLocalizingId(this._logBox, "LogBox"); - this._logBox.Location = new System.Drawing.Point(0, 18); - this._logBox.Margin = new System.Windows.Forms.Padding(0, 5, 0, 5); - this._logBox.Name = "_logBox"; - this._logBox.ProgressIndicator = null; - this._logBox.ShowCopyToClipboardMenuItem = false; - this._logBox.ShowDetailsMenuItem = false; - this._logBox.ShowDiagnosticsMenuItem = false; - this._logBox.ShowFontMenuItem = false; - this._logBox.ShowMenu = false; - this._logBox.Size = new System.Drawing.Size(355, 303); - this._logBox.TabIndex = 5; - this._logBox.TabStop = false; - this._logBox.ReportErrorLinkClicked += new System.EventHandler(this.HandleLogBoxReportErrorLinkClicked); - // - // _buttonLaunchRamp - // - this._buttonLaunchRamp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this._buttonLaunchRamp.AutoSize = true; - this._buttonLaunchRamp.DialogResult = System.Windows.Forms.DialogResult.OK; - this.locExtender.SetLocalizableToolTip(this._buttonLaunchRamp, null); - this.locExtender.SetLocalizationComment(this._buttonLaunchRamp, null); - this.locExtender.SetLocalizingId(this._buttonLaunchRamp, "DialogBoxes.ArchivingDlg._buttonLaunchRamp"); - this._buttonLaunchRamp.Location = new System.Drawing.Point(172, 382); - this._buttonLaunchRamp.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); - this._buttonLaunchRamp.Name = "_buttonLaunchRamp"; - this._buttonLaunchRamp.Size = new System.Drawing.Size(100, 26); - this._buttonLaunchRamp.TabIndex = 1; - this._buttonLaunchRamp.Text = "&2) Launch {0}"; - this._buttonLaunchRamp.UseVisualStyleBackColor = true; - // - // _buttonCancel - // - this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this._buttonCancel.AutoSize = true; - this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.locExtender.SetLocalizableToolTip(this._buttonCancel, null); - this.locExtender.SetLocalizationComment(this._buttonCancel, null); - this.locExtender.SetLocalizingId(this._buttonCancel, "DialogBoxes.ArchivingDlg._buttonCancel"); - this._buttonCancel.Location = new System.Drawing.Point(280, 382); - this._buttonCancel.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); - this._buttonCancel.Name = "_buttonCancel"; - this._buttonCancel.Size = new System.Drawing.Size(75, 26); - this._buttonCancel.TabIndex = 2; - this._buttonCancel.Text = "Cancel"; - this._buttonCancel.UseVisualStyleBackColor = true; - this._buttonCancel.Click += new System.EventHandler(this.HandleButtonCancelClick); - // - // _flowLayoutExtra - // - this._flowLayoutExtra.AutoSize = true; - this._flowLayoutExtra.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this._tableLayoutPanel.SetColumnSpan(this._flowLayoutExtra, 3); - this._flowLayoutExtra.Controls.Add(this._chkMetadataOnly); - this._flowLayoutExtra.Dock = System.Windows.Forms.DockStyle.Top; - this._flowLayoutExtra.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; - this._flowLayoutExtra.Location = new System.Drawing.Point(3, 356); - this._flowLayoutExtra.Name = "_flowLayoutExtra"; - this._flowLayoutExtra.Size = new System.Drawing.Size(349, 23); - this._flowLayoutExtra.TabIndex = 6; - // - // locExtender - // - this.locExtender.LocalizationManagerId = "SIL.Windows.Forms.Archiving"; - this.locExtender.PrefixForNewItems = null; - // - // _chkMetadataOnly - // - this._chkMetadataOnly.AutoSize = true; - this.locExtender.SetLocalizableToolTip(this._chkMetadataOnly, "Select this to prevent copying actual data files into archive"); - this.locExtender.SetLocalizationComment(this._chkMetadataOnly, null); - this.locExtender.SetLocalizingId(this._chkMetadataOnly, "ArchivingDlg._chkMetadataOnly"); - this._chkMetadataOnly.Location = new System.Drawing.Point(3, 3); - this._chkMetadataOnly.Name = "_chkMetadataOnly"; - this._chkMetadataOnly.Size = new System.Drawing.Size(93, 17); - this._chkMetadataOnly.TabIndex = 0; - this._chkMetadataOnly.Text = "Metadata only"; - this._chkMetadataOnly.UseVisualStyleBackColor = true; - this._chkMetadataOnly.Visible = false; - this._chkMetadataOnly.CheckedChanged += new System.EventHandler(this._chkMetadataOnly_CheckedChanged); - // - // ArchivingDlg - // - this.AcceptButton = this._buttonLaunchRamp; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this._buttonCancel; - this.ClientSize = new System.Drawing.Size(379, 432); - this.Controls.Add(this._tableLayoutPanel); - this.locExtender.SetLocalizableToolTip(this, null); - this.locExtender.SetLocalizationComment(this, "Parameter is application name"); - this.locExtender.SetLocalizingId(this, "DialogBoxes.ArchivingDlg.WindowTitle"); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.MinimumSize = new System.Drawing.Size(355, 320); - this.Name = "ArchivingDlg"; - this.Padding = new System.Windows.Forms.Padding(12); - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; - this.Text = "{0}: Archive using {1}"; - this._tableLayoutPanel.ResumeLayout(false); - this._tableLayoutPanel.PerformLayout(); - this._flowLayoutExtra.ResumeLayout(false); - this._flowLayoutExtra.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.locExtender)).EndInit(); - this.ResumeLayout(false); + this._logBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._logBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(173)))), ((int)(((byte)(179))))); + this._logBox.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this._logBox.CancelRequested = false; + this._tableLayoutPanel.SetColumnSpan(this._logBox, 3); + this._logBox.ErrorEncountered = false; + this._logBox.Font = new System.Drawing.Font("Segoe UI", 9F); + this._logBox.GetDiagnosticsMethod = null; + this.locExtender.SetLocalizableToolTip(this._logBox, null); + this.locExtender.SetLocalizationComment(this._logBox, null); + this.locExtender.SetLocalizingId(this._logBox, "LogBox"); + this._logBox.Location = new System.Drawing.Point(0, 18); + this._logBox.Margin = new System.Windows.Forms.Padding(0, 5, 0, 5); + this._logBox.MaxLength = 715827882; + this._logBox.MaxLengthErrorMessage = "Maximum length exceeded!"; + this._logBox.Name = "_logBox"; + this._logBox.ProgressIndicator = null; + this._logBox.ShowCopyToClipboardMenuItem = false; + this._logBox.ShowDetailsMenuItem = false; + this._logBox.ShowDiagnosticsMenuItem = false; + this._logBox.ShowFontMenuItem = false; + this._logBox.ShowMenu = false; + this._logBox.Size = new System.Drawing.Size(355, 303); + this._logBox.TabIndex = 5; + this._logBox.TabStop = false; + this._logBox.ReportErrorLinkClicked += new System.EventHandler(this.HandleLogBoxReportErrorLinkClicked); + // + // _buttonLaunchRamp + // + this._buttonLaunchRamp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this._buttonLaunchRamp.AutoSize = true; + this._buttonLaunchRamp.DialogResult = System.Windows.Forms.DialogResult.OK; + this._buttonLaunchRamp.Enabled = false; + this.locExtender.SetLocalizableToolTip(this._buttonLaunchRamp, null); + this.locExtender.SetLocalizationComment(this._buttonLaunchRamp, null); + this.locExtender.SetLocalizingId(this._buttonLaunchRamp, "DialogBoxes.ArchivingDlg._buttonLaunchRamp"); + this._buttonLaunchRamp.Location = new System.Drawing.Point(172, 382); + this._buttonLaunchRamp.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); + this._buttonLaunchRamp.Name = "_buttonLaunchRamp"; + this._buttonLaunchRamp.Size = new System.Drawing.Size(100, 26); + this._buttonLaunchRamp.TabIndex = 1; + this._buttonLaunchRamp.Text = "&2) Launch {0}"; + this._buttonLaunchRamp.UseVisualStyleBackColor = true; + // + // _buttonCancel + // + this._buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this._buttonCancel.AutoSize = true; + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.locExtender.SetLocalizableToolTip(this._buttonCancel, null); + this.locExtender.SetLocalizationComment(this._buttonCancel, null); + this.locExtender.SetLocalizingId(this._buttonCancel, "DialogBoxes.ArchivingDlg._buttonCancel"); + this._buttonCancel.Location = new System.Drawing.Point(280, 382); + this._buttonCancel.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 26); + this._buttonCancel.TabIndex = 2; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + this._buttonCancel.Click += new System.EventHandler(this.HandleButtonCancelClick); + // + // _flowLayoutExtra + // + this._flowLayoutExtra.AutoSize = true; + this._flowLayoutExtra.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._tableLayoutPanel.SetColumnSpan(this._flowLayoutExtra, 3); + this._flowLayoutExtra.Controls.Add(this._chkMetadataOnly); + this._flowLayoutExtra.Dock = System.Windows.Forms.DockStyle.Top; + this._flowLayoutExtra.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this._flowLayoutExtra.Location = new System.Drawing.Point(3, 356); + this._flowLayoutExtra.Name = "_flowLayoutExtra"; + this._flowLayoutExtra.Size = new System.Drawing.Size(349, 23); + this._flowLayoutExtra.TabIndex = 6; + // + // _chkMetadataOnly + // + this._chkMetadataOnly.AutoSize = true; + this.locExtender.SetLocalizableToolTip(this._chkMetadataOnly, "Select this to prevent copying actual data files into archive"); + this.locExtender.SetLocalizationComment(this._chkMetadataOnly, null); + this.locExtender.SetLocalizingId(this._chkMetadataOnly, "ArchivingDlg._chkMetadataOnly"); + this._chkMetadataOnly.Location = new System.Drawing.Point(3, 3); + this._chkMetadataOnly.Name = "_chkMetadataOnly"; + this._chkMetadataOnly.Size = new System.Drawing.Size(93, 17); + this._chkMetadataOnly.TabIndex = 0; + this._chkMetadataOnly.Text = "Metadata only"; + this._chkMetadataOnly.UseVisualStyleBackColor = true; + this._chkMetadataOnly.Visible = false; + this._chkMetadataOnly.CheckedChanged += new System.EventHandler(this._chkMetadataOnly_CheckedChanged); + // + // locExtender + // + this.locExtender.LocalizationManagerId = "SIL.Windows.Forms.Archiving"; + this.locExtender.PrefixForNewItems = null; + // + // ArchivingDlg + // + this.AcceptButton = this._buttonLaunchRamp; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this._buttonCancel; + this.ClientSize = new System.Drawing.Size(379, 432); + this.Controls.Add(this._tableLayoutPanel); + this.locExtender.SetLocalizableToolTip(this, null); + this.locExtender.SetLocalizationComment(this, "Parameter is application name"); + this.locExtender.SetLocalizingId(this, "DialogBoxes.ArchivingDlg.WindowTitle"); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(355, 320); + this.Name = "ArchivingDlg"; + this.Padding = new System.Windows.Forms.Padding(12); + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; + this.Text = "{0}: Archive using {1}"; + this._tableLayoutPanel.ResumeLayout(false); + this._tableLayoutPanel.PerformLayout(); + this._flowLayoutExtra.ResumeLayout(false); + this._flowLayoutExtra.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.locExtender)).EndInit(); + this.ResumeLayout(false); } diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs index d727da43d..1bc5a16db 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs @@ -254,8 +254,10 @@ private async Task CreatePackageAsync() } finally { - _progressBar.Visible = false; - WaitCursor.Hide(); + if (InvokeRequired) + Invoke(new Action (ResetUIForUserInteraction)); + else + ResetUIForUserInteraction(); try { @@ -269,6 +271,12 @@ private async Task CreatePackageAsync() } } + private void ResetUIForUserInteraction() + { + _progressBar.Visible = false; + WaitCursor.Hide(); + } + private void CompleteCancellation() { // American spelling for the ID. British spelling for the string :-) @@ -283,7 +291,11 @@ private void CompleteCancellation() protected virtual void PackageCreationComplete(string result) { - _buttonLaunchRamp.Enabled = true; + + if (InvokeRequired) + Invoke(new Action(() => { _buttonLaunchRamp.Enabled = true; })); + else + _buttonLaunchRamp.Enabled = true; } protected virtual void DisableControlsDuringPackageCreation() @@ -308,7 +320,10 @@ protected void UpdateOverviewText() public void IncrementProgress() { - _progressBar.Increment(1); + if (InvokeRequired) + Invoke(new Action(() => { _progressBar.Increment(1); })); + else + _progressBar.Increment(1); } /// ------------------------------------------------------------------------------------ @@ -487,7 +502,6 @@ protected override void OnLoad(EventArgs e) Text = Format(Text, _viewModel.AppName, ArchiveTypeForTitleBar ?? ArchiveTypeName); UpdateLaunchButtonText(); - _buttonLaunchRamp.Enabled = false; //!string.IsNullOrEmpty(model.PathToProgramToLaunch); _linkOverview.Text = InformativeText; _linkOverview.Links.Clear(); @@ -508,21 +522,20 @@ protected override void OnShown(EventArgs e) { base.OnShown(e); Initialize(); - WaitCursor.Show(); - _buttonCreatePackage.Enabled = false; } /// ------------------------------------------------------------------------------------ protected async void Initialize() { _cts = new CancellationTokenSource(); + WaitCursor.Show(); try { - _buttonCreatePackage.Enabled = await _viewModel.Initialize(this, _cts.Token); + _buttonCreatePackage.Enabled = _chkMetadataOnly.Enabled = + await _viewModel.Initialize(this, _cts.Token); _logBox.ScrollToTop(); _progressBar.Maximum = _viewModel.CalculateMaxProgressBarValue(); - _buttonCreatePackage.Enabled = true; } catch (OperationCanceledException) { @@ -535,7 +548,10 @@ protected async void Initialize() } finally { - WaitCursor.Hide(); + if (InvokeRequired) + Invoke(new Action (ResetUIForUserInteraction)); + else + ResetUIForUserInteraction(); try { diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlg.resx b/SIL.Windows.Forms.Archiving/ArchivingDlg.resx index b0ea264f8..3c8fb332c 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlg.resx +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.resx @@ -120,9 +120,6 @@ 17, 17 - - 17, 17 - 42 diff --git a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs index 8b316583d..50ccb56ca 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs @@ -37,8 +37,8 @@ public class IMDIArchivingDlg : ArchivingDlg /// dialog box to appear (can be null) /// ------------------------------------------------------------------------------------ public IMDIArchivingDlg(IMDIArchivingDlgViewModel model, - string appSpecificArchivalProcessInfo, string localizationManagerId, - Font programDialogFont, FormSettings settings) + string appSpecificArchivalProcessInfo, string localizationManagerId = null, + Font programDialogFont = null, FormSettings settings = null) : base(model, appSpecificArchivalProcessInfo, localizationManagerId, programDialogFont, settings, LocalizationManager.GetString( "DialogBoxes.ArchivingDlg.IsleMetadataInitiative", "Isle Metadata Initiative", @@ -46,6 +46,7 @@ public IMDIArchivingDlg(IMDIArchivingDlgViewModel model, { // DO NOT SHOW THE LAUNCH OPTION AT THIS TIME model.PathToProgramToLaunch = null; + model.InitializationFailed += Model_InitializationFailed; InitializeNewControls(); @@ -56,6 +57,11 @@ public IMDIArchivingDlg(IMDIArchivingDlgViewModel model, SetControlProperties(); } + private void Model_InitializationFailed(object sender, EventArgs e) + { + _browseDestinationFolder.Enabled = false; + } + private void InitializeNewControls() { AddDestinationFolder(); @@ -153,13 +159,21 @@ protected override void PackageCreationComplete(string result) if (mainExportFile != null) { - // copy the path to the imdi file to the clipboard + void PutIMDIPackagePathOnClipboard() + { + // copy the path to the imdi file to the clipboard - // SP-818: Crash in IMDI export when dialog tries to put string on clipboard - // 18 FEB 2014, Phil Hopper: I found this possible solution using retries on StackOverflow - // https://stackoverflow.com/questions/5707990/requested-clipboard-operation-did-not-succeed - //Clipboard.SetData(DataFormats.Text, _imdiData.MainExportFile); - Clipboard.SetDataObject(mainExportFile, true, 3, 500); + // SP-818: Crash in IMDI export when dialog tries to put string on clipboard + // 18 FEB 2014, Phil Hopper: I found this possible solution using retries on StackOverflow + // https://stackoverflow.com/questions/5707990/requested-clipboard-operation-did-not-succeed + //Clipboard.SetData(DataFormats.Text, _imdiData.MainExportFile); + Clipboard.SetDataObject(mainExportFile, true, 3, 500); + } + + if (InvokeRequired) + Invoke(new Action(PutIMDIPackagePathOnClipboard)); + else + PutIMDIPackagePathOnClipboard(); var successMsg = LocalizationManager.GetString("DialogBoxes.ArchivingDlg.ReadyToCallIMDIMsg", "Exported to {0}. This path is now on your clipboard. If you are using Arbil, go to File, Import, then paste this path in."); @@ -171,6 +185,11 @@ public override string GetMessage(ArchivingDlgViewModel.StringId msgId) { switch (msgId) { + case ArchivingDlgViewModel.StringId.IMDIPackageInvalid: + return LocalizationManager.GetString( + "DialogBoxes.ArchivingDlg.IMDIPackageInvalid", "The IMDI package is invalid.", + "This is displayed in the Archive Using IMDI dialog box if the calling " + + "program fails to initialize the IMDI package with valid settings."); case ArchivingDlgViewModel.StringId.IMDIActorsGroup: return LocalizationManager.GetString( "DialogBoxes.ArchivingDlg.IMDIActorsGroup", "Actors", @@ -275,7 +294,6 @@ private void SelectIMDIProgramOnClick(object sender, EventArgs eventArgs) { ((IMDIArchivingDlgViewModel)_viewModel).OtherProgramPath = chooseIMDIProgram.FileName; SetControlProperties(); - } } } From 62d0165ae83ee0e1be7c7f6302671e7d4a222aa5 Mon Sep 17 00:00:00 2001 From: tombogle Date: Tue, 6 Aug 2024 10:33:51 -0400 Subject: [PATCH 09/15] Moved ArchivingTestApp into the TestApps folder and removed redundant TargetFrameworks property --- Palaso.sln | 2 +- .../ArchivingTestApp}/ArchivingTestApp.csproj | 7 +++---- .../ArchivingTestApp}/MainForm.Designer.cs | 0 .../ArchivingTestApp}/MainForm.cs | 0 .../ArchivingTestApp}/MainForm.resx | 0 {ArchivingTestApp => TestApps/ArchivingTestApp}/Program.cs | 0 6 files changed, 4 insertions(+), 5 deletions(-) rename {ArchivingTestApp => TestApps/ArchivingTestApp}/ArchivingTestApp.csproj (64%) rename {ArchivingTestApp => TestApps/ArchivingTestApp}/MainForm.Designer.cs (100%) rename {ArchivingTestApp => TestApps/ArchivingTestApp}/MainForm.cs (100%) rename {ArchivingTestApp => TestApps/ArchivingTestApp}/MainForm.resx (100%) rename {ArchivingTestApp => TestApps/ArchivingTestApp}/Program.cs (100%) diff --git a/Palaso.sln b/Palaso.sln index 0085644f8..e7e313c7c 100755 --- a/Palaso.sln +++ b/Palaso.sln @@ -122,7 +122,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving", "SIL.Archiv EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SIL.Archiving.Tests", "SIL.Archiving.Tests\SIL.Archiving.Tests.csproj", "{698FDB66-0ACE-46E0-843C-3AB70DC7B055}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchivingTestApp", "ArchivingTestApp\ArchivingTestApp.csproj", "{321BB622-8185-4173-8770-742CD620BC18}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchivingTestApp", "TestApps\ArchivingTestApp\ArchivingTestApp.csproj", "{321BB622-8185-4173-8770-742CD620BC18}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/ArchivingTestApp/ArchivingTestApp.csproj b/TestApps/ArchivingTestApp/ArchivingTestApp.csproj similarity index 64% rename from ArchivingTestApp/ArchivingTestApp.csproj rename to TestApps/ArchivingTestApp/ArchivingTestApp.csproj index 7fd3012c8..dadeb7c39 100644 --- a/ArchivingTestApp/ArchivingTestApp.csproj +++ b/TestApps/ArchivingTestApp/ArchivingTestApp.csproj @@ -6,7 +6,6 @@ enable true enable - net8.0-windows latest ArchivingTestApp.Program @@ -16,9 +15,9 @@ - - - + + + \ No newline at end of file diff --git a/ArchivingTestApp/MainForm.Designer.cs b/TestApps/ArchivingTestApp/MainForm.Designer.cs similarity index 100% rename from ArchivingTestApp/MainForm.Designer.cs rename to TestApps/ArchivingTestApp/MainForm.Designer.cs diff --git a/ArchivingTestApp/MainForm.cs b/TestApps/ArchivingTestApp/MainForm.cs similarity index 100% rename from ArchivingTestApp/MainForm.cs rename to TestApps/ArchivingTestApp/MainForm.cs diff --git a/ArchivingTestApp/MainForm.resx b/TestApps/ArchivingTestApp/MainForm.resx similarity index 100% rename from ArchivingTestApp/MainForm.resx rename to TestApps/ArchivingTestApp/MainForm.resx diff --git a/ArchivingTestApp/Program.cs b/TestApps/ArchivingTestApp/Program.cs similarity index 100% rename from ArchivingTestApp/Program.cs rename to TestApps/ArchivingTestApp/Program.cs From 14393d5558f38de6145b106ff1fc592d04d67b6a Mon Sep 17 00:00:00 2001 From: tombogle Date: Tue, 6 Aug 2024 12:54:05 -0400 Subject: [PATCH 10/15] Improved Archiving to make async stuff and cancelling work better. Changed OlacSystem.GetRoles to report a non-fatal exception if the custom XML file cannot be loaded. Removed ArchivingPackage and AddSession from ArchivingDlgViewModel and RampArchivingDlgViewModel --- CHANGELOG.md | 1 + Palaso.sln.DotSettings | 2 + SIL.Archiving/ArchivingDlgViewModel.cs | 17 +---- .../IMDI/IMDIArchivingDlgViewModel.cs | 27 +++++--- SIL.Archiving/RampArchivingDlgViewModel.cs | 64 ++++++++++++------- SIL.Core/ClearShare/OlacSystem.cs | 64 +++++++++++-------- SIL.Windows.Forms.Archiving/ArchivingDlg.cs | 11 ++-- .../IMDI/IMDIArchivingDlg.cs | 1 - 8 files changed, 107 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b27fe3f54..b315a1e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Archiving] Removed protected fields (renamed and made private) from ArchivingLanguage: _iso3Code, _englishName - [SIL.Archiving] Removed protected fields (made private) from ArchivingFile: _fullName, _fileName, _fileSize, _mimeType, _descriptions, _accessProtocol - [SIL.Archiving] Removed public methods CreateMetsFile and CreateRampPackage from RampArchivingDlgViewModel (made internal). +- [SIL.Archiving] Removed ArchivingPackage and AddSession from ArchivingDlgViewModel and RampArchivingDlgViewModel (where they threw NotImplementedExceptions) ### Fixed diff --git a/Palaso.sln.DotSettings b/Palaso.sln.DotSettings index 53e0bb3f5..9bd1aa386 100644 --- a/Palaso.sln.DotSettings +++ b/Palaso.sln.DotSettings @@ -92,10 +92,12 @@ True True True + True True True True True + True True True True diff --git a/SIL.Archiving/ArchivingDlgViewModel.cs b/SIL.Archiving/ArchivingDlgViewModel.cs index 0de1c4c6a..6548d1656 100644 --- a/SIL.Archiving/ArchivingDlgViewModel.cs +++ b/SIL.Archiving/ArchivingDlgViewModel.cs @@ -259,7 +259,7 @@ private async Task SetFilesToArchive(CancellationToken cancellationToken) await Task.Run(() => { _setFilesToArchive(this, cancellationToken); - }); + }, cancellationToken); } /// ------------------------------------------------------------------------------------ @@ -598,21 +598,6 @@ protected string GetFileExcludedMsg(string file) => /// ------------------------------------------------------------------------------------ public static bool IsMono => (Type.GetType("Mono.Runtime") != null); - /// ------------------------------------------------------------------------------------ - /// Adds a "session" or "resource bundle". This usually corresponds to a - /// meaningful unit of analysis, e.g., to a piece of data having the same overall - /// content, the same set of actors, and the same location and time (e.g., one - /// elicitation session on topic X, or one folktale, or one ‘matching game’, or one - /// conversation between several speakers). - /// Unique Identifier for this session. - /// ------------------------------------------------------------------------------------ - [PublicAPI] - public abstract IArchivingSession AddSession(string sessionId); - - /// - [PublicAPI] - public abstract IArchivingPackage ArchivingPackage { get; } - /// public Dictionary AdditionalMessages { get; } diff --git a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs index 6d695228e..c374681ec 100644 --- a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs +++ b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs @@ -198,7 +198,7 @@ public override async Task CreatePackage(CancellationToken cancellationT } /// ------------------------------------------------------------------------------------ - private Task CreateIMDIPackageAsync(CancellationToken cancellationToken) + private async Task CreateIMDIPackageAsync(CancellationToken cancellationToken) { try { @@ -241,6 +241,7 @@ private Task CreateIMDIPackageAsync(CancellationToken cancellationToken) foreach (var fileToCopy in filesToCopy) { ReportProgress(Path.GetFileName(fileToCopy.Key), MessageType.Detail, cancellationToken); + if (FileCopyOverride != null) { try @@ -259,21 +260,21 @@ private Task CreateIMDIPackageAsync(CancellationToken cancellationToken) } } // Don't use File.Copy because it's asynchronous. - CopyFile(fileToCopy.Key, fileToCopy.Value); + await Task.Run(() => CopyFile(fileToCopy.Key, fileToCopy.Value), cancellationToken); } ReportMajorProgressPoint(StringId.SavingFilesInPackage, cancellationToken, false); - return Task.FromResult(true); + return true; } catch (OperationCanceledException) { - return Task.FromResult(false); + return false; } catch (Exception exception) { ReportError(exception, Progress.GetMessage(StringId.ErrorCreatingArchive)); - return Task.FromResult(false); + return false; } } @@ -322,9 +323,17 @@ public string CorpusDirectoryName } } - /// Adds a new session and returns it - /// - public override IArchivingSession AddSession(string sessionId) + /// ------------------------------------------------------------------------------------ + /// Adds a "session" or "resource bundle". This usually corresponds to a + /// meaningful unit of analysis, e.g., to a piece of data having the same overall + /// content, the same set of actors, and the same location and time (e.g., one + /// elicitation session on topic X, or one folktale, or one ‘matching game’, or one + /// conversation between several speakers). + /// Unique Identifier for this session. + /// The added session, or the existing one if a session with the given sessionId + /// already exists. + /// ------------------------------------------------------------------------------------ + public IArchivingSession AddSession(string sessionId) { // look for existing session var session = _imdiData.Sessions.FirstOrDefault(s => s.Name == sessionId); @@ -340,7 +349,7 @@ public override IArchivingSession AddSession(string sessionId) return session; } - public override IArchivingPackage ArchivingPackage => _imdiData; + public IArchivingPackage ArchivingPackage => _imdiData; /// public new string PathToProgramToLaunch diff --git a/SIL.Archiving/RampArchivingDlgViewModel.cs b/SIL.Archiving/RampArchivingDlgViewModel.cs index 0d224df7a..46478851a 100644 --- a/SIL.Archiving/RampArchivingDlgViewModel.cs +++ b/SIL.Archiving/RampArchivingDlgViewModel.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using Ionic.Zip; using JetBrains.Annotations; -using SIL.Archiving.Generic; using SIL.Core.ClearShare; using SIL.Extensions; using SIL.IO; @@ -49,6 +48,7 @@ public class RampArchivingDlgViewModel: ArchivingDlgViewModel public const string kContributor = "dc.contributor"; public const string kAbstractDescription = "dc.description.abstract"; public const string kStageDescription = "dc.description.stage"; + [PublicAPI] public const string kTableOfContentsDescription = "dc.description.tableofcontents"; public const string kVernacularContent = "dc.subject.vernacularContent"; @@ -57,6 +57,7 @@ public class RampArchivingDlgViewModel: ArchivingDlgViewModel public const string kFlagHasSoftwareOrFontRequirements = "relation.requires.has"; public const string kFlagHasGeneralDescription = "description.has"; public const string kFlagHasAbstractDescription = "description.abstract.has"; + [PublicAPI] public const string kFlagHasTableOfContentsDescription = "description.tableofcontents.has"; public const string kFlagHasPromotionDescription = "description.promotion.has"; public const string kTrue = "Y"; @@ -132,7 +133,9 @@ public class RampArchivingDlgViewModel: ArchivingDlgViewModel public const string kFileDescription = "description"; public const string kFileRelationship = "relationship"; public const string kRelationshipSource = "Source"; + [PublicAPI] public const string kRelationshipPresentation = "Presentation"; + [PublicAPI] public const string kRelationshipSupporting = "Supporting"; // ReSharper restore CSharpWarnings::CS1591 #endregion @@ -182,37 +185,50 @@ public class RampArchivingDlgViewModel: ArchivingDlgViewModel /// /// Gets the number of image files in the list(s) of files to archive. /// - /// Public (and self-populating on-demand) to facilitate testing + /// Public (and self-populating on-demand) to facilitate testing. If this + /// property is accessed before initialization is complete, it will return -1. /// ------------------------------------------------------------------------------------ public int ImageCount { get { - if (FileLists != null && _imageCount < 0) + if (FileLists.Count > 0 && _imageCount < 0) ExtractInformationFromFiles(); return _imageCount; } } + /// ------------------------------------------------------------------------------------ + /// + /// Gets the number of audio files in the list(s) of files to archive. + /// + /// Public (and self-populating on-demand) to facilitate testing. If this + /// property is accessed before initialization is complete, it will return -1. /// ------------------------------------------------------------------------------------ [PublicAPI] public int AudioCount { get { - if (FileLists != null && _audioCount < 0) + if (FileLists.Count > 0 && _audioCount < 0) ExtractInformationFromFiles(); return _audioCount; } } + /// ------------------------------------------------------------------------------------ + /// + /// Gets the number of video files in the list(s) of files to archive. + /// + /// Public (and self-populating on-demand) to facilitate testing. If this + /// property is accessed before initialization is complete, it will return -1. /// ------------------------------------------------------------------------------------ [PublicAPI] public int VideoCount { get { - if (FileLists != null && _videoCount < 0) + if (FileLists.Count > 0 && _videoCount < 0) ExtractInformationFromFiles(); return _videoCount; } @@ -1477,9 +1493,9 @@ private void SetMetsPairsForFiles() } if (ImageCount > 0) - _metsPairs.Add(JSONUtils.MakeKeyValuePair(kImageExtent, Format("{0} image{1}.", - _imageCount.ToString(CultureInfo.InvariantCulture), - (_imageCount == 1) ? "" : "s"))); + _metsPairs.Add(JSONUtils.MakeKeyValuePair(kImageExtent, + $"{_imageCount.ToString(CultureInfo.InvariantCulture)} " + + $"image{(_imageCount == 1 ? "" : "s")}.")); var avExtent = new StringBuilder(); const string delimiter = "; "; @@ -1487,10 +1503,16 @@ private void SetMetsPairsForFiles() if (ShowRecordingCountNotLength) { if (_audioCount > 0) - avExtent.AppendLineFormat("{0} audio recording file{1}", new object[] { _audioCount, (_audioCount == 1) ? "" : "s" }, delimiter); + { + avExtent.AppendLineFormat("{0} audio recording file{1}", + new object[] { _audioCount, _audioCount == 1 ? "" : "s" }, delimiter); + } if (_videoCount > 0) - avExtent.AppendLineFormat("{0} video recording file{1}", new object[] { _videoCount, (_videoCount == 1) ? "" : "s" }, delimiter); + { + avExtent.AppendLineFormat("{0} video recording file{1}", + new object[] { _videoCount, _videoCount == 1 ? "" : "s" }, delimiter); + } SetAudioVideoExtent(avExtent + "."); } @@ -1509,8 +1531,12 @@ private string GetMode() ExtractInformationFromFiles(); if ((_modes == null) || - (IsMetadataPropertySet(MetadataProperties.DatasetExtent) && !_modes.Contains(kModeDataset))) - throw new InvalidOperationException("Cannot set dataset extent for a resource which does not contain any \"dataset\" files."); + (IsMetadataPropertySet(MetadataProperties.DatasetExtent) && + !_modes.Contains(kModeDataset))) + { + throw new InvalidOperationException( + "Cannot set dataset extent for a resource which does not contain any \"dataset\" files."); + } return JSONUtils.MakeBracketedListFromValues(kFileTypeModeList, _modes); } @@ -1566,14 +1592,14 @@ protected override StringBuilder DoArchiveSpecificFilenameNormalization(string k #region Creating RAMP package (zip file) asynchronously. /// ------------------------------------------------------------------------------------ - internal Task CreateRampPackage(CancellationToken cancellationToken) + internal async Task CreateRampPackage(CancellationToken cancellationToken) { bool result = false; try { PackagePath = Path.Combine(Path.GetTempPath(), PackageId + kRampFileExtension); - CreateZipFile(cancellationToken); + await Task.Run(() => CreateZipFile(cancellationToken), cancellationToken); if (!File.Exists(PackagePath)) ReportError(null, Progress.GetMessage(StringId.FailedToMakePackage)); @@ -1588,7 +1614,7 @@ internal Task CreateRampPackage(CancellationToken cancellationToken) ReportError(exception, Progress.GetMessage(StringId.ErrorCreatingArchive)); } - return Task.FromResult(result); + return result; } /// ------------------------------------------------------------------------------------ @@ -1798,14 +1824,6 @@ public string GetLanguageName(string iso3Code) } #endregion - /// ------------------------------------------------------------------------------------ - public override IArchivingSession AddSession(string sessionId) - { - throw new NotImplementedException(); - } - - public override IArchivingPackage ArchivingPackage => throw new NotImplementedException(); - #region Clean-up methods /// ------------------------------------------------------------------------------------ protected internal override void CleanUp() diff --git a/SIL.Core/ClearShare/OlacSystem.cs b/SIL.Core/ClearShare/OlacSystem.cs index 71da83a1c..f2fe677c8 100644 --- a/SIL.Core/ClearShare/OlacSystem.cs +++ b/SIL.Core/ClearShare/OlacSystem.cs @@ -6,7 +6,9 @@ using System.Text; using System.Xml; using System.Xml.Linq; +using JetBrains.Annotations; using SIL.Code; +using SIL.Reporting; namespace SIL.Core.ClearShare { @@ -23,6 +25,7 @@ public class OlacSystem private static readonly XNamespace s_nsDc = "http://purl.org/dc/elements/1.1/"; /// ------------------------------------------------------------------------------------ + [PublicAPI] public void LoadWorkFromXml(Work work, string xml) { //TODO: parse the xml as olac. For a first pass, we can ignore anything we don't understand. @@ -44,10 +47,10 @@ public void LoadWorkFromXml(Work work, string xml) /// ------------------------------------------------------------------------------------ public string GetOlacRecordElement() { - return string.Format(@"", s_nsOlac, s_nsDc); + return $@""; } /// ------------------------------------------------------------------------------------ @@ -56,11 +59,12 @@ public string GetContributorElement(string roleCode, string contributorName) Guard.AgainstNull(roleCode, "roleCode"); Guard.AgainstNull(contributorName, "contributorName"); - return string.Format("{1}", roleCode, contributorName); + return $"{contributorName}"; } /// ------------------------------------------------------------------------------------ + [PublicAPI] public string GetXmlForWork(Work work) { var bldr = new StringBuilder(); @@ -101,28 +105,34 @@ public IEnumerable GetRoles(string customRolesXmlFilename = null) List ReadRoles(Stream stream) { List roles; - using (var xmlReader = XmlReader.Create(stream)) + + try + { + using (var xmlReader = XmlReader.Create(stream)) + { + var doc = XDocument.Load(xmlReader); + + // This is a bit confusing because the role heading node is at the same level + // (i.e. a sibling of) as all the associated term nodes. Therefore, the first + // thing to do is get the heading nodes that are children of section nodes. + // Then find the one heading node whose content is "Role". Then backup to the + // section containing that heading node and take all "term" child nodes of + // that section (i.e. that are siblings of the role heading node). + roles = doc.Descendants("body").Descendants("section") + .Elements("heading") + .Where(n => n.Value == "Role").Ancestors("section").First() + .Descendants("term") + .Select(n => new Role(n.Element("code").Value, + n.Element("name").Value, n.Element("definition").Value)).ToList(); + xmlReader.Close(); + } + } + finally { - var doc = XDocument.Load(xmlReader); - - // This is a bit confusing because the role heading node is at the same level - // (i.e. a sibling of) as all the associated term nodes. Therefore, the first - // thing to do is get the heading nodes that are children of section nodes. - // Then find the one heading node whose content is "Role". Then backup to the - // section containing that heading node and take all "term" child nodes of - // that section (i.e. that are siblings of the role heading node). - roles = doc.Descendants("body").Descendants("section") - .Elements("heading") - .Where(n => n.Value == "Role").Ancestors("section").First() - .Descendants("term") - .Select(n => new Role(n.Element("code").Value, - n.Element("name").Value, n.Element("definition").Value)).ToList(); - xmlReader.Close(); + stream.Close(); + stream.Dispose(); } - stream.Close(); - stream.Dispose(); - return roles; } @@ -136,7 +146,7 @@ List ReadRoles(Stream stream) } catch (Exception e) { - Console.WriteLine(e); + ErrorReport.ReportNonFatalException(e); } } @@ -163,6 +173,7 @@ public bool TryGetRoleByCode(string code, out Role role) /// Used to look up roles in the system's controlled vocabulary /// /// ------------------------------------------------------------------------------------ + [PublicAPI] public Role GetRoleByCodeOrThrow(string code) { var role = GetRoles().FirstOrDefault(r => r.Code == code); @@ -181,6 +192,7 @@ public Role GetRoleByCodeOrThrow(string code) /// Used to look up roles in the system's controlled vocabulary ///
/// ------------------------------------------------------------------------------------ + [PublicAPI] public bool TryGetRoleByName(string name, out Role role) { role = GetRoles().FirstOrDefault(r => r.Name == name); diff --git a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs index 1bc5a16db..9754ab988 100644 --- a/SIL.Windows.Forms.Archiving/ArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/ArchivingDlg.cs @@ -254,11 +254,6 @@ private async Task CreatePackageAsync() } finally { - if (InvokeRequired) - Invoke(new Action (ResetUIForUserInteraction)); - else - ResetUIForUserInteraction(); - try { _cts.Dispose(); @@ -267,7 +262,13 @@ private async Task CreatePackageAsync() { Logger.WriteError(e); } + _cts = null; + + if (InvokeRequired) + Invoke(new Action (ResetUIForUserInteraction)); + else + ResetUIForUserInteraction(); } } diff --git a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs index 50ccb56ca..4ce45d64f 100644 --- a/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs +++ b/SIL.Windows.Forms.Archiving/IMDI/IMDIArchivingDlg.cs @@ -345,7 +345,6 @@ private void SetControlProperties() //UpdateLaunchButtonText(); _buttonLaunchRamp.Visible = false; _tableLayoutPanel.SetColumn(_buttonCreatePackage, 1); - _buttonCancel.Text = LocalizationManager.GetString("DialogBoxes.IMDIArchivingDlg.CloseButtonLabel", "Close"); _buttonCreatePackage.Text = LocalizationManager.GetString("DialogBoxes.IMDIArchivingDlg.CreatePackageButtonLabel", "Create Package"); UpdateOverviewText(); } From 921ce3c5f617069de7d335e510db259126f2a0ac Mon Sep 17 00:00:00 2001 From: tombogle Date: Tue, 6 Aug 2024 17:17:10 -0400 Subject: [PATCH 11/15] Changed from TargetFramework to TargetFrameworks in csproj --- TestApps/ArchivingTestApp/ArchivingTestApp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestApps/ArchivingTestApp/ArchivingTestApp.csproj b/TestApps/ArchivingTestApp/ArchivingTestApp.csproj index dadeb7c39..a870d4a17 100644 --- a/TestApps/ArchivingTestApp/ArchivingTestApp.csproj +++ b/TestApps/ArchivingTestApp/ArchivingTestApp.csproj @@ -2,7 +2,7 @@ WinExe - net8.0-windows + net8.0-windows enable true enable From 7f5b1007a2508d062693db8f9703b8dd5dcd9b4e Mon Sep 17 00:00:00 2001 From: tombogle Date: Wed, 7 Aug 2024 23:12:18 -0400 Subject: [PATCH 12/15] Refactoring (in response to code review) to simplify SetFilesToArchive --- SIL.Archiving/ArchivingDlgViewModel.cs | 3 +-- SIL.Archiving/RampArchivingDlgViewModel.cs | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/SIL.Archiving/ArchivingDlgViewModel.cs b/SIL.Archiving/ArchivingDlgViewModel.cs index 6548d1656..3c50a99a4 100644 --- a/SIL.Archiving/ArchivingDlgViewModel.cs +++ b/SIL.Archiving/ArchivingDlgViewModel.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; -using SIL.Archiving.Generic; using SIL.Archiving.IMDI.Lists; using SIL.Code; using SIL.EventsAndDelegates; @@ -254,7 +253,7 @@ public async Task Initialize(IArchivingProgressDisplay progress, Cancellat return true; } - private async Task SetFilesToArchive(CancellationToken cancellationToken) + protected virtual async Task SetFilesToArchive(CancellationToken cancellationToken) { await Task.Run(() => { diff --git a/SIL.Archiving/RampArchivingDlgViewModel.cs b/SIL.Archiving/RampArchivingDlgViewModel.cs index 46478851a..cd5780a83 100644 --- a/SIL.Archiving/RampArchivingDlgViewModel.cs +++ b/SIL.Archiving/RampArchivingDlgViewModel.cs @@ -149,7 +149,6 @@ public class RampArchivingDlgViewModel: ArchivingDlgViewModel private Timer _timer; private Dictionary _languageList; private readonly Func _getFileDescription; // first param is file list key, second param is filename - private readonly Action _setFilesToArchive; private int _imageCount = -1; private int _audioCount = -1; @@ -317,10 +316,9 @@ private void AddModesToSet(IEnumerable files) public RampArchivingDlgViewModel(string appName, string title, string id, Action setFilesToArchive, Func getFileDescription) : base(appName, title, id, - (m, c) => { ((RampArchivingDlgViewModel)m).SetFilesToArchive(c); }) + setFilesToArchive) { _getFileDescription = getFileDescription ?? throw new ArgumentNullException(nameof(getFileDescription)); - _setFilesToArchive = setFilesToArchive; ShowRecordingCountNotLength = false; ImagesArePhotographs = true; @@ -335,11 +333,13 @@ public RampArchivingDlgViewModel(string appName, string title, string id, } } - private void SetFilesToArchive(CancellationToken cancellationToken) + protected override async Task SetFilesToArchive(CancellationToken cancellationToken) { - _setFilesToArchive(this, cancellationToken); + await base.SetFilesToArchive(cancellationToken); + if (cancellationToken.IsCancellationRequested) throw new OperationCanceledException(); + foreach (var fileList in FileLists.Where(fileList => fileList.Value.Item1.Any())) { var normalizedName = NormalizeFilename(fileList.Key, From 8874e89b6e93b6e23371ff8fd9e89efb15a68697 Mon Sep 17 00:00:00 2001 From: tombogle Date: Wed, 14 Aug 2024 10:58:51 -0400 Subject: [PATCH 13/15] Changed creation of IMDIPackages to be asynchronous --- CHANGELOG.md | 2 ++ .../IMDI/IMDIArchivingDlgViewModel.cs | 2 +- SIL.Archiving/IMDI/IMDIPackage.cs | 28 +++++++++++-------- SIL.Archiving/IMDI/Schema/IMDI_3_0.cs | 21 +++++++------- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b315a1e1f..fe01a43cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Core] Added optional parameter to OlacSystem.GetRoles to allow caller to provide its own XML with role definitions. - [SIL.Windows.Forms] Split License into a base class called License and a derived LicenseWithLogo, so that License could be in SIL.Core. - [SIL.Archiving] Changed IArchivingSession.Files (and Session.Files) into an IReadonlyList. +- [SIL.Archiving] Made IMDIPackage.CreateIMDIPackage asynchronous, changing its signature to take a CancellationToken parameter and return Task. +- [SIL.Archiving] Made MetaTranscript.WriteCorpusImdiFile asynchronous, changing its signature to return Task. ### Fixed - [SIL.Archiving] Fixed typo in RampArchivingDlgViewModel for Ethnomusicology performance collection. diff --git a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs index c374681ec..fb0abaab0 100644 --- a/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs +++ b/SIL.Archiving/IMDI/IMDIArchivingDlgViewModel.cs @@ -186,7 +186,7 @@ public override async Task CreatePackage(CancellationToken cancellationT // write the xml files if (success) - success = _imdiData.CreateIMDIPackage(); // REVIEW: Should this also be awaited? + success = await _imdiData.CreateIMDIPackage(cancellationToken); // copy the content files if (success && !MetadataOnly) diff --git a/SIL.Archiving/IMDI/IMDIPackage.cs b/SIL.Archiving/IMDI/IMDIPackage.cs index c45ccaa98..951f36479 100644 --- a/SIL.Archiving/IMDI/IMDIPackage.cs +++ b/SIL.Archiving/IMDI/IMDIPackage.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; +using System.Threading; using SIL.Archiving.Generic; using SIL.Archiving.IMDI.Lists; using SIL.Archiving.IMDI.Schema; @@ -71,9 +73,10 @@ public string PackagePath // Test_Corpus\Test_Session\Files*.* (session files) // Test_Corpus\Contributors\Files*.* (contributor/actor files) - /// Creates the corpus directory structure, meta data files, and copies content files + /// Creates the corpus directory structure, meta data files, and copies content + /// files, checking for cancellation before each IO operation. /// - public bool CreateIMDIPackage() + public async Task CreateIMDIPackage(CancellationToken cancellationToken) { if (!IsValid) return false; @@ -84,14 +87,15 @@ public bool CreateIMDIPackage() List sessionFiles = new List(); // create the session directories -// ReSharper disable once LoopCanBeConvertedToQuery foreach (var session in Sessions) { + cancellationToken.ThrowIfCancellationRequested(); + var sessionImdi = new MetaTranscript { Items = new object[] { session }, Type = MetatranscriptValueType.SESSION }; - sessionFiles.Add(sessionImdi.WriteImdiFile(PackagePath, Name)); + sessionFiles.Add(await sessionImdi.WriteImdiFile(PackagePath, Name)); } if (!_corpus) @@ -109,16 +113,20 @@ public bool CreateIMDIPackage() foreach (var fileName in sessionFiles) corpus.CorpusLink.Add(new CorpusLinkType { Value = fileName.Replace("\\", "/"), Name = string.Empty }); + cancellationToken.ThrowIfCancellationRequested(); + // create the catalogue - corpus.CatalogueLink = CreateCorpusCatalogue(); + corpus.CatalogueLink = await CreateCorpusCatalogue(); + + cancellationToken.ThrowIfCancellationRequested(); // Create the corpus imdi file - MainExportFile = BaseImdiFile.WriteImdiFile(PackagePath, Name); + MainExportFile = await BaseImdiFile.WriteImdiFile(PackagePath, Name); return true; } - private string CreateCorpusCatalogue() + private async Task CreateCorpusCatalogue() { // Create the package catalogue imdi file var catalogue = new Catalogue @@ -192,7 +200,7 @@ private string CreateCorpusCatalogue() // write the xml file var catImdi = new MetaTranscript { Items = new object[] { catalogue }, Type = MetatranscriptValueType.CATALOGUE }; - return catImdi.WriteImdiFile(PackagePath, Name).Replace("\\", "/"); + return (await catImdi.WriteImdiFile(PackagePath, Name)).Replace("\\", "/"); } /// Add a description of the package/corpus @@ -218,10 +226,8 @@ public void AddDescription(string sessionId, LanguageString description) // prevent duplicate description if (_corpus) { - foreach (var session in Sessions.Where(sess => sess.Name == sessionId)) - { + foreach (var session in Sessions.Where(s => s.Name == sessionId)) session.AddDescription(description); - } } else { diff --git a/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs b/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs index a9d84ee75..9b904611f 100644 --- a/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs +++ b/SIL.Archiving/IMDI/Schema/IMDI_3_0.cs @@ -14,6 +14,7 @@ using SIL.Archiving.IMDI.Lists; using SIL.Extensions; using static SIL.Archiving.IMDI.Lists.ListType; +using System.Threading.Tasks; namespace SIL.Archiving.IMDI.Schema { @@ -133,26 +134,26 @@ public override string ToString() /// /// /// IMDI file name - public string WriteImdiFile(string outputDirectoryName, string corpusName) + public async Task WriteImdiFile(string outputDirectoryName, string corpusName) { string corpusDirectoryName = IMDIArchivingDlgViewModel.NormalizeDirectoryName(corpusName); switch (Type) { case MetatranscriptValueType.CORPUS: - return WriteCorpusImdiFile(outputDirectoryName, corpusDirectoryName); + return await WriteCorpusImdiFile(outputDirectoryName, corpusDirectoryName); case MetatranscriptValueType.CATALOGUE: - return WriteCatalogueImdiFile(outputDirectoryName, corpusDirectoryName); + return await WriteCatalogueImdiFile(outputDirectoryName, corpusDirectoryName); case MetatranscriptValueType.SESSION: - return WriteSessionImdiFile(outputDirectoryName, corpusDirectoryName); + return await WriteSessionImdiFile(outputDirectoryName, corpusDirectoryName); } return null; } - private string WriteCorpusImdiFile(string outputDirectoryName, string corpusDirectoryName) + private async Task WriteCorpusImdiFile(string outputDirectoryName, string corpusDirectoryName) { // create the corpus directory Directory.CreateDirectory(Path.Combine(outputDirectoryName, corpusDirectoryName)); @@ -164,13 +165,13 @@ private string WriteCorpusImdiFile(string outputDirectoryName, string corpusDire var imdiFile = Path.Combine(outputDirectoryName, corpusDirectoryName + ".imdi"); TextWriter writer = new StreamWriter(imdiFile); - writer.Write(ToString()); + await writer.WriteAsync(ToString()); writer.Close(); return imdiFile; } - private string WriteCatalogueImdiFile(string outputDirectoryName, string corpusDirectoryName) + private async Task WriteCatalogueImdiFile(string outputDirectoryName, string corpusDirectoryName) { // create the corpus directory Directory.CreateDirectory(Path.Combine(outputDirectoryName, corpusDirectoryName)); @@ -182,13 +183,13 @@ private string WriteCatalogueImdiFile(string outputDirectoryName, string corpusD var imdiFile = Path.Combine(outputDirectoryName, corpusDirectoryName, corpusDirectoryName + "_Catalogue.imdi"); TextWriter writer = new StreamWriter(imdiFile); - writer.Write(ToString()); + await writer.WriteAsync(ToString()); writer.Close(); return Path.Combine(corpusDirectoryName, corpusDirectoryName + "_Catalogue.imdi"); } - private string WriteSessionImdiFile(string outputDirectoryName, string corpusDirectoryName) + private async Task WriteSessionImdiFile(string outputDirectoryName, string corpusDirectoryName) { // session object Session s = (Session)Items[0]; @@ -208,7 +209,7 @@ private string WriteSessionImdiFile(string outputDirectoryName, string corpusDir var imdiFile = Path.Combine(outputDirectoryName, corpusDirectoryName, sessionDirectoryName + ".imdi"); TextWriter writer = new StreamWriter(imdiFile); - writer.Write(ToString()); + await writer.WriteAsync(ToString()); writer.Close(); return Path.Combine(corpusDirectoryName, sessionDirectoryName + ".imdi"); From 40b89252b093d2e6b857ad2ea5fc4c19a9e6d874 Mon Sep 17 00:00:00 2001 From: tombogle Date: Wed, 14 Aug 2024 16:06:52 -0400 Subject: [PATCH 14/15] Trying to get Appveyor build to work --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 327100da9..3587e5062 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ version: '{build}' branches: only: - master -image: Visual Studio 2019 +image: Visual Studio 2022 init: - cmd: | set GITVERSION_BUILD_NUMBER=%APPVEYOR_BUILD_NUMBER% From 67b1ecd13a0901dffb5bb5fde65681a177fadba4 Mon Sep 17 00:00:00 2001 From: tombogle Date: Wed, 14 Aug 2024 16:08:00 -0400 Subject: [PATCH 15/15] Fixed naming error in unit test --- SIL.WritingSystems.Tests/WritingSystemOrphanFinderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SIL.WritingSystems.Tests/WritingSystemOrphanFinderTests.cs b/SIL.WritingSystems.Tests/WritingSystemOrphanFinderTests.cs index 983279792..8ed28fb1c 100644 --- a/SIL.WritingSystems.Tests/WritingSystemOrphanFinderTests.cs +++ b/SIL.WritingSystems.Tests/WritingSystemOrphanFinderTests.cs @@ -80,7 +80,7 @@ public void FindOrphans_NoOrphansFound_WritingSystemRepoAndFileUntouched() } [Test] - public void FindOrphans_OrphanFoundIsValidRfcTag_WritingsystemIsAddedToWritingSystemRepoAndFileUntouched() + public void FindOrphans_OrphanFoundIsValidRfcTag_WritingSystemIsAddedToWritingSystemRepoAndFileUntouched() { using (var e = new TestEnvironment("en", "de")) {