protected override void ShowRecord() { //todo: add the document view name to the task label //todo: fast machine, this doesn't really seem to do any good. I think maybe the parts that //are taking a longtime are not getting Breath(). //todo: test on a machine that is slow enough to see if this is helpful or not! using (ProgressState progress = FwXWindow.CreatePredictiveProgressState(m_mediator, this.m_vectorName)) { progress.Breath(); Debug.Assert(m_rootSite != null); progress.Breath(); base.ShowRecord(); Clerk.SaveOnChangeRecord(); progress.Breath(); if (Clerk.CurrentObject == null) { m_rootSite.Hide(); return; } try { progress.SetMilestone(); m_rootSite.Show(); using (new WaitCursor(this)) { IChangeRootObject root = m_rootSite as IChangeRootObject; if (root != null && !Clerk.SuspendLoadingRecordUntilOnJumpToRecord) { root.SetRoot(Clerk.CurrentObject.Hvo); } } } catch (Exception error) { if (m_mediator.PropertyTable.GetBoolProperty("DoingAutomatedTest", false)) { throw; } else //don't really need to make the program stop just because we could not show this record. { IApp app = (IApp)m_mediator.PropertyTable.GetValue("App"); ErrorReporter.ReportException(error, app.SettingsKey, m_mediator.FeedbackInfoProvider.SupportEmailAddress, null, false); } } } }
/// <summary> /// Execute the change requested by the current selection in the combo. /// Basically we want the PartOfSpeech indicated by m_selectedHvo, even if 0, /// to become the POS of each record that is appropriate to change. /// We do nothing to records where the check box is turned off, /// and nothing to ones that currently have an MSA other than an IMoStemMsa. /// (a) If the owning entry has an IMoStemMsa with the /// right POS, set the sense to use it. /// (b) If the sense already refers to an IMoStemMsa, and any other senses /// of that entry which point at it are also to be changed, change the POS /// of the MSA. /// (c) If the entry has an IMoStemMsa which is not used at all, change it to the /// required POS and use it. /// (d) Make a new IMoStemMsa in the ILexEntry with the required POS and point the sense at it. /// </summary> public override void DoIt(IEnumerable <int> itemsToChange, ProgressState state) { CheckDisposed(); m_cache.DomainDataByFlid.BeginUndoTask(LexEdStrings.ksUndoBulkEditRevPOS, LexEdStrings.ksRedoBulkEditRevPOS); int i = 0; int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); foreach (int entryId in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / itemsToChange.Count() + 20; state.Breath(); } IReversalIndexEntry entry = m_cache.ServiceLocator.GetInstance <IReversalIndexEntryRepository>().GetObject(entryId); if (m_selectedHvo == 0) { entry.PartOfSpeechRA = null; } else { entry.PartOfSpeechRA = m_cache.ServiceLocator.GetInstance <IPartOfSpeechRepository>().GetObject(m_selectedHvo); } } m_cache.DomainDataByFlid.EndUndoTask(); }
/// <summary> /// Fake doing the change by setting the specified property to the appropriate value /// for each item in the set. Disable items that can't be set. /// </summary> /// <param name="itemsToChange"></param> /// <param name="tagFakeFlid"></param> /// <param name="tagEnable"></param> /// <param name="state"></param> public void FakeDoit(IEnumerable <int> itemsToChange, int tagFakeFlid, int tagEnable, ProgressState state) { CheckDisposed(); ITsString tss = TsStringUtils.MakeString(m_selectedLabel, m_cache.DefaultAnalWs); // Build a Set of parts of speech that can take this class. HashSet <int> possiblePOS = GetPossiblePartsOfSpeech(); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); foreach (int hvo in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 100 / itemsToChange.Count(); state.Breath(); } bool fEnable = IsItemEligible(m_sda, hvo, possiblePOS); if (fEnable) { m_sda.SetString(hvo, tagFakeFlid, tss); } m_sda.SetInt(hvo, tagEnable, (fEnable ? 1 : 0)); } }
/// <summary> /// Fake doing the change by setting the specified property to the appropriate value /// for each item in the list. Disable items that can't be set. /// </summary> /// <param name="itemsToChange"></param> /// <param name="ktagFakeFlid"></param> public void FakeDoit(Set <int> itemsToChange, int tagFakeFlid, int tagEnable, ProgressState state) { CheckDisposed(); IVwCacheDa cda = m_cache.VwCacheDaAccessor; ISilDataAccess sda = m_cache.MainCacheAccessor; ITsString tss = m_cache.MakeAnalysisTss(m_selectedLabel); // Build a Set of parts of speech that can take this class. Set <int> possiblePOS = GetPossiblePartsOfSpeech(); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count / 50, 1)); foreach (int hvo in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 100 / itemsToChange.Count; state.Breath(); } bool fEnable = IsItemEligible(sda, hvo, possiblePOS); if (fEnable) { cda.CacheStringProp(hvo, tagFakeFlid, tss); } cda.CacheIntProp(hvo, tagEnable, (fEnable ? 1 : 0)); } }
public void FakeDoit(IEnumerable <int> itemsToChange, int tagFakeFlid, int tagEnable, ProgressState state) { CheckDisposed(); ITsString tss = TsStringUtils.MakeTss(m_selectedLabel, m_cache.DefaultAnalWs); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); foreach (int hvo in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 100 / itemsToChange.Count(); state.Breath(); } bool fEnable = CanFakeIt(hvo); if (fEnable) { m_sda.SetString(hvo, tagFakeFlid, tss); } m_sda.SetInt(hvo, tagEnable, (fEnable ? 1 : 0)); } }
private void Do(double secs, string label) { m_state.SetMilestone(label); int mils = (int)(secs * 1000); int step = 100; for (int m = 0; m < mils; m += step) { m_state.Breath(); System.Threading.Thread.Sleep(step); } }
/// <summary> /// Execute the change requested by the current selection in the combo. /// There are two main cases: /// 1. The user is removing a feature. /// 2. The user is using priority union to include the values of a feature structure. /// The latter has two subcases: /// a. The user has selected a value for the targeted feature and we have put that value in a FsFeatStruc. /// b. The user has employed the chooser to build a FsFeatStruc with the value(s) to change. These values /// may or may not be for the targeted feature. /// We do nothing to (phoneme) records where the check box is turned off. /// For phonemes with the check box on, we either /// 1. remove the specified feature from the phoneme or /// 2. use priority union to set the value(s) in the FsFeatStruc. /// </summary> public void DoIt(IEnumerable <int> itemsToChange, ProgressState state) { CheckDisposed(); string labelToShow = SelectedLabel; var selectedObject = m_cache.ServiceLocator.GetInstance <ICmObjectRepository>().GetObject(SelectedHvo); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); m_cache.DomainDataByFlid.BeginUndoTask(FdoUiStrings.ksUndoBEPhonemeFeatures, FdoUiStrings.ksRedoBEPhonemeFeatures); if (SelectedHvo != 0) { IFsFeatStruc fsTarget = GetTargetFsFeatStruc(); foreach (var hvoPhoneme in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 100 / itemsToChange.Count() + 20; state.Breath(); } var phoneme = m_cache.ServiceLocator.GetInstance <IPhPhonemeRepository>().GetObject(hvoPhoneme); if (phoneme.FeaturesOA == null) { phoneme.FeaturesOA = Cache.ServiceLocator.GetInstance <IFsFeatStrucFactory>().Create(); } if (fsTarget == null && selectedObject is IFsClosedFeature) { // it's the remove option var closedValues = from s in phoneme.FeaturesOA.FeatureSpecsOC where s.FeatureRA == selectedObject select s; if (closedValues.Any()) { phoneme.FeaturesOA.FeatureSpecsOC.Remove(closedValues.First()); } } else { phoneme.FeaturesOA.PriorityUnion(fsTarget); } } } m_cache.DomainDataByFlid.EndUndoTask(); }
public override void DoIt(IEnumerable <int> itemsToChange, ProgressState state) { CheckDisposed(); var senseRepo = m_cache.ServiceLocator.GetInstance <ILexSenseRepository>(); // FWR-2781 should be able to bulk edit entries to POS <Not sure>. IPartOfSpeech posWanted = null; if (m_selectedHvo > 0) { posWanted = (IPartOfSpeech)m_cache.ServiceLocator.GetObject(m_selectedHvo); } // Make a hashtable from entry to list of modified senses. var sensesByEntry = new Dictionary <ILexEntry, List <ILexSense> >(); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); foreach (int hvoSense in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 20 / itemsToChange.Count(); state.Breath(); } var sense = senseRepo.GetObject(hvoSense); var msa = sense.MorphoSyntaxAnalysisRA; if (msa != null && msa.ClassID != MoStemMsaTags.kClassId) { continue; // can't fix this one, not a stem. } var entry = sense.OwnerOfClass(LexEntryTags.kClassId) as ILexEntry; List <ILexSense> senses; if (!sensesByEntry.TryGetValue(entry, out senses)) { senses = new List <ILexSense>(); sensesByEntry[entry] = senses; } senses.Add(sense); } UndoableUnitOfWorkHelper.Do(FdoUiStrings.ksUndoBulkEditPOS, FdoUiStrings.ksRedoBulkEditPOS, m_cache.ActionHandlerAccessor, () => DoUpdatePos(state, sensesByEntry, posWanted)); }
/// <summary> /// Execute the change requested by the current selection in the combo. /// Basically we want the PartOfSpeech indicated by m_selectedHvo, even if 0, /// to become the POS of each record that is appropriate to change. /// We do nothing to records where the check box is turned off, /// and nothing to ones that currently have an MSA other than an MoStemMsa. /// (a) If the owning entry has an MoStemMsa with the /// right POS, set the sense to use it. /// (b) If the sense already refers to an MoStemMsa, and any other senses /// of that entry which point at it are also to be changed, change the POS /// of the MSA. /// (c) If the entry has an MoStemMsa which is not used at all, change it to the /// required POS and use it. /// (d) Make a new MoStemMsa in the LexEntry with the required POS and point the sense at it. /// </summary> public override void DoIt(Set <int> itemsToChange, ProgressState state) { CheckDisposed(); m_cache.BeginUndoTask(LexEdStrings.ksUndoBulkEditRevPOS, LexEdStrings.ksRedoBulkEditRevPOS); BulkEditBar.ForceRefreshOnUndoRedo(m_cache.MainCacheAccessor); int i = 0; int interval = Math.Min(100, Math.Max(itemsToChange.Count / 50, 1)); foreach (int entryId in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / itemsToChange.Count + 20; state.Breath(); } IReversalIndexEntry entry = ReversalIndexEntry.CreateFromDBObject(m_cache, entryId); entry.PartOfSpeechRAHvo = m_selectedHvo; } m_cache.EndUndoTask(); }
/// <summary> /// Fake doing the change by setting the specified property to the appropriate value /// for each item in the set. Disable items that can't be set. /// </summary> /// <param name="itemsToChange"></param> /// <param name="tagFakeFlid"></param> /// <param name="tagEnable"></param> /// <param name="state"></param> public void FakeDoit(IEnumerable <int> itemsToChange, int tagFakeFlid, int tagEnable, ProgressState state) { CheckDisposed(); string labelToShow = SelectedLabel; // selectedHvo refers to either a FsFeatStruc we've made or the targeted feature var selectedObject = m_cache.ServiceLocator.GetInstance <ICmObjectRepository>().GetObject(SelectedHvo); if (selectedObject is IFsFeatStruc) { labelToShow = GetLabelToShow(); // get the value for the targeted feature from the FsFeatStruc } else if (selectedObject is IFsClosedFeature) { labelToShow = " "; // it is the remove option so we just show nothing after the arrow } ITsString tss = TsStringUtils.MakeString(labelToShow, m_cache.DefaultAnalWs); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); foreach (int hvo in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 100 / itemsToChange.Count(); state.Breath(); } bool fEnable = IsItemEligible(m_sda, hvo, selectedObject, labelToShow); if (fEnable) { m_sda.SetString(hvo, tagFakeFlid, tss); } m_sda.SetInt(hvo, tagEnable, (fEnable ? 1 : 0)); } }
/// <summary> /// Execute the change requested by the current selection in the combo. /// Basically we want the MoInflClass indicated by m_selectedHvo, (even if 0?? not yet possible), /// to become the InflectionClass of each record that is appropriate to change. /// We do nothing to records where the check box is turned off, /// and nothing to ones that currently have an MSA other than an MoStemMsa, /// and nothing to ones that currently have an MSA with the wrong POS. /// (a) If the owning entry has an MoStemMsa with the right inflection class (and presumably POS), /// set the sense to use it. /// (b) If all senses using the current MoStemMsa are to be changed, just update /// the inflection class of that MoStemMsa. /// We could add this...but very probably unused MSAs would have been taken over /// when setting the POS. /// --(c) If the entry has an MoStemMsa which is not being used at all, change it to /// --the required POS and inflection class and use it. /// (d) Make a new MoStemMsa in the LexEntry with the required POS and inflection class /// and point the sense at it. /// </summary> public void DoIt(Set <int> itemsToChange, ProgressState state) { CheckDisposed(); int hvoPos = GetPOS(); // A Set of eligible parts of speech to use in filtering. Set <int> possiblePOS = GetPossiblePartsOfSpeech(); // Make a Dictionary from HVO of entry to list of modified senses. Dictionary <int, List <ILexSense> > sensesByEntry = new Dictionary <int, List <ILexSense> >(); int tagOwningEntry = m_cache.VwCacheDaAccessor.GetVirtualHandlerName("LexSense", "OwningEntry").Tag; int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count / 50, 1)); foreach (int hvoSense in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 20 / itemsToChange.Count; state.Breath(); } if (!IsItemEligible(m_cache.MainCacheAccessor, hvoSense, possiblePOS)) { continue; } ILexSense ls = (ILexSense)CmObject.CreateFromDBObject(m_cache, hvoSense, false); IMoMorphSynAnalysis msa = ls.MorphoSyntaxAnalysisRA; int hvoEntry = m_cache.MainCacheAccessor.get_ObjectProp(ls.Hvo, tagOwningEntry); if (!sensesByEntry.ContainsKey(hvoEntry)) { sensesByEntry[hvoEntry] = new List <ILexSense>(); } sensesByEntry[hvoEntry].Add(ls); } m_cache.BeginUndoTask(FdoUiStrings.ksUndoBEInflClass, FdoUiStrings.ksRedoBEInflClass); BulkEditBar.ForceRefreshOnUndoRedo(m_cache.MainCacheAccessor); i = 0; interval = Math.Min(100, Math.Max(sensesByEntry.Count / 50, 1)); foreach (KeyValuePair <int, List <ILexSense> > kvp in sensesByEntry) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / sensesByEntry.Count + 20; state.Breath(); } ILexEntry entry = (ILexEntry)CmObject.CreateFromDBObject(m_cache, kvp.Key, false); List <ILexSense> sensesToChange = kvp.Value; IMoStemMsa msmTarget = null; foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { IMoStemMsa msm = msa as IMoStemMsa; if (msm != null && msm.InflectionClassRAHvo == m_selectedHvo) { // Can reuse this one! msmTarget = msm; break; } } if (msmTarget == null) { // See if we can reuse an existing MoStemMsa by changing it. // This is possible if it is used only by senses in the list, or not used at all. List <ILexSense> otherSenses = new List <ILexSense>(); if (entry.SensesOS.Count != sensesToChange.Count) { foreach (ILexSense ls in entry.SensesOS) { if (!sensesToChange.Contains(ls)) { otherSenses.Add(ls); } } } foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { IMoStemMsa msm = msa as IMoStemMsa; if (msm == null) { continue; } bool fOk = true; foreach (ILexSense ls in otherSenses) { if (ls.MorphoSyntaxAnalysisRA == msm) { fOk = false; break; } } if (fOk) { // Can reuse this one! Nothing we don't want to change uses it. // Adjust its POS as well as its inflection class, just to be sure. msmTarget = msm; msmTarget.PartOfSpeechRAHvo = hvoPos; msmTarget.InflectionClassRAHvo = m_selectedHvo; break; } } } if (msmTarget == null) { // Nothing we can reuse...make a new one. msmTarget = new MoStemMsa(); entry.MorphoSyntaxAnalysesOC.Add(msmTarget); msmTarget.PartOfSpeechRAHvo = hvoPos; msmTarget.InflectionClassRAHvo = m_selectedHvo; } // Finally! Make the senses we want to change use it. foreach (ILexSense ls in sensesToChange) { ls.MorphoSyntaxAnalysisRA = msmTarget; } } m_cache.EndUndoTask(); }
private void DoUpdatePos(ProgressState state, Dictionary <ILexEntry, List <ILexSense> > sensesByEntry, IPartOfSpeech posWanted) { int i; int interval; i = 0; interval = Math.Min(100, Math.Max(sensesByEntry.Count / 50, 1)); foreach (var kvp in sensesByEntry) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / sensesByEntry.Count + 20; state.Breath(); } var entry = kvp.Key; var sensesToChange = kvp.Value; // Try to find an existing MSA with the right POS. var msmTarget = (from msa in entry.MorphoSyntaxAnalysesOC where msa.ClassID == (uint)MoStemMsaTags.kClassId && ((IMoStemMsa)msa).PartOfSpeechRA == posWanted select(IMoStemMsa) msa).FirstOrDefault(); if (msmTarget == null) { // No existing MSA has the desired POS. // See if we can reuse an existing MoStemMsa by changing it. // This is possible if it is used only by senses in the list, or not used at all. var otherSenses = new List <ILexSense>(); AddExcludedSenses(entry, otherSenses, sensesToChange); // Get all the unchanged senses of the entry. foreach (var msa in entry.MorphoSyntaxAnalysesOC) { if (msa.ClassID != MoStemMsaTags.kClassId) { continue; } bool fOk = true; foreach (var otherSense in otherSenses) { if (otherSense.MorphoSyntaxAnalysisRA == msa) { fOk = false; // we can't change it, one of the unchanged senses uses it break; } } if (fOk) { // Can reuse this one! Nothing we don't want to change uses it. Go ahead and set it to the // required POS. msmTarget = (IMoStemMsa)msa; var oldPOS = msmTarget.PartOfSpeechRA; msmTarget.PartOfSpeechRA = posWanted; // compare MoStemMsa.ResetInflectionClass: changing POS requires us to clear inflection class, // if it is set. if (oldPOS != null && msmTarget.InflectionClassRA != null) { msmTarget.InflectionClassRA = null; } break; } } } if (msmTarget == null) { // Nothing we can reuse...make a new one. msmTarget = m_cache.ServiceLocator.GetInstance <IMoStemMsaFactory>().Create(); entry.MorphoSyntaxAnalysesOC.Add(msmTarget); msmTarget.PartOfSpeechRA = posWanted; } // Finally! Make the senses we want to change use it. foreach (var sense in sensesToChange) { if (sense.MorphoSyntaxAnalysisRA == msmTarget) { continue; // reusing a modified msa. } sense.MorphoSyntaxAnalysisRA = msmTarget; } } }
/// <summary> /// Execute the change requested by the current selection in the combo. /// Basically we want a copy of the FsFeatStruc indicated by m_selectedHvo, (even if 0?? not yet possible), /// to become the MsFeatures of each record that is appropriate to change. /// We do nothing to records where the check box is turned off, /// and nothing to ones that currently have an MSA other than an MoStemMsa, /// and nothing to ones that currently have an MSA with the wrong POS. /// (a) If the owning entry has an MoStemMsa with a matching MsFeatures (and presumably POS), /// set the sense to use it. /// (b) If all senses using the current MoStemMsa are to be changed, just update /// the MsFeatures of that MoStemMsa. /// We could add this...but very probably unused MSAs would have been taken over /// when setting the POS. /// --(c) If the entry has an MoStemMsa which is not being used at all, change it to /// --the required POS and inflection class and use it. /// (d) Make a new MoStemMsa in the LexEntry with the required POS and features /// and point the sense at it. /// </summary> public void DoIt(IEnumerable <int> itemsToChange, ProgressState state) { CheckDisposed(); var pos = GetPOS(); // Make a Set of eligible parts of speech to use in filtering. HashSet <int> possiblePOS = GetPossiblePartsOfSpeech(); // Make a Dictionary from HVO of entry to list of modified senses. var sensesByEntry = new Dictionary <int, HashSet <ILexSense> >(); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); foreach (int hvoSense in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 20 / itemsToChange.Count(); state.Breath(); } if (!IsItemEligible(m_cache.DomainDataByFlid, hvoSense, possiblePOS)) { continue; } var ls = m_cache.ServiceLocator.GetInstance <ILexSenseRepository>().GetObject(hvoSense); var msa = ls.MorphoSyntaxAnalysisRA; int hvoEntry = ls.EntryID; if (!sensesByEntry.ContainsKey(hvoEntry)) { sensesByEntry[hvoEntry] = new HashSet <ILexSense>(); } sensesByEntry[hvoEntry].Add(ls); } //REVIEW: Should these really be the same Undo/Redo strings as for InflectionClassEditor.cs? m_cache.DomainDataByFlid.BeginUndoTask(FdoUiStrings.ksUndoBEInflClass, FdoUiStrings.ksRedoBEInflClass); i = 0; interval = Math.Min(100, Math.Max(sensesByEntry.Count / 50, 1)); IFsFeatStruc fsTarget = null; if (m_selectedHvo != 0) { fsTarget = Cache.ServiceLocator.GetInstance <IFsFeatStrucRepository>().GetObject(m_selectedHvo); } foreach (var kvp in sensesByEntry) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / sensesByEntry.Count + 20; state.Breath(); } var entry = m_cache.ServiceLocator.GetInstance <ILexEntryRepository>().GetObject(kvp.Key); var sensesToChange = kvp.Value; IMoStemMsa msmTarget = null; foreach (var msa in entry.MorphoSyntaxAnalysesOC) { var msm = msa as IMoStemMsa; if (msm != null && MsaMatchesTarget(msm, fsTarget)) { // Can reuse this one! msmTarget = msm; break; } } if (msmTarget == null) { // See if we can reuse an existing MoStemMsa by changing it. // This is possible if it is used only by senses in the list, or not used at all. var otherSenses = new HashSet <ILexSense>(); var senses = new HashSet <ILexSense>(entry.AllSenses.ToArray()); if (senses.Count != sensesToChange.Count) { foreach (var ls in senses) { if (!sensesToChange.Contains(ls)) { otherSenses.Add(ls); } } } foreach (var msa in entry.MorphoSyntaxAnalysesOC) { var msm = msa as IMoStemMsa; if (msm == null) { continue; } bool fOk = true; foreach (var ls in otherSenses) { if (ls.MorphoSyntaxAnalysisRA == msm) { fOk = false; break; } } if (fOk) { // Can reuse this one! Nothing we don't want to change uses it. // Adjust its POS as well as its inflection feature, just to be sure. // Ensure that we don't change the POS! See LT-6835. msmTarget = msm; InitMsa(msmTarget, msm.PartOfSpeechRA.Hvo); break; } } } if (msmTarget == null) { // Nothing we can reuse...make a new one. msmTarget = m_cache.ServiceLocator.GetInstance <IMoStemMsaFactory>().Create(); entry.MorphoSyntaxAnalysesOC.Add(msmTarget); InitMsa(msmTarget, pos.Hvo); } // Finally! Make the senses we want to change use it. foreach (var ls in sensesToChange) { ls.MorphoSyntaxAnalysisRA = msmTarget; } } m_cache.DomainDataByFlid.EndUndoTask(); }
public override void DoIt(Set <int> itemsToChange, ProgressState state) { CheckDisposed(); ISilDataAccess sda = m_cache.MainCacheAccessor; // Make a hashtable from HVO of entry to list of modified senses. Dictionary <int, List <int> > sensesByEntry = new Dictionary <int, List <int> >(); int tagOwningEntry = m_cache.VwCacheDaAccessor.GetVirtualHandlerName("LexSense", "OwningEntry").Tag; int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count / 50, 1)); foreach (int hvoSense in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 20 / itemsToChange.Count; state.Breath(); } int hvoMsa = sda.get_ObjectProp(hvoSense, (int)LexSense.LexSenseTags.kflidMorphoSyntaxAnalysis); if (hvoMsa != 0 && m_cache.GetClassOfObject(hvoMsa) != MoStemMsa.kclsidMoStemMsa) { continue; // can't fix this one, not a stem. } int hvoEntry = sda.get_ObjectProp(hvoSense, tagOwningEntry); List <int> senses = null; if (!sensesByEntry.TryGetValue(hvoEntry, out senses)) { senses = new List <int>(); sensesByEntry[hvoEntry] = senses; } senses.Add(hvoSense); } m_cache.BeginUndoTask(FdoUiStrings.ksUndoBulkEditPOS, FdoUiStrings.ksRedoBulkEditPOS); BulkEditBar.ForceRefreshOnUndoRedo(sda); i = 0; interval = Math.Min(100, Math.Max(sensesByEntry.Count / 50, 1)); foreach (KeyValuePair <int, List <int> > kvp in sensesByEntry) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / sensesByEntry.Count + 20; state.Breath(); } int hvoEntry = kvp.Key; List <int> sensesToChange = kvp.Value; int hvoMsmTarget = 0; int cmsa = sda.get_VecSize(hvoEntry, (int)LexEntry.LexEntryTags.kflidMorphoSyntaxAnalyses); bool fAssumeSurvives = true; // true if we know all old MSAs will survive. for (int imsa = 0; imsa < cmsa; imsa++) { int hvoMsa = sda.get_VecItem(hvoEntry, (int)LexEntry.LexEntryTags.kflidMorphoSyntaxAnalyses, imsa); if (m_cache.GetClassOfObject(hvoMsa) == MoStemMsa.kclsidMoStemMsa && sda.get_ObjectProp(hvoMsa, (int)MoStemMsa.MoStemMsaTags.kflidPartOfSpeech) == m_selectedHvo) { // Can reuse this one! hvoMsmTarget = hvoMsa; fAssumeSurvives = false; // old MSA may be redundant. break; } } if (hvoMsmTarget == 0) { // See if we can reuse an existing MoStemMsa by changing it. // This is possible if it is used only by senses in the list, or not used at all. List <int> otherSenses = new List <int>(); AddExcludedSenses(sda, hvoEntry, (int)LexEntry.LexEntryTags.kflidSenses, otherSenses, sensesToChange); for (int imsa = 0; imsa < cmsa; imsa++) { int hvoMsa = sda.get_VecItem(hvoEntry, (int)LexEntry.LexEntryTags.kflidMorphoSyntaxAnalyses, imsa); if (m_cache.GetClassOfObject(hvoMsa) != MoStemMsa.kclsidMoStemMsa) { continue; } bool fOk = true; foreach (int hvoOtherSense in otherSenses) { if (sda.get_ObjectProp(hvoOtherSense, (int)LexSense.LexSenseTags.kflidMorphoSyntaxAnalysis) == hvoMsa) { fOk = false; // we can't change it, one of the unchanged senses uses it break; } } if (fOk) { // Can reuse this one! Nothing we don't want to change uses it. Go ahead and set it to the // required POS. hvoMsmTarget = hvoMsa; int hvoOld = sda.get_ObjectProp(hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidPartOfSpeech); sda.SetObjProp(hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidPartOfSpeech, m_selectedHvo); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidPartOfSpeech, 0, 1, hvoOld == 0 ? 1 : 0); // compare MoStemMsa.ResetInflectionClass: changing POS requires us to clear inflection class, // if it is set. if (hvoOld != 0 && sda.get_ObjectProp(hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidInflectionClass) != 0) { sda.SetObjProp(hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidInflectionClass, 0); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidInflectionClass, 0, 0, 1); } break; } } } if (hvoMsmTarget == 0) { // Nothing we can reuse...make a new one. hvoMsmTarget = sda.MakeNewObject((int)MoStemMsa.kclsidMoStemMsa, hvoEntry, (int)LexEntry.LexEntryTags.kflidMorphoSyntaxAnalyses, -1); sda.SetObjProp(hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidPartOfSpeech, m_selectedHvo); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoMsmTarget, (int)MoStemMsa.MoStemMsaTags.kflidInflectionClass, m_cache.GetObjIndex(hvoEntry, (int)LexEntry.LexEntryTags.kflidMorphoSyntaxAnalyses, hvoMsmTarget), 1, 0); } // Finally! Make the senses we want to change use it. foreach (int hvoSense in sensesToChange) { int hvoOld = sda.get_ObjectProp(hvoSense, (int)LexSense.LexSenseTags.kflidMorphoSyntaxAnalysis); if (hvoOld == hvoMsmTarget) { continue; // reusing a modified msa. } LexSense.HandleOldMSA(m_cache, hvoSense, hvoMsmTarget, fAssumeSurvives); sda.SetObjProp(hvoSense, (int)LexSense.LexSenseTags.kflidMorphoSyntaxAnalysis, hvoMsmTarget); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoSense, (int)LexSense.LexSenseTags.kflidMorphoSyntaxAnalysis, 0, 1, hvoOld == 0 ? 1 : 0); } } m_cache.EndUndoTask(); }
/// <summary> /// Execute the change requested by the current selection in the combo. /// Basically we want the MoInflClass indicated by m_selectedHvo, (even if 0?? not yet possible), /// to become the InflectionClass of each record that is appropriate to change. /// We do nothing to records where the check box is turned off, /// and nothing to ones that currently have an MSA other than an MoStemMsa, /// and nothing to ones that currently have an MSA with the wrong POS. /// (a) If the owning entry has an MoStemMsa with the right inflection class (and presumably POS), /// set the sense to use it. /// (b) If all senses using the current MoStemMsa are to be changed, just update /// the inflection class of that MoStemMsa. /// We could add this...but very probably unused MSAs would have been taken over /// when setting the POS. /// --(c) If the entry has an MoStemMsa which is not being used at all, change it to /// --the required POS and inflection class and use it. /// (d) Make a new MoStemMsa in the LexEntry with the required POS and inflection class /// and point the sense at it. /// </summary> public void DoIt(IEnumerable <int> itemsToChange, ProgressState state) { CheckDisposed(); var pos = GetPOS(); // A Set of eligible parts of speech to use in filtering. Set <int> possiblePOS = GetPossiblePartsOfSpeech(); // Make a Dictionary from HVO of entry to list of modified senses. var sensesByEntryAndPos = new Dictionary <Tuple <ILexEntry, IPartOfSpeech>, List <ILexSense> >(); int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count() / 50, 1)); foreach (int hvoSense in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 20 / itemsToChange.Count(); state.Breath(); } if (!IsItemEligible(m_cache.DomainDataByFlid, hvoSense, possiblePOS)) { continue; } var ls = m_cache.ServiceLocator.GetInstance <ILexSenseRepository>().GetObject(hvoSense); var msa = (IMoStemMsa)ls.MorphoSyntaxAnalysisRA; var entry1 = ls.Entry; var key = new Tuple <ILexEntry, IPartOfSpeech>(entry1, msa.PartOfSpeechRA); if (!sensesByEntryAndPos.ContainsKey(key)) { sensesByEntryAndPos[key] = new List <ILexSense>(); } sensesByEntryAndPos[key].Add(ls); } m_cache.DomainDataByFlid.BeginUndoTask(FdoUiStrings.ksUndoBEInflClass, FdoUiStrings.ksRedoBEInflClass); i = 0; interval = Math.Min(100, Math.Max(sensesByEntryAndPos.Count / 50, 1)); foreach (var kvp in sensesByEntryAndPos) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / sensesByEntryAndPos.Count + 20; state.Breath(); } var entry = kvp.Key.Item1; var sensesToChange = kvp.Value; IMoStemMsa msmTarget = null; foreach (var msa in entry.MorphoSyntaxAnalysesOC) { var msm = msa as IMoStemMsa; if (msm != null && msm.InflectionClassRA != null && msm.InflectionClassRA.Hvo == m_selectedHvo) { // Can reuse this one! msmTarget = msm; break; } } if (msmTarget == null) { // See if we can reuse an existing MoStemMsa by changing it. // This is possible if it is used only by senses in the list, or not used at all. var otherSenses = new List <ILexSense>(); if (entry.SensesOS.Count != sensesToChange.Count) { foreach (var ls in entry.SensesOS) { if (!sensesToChange.Contains(ls)) { otherSenses.Add(ls); } } } foreach (var msa in entry.MorphoSyntaxAnalysesOC) { var msm = msa as IMoStemMsa; if (msm == null) { continue; } bool fOk = true; foreach (var ls in otherSenses) { if (ls.MorphoSyntaxAnalysisRA == msm) { fOk = false; break; } } if (fOk) { // Can reuse this one! Nothing we don't want to change uses it. // Adjust its POS as well as its inflection class, just to be sure. msmTarget = msm; msmTarget.PartOfSpeechRA = kvp.Key.Item2; msmTarget.InflectionClassRA = m_cache.ServiceLocator.GetInstance <IMoInflClassRepository>().GetObject(m_selectedHvo); break; } } } if (msmTarget == null) { // Nothing we can reuse...make a new one. msmTarget = m_cache.ServiceLocator.GetInstance <IMoStemMsaFactory>().Create(); entry.MorphoSyntaxAnalysesOC.Add(msmTarget); msmTarget.PartOfSpeechRA = kvp.Key.Item2; msmTarget.InflectionClassRA = m_cache.ServiceLocator.GetInstance <IMoInflClassRepository>().GetObject(m_selectedHvo); } // Finally! Make the senses we want to change use it. foreach (var ls in sensesToChange) { ls.MorphoSyntaxAnalysisRA = msmTarget; } } m_cache.DomainDataByFlid.EndUndoTask(); }