internal int EnqueuePagesForTagging(TagOperation op) { // bring suggestions up-to-date with new tags that may have been entered TagSuggestions.AddAll(from t in _pageTags where !TagSuggestions.ContainsKey(t.Key) select new HitHighlightedTagButtonModel() { TagName = t.TagName }); TagSuggestions.Save(); // covert scope to context TagContext ctx; switch (Scope) { default: case TaggingScope.CurrentNote: ctx = TagContext.CurrentNote; break; case TaggingScope.SelectedNotes: ctx = TagContext.SelectedNotes; break; case TaggingScope.CurrentSection: ctx = TagContext.CurrentSection; break; } IEnumerable <string> pageIDs = null; if (ScopesEnabled) { TagsAndPages tc = new TagsAndPages(OneNoteApp); tc.LoadPageTags(ctx); pageIDs = tc.Pages.Select(p => p.Key); } else { pageIDs = PagesToTag; } int enqueuedPages = 0; string[] pageTags = (from t in _pageTags.Values select t.TagName).ToArray(); foreach (string pageID in pageIDs) { OneNoteApp.TaggingService.Add(new TaggingJob(pageID, pageTags, op)); enqueuedPages++; } TraceLogger.Log(TraceCategory.Info(), "{0} page(s) enqueued for tagging with '{1}' using {2}", enqueuedPages, string.Join(";", pageTags), op); TraceLogger.Flush(); return(enqueuedPages); }
/// <summary> /// Extract tags from page descriptors. /// </summary> /// <param name="pageDescriptors"> /// XML document describing pages in the OneNote hierarchy or search result. /// </param> /// <param name="selectedPagesOnly">true to process only pages selected by user</param> /// <param name="omitUntaggedPages">drip untagged pages</param> internal void ExtractTags(XDocument pageDescriptors, bool selectedPagesOnly, bool omitUntaggedPages = false) { // parse the search results _tags.Clear(); _pages.Clear(); try { XNamespace one = pageDescriptors.Root.GetNamespaceOfPrefix("one"); Dictionary <string, TagPageSet> tags = new Dictionary <string, TagPageSet>(); foreach (XElement page in pageDescriptors.Descendants(one.GetName("Page"))) { TaggedPage tp = new TaggedPage(page); if (selectedPagesOnly && !tp.IsSelected) { continue; } // assign Tags int tagcount = 0; foreach (string tagname in tp.TagNames) { tagcount++; TagPageSet t; if (!tags.TryGetValue(tagname, out t)) { t = new TagPageSet(tagname); tags.Add(tagname, t); } t.AddPage(tp); tp.Tags.Add(t); } if (!omitUntaggedPages || tagcount > 0) { _pages.Add(tp.Key, tp); } } // bulk update for performance reasons _tags.UnionWith(tags.Values); TraceLogger.Log(TraceCategory.Info(), "Extracted {0} tags from {1} pages.", _tags.Count, _pages.Count); } catch (Exception ex) { TraceLogger.Log(TraceCategory.Error(), "Parsing Hierarchy data failed: {0}", ex); TraceLogger.Flush(); } }
/// <summary> /// Run the background tagger. /// </summary> /// <returns></returns> public Task Run() { TaskFactory tf = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None); CancellationToken cancel = _cancel.Token; return(tf.StartNew(() => { TraceLogger.Log(TraceCategory.Info(), "Background tagging service started"); try { OneNotePageProxy lastPage = null; while (!_jobs.IsCompleted) { TaggingJob j = _jobs.Take(); cancel.ThrowIfCancellationRequested(); try { lastPage = j.Execute(_onenote, lastPage); if (lastPage != null && _jobs.Count == 0) { // no more pending pages - must update the last one and stop carrying forward lastPage.Update(); lastPage = null; } } catch (Exception e) { lastPage = null; TraceLogger.ShowGenericErrorBox("page tagging failed", e); } } } catch (InvalidOperationException) { TraceLogger.Log(TraceCategory.Warning(), "Background tagging job queue depleted"); TraceLogger.Flush(); } catch (OperationCanceledException) { TraceLogger.Log(TraceCategory.Warning(), "Background tagging canceled"); TraceLogger.Flush(); } }, cancel)); }
/// <summary> /// Remove or rename tag from suggestions when user control is tapped. /// </summary> /// <param name="sender">user control emitting this event</param> /// <param name="e"> event details</param> private void Tag_Action(object sender, RoutedEventArgs e) { var rt = sender as RemovableTag; var rt_mdl = rt.DataContext as RemovableTagModel; string[] toRemove = new string[] { rt_mdl.Key }; if ("DeleteTag".Equals(rt.Tag)) { _model.SuggestedTags.RemoveAll(toRemove); // schedule all pages with this tag for tag removal if (rt_mdl.Tag != null) { foreach (var tp in rt_mdl.Tag.Pages) { _model.OneNoteApp.TaggingService.Add(new TaggingJob(tp.ID, toRemove, TagOperation.SUBTRACT)); } suggestedTags.Notification = rt_mdl.Tag.Pages.Count == 0 ? Properties.Resources.TagEditor_Popup_NothingTagged : string.Format(Properties.Resources.TagEditor_Popup_TaggingInProgress, rt_mdl.Tag.Pages.Count); TraceLogger.Log(TraceCategory.Info(), "{0} page(s) enqueued for background tagging; Operation SUBTRACT {1}", rt_mdl.Tag.Pages.Count, toRemove[0]); } else { suggestedTags.Notification = Properties.Resources.TagEditor_Popup_NothingTagged; } } else if ("RenameTag".Equals(rt.Tag)) { _model.SuggestedTags.RemoveAll(toRemove); string[] newTagNames = (from tn in OneNotePageProxy.ParseTags(rt_mdl.LocalName) select TagFormatter.Format(tn)).ToArray(); // create new tag models unless they already exist List <RemovableTagModel> newTagModels = new List <RemovableTagModel>(); foreach (var newName in newTagNames) { RemovableTagModel tagmodel; if (!_model.SuggestedTags.TryGetValue(newName, out tagmodel)) { tagmodel = new RemovableTagModel() { Tag = new TagPageSet(newName) }; newTagModels.Add(tagmodel); } else if (tagmodel.Tag == null && rt_mdl.Tag != null) { tagmodel.Tag = new TagPageSet(newName); } if (rt_mdl.Tag != null) { // copy the pages into the new tag and update the tag count foreach (var pg in rt_mdl.Tag.Pages) { tagmodel.Tag.Pages.Add(pg); } tagmodel.UseCount = tagmodel.Tag.Pages.Count; } } _model.SuggestedTags.AddAll(newTagModels); if (rt_mdl.Tag != null) { // remove the old tag and add new tag to the pages foreach (var tp in rt_mdl.Tag.Pages) { _model.OneNoteApp.TaggingService.Add(new TaggingJob(tp.ID, toRemove, TagOperation.SUBTRACT)); _model.OneNoteApp.TaggingService.Add(new TaggingJob(tp.ID, newTagNames, TagOperation.UNITE)); } suggestedTags.Notification = rt_mdl.Tag.Pages.Count == 0 ? Properties.Resources.TagEditor_Popup_NothingTagged : string.Format(Properties.Resources.TagEditor_Popup_TaggingInProgress, rt_mdl.Tag.Pages.Count); TraceLogger.Log(TraceCategory.Info(), "{0} page(s) enqueued for background tagging; Operation UNITE {1} SUBTRACT {2}", rt_mdl.Tag.Pages.Count, string.Join(",", newTagNames), toRemove[0]); } else { suggestedTags.Notification = Properties.Resources.TagEditor_Popup_NothingTagged; } } TraceLogger.Flush(); _model.SaveChanges(); }