/// ------------------------------------------------------------------------------------ /// <summary> /// Sets the current book, particularly picking the right set of annotations /// to add new ones to. Also (and more conspicuously) ends the current Undo task /// and makes a new one for importing the new book. Should therefore be called /// BEFORE setting up the Undo action for the creation of the book. /// </summary> /// <param name="nCanonicalBookNumber">The canonical book number.</param> /// <returns>The action handler</returns> /// ------------------------------------------------------------------------------------ private IActionHandler SetCurrentBookInternal(int nCanonicalBookNumber) { // We temporarily un-suppress our action handler long enough to get it so we can // grab a local copy. m_suppressor.Dispose(); m_suppressor = null; IActionHandler actionHandler = m_cache.ActionHandlerAccessor; m_suppressor = new SuppressSubTasks(m_cache); if ((m_importedSavedVersion != null && m_importedSavedVersion.BooksOS.Count > 0) || (m_savedVersion != null && m_savedVersion.BooksOS.Count > 0)) { // We want a new undo task for each new book, except the first one actionHandler.EndOuterUndoTask(); } // No need to use localizable string from resources because the user will never // see these labels because we collapse to a single undo task when the import // completes. actionHandler.BeginUndoTask("Undo Import Book " + nCanonicalBookNumber, "Redo Import Book " + nCanonicalBookNumber); m_annotations = (ScrBookAnnotations)m_scr.BookAnnotationsOS[nCanonicalBookNumber - 1]; return(actionHandler); }
/// <summary> /// Add the specified type of freeform annotation to the given segment. /// Undoable by default. /// </summary> /// <param name="hvoSeg"></param> /// <param name="hvoType">freeform annotation type</param> /// <returns></returns> public ICmIndirectAnnotation AddFreeformAnnotation(int hvoSeg, int hvoType) { using (SuppressSubTasks suppressor = new SuppressSubTasks(m_fdoCache, true)) { // convert any preceeding dummy segments, so paragraph parser does not push this to the first dummy sentence. (LT-7318) int hvoPara = m_fdoCache.GetObjProperty(hvoSeg, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject); StTxtPara para = StTxtPara.CreateFromDBObject(m_fdoCache, hvoPara) as StTxtPara; para.EnsurePreceedingSegmentsAreReal(hvoSeg); string undoString = ""; string redoString = ""; if (hvoType == ktagSegFF_freeTranslation) { undoString = ITextStrings.ksUndoAddFreeformTranslation; redoString = ITextStrings.ksRedoAddFreeformTranslation; } else if (hvoType == ktagSegFF_literalTranslation) { undoString = ITextStrings.ksUndoAddLiteralTranslation; redoString = ITextStrings.ksRedoAddLiteralTranslation; } else if (hvoType == ktagSegFF_note) { undoString = ITextStrings.ksUndoAddNote; redoString = ITextStrings.ksRedoAddNote; } else { throw new ArgumentException(String.Format("segment freeform type {0} is not yet supported here.", hvoType)); } ICmIndirectAnnotation ann; m_fdoCache.BeginUndoTask(undoString, redoString); { ann = CmIndirectAnnotation.CreateUnownedIndirectAnnotation(m_fdoCache); ann.AppliesToRS.Append(hvoSeg); ann.AnnotationTypeRAHvo = hvoType; // Add it to the cached collection of freeform annotations. This is a bit clumsy because // it isn't a real property so we can't just use the normal methods for modifying a property. // Enhance JohnT: put it with the other ones of the same type. ISilDataAccess sda = m_fdoCache.MainCacheAccessor; IVwCacheDa cda = (IVwCacheDa)sda; int cFreeForm = sda.get_VecSize(hvoSeg, ktagSegFF); int[] freeForms = new int[cFreeForm + 1]; for (int i = 0; i < cFreeForm; i++) { freeForms[i] = sda.get_VecItem(hvoSeg, ktagSegFF, i); } freeForms[cFreeForm] = ann.Hvo; cda.CacheVecProp(hvoSeg, ktagSegFF, freeForms, cFreeForm + 1); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoSeg, ktagSegFF, cFreeForm, 1, 0); } m_fdoCache.EndUndoTask(); return(ann); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Creator of this object MUST call this after import is done, whether or not it /// succeeded. /// </summary> /// <param name="fRollbackLastSequence"><c>false</c> if import completed normally or was /// stopped by user after importing one or more complete books. <c>true</c> if an error /// occurred during import or user cancelled import in the middle of a book.</param> /// ------------------------------------------------------------------------------------ public void DoneImportingFiles(bool fRollbackLastSequence) { if (m_suppressor != null) { m_suppressor.Dispose(); m_suppressor = null; } if (fRollbackLastSequence) { m_cache.ActionHandlerAccessor.Rollback(0); } else { m_cache.ActionHandlerAccessor.EndOuterUndoTask(); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="T:UndoImportInfo"/> class. /// </summary> /// <param name="cache">The cache.</param> /// <param name="bookFilter">The book filter.</param> /// ------------------------------------------------------------------------------------ public UndoImportManager(FdoCache cache, FilteredScrBooks bookFilter) { m_cache = cache; m_bookFilter = bookFilter; m_scr = m_cache.LangProject.TranslatedScriptureOA; Debug.Assert(m_cache.ActionHandlerAccessor != null); Debug.Assert(m_cache.ActionHandlerAccessor.CurrentDepth == 0); m_hMark = m_cache.ActionHandlerAccessor.Mark(); IActionHandler actionHandler = m_cache.ActionHandlerAccessor; m_suppressor = new SuppressSubTasks(m_cache); // don't need to undo setting properties. // Create new archive for saving backup versions of imported book m_savedVersion = new ScrDraft(); m_scr.ArchivedDraftsOC.Add(m_savedVersion); actionHandler.AddAction(new UndoImportObjectAction(m_savedVersion)); m_savedVersion.Description = TeResourceHelper.GetResourceString("kstidSavedVersionDescriptionOriginal"); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Inserts a Scriture annotation for the book currently being imported. /// </summary> /// <param name="bcvStartReference">The starting BCV reference.</param> /// <param name="bcvEndReference">The ending BCV reference.</param> /// <param name="obj">The object being annotated (either a paragraph or a IScrBook)</param> /// <param name="bldr">The paragraph builder containing the guts of the annotation /// description</param> /// <param name="guidNoteType">The GUID representing the CmAnnotationDefn to use for /// the type</param> /// <returns>The newly created annotation</returns> /// ------------------------------------------------------------------------------------ public IScrScriptureNote InsertNote(int bcvStartReference, int bcvEndReference, ICmObject obj, StTxtParaBldr bldr, Guid guidNoteType) { bool fOpenedTransaction = false; if (m_cache.DatabaseAccessor != null && !m_cache.DatabaseAccessor.IsTransactionOpen()) { fOpenedTransaction = true; m_cache.DatabaseAccessor.BeginTrans(); } try { IScrScriptureNote note = m_annotations.InsertImportedNote( bcvStartReference, bcvEndReference, obj, obj, guidNoteType, bldr); m_suppressor.Dispose(); m_suppressor = null; m_cache.ActionHandlerAccessor.AddAction(new UndoImportObjectAction(note)); if (fOpenedTransaction) { m_cache.DatabaseAccessor.CommitTrans(); } m_suppressor = new SuppressSubTasks(m_cache); return(note); } catch { if (fOpenedTransaction) { m_cache.DatabaseAccessor.RollbackTrans(); } throw; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Sets the current book, particularly picking the right set of annotations /// to add new ones to. Also (and more conspicuously) ends the current Undo task /// and makes a new one for importing the new book. Should therefore be called /// BEFORE setting up the Undo action for the creation of the book. /// </summary> /// <param name="nCanonicalBookNumber">The canonical book number.</param> /// <returns>The action handler</returns> /// ------------------------------------------------------------------------------------ private IActionHandler SetCurrentBookInternal(int nCanonicalBookNumber) { // We temporarily un-suppress our action handler long enough to get it so we can // grab a local copy. m_suppressor.Dispose(); m_suppressor = null; IActionHandler actionHandler = m_cache.ActionHandlerAccessor; m_suppressor = new SuppressSubTasks(m_cache); if ((m_importedSavedVersion != null && m_importedSavedVersion.BooksOS.Count > 0) || (m_savedVersion != null && m_savedVersion.BooksOS.Count > 0)) { // We want a new undo task for each new book, except the first one actionHandler.EndOuterUndoTask(); } // No need to use localizable string from resources because the user will never // see these labels because we collapse to a single undo task when the import // completes. actionHandler.BeginUndoTask("Undo Import Book " + nCanonicalBookNumber, "Redo Import Book " + nCanonicalBookNumber); m_annotations = (ScrBookAnnotations)m_scr.BookAnnotationsOS[nCanonicalBookNumber - 1]; return actionHandler; }
/// <summary> /// Parse through all the given texts, even if they've been fully analyzed. /// Collect occurrences of words and cache all paragraph and wordform related virtual properties. /// </summary> /// <param name="cache"></param> /// <param name="hvosStText">list of hvos for StText objects</param> public static void ConcordTexts(FdoCache cache, int[] hvosStText, ProgressState progress) { if (progress == null) progress = new NullProgressState(); using (ParagraphParser pp = new ParagraphParser(cache)) { #if PROFILING long ticks = DateTime.Now.Ticks; #endif // Ensure all info about paragraphs of texts and contents of paragraphs is in cache and current. // Enhance JohnT: possibly performance would be helped, especially in cases where we have a lot // of archived Scripture versions, by restricting this to just the texts in hvosStText. cache.LoadAllOfAnOwningVectorProp((int)StText.StTextTags.kflidParagraphs, "StText"); cache.LoadAllOfAStringProp((int)StTxtPara.StTxtParaTags.kflidContents); #if PROFILING Debug.WriteLine("Time to end of loading text data = " + (DateTime.Now.Ticks - ticks)); #endif pp.m_hvosStText = hvosStText; //// Get a list of all the paragraphs. //List<int> targetParagraphs = new List<int>(); //foreach (IStText text in new FdoObjectSet<IStText>(cache, pp.m_hvosStText, true)) //{ // targetParagraphs.AddRange(text.ParagraphsOS.HvoArray); //} pp.RebuildingConcordanceWordforms = true; WordformInventory wfi = (cache.LangProject.WordformInventoryOA as WordformInventory); wfi.ResetConcordanceWordformsAndOccurrences(); #if PROFILING Debug.WriteLine("Time to end of reset occurrenes = " + (DateTime.Now.Ticks - ticks)); #endif ParagraphParser.ResetParseSessionDependentStaticData(); // Estimate the number of total number of milestones we'll set. // Enhance: we could construct a way to set percentage done based upon // number of texts and paragraphs in each text. if (progress is MilestoneProgressState) { MilestoneProgressState mp = progress as SIL.FieldWorks.Common.Controls.MilestoneProgressState; for (int i = 0; i < pp.m_hvosStText.Length; ++i) { AddParseTextMilestones(mp); } } // Parse each text to load our paragraph and wordform segment annotations. using (SuppressSubTasks suppressor = new SuppressSubTasks(cache, true)) { List<IStText> texts = new List<IStText>(new FdoObjectSet<IStText>(cache, pp.m_hvosStText, false)); // Anything like this is currently redundant, we loaded the contents of ALL paragraphs above. //List<IStText> parsedTexts = texts.FindAll(HasLastParsedTimestamp); //if (parsedTexts.Count != 0) //{ // // We actually have parsed some texts before...yet we have to again. Possibly another program changed // // the data. Reload it as efficiently as possible. // int[] parsedHvos = new int[parsedTexts.Count]; // for (int i = 0; i < parsedHvos.Length; i++) // parsedHvos[i] = parsedTexts[i].Hvo; // int index = 0; // string Hvos = DbOps.MakePartialIdList(ref index, parsedHvos); // string whereClause = ""; // if (index == parsedHvos.Length) // { // // If we can make a single where clause we'll do it; otherwise do them all // whereClause = " where Owner$ in (" + Hvos + ")"; // } // string sql = "select Owner$, Id, UpdStmp, Contents, Contents_Fmt from StTxtPara_ " + whereClause + " order by owner$, OwnOrd$"; // IDbColSpec dcs = DbColSpecClass.Create(); // dcs.Push((int)DbColType.koctBaseId, 0, 0, 0); // dcs.Push((int)DbColType.koctObjVecOwn, 1, (int)StText.StTextTags.kflidParagraphs, 0); // dcs.Push((int)DbColType.koctTimeStamp, 2, 0, 0); // dcs.Push((int)DbColType.koctString, 2, (int)StTxtPara.StTxtParaTags.kflidContents, 0); // dcs.Push((int)DbColType.koctFmt, 2, (int)StTxtPara.StTxtParaTags.kflidContents, 0); // cache.VwOleDbDaAccessor.Load(sql, dcs, 0, 0, null, false); //} // Need a separate loop for these, otherwise things get confused as we start to reuse // annotations in pp.Parse() and then re-encounter them in later attempts to salvage Pfics and segments. #if PROFILING Debug.WriteLine("Time to end of preliminaries = " + (DateTime.Now.Ticks - ticks)); #endif foreach (IStText text in texts) pp.SalvageDummyAnnotations(text); #if PROFILING Debug.WriteLine("Time to start of main parse loop = " + (DateTime.Now.Ticks - ticks)); #endif foreach (IStText text in texts) { pp.Parse(text, progress); } #if PROFILING Debug.WriteLine("Time to end of main parse loop = " + (DateTime.Now.Ticks - ticks)); #endif StText.RecordParseTimestamps(texts); pp.CleanupLeftoverAnnotations(progress); } //Debug.WriteLine("Time for whole ConcordTexts = " + (DateTime.Now.Ticks - ticks)); progress.SetMilestone(); progress.Breath(); #if PROFILING Debug.WriteLine("Parse required " + pp.m_cDummyAnnotations + " dummy annotations" + " but could only reuse " + pp.m_dummyAnnotationsToReuse.Count); Debug.WriteLine(" Parse created " + pp.m_cWficsMade + " Wfics, " + pp.m_cPficsMade + " Pfics, and " + pp.m_cSegmentsMade + " Segments"); Debug.WriteLine(" So far we made a total of " + s_cTotalDummiesMade + "; this parse making dummies took " + pp.m_cTicksMakingDummies); Debug.WriteLine(" This parse we reset " + pp.m_cTotalDummiesReset + " in a time of " + pp.m_cTicksResettingDummies); #endif } }
private void MakeAllAnnotationsReal(int hvoStText) { int ktagParaSegments = StTxtPara.SegmentsFlid(m_cache); int ktagSegmentForms = DummyVirtualHandler.InstallDummyHandler(m_cache.VwCacheDaAccessor, "CmBaseAnnotation", "SegmentForms", (int)CellarModuleDefns.kcptReferenceSequence).Tag; using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(m_cache, true)) { int hvoWficDefn = CmAnnotationDefn.Twfic(m_cache).Hvo; int cpara = m_cache.GetVectorSize(hvoStText, kflidParagraphs); for (int ipara = 0; ipara < cpara; ipara++) { int hvoPara = m_cache.GetVectorItem(hvoStText, kflidParagraphs, ipara); int cseg = m_cache.GetVectorSize(hvoPara, ktagParaSegments); for (int iseg = 0; iseg < cseg; iseg++) { int hvoSeg = m_cache.GetVectorItem(hvoPara, ktagParaSegments, iseg); int cform = m_cache.GetVectorSize(hvoSeg, ktagSegmentForms); for (int iform = 0; iform < cform; iform++) { int hvoAnnotation = m_cache.GetVectorItem(hvoSeg, ktagSegmentForms, iform); // Don't try to convert punctuation...we don't use it and converting it doesn't work anyway. if (m_cache.IsDummyObject(hvoAnnotation) && m_cache.GetObjProperty(hvoAnnotation, kflidAnnotationType) == hvoWficDefn) { hvoAnnotation = CmObject.ConvertDummyToReal(m_cache, hvoAnnotation).Hvo; } } } } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Creator of this object MUST call this after import is done, whether or not it /// succeeded. /// </summary> /// <param name="fRollbackLastSequence"><c>false</c> if import completed normally or was /// stopped by user after importing one or more complete books. <c>true</c> if an error /// occurred during import or user cancelled import in the middle of a book.</param> /// ------------------------------------------------------------------------------------ public void DoneImportingFiles(bool fRollbackLastSequence) { if (m_suppressor != null) { m_suppressor.Dispose(); m_suppressor = null; } if (fRollbackLastSequence) m_cache.ActionHandlerAccessor.Rollback(0); else m_cache.ActionHandlerAccessor.EndOuterUndoTask(); }
/// <summary> /// Process any pending objects that need to be converted to real objects. /// Review: Is there some other event we could use to do this, before OnIdle()? /// </summary> /// <param name="argument"></param> /// <returns></returns> public bool OnIdle(object argument) { CheckDisposed(); if (m_requestedDummiesToConvertQueue.Count == 0 && (m_fConvertRemainingDummiesOnIdle == false || m_fConvertRemainingDummiesOnIdle && m_remainingDummiesToConvertOnIdle.Count == 0)) { return false; } List<int> dummiesToConvert = new List<int>(kMaxDummiesToConvertAtOnce); // Process those that are already in the queue, followed by any remaining ones. BuildDummiesToConvertList(m_requestedDummiesToConvertQueue, dummiesToConvert); if (m_fConvertRemainingDummiesOnIdle) BuildDummiesToConvertList(m_remainingDummiesToConvertOnIdle, dummiesToConvert); Debug.Assert(m_requestedDummiesToConvertQueue.Count == 0 || m_requestedDummiesToConvertQueue[0] == dummiesToConvert[0], "We should empty our request queue first."); using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(Cache)) { ConvertDummiesToReal(m_flid, dummiesToConvert.ToArray()); } return false; }
/// <summary> /// Enhance JohnT/EricP: note that we are gradually developing mechanisms to prevent this happening. /// It may eventually be unnecessary. See for example CmBaseAnnotatin.CollectLinkedItemsForDeletion and ReserveAnnotations. /// (However, that CollectLinkedItems isn't currently called when annotations are bulk deleted, /// for example during parsing paragraphs, and ReserveAnnotations doesn't do all this yet.) /// </summary> private void CleanupInvalidWfics() { using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(m_cache, true)) { Set<int> hvosToDelete = new Set<int>(); bool fReported = false; bool fDeletedCcasOrRows = false; // Clobber any deleted words, etc. int crows = m_chart.RowsRS.Count; int crowsOriginal = crows; // Save for PropChanged after fixing chart. for (int irow = 0; irow < crows; irow++ ) // not foreach here, as we may delete some as we go { int hvoRow = m_cache.GetVectorItem(m_chart.Hvo, kflidRows, irow); int citems = m_cache.GetVectorSize(hvoRow, kflidAppliesTo); // If there are already no items, it's presumably an empty row the user inserted manually // and plans to put something into, not a sign of a corrupted chart. So we don't want // to throw up the error message. Just skip it. See LT-7861. if (citems == 0) continue; for (int icca = 0; icca < citems; icca++) // not foreach here, as we may delete some as we go { int hvoCca = m_cache.GetVectorItem(hvoRow, kflidAppliesTo, icca); if (!ConstituentChartLogic.IsWficGroup(m_cache, hvoCca)) { // Check to see if this is a MovedText marker and make sure Target feature is set if (!m_logic.CheckForUnsetMovedTextOrInvalidMrkr(hvoCca)) { // This is the invalid MovedText Marker case. We need to delete the CCA. ReportWarningAndUpdateCount(ref fReported, hvoRow, kflidAppliesTo, ref icca, ref citems); hvosToDelete.Add(hvoCca); fDeletedCcasOrRows = true; } continue; // in any case, this isn't a Wfic group (dataCca), so skip to next. } int cwfic = m_cache.GetVectorSize(hvoCca, kflidAppliesTo); for (int iwfic = 0; iwfic < cwfic; iwfic++) { int hvoWfic = m_cache.GetVectorItem(hvoCca, kflidAppliesTo, iwfic); if (m_cache.GetObjProperty(hvoWfic, kflidBeginObject) == 0) { // It's an obsolete annotation left over after someone deleted the word from the text. // auto-correct by taking wfic out of cca. ReportWarningAndUpdateCount(ref fReported, hvoCca, kflidAppliesTo, ref iwfic, ref cwfic); // No need to delete the Wfic, it's saved for possible reuse. //hvosToDelete.Add(hvoWfic); } } if (cwfic == 0) { // CCA is now empty, take it out of row ReportWarningAndUpdateCount(ref fReported, hvoRow, kflidAppliesTo, ref icca, ref citems); hvosToDelete.Add(hvoCca); fDeletedCcasOrRows = true; } } if (citems == 0) { // row is now empty, take it out of chart ReportWarningAndUpdateCount(ref fReported, m_chart.Hvo, kflidRows, ref irow, ref crows); hvosToDelete.Add(hvoRow); fDeletedCcasOrRows = true; } } if (fDeletedCcasOrRows) { RemoveTargetlessPlaceholders(ref hvosToDelete); } CmObject.DeleteObjects(hvosToDelete, m_cache, false); // We've been bypassing propchanged, because we might already be showing the chart, // and PropChanged will redraw before we've fixed enough. But now, if we did anything, // and if we're showing it, we'd better update. if (fReported) m_cache.PropChanged(m_chart.Hvo, kflidRows, 0, crows, crowsOriginal); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adds the "invalid" character as a valid character. /// </summary> /// <param name="addedCharError">The checking error containing the character that will /// be added to the valid character inventory.</param> /// ------------------------------------------------------------------------------------ private void AddAsValidCharacter(CheckingError addedCharError) { Debug.Assert(addedCharError.CheckId == StandardCheckIds.kguidCharacters, "Checking error should be from the valid characters check"); ILgWritingSystemFactory lgwsf = m_cache.LanguageWritingSystemFactoryAccessor; int hvoWs = m_cache.DefaultVernWs; IWritingSystem ws = lgwsf.get_EngineOrNull(hvoWs); LanguageDefinition langDef = new LanguageDefinition(ws); LgWritingSystem lgWs = new LgWritingSystem(m_cache, hvoWs); langDef.ValidChars = ws.ValidChars; if (StringUtils.IsCharacterDefined(addedCharError.CitedText)) { using (new WaitCursor(Parent)) { // Get the valid characters from the database ValidCharacters validChars = ValidCharacters.Load(langDef); if (validChars != null) { validChars.AddCharacter(addedCharError.CitedText); ws.ValidChars = langDef.ValidChars = validChars.XmlString; StringUtils.UpdatePUACollection(langDef, validChars.AllCharacters); ws.SaveIfDirty(m_cache.DatabaseAccessor); langDef.Serialize(); } // Mark all data grid view rows containing the newly-defined valid character to irrelevant. for (int iRow = 0; iRow < m_list.Count; iRow++) { CheckingError checkError = GetCheckingError(iRow); if (((StTxtPara)checkError.QuoteOA.ParagraphsOS[0]).Contents.Text == addedCharError.CitedText) { // We don't want to create an undoable action, so we suppress subtasks. using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(m_cache, true)) checkError.Status = CheckingStatus.StatusEnum.Irrelevant; } } IsStale = true; m_dataGridView.Invalidate(); } } else { string msg = ResourceHelper.GetResourceString("kstidUndefinedCharacterMsg"); MessageBox.Show(this, msg, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); } }
/// <summary> /// /// </summary> /// <param name="flid"></param> /// <param name="hvoDummy"></param> /// <returns></returns> public ICmObject ConvertDummyToReal(int flid, int hvoDummy) { using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(Cache, true)) { ICmObject realObj = null; if (flid == ConcordanceWordformsFlid(Cache) && Cache.GetClassOfObject(hvoDummy) == (int)WfiWordform.kclsidWfiWordform) { // Do the conversion. ISilDataAccess sda = Cache.MainCacheAccessor; Debug.Assert(Cache.IsDummyObject(hvoDummy), "this should be a dummy wordform."); // a dummy wordform should only have one ws associated with it. // try to find it, so we can make a new one out of its form. MultiAccessor ma = MultiAccessor.CreateMultiAccessor(Cache, hvoDummy, (int)WfiWordform.WfiWordformTags.kflidForm, ""); IWfiWordform wf = null; ITsString tssForm; int wsActual; if (ma.TryWs(LangProject.kwsFirstVernOrNamed, out wsActual, out tssForm)) { int hvoWf = 0; if (FormToWfIdTable.TryGetValue(tssForm.Text + wsActual.ToString(), out hvoWf)) { if (Cache.IsDummyObject(hvoWf)) wf = this.AddRealWordform(tssForm, false); // do the conversion. else wf = WfiWordform.CreateFromDBObject(Cache, hvoWf); // return the conversion } else { string msg = String.Format("Can't convert the dummy({0}) form({1}) ws({2}). Wasn't found in our FormToIdTable.", hvoDummy, tssForm.Text, wsActual); Debug.Fail(msg); throw new ArgumentException(msg); } WfiWordform.CleanupDummyWordformReferences(Cache, hvoDummy, wf.Hvo); if (!SuspendUpdatingConcordanceWordforms) { // Replace the dummy with the real wordform in our ConcordanceWordforms. TryUpdatingConcordanceWordforms(Cache, hvoDummy, wf.Hvo); } } realObj = wf; } else { throw new Exception("The method or operation is not implemented."); } return realObj; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Looks to see if we currently have a translation of the given type, returning it if /// we do. If no such CmTranslation exists, a new one is created and returned. /// </summary> /// <param name="transType">The CmPossibility representing the type of translation to /// get or create</param> /// <returns>CmTranslation of the given type</returns> /// ------------------------------------------------------------------------------------ public ICmTranslation GetOrCreateTrans(ICmPossibility transType) { Debug.Assert(transType != null); ICmTranslation trans = GetTrans(transType.Guid); if (trans == null) { // we need to create an empty translation if one does not exist. IActionHandler acth = m_cache.ActionHandlerAccessor; SuppressSubTasks suppressSubTasks = null; // We don't want to create an undo task if there isn't one already open, so we // set the ActionHandler to null while we create the back translation. bool fNewTransaction = false; string sSavePointName = string.Empty; IOleDbEncap dbAccess = m_cache.DatabaseAccessor; if (acth != null && acth.CurrentDepth == 0) { suppressSubTasks = new SuppressSubTasks(m_cache); } else if (dbAccess != null && !dbAccess.IsTransactionOpen()) { // Set a save point in case there is a problem with the database server. // If there is a problem adding the translation or setting the type, this // transaction will be rolled back rather than not completely initializing // the translation. dbAccess.SetSavePointOrBeginTrans(out sSavePointName); fNewTransaction = true; } try { trans = new CmTranslation(); TranslationsOC.Add(trans); trans.TypeRA = transType; } finally { if (suppressSubTasks != null) suppressSubTasks.Dispose(); } if (fNewTransaction) dbAccess.CommitTrans(); } return trans; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Inserts a Scriture annotation for the book currently being imported. /// </summary> /// <param name="bcvStartReference">The starting BCV reference.</param> /// <param name="bcvEndReference">The ending BCV reference.</param> /// <param name="obj">The object being annotated (either a paragraph or a IScrBook)</param> /// <param name="bldr">The paragraph builder containing the guts of the annotation /// description</param> /// <param name="guidNoteType">The GUID representing the CmAnnotationDefn to use for /// the type</param> /// <returns>The newly created annotation</returns> /// ------------------------------------------------------------------------------------ public IScrScriptureNote InsertNote(int bcvStartReference, int bcvEndReference, ICmObject obj, StTxtParaBldr bldr, Guid guidNoteType) { bool fOpenedTransaction = false; if (m_cache.DatabaseAccessor != null && !m_cache.DatabaseAccessor.IsTransactionOpen()) { fOpenedTransaction = true; m_cache.DatabaseAccessor.BeginTrans(); } try { IScrScriptureNote note = m_annotations.InsertImportedNote( bcvStartReference, bcvEndReference, obj, obj, guidNoteType, bldr); m_suppressor.Dispose(); m_suppressor = null; m_cache.ActionHandlerAccessor.AddAction(new UndoImportObjectAction(note)); if (fOpenedTransaction) m_cache.DatabaseAccessor.CommitTrans(); m_suppressor = new SuppressSubTasks(m_cache); return note; } catch { if (fOpenedTransaction) m_cache.DatabaseAccessor.RollbackTrans(); throw; } }
protected virtual void EnsureRealSegmentsForNonTrivialAnalyses(List<int> segments, int[] segmentsArray, int iseg, List<int> formsInSegment) { if (m_cache.IsDummyObject(segmentsArray[iseg]) && HasNonTrivialAnalysis(formsInSegment)) { using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(Cache, true)) { // replace the dummy segment with a real one. segmentsArray[iseg] = CmBaseAnnotation.ConvertBaseAnnotationToReal(Cache, segmentsArray[iseg]).Hvo; segments.RemoveAt(iseg); segments.Insert(iseg, segmentsArray[iseg]); } } }
private void Parse(IStTxtPara para, IMatcher matcher, ConcordanceControl.ConcordanceLines line, bool fUseRealData) { if (m_fSuppressSubTasks) { using (SuppressSubTasks suppressor = new SuppressSubTasks(para.Cache, true)) { ParseCore(para, matcher, line, fUseRealData); } } else { ParseCore(para, matcher, line, fUseRealData); } }
/// <summary> /// Takes the information from a dummy object and allows its owner to create a real object in the database. /// NOTE: after calling this, users need to make sure they no longer try to use the old hvoDummy object. /// </summary> /// <param name="fcCache"></param> /// <param name="hvoDummy">id corresponding to the object to convert. Minimally it should have a class id cached /// and an OwningFlid corresponding to a virtual handler that implements IDummyRequestConversion. </param> /// <returns>real object based on new database entry created for the dummy object, /// null if conversion did not take place.</returns> public static ICmObject ConvertDummyToReal(FdoCache fcCache, int hvoDummy) { // suppress changes in display. using (new IgnorePropChanged(fcCache, PropChangedHandling.SuppressView)) { // This conversion should not be an undoable task, so suppress the action handler. // (cf. LT-5330, LT-5417). using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(fcCache, true)) { ICmObject realObj = null; Debug.Assert(fcCache.IsDummyObject(hvoDummy)); if (fcCache.IsDummyObject(hvoDummy)) { // see if we can convert this to a real object before loading it. int owningFlid = fcCache.GetOwningFlidOfObject(hvoDummy); IVwVirtualHandler vh = fcCache.VwCacheDaAccessor.GetVirtualHandlerId(owningFlid); Debug.Assert(vh != null && vh is IDummyRequestConversion); if (vh != null && vh is IDummyRequestConversion) { RequestConversionToRealEventArgs args = new RequestConversionToRealEventArgs(hvoDummy, 0, null, true); args.OwningFlid = owningFlid; (vh as IDummyRequestConversion).OnRequestConversionToReal(hvoDummy, args); realObj = args.RealObject as ICmObject; } } return realObj; } } }
/// <summary> /// Move the sandbox to the annotation hvoAnnotation, currently analyzed as hvoAnalysis /// (which may be a WfiWordform, WfiAnalysis, or WfiGloss). /// </summary> /// <param name="hvoAnnotation"></param> /// <param name="hvoAnalysis"></param> /// <param name="fSaveGuess">if true, saves guesses; if false, skips guesses but still saves edits.</param> /// <param name="fMakeDefaultSelection">true to make the default selection within the /// new sandbox.</param> public virtual void TriggerAnnotationSelected(int hvoAnnotation, int hvoAnalysis, bool fSaveGuess, bool fMakeDefaultSelection) { // This can happen, though it is rare...see LT-8193. if (hvoAnnotation == 0) return; StTxtPara.TwficInfo twficInfo = new StTxtPara.TwficInfo(Cache, hvoAnnotation); if (!twficInfo.IsObjectValid()) { this.MessageBoxMasterRefresh(); return; } if (Cache.IsDummyObject(hvoAnnotation)) { // convert this to a real object. using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(Cache, true)) { int hvoAnnDummy = hvoAnnotation; CmBaseAnnotation realAnn = CmObject.ConvertDummyToReal(Cache, hvoAnnotation) as CmBaseAnnotation; hvoAnnotation = realAnn.Hvo; // re-cache items important to this view, without which some things like guesses may not appear // until after a refresh. TryCacheRealWordForm(hvoAnnotation); TryCacheLowercasedForm(hvoAnnotation); } } //if (hvoAnnotation != m_hvoAnnotation) //{ TryHideFocusBox(); Sandbox sandbox = ChangeOrCreateSandbox(hvoAnnotation, ref hvoAnalysis, fSaveGuess); FocusBox.InterlinWordControl = sandbox; if (!Controls.Contains(FocusBox)) Controls.Add(FocusBox); // Makes it real and may give it a root box. SetSandboxSize(); int hvoOldAnnotation = m_hvoAnnotation; HvoAnnotation = hvoAnnotation; m_hvoAnalysis = hvoAnalysis; SimulateReplaceAnnotation(hvoOldAnnotation); SimulateReplaceAnnotation(m_hvoAnnotation); MoveFocusBoxIntoPlace(); // Now it is the right size and place we can show it. TryShowFocusBox(); sandbox.Focus(); CheckForFreeOrLitAnnotations(MakeSandboxSel()); if (m_fCanAddFreeTrans) { // add a free translation for this segment, // but don't change the selection from the sandbox. AddFreeTrans(false); } if (fMakeDefaultSelection) FocusBox.InterlinWordControl.MakeDefaultSelection(); //} if (AnnnotationSelected != null) AnnnotationSelected(this, new AnnotationSelectedArgs(hvoAnnotation, hvoAnalysis)); }
internal static List<int> ConcordParagraphs(FdoCache cache, int[] hvosStTxtPara, ProgressState progress, IMatcher matcher, ConcordanceControl.ConcordanceLines line) { using (ParagraphParser pp = new ParagraphParser(cache)) { // this will effectively clear ConcordanceWordforms, which seems overkill, but // since we are changing the occurrences on those wordforms, // and also possibly adding many new wordforms, we should just allow RecordLists that use // ConcordanceWordforms to reload the list. // (Enhance: is there any way we can make those lists be smart about when they need to reload, // rather than forcing them to?) (pp.m_wfi as WordformInventory).SuspendUpdatingConcordanceWordforms = true; pp.CreateDummyWordforms = true; pp.m_hvosStTxtPara = hvosStTxtPara; if (matcher != null) pp.m_matchingAnnotations = new List<int>(); ParagraphParser.ResetParseSessionDependentStaticData(); // Estimate the number of total number of milestones we'll set. // Enhance: we could construct a way to set percentage done based upon // number of texts and paragraphs in each text. if (progress is MilestoneProgressState) { MilestoneProgressState mp = progress as SIL.FieldWorks.Common.Controls.MilestoneProgressState; for (int i = 0; i < pp.m_hvosStTxtPara.Length; ++i) { mp.AddMilestone(1); } } // Preload all the paragraphs. cache.PreloadIfMissing(hvosStTxtPara, (int)StTxtPara.StTxtParaTags.kflidContents, 0, false); // Parse each text to load our paragraph and wordform segment annotations. int cPara = 0; using (SuppressSubTasks suppressor = new SuppressSubTasks(cache, true)) { foreach (IStTxtPara para in new FdoObjectSet<IStTxtPara>(cache, pp.m_hvosStTxtPara, false)) { ++cPara; pp.Parse(para, matcher, line); progress.SetMilestone(); progress.Breath(); if (pp.m_matchingAnnotations != null && pp.m_matchingAnnotations.Count >= ConcordanceControl.MaxConcordanceMatches()) { MessageBox.Show(String.Format(ITextStrings.ksShowingOnlyTheFirstXXXMatches, pp.m_matchingAnnotations.Count, cPara, pp.m_hvosStTxtPara.Length), ITextStrings.ksNotice, MessageBoxButtons.OK, MessageBoxIcon.Information); break; } } pp.CleanupLeftoverAnnotations(progress); } progress.SetMilestone(); progress.Breath(); (pp.m_wfi as WordformInventory).SuspendUpdatingConcordanceWordforms = false; return pp.m_matchingAnnotations; } }
/// <summary> /// /// </summary> /// <param name="fdoCache"></param> /// <param name="dummyAnnHvo"></param> /// <returns></returns> public static ICmBaseAnnotation ConvertBaseAnnotationToReal(FdoCache fdoCache, int dummyAnnHvo) { using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(fdoCache, true)) { Debug.Assert(fdoCache.IsDummyObject(dummyAnnHvo)); if (!fdoCache.IsDummyObject(dummyAnnHvo) || fdoCache.GetClassOfObject(dummyAnnHvo) != CmBaseAnnotation.kclsidCmBaseAnnotation) { return null; // indicate no change. } ISilDataAccess sda = fdoCache.MainCacheAccessor; ICmBaseAnnotation cbaDummy = (ICmBaseAnnotation)CmObject.CreateFromDBObject(fdoCache, dummyAnnHvo, false); ICmBaseAnnotation cbaReal = CreateRealAnnotation(fdoCache, cbaDummy.AnnotationTypeRAHvo, cbaDummy.InstanceOfRAHvo, cbaDummy.BeginObjectRAHvo, cbaDummy.Flid, cbaDummy.BeginOffset, cbaDummy.EndOffset); cbaReal.WritingSystemRAHvo = cbaDummy.WritingSystemRAHvo; int hvoRealAnn = cbaReal.Hvo; // transfer any default analysis (guess) int ktagTwficDefault = StTxtPara.TwficDefaultFlid(fdoCache); int hvoTwficAnalysisGuess = fdoCache.GetObjProperty(dummyAnnHvo, ktagTwficDefault); if (hvoTwficAnalysisGuess != 0) { fdoCache.VwCacheDaAccessor.CacheObjProp(hvoRealAnn, ktagTwficDefault, hvoTwficAnalysisGuess); } int textSegType = CmAnnotationDefn.TextSegment(fdoCache).Hvo; int twficType = CmAnnotationDefn.Twfic(fdoCache).Hvo; if (cbaDummy.AnnotationTypeRAHvo == twficType) StTxtPara.CacheReplaceTWFICAnnotation(fdoCache, dummyAnnHvo, hvoRealAnn); else if (cbaDummy.AnnotationTypeRAHvo == textSegType) StTxtPara.CacheReplaceTextSegmentAnnotation(fdoCache, dummyAnnHvo, hvoRealAnn); else Debug.Assert(true, "CacheReplace does not yet support annotation type " + cbaDummy.AnnotationTypeRAHvo); // now clear it from the cache, since we're done with it. if (fdoCache.ActionHandlerAccessor != null) fdoCache.ActionHandlerAccessor.AddAction(new ClearInfoOnCommitUndoAction(fdoCache, dummyAnnHvo)); return cbaReal; } }
private void ParseWithOptions(IStTxtPara para, ParagraphParserOptions options) { m_fSuppressSubTasks = options.SuppressSubTasks; m_fCreateRealSegments = options.CreateRealSegments; if (options.SuppressSubTasks) { using (SuppressSubTasks suppressor = new SuppressSubTasks(Cache, true)) { ParseWithOptionsCore(para, options); } } else { ParseWithOptionsCore(para, options); } }
/// <summary> /// Add the specified type of freeform annotation to the given segment. /// Undoable by default. /// </summary> /// <param name="hvoSeg"></param> /// <param name="hvoType">freeform annotation type</param> /// <returns></returns> public ICmIndirectAnnotation AddFreeformAnnotation(int hvoSeg, int hvoType) { using (SuppressSubTasks suppressor = new SuppressSubTasks(m_fdoCache, true)) { // convert any preceeding dummy segments, so paragraph parser does not push this to the first dummy sentence. (LT-7318) int hvoPara = m_fdoCache.GetObjProperty(hvoSeg, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject); StTxtPara para = StTxtPara.CreateFromDBObject(m_fdoCache, hvoPara) as StTxtPara; para.EnsurePreceedingSegmentsAreReal(hvoSeg); string undoString = ""; string redoString = ""; if (hvoType == ktagSegFF_freeTranslation) { undoString = ITextStrings.ksUndoAddFreeformTranslation; redoString = ITextStrings.ksRedoAddFreeformTranslation; } else if (hvoType == ktagSegFF_literalTranslation) { undoString = ITextStrings.ksUndoAddLiteralTranslation; redoString = ITextStrings.ksRedoAddLiteralTranslation; } else if (hvoType == ktagSegFF_note) { undoString = ITextStrings.ksUndoAddNote; redoString = ITextStrings.ksRedoAddNote; } else { throw new ArgumentException(String.Format("segment freeform type {0} is not yet supported here.", hvoType)); } ICmIndirectAnnotation ann; m_fdoCache.BeginUndoTask(undoString, redoString); { ann = CmIndirectAnnotation.CreateUnownedIndirectAnnotation(m_fdoCache); ann.AppliesToRS.Append(hvoSeg); ann.AnnotationTypeRAHvo = hvoType; // Add it to the cached collection of freeform annotations. This is a bit clumsy because // it isn't a real property so we can't just use the normal methods for modifying a property. // Enhance JohnT: put it with the other ones of the same type. ISilDataAccess sda = m_fdoCache.MainCacheAccessor; IVwCacheDa cda = (IVwCacheDa)sda; int cFreeForm = sda.get_VecSize(hvoSeg, ktagSegFF); int[] freeForms = new int[cFreeForm + 1]; for (int i = 0; i < cFreeForm; i++) freeForms[i] = sda.get_VecItem(hvoSeg, ktagSegFF, i); freeForms[cFreeForm] = ann.Hvo; cda.CacheVecProp(hvoSeg, ktagSegFF, freeForms, cFreeForm + 1); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoSeg, ktagSegFF, cFreeForm, 1, 0); } m_fdoCache.EndUndoTask(); return ann; } }
public static bool ParseText(IStText text, ParagraphParserOptions options, ProgressState progress, out bool fDidParse) { fDidParse = false; if (text == null || !text.IsValidObject()) return false; if (text.ParagraphsOS.Count == 0) return false; #if DEBUG //TimeRecorder.Begin("deciding whether to parse para"); #endif if (text.IsUpToDate()) return true; #if DEBUG //TimeRecorder.End("deciding whether to parse para"); #endif fDidParse = true; // we're going to parse! #if DEBUG //TimeRecorder.Begin("parse text"); #endif if (progress is MilestoneProgressState) { MilestoneProgressState mp = progress as SIL.FieldWorks.Common.Controls.MilestoneProgressState; AddParseTextMilestones(mp); } // Reparsing a whole text, words may have moved from one paragraph to another. // Do the whole with a single ParagraphParser. #if DEBUG //TimeRecorder.Begin("setup"); #endif ParagraphParser.ResetParseSessionDependentStaticData(); WordformInventory wfi = (text.Cache.LangProject.WordformInventoryOA as WordformInventory); if (options.SuppressSubTasks) { using (SuppressSubTasks suppressor = new SuppressSubTasks(text.Cache, true)) { ParseTextCore(text, options, progress); } } else { ParseTextCore(text, options, progress); } return true; // succeeded. #if DEBUG //TimeRecorder.End("note parse times"); //TimeRecorder.Report(); #endif }
/// <summary> /// /// </summary> /// <param name="owningFlid"></param> /// <param name="hvoDummy"></param> /// <returns></returns> public ICmObject ConvertDummyToReal(int owningFlid, int hvoDummy) { using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(Cache, true)) { ICmObject realObj = null; if (owningFlid == OccurrencesFlid(Cache)) { realObj = CmBaseAnnotation.ConvertBaseAnnotationToReal(Cache, hvoDummy); } else { throw new Exception("The method or operation is not implemented."); } return realObj; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Check scripture annotations for titles and introductions to make sure they point to /// paragraphs in the current version of books. This will ensure that they are included /// at the proper location in the export. /// </summary> /// ------------------------------------------------------------------------------------ private void AdjustScriptureAnnotations() { using (SuppressSubTasks suppressor = new SuppressSubTasks(Cache)) { ((Scripture)m_scr).AdjustAnnotationReferences(); } }