From 921a4a0f0d75f3387088a008039042b04c91c20a Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Fri, 20 Sep 2024 11:49:29 -0700 Subject: [PATCH 1/3] Fix LT-20509: Can't delete words with undefined phonemes --- Src/FdoUi/WfiWordformUi.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Src/FdoUi/WfiWordformUi.cs b/Src/FdoUi/WfiWordformUi.cs index eebb682cf8..0ebf95a1da 100644 --- a/Src/FdoUi/WfiWordformUi.cs +++ b/Src/FdoUi/WfiWordformUi.cs @@ -2,10 +2,13 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Windows.Forms; using SIL.LCModel; +using SIL.LCModel.Infrastructure; namespace SIL.FieldWorks.FdoUi { @@ -76,6 +79,19 @@ protected override bool IsAcceptableContextToJump(string toolCurrent, string too public override bool CanDelete(out string cannotDeleteMsg) { + // Delete problem annotations of the word form. + // These aren't used within FieldWorks, and they block deletion. + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => + { + ICmBaseAnnotationRepository repository = base.Object.Cache.ServiceLocator.GetInstance(); + IEnumerable problemAnnotations = + from ann in repository.AllInstances() + where ann.BeginObjectRA == base.Object && ann.SourceRA is ICmAgent + select ann; + foreach (ICmBaseAnnotation problem in problemAnnotations) + m_cache.DomainDataByFlid.DeleteObj(problem.Hvo); + }); + if (base.CanDelete(out cannotDeleteMsg)) return true; cannotDeleteMsg = FdoUiStrings.ksCannotDeleteWordform; From 5e7e75ea46b7c462c6b77b5c6dcb1f58328c2872 Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Thu, 3 Oct 2024 08:06:00 -0700 Subject: [PATCH 2/3] Create utility for deleting problem annotations --- .../Configuration/UtilityCatalogInclude.xml | 1 + .../Configuration/strings-en.xml | 6 + Src/FdoUi/FdoUiStrings.Designer.cs | 13 +- Src/FdoUi/FdoUiStrings.resx | 3 + Src/FdoUi/WfiWordformUi.cs | 21 ++-- .../Morphology/MorphologyEditorDll.csproj | 5 +- .../Morphology/ParserAnnotationRemover.cs | 117 ++++++++++++++++++ Src/LexText/ParserCore/ParseFiler.cs | 12 +- 8 files changed, 153 insertions(+), 25 deletions(-) create mode 100644 Src/LexText/Morphology/ParserAnnotationRemover.cs diff --git a/DistFiles/Language Explorer/Configuration/UtilityCatalogInclude.xml b/DistFiles/Language Explorer/Configuration/UtilityCatalogInclude.xml index 6a364a6a88..d741ba7198 100644 --- a/DistFiles/Language Explorer/Configuration/UtilityCatalogInclude.xml +++ b/DistFiles/Language Explorer/Configuration/UtilityCatalogInclude.xml @@ -2,6 +2,7 @@ + diff --git a/DistFiles/Language Explorer/Configuration/strings-en.xml b/DistFiles/Language Explorer/Configuration/strings-en.xml index e70f63e676..f7a9ceacc7 100644 --- a/DistFiles/Language Explorer/Configuration/strings-en.xml +++ b/DistFiles/Language Explorer/Configuration/strings-en.xml @@ -297,6 +297,12 @@ + + + + + + diff --git a/Src/FdoUi/FdoUiStrings.Designer.cs b/Src/FdoUi/FdoUiStrings.Designer.cs index a08d152f95..c547855370 100644 --- a/Src/FdoUi/FdoUiStrings.Designer.cs +++ b/Src/FdoUi/FdoUiStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18052 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -19,7 +19,7 @@ namespace SIL.FieldWorks.FdoUi { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class FdoUiStrings { @@ -105,6 +105,15 @@ internal static string ksCannotDeleteWordform { } } + /// + /// Looks up a localized string similar to Sorry, FieldWorks cannot delete this wordform because there are parsing annotations attached. Please invoke "Remove Parser annotations" in Tools > Utilities first.. + /// + internal static string ksCannotDeleteWordformBecauseOfAnnotations { + get { + return ResourceManager.GetString("ksCannotDeleteWordformBecauseOfAnnotations", resourceCulture); + } + } + /// /// Looks up a localized string similar to Could not find the correct object to jump to.. /// diff --git a/Src/FdoUi/FdoUiStrings.resx b/Src/FdoUi/FdoUiStrings.resx index 00c862eb0b..064af934c9 100644 --- a/Src/FdoUi/FdoUiStrings.resx +++ b/Src/FdoUi/FdoUiStrings.resx @@ -337,4 +337,7 @@ Without these, we cannot find related entries. Problem opening file Caption for error dialog + + Sorry, FieldWorks cannot delete this wordform because there are parsing annotations attached. Please invoke "Remove Parser annotations" in Tools > Utilities first. + \ No newline at end of file diff --git a/Src/FdoUi/WfiWordformUi.cs b/Src/FdoUi/WfiWordformUi.cs index 0ebf95a1da..a62c36cc61 100644 --- a/Src/FdoUi/WfiWordformUi.cs +++ b/Src/FdoUi/WfiWordformUi.cs @@ -79,19 +79,16 @@ protected override bool IsAcceptableContextToJump(string toolCurrent, string too public override bool CanDelete(out string cannotDeleteMsg) { - // Delete problem annotations of the word form. - // These aren't used within FieldWorks, and they block deletion. - NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => + ICmBaseAnnotationRepository repository = base.Object.Cache.ServiceLocator.GetInstance(); + IEnumerable problemAnnotations = + from ann in repository.AllInstances() + where ann.BeginObjectRA == base.Object && ann.SourceRA is ICmAgent + select ann; + if (problemAnnotations.Any()) { - ICmBaseAnnotationRepository repository = base.Object.Cache.ServiceLocator.GetInstance(); - IEnumerable problemAnnotations = - from ann in repository.AllInstances() - where ann.BeginObjectRA == base.Object && ann.SourceRA is ICmAgent - select ann; - foreach (ICmBaseAnnotation problem in problemAnnotations) - m_cache.DomainDataByFlid.DeleteObj(problem.Hvo); - }); - + cannotDeleteMsg = FdoUiStrings.ksCannotDeleteWordformBecauseOfAnnotations; + return false; + } if (base.CanDelete(out cannotDeleteMsg)) return true; cannotDeleteMsg = FdoUiStrings.ksCannotDeleteWordform; diff --git a/Src/LexText/Morphology/MorphologyEditorDll.csproj b/Src/LexText/Morphology/MorphologyEditorDll.csproj index 45ee847d5e..2e8566083b 100644 --- a/Src/LexText/Morphology/MorphologyEditorDll.csproj +++ b/Src/LexText/Morphology/MorphologyEditorDll.csproj @@ -100,7 +100,7 @@ prompt AllRules.ruleset AnyCPU - + ..\..\..\Output\Debug\ false @@ -353,6 +353,7 @@ Code + UserControl @@ -460,4 +461,4 @@ - + \ No newline at end of file diff --git a/Src/LexText/Morphology/ParserAnnotationRemover.cs b/Src/LexText/Morphology/ParserAnnotationRemover.cs new file mode 100644 index 0000000000..7e620fc257 --- /dev/null +++ b/Src/LexText/Morphology/ParserAnnotationRemover.cs @@ -0,0 +1,117 @@ +using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FwCoreDlgs; +using SIL.LCModel.Infrastructure; +using SIL.LCModel; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SIL.Data; + +namespace SIL.FieldWorks.XWorks.MorphologyEditor +{ + /// + /// This class serves to remove all annotations produced by the parser. + /// + public class ParserAnnotationRemover : IUtility + { + #region Data members + + private UtilityDlg m_dlg; + const string kPath = "/group[@id='Linguistics']/group[@id='Morphology']/group[@id='RemoveParserAnnotations']/"; + + #endregion Data members + + /// + /// Override method to return the Label property. + /// + /// + public override string ToString() + { + return Label; + } + + #region IUtility implementation + + /// + /// Get the main label describing the utility. + /// + public string Label + { + get + { + Debug.Assert(m_dlg != null); + return StringTable.Table.GetStringWithXPath("Label", kPath); + } + } + + /// + /// Set the UtilityDlg. + /// + /// + /// This must be set, before calling any other property or method. + /// + public UtilityDlg Dialog + { + set + { + Debug.Assert(value != null); + Debug.Assert(m_dlg == null); + + m_dlg = value; + } + } + + /// + /// Load 0 or more items in the list box. + /// + public void LoadUtilities() + { + Debug.Assert(m_dlg != null); + m_dlg.Utilities.Items.Add(this); + + } + + /// + /// Notify the utility that has been selected in the dlg. + /// + public void OnSelection() + { + Debug.Assert(m_dlg != null); + m_dlg.WhenDescription = StringTable.Table.GetStringWithXPath("WhenDescription", kPath); + m_dlg.WhatDescription = StringTable.Table.GetStringWithXPath("WhatDescription", kPath); + m_dlg.RedoDescription = StringTable.Table.GetStringWithXPath("RedoDescription", kPath); + } + + /// + /// Have the utility do what it does. + /// + public void Process() + { + Debug.Assert(m_dlg != null); + var cache = m_dlg.PropTable.GetValue("cache"); + ICmBaseAnnotationRepository repository = cache.ServiceLocator.GetInstance(); + IList problemAnnotations = (from ann in repository.AllInstances() where ann.SourceRA is ICmAgent select ann).ToList(); + if (problemAnnotations.Count > 0) + { + // Set up progress bar. + m_dlg.ProgressBar.Minimum = 0; + m_dlg.ProgressBar.Maximum = problemAnnotations.Count; + m_dlg.ProgressBar.Step = 1; + + NonUndoableUnitOfWorkHelper.Do(cache.ActionHandlerAccessor, () => + { + foreach (ICmBaseAnnotation problem in problemAnnotations) + { + cache.DomainDataByFlid.DeleteObj(problem.Hvo); + m_dlg.ProgressBar.PerformStep(); + } + }); + } + } + + #endregion IUtility implementation + } +} diff --git a/Src/LexText/ParserCore/ParseFiler.cs b/Src/LexText/ParserCore/ParseFiler.cs index 6f635cad6a..4e8db43ca8 100644 --- a/Src/LexText/ParserCore/ParseFiler.cs +++ b/Src/LexText/ParserCore/ParseFiler.cs @@ -181,10 +181,11 @@ private bool UpdateWordforms(object parameter) string form = work.Wordform.Form.BestVernacularAlternative.Text; using (new TaskReport(String.Format(ParserCoreStrings.ksUpdateX, form), m_taskUpdateHandler)) { - // delete old problem annotations + // delete all old problem annotations + // (We no longer create new problem annotations.) IEnumerable problemAnnotations = from ann in m_baseAnnotationRepository.AllInstances() - where ann.BeginObjectRA == work.Wordform && ann.SourceRA == m_parserAgent + where ann.SourceRA == m_parserAgent select ann; foreach (ICmBaseAnnotation problem in problemAnnotations) m_cache.DomainDataByFlid.DeleteObj(problem.Hvo); @@ -194,13 +195,6 @@ from ann in m_baseAnnotationRepository.AllInstances() if (work.ParseResult.ErrorMessage != null) { - // there was an error, so create a problem annotation - ICmBaseAnnotation problemReport = m_baseAnnotationFactory.Create(); - m_cache.LangProject.AnnotationsOC.Add(problemReport); - problemReport.CompDetails = work.ParseResult.ErrorMessage; - problemReport.SourceRA = m_parserAgent; - problemReport.AnnotationTypeRA = null; - problemReport.BeginObjectRA = work.Wordform; SetUnsuccessfulParseEvals(work.Wordform, Opinions.noopinion); } else From 109aacad745bdc4f9f12460374867a90ef4c2f96 Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Thu, 3 Oct 2024 08:35:56 -0700 Subject: [PATCH 3/3] Remove annotation tests --- .../ParseFilerProcessingTests.cs | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/Src/LexText/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs b/Src/LexText/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs index dad14713a5..df51f370f1 100644 --- a/Src/LexText/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs @@ -63,20 +63,6 @@ protected ICmAgent HumanAgent } } - protected IWfiWordform CheckAnnotationSize(string form, int expectedSize, bool isStarting) - { - ILcmServiceLocator servLoc = Cache.ServiceLocator; - IWfiWordform wf = FindOrCreateWordform(form); - int actualSize = - (from ann in servLoc.GetInstance().AllInstances() - where ann.BeginObjectRA == wf - select ann).Count(); - // wf.RefsFrom_CmBaseAnnotation_BeginObject.Count; - string msg = String.Format("Wrong number of {0} annotations for: {1}", isStarting ? "starting" : "ending", form); - Assert.AreEqual(expectedSize, actualSize, msg); - return wf; - } - private IWfiWordform FindOrCreateWordform(string form) { ILcmServiceLocator servLoc = Cache.ServiceLocator; @@ -176,26 +162,6 @@ protected void UndoAll() #region Tests - [Test] - public void TooManyAnalyses() - { - IWfiWordform bearsTest = CheckAnnotationSize("bearsTEST", 0, true); - var result = new ParseResult("Maximum permitted analyses (448) reached."); - m_filer.ProcessParse(bearsTest, ParserPriority.Low, result); - ExecuteIdleQueue(); - CheckAnnotationSize("bearsTEST", 1, false); - } - - [Test] - public void BufferOverrun() - { - IWfiWordform dogsTest = CheckAnnotationSize("dogsTEST", 0, true); - var result = new ParseResult("Maximum internal buffer size (117) reached."); - m_filer.ProcessParse(dogsTest, ParserPriority.Low, result); - ExecuteIdleQueue(); - CheckAnnotationSize("dogsTEST", 1, false); - } - [Test] public void TwoAnalyses() {