private void Rebuild() { WPFDoEvents.AssertThisCodeIsRunningInTheUIThread(); ObjDocumentViewer.Document = null; ObjTooManyAnnotationsButton.Visibility = Visibility.Collapsed; AugmentedBindable <PDFDocument> pdf_document_bindable = DataContext as AugmentedBindable <PDFDocument>; if (null != pdf_document_bindable) { PDFDocument pdf_document = pdf_document_bindable.Underlying; SafeThreadPool.QueueUserWorkItem(o => { // TODO: [GHo] what are these 'heuristic' conditions good for?!?! if (pdf_document.GetAnnotations().Count > 50 || pdf_document.Highlights.Count > 1000) { WPFDoEvents.InvokeAsyncInUIThread(() => { ObjTooManyAnnotationsButton.Visibility = Visibility.Visible; ObjTooManyAnnotationsButton.Tag = pdf_document; }); } else { PopulateWithAnnotationReport(pdf_document); } }); } }
private static void DoPostUpgrade() { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); // NB NB NB NB: You CANT USE ANYTHING IN THE USER CONFIG AT THIS POINT - it is not yet decided until LOGIN has completed... WPFDoEvents.InvokeInUIThread(() => { StatusManager.Instance.UpdateStatus("AppStart", "Loading themes"); Theme.Initialize(); DualTabbedLayout.GetWindowOverride = delegate() { return(new StandardWindow()); }; // Force tooltips to stay open ToolTipService.ShowDurationProperty.OverrideMetadata(typeof(DependencyObject), new FrameworkPropertyMetadata(3600000)); }); // Make sure the data directories exist... if (!Directory.Exists(ConfigurationManager.Instance.BaseDirectoryForUser)) { Directory.CreateDirectory(ConfigurationManager.Instance.BaseDirectoryForUser); } // and kick off the Login Dialog to start the application proper: WPFDoEvents.InvokeAsyncInUIThread(() => ShowLoginDialog()); // NB NB NB NB: You CANT USE ANYTHING IN THE USER CONFIG AT THIS POINT - it is not yet decided until LOGIN has completed... }
private void MenuForgetLegacyAnnotations_Click(object sender, RoutedEventArgs e) { popup.Close(); SafeThreadPool.QueueUserWorkItem(o => { FeatureTrackingManager.Instance.UseFeature(Features.Library_ForgetLegacyAnnotations); foreach (var pdf_document in pdf_documents) { try { LegacyAnnotationConvertor.ForgetLegacyAnnotations(pdf_document); } catch (Exception ex) { Logging.Error(ex, "Error while forgetting legacy annotations."); } } WPFDoEvents.InvokeAsyncInUIThread(() => { MessageBoxes.Info("Legacy annotations removed."); }); }); }
private static void DoInterestingAnalysis_GoogleScholar(PDFReadingControl pdf_reading_control, PDFDocument pdf_document) { bool attempt_scrape = Qiqqa.Common.Configuration.ConfigurationManager.Instance.ConfigurationRecord.GoogleScholar_DoExtraBackgroundQueries; if (attempt_scrape) { Logging.Info("You are accessing Google Scholar in the background as you have the 'Send extra background queries to Google Scholar' Configuration option ticked. Be aware that this can lead to a quick denial of service response by Google in the form of a 40x HTTP Error or RECAPTCHA page instead of the search response you seek! Also refer to GitHub issues #225 & #113."); // Get the GoogleScholar similar documents try { string title = pdf_document.TitleCombined; if (Constants.TITLE_UNKNOWN != title) { GoogleScholarScrapePaperSet gssp_set = GoogleScholarScrapePaperSet.GenerateFromQuery(title, 10); WPFDoEvents.InvokeAsyncInUIThread(() => { pdf_reading_control?.SimilarDocsControl.SpecifyPaperSet(gssp_set); }); } else { Logging.Info("We don't have a title, so skipping GoogleScholar similar documents"); } } catch (Exception ex) { Logging.Error(ex, "There was a problem getting the GoogleScholar similar documents for document {0}", pdf_document.Fingerprint); } } }
private void word_connector_ContextChanged_BACKGROUND_FindRecommendations() { while (true) { // Get the next context to search for, and if there is none, then exit the background thread string context; // Utilities.LockPerfTimer l1_clk = Utilities.LockPerfChecker.Start(); lock (context_thread_lock) { // l1_clk.LockPerfTimerStop(); context = context_thread_next_context; context_thread_next_context = null; if (null == context) { context_thread_running = false; break; } } // Now that we have the context, do the query List <PDFDocument> context_pdf_documents = new List <PDFDocument>(); { WebLibraryDetail web_library_detail = this.default_library; if (null != web_library_detail) { string context_search_string = PolishContextForLucene(context); context_search_string = context_search_string.Trim(); if (!String.IsNullOrEmpty(context_search_string)) { List <IndexResult> fingerprints = LibrarySearcher.FindAllFingerprintsMatchingQuery(web_library_detail, context_search_string); if (null != fingerprints && 0 != fingerprints.Count) { foreach (var fingerprint in fingerprints) { if (20 <= context_pdf_documents.Count) { break; } PDFDocument pdf_document = web_library_detail.Xlibrary.GetDocumentByFingerprint(fingerprint.fingerprint); if (null != pdf_document) { context_pdf_documents.Add(pdf_document); } } } } } } // And get the GUI to update with the results WPFDoEvents.InvokeAsyncInUIThread(() => { word_connector_ContextChanged_BACKGROUND_PopulateRecommendations(context_pdf_documents); }, DispatcherPriority.Background); } }
public void Download(object obj) { WPFDoEvents.InvokeAsyncInUIThread(() => { MainWindowServiceDispatcher.Instance.ShowBundleLibraryJoiningControl(manifest_latest); } ); }
private void ipc_server_IPCServerMessage(string message) { WPFDoEvents.InvokeAsyncInUIThread(() => { MainWindowServiceDispatcher.Instance.ProcessCommandLineFile(message); } ); }
public static void Popup() { FeatureTrackingManager.Instance.UseFeature(Features.InCite_OpenPopup); WPFDoEvents.InvokeAsyncInUIThread(() => { Popup_DISPATCHER(); } ); }
private void word_connector_CitationClusterChanged(CitationCluster context_citation_cluster) { Logging.Debug特("InCite: CitationClusterChanged: {0}", context_citation_cluster); WPFDoEvents.InvokeAsyncInUIThread(() => { ObjCitationClusterEditorControl.SetCitationCluster(context_citation_cluster); } ); }
private void NotifySceneRenderingControl() { WPFDoEvents.InvokeAsyncInUIThread(() => { SceneRenderingControl scene_rendering_control = SceneRenderingControl; if (scene_rendering_control != null) { scene_rendering_control.RecalculateAllNodeControlDimensions(); } }, DispatcherPriority.Background); }
public RegionWebLibraries() { InitializeComponent(); ObjWebLibraryListControl.OnWebLibrarySelected += ObjWebLibraryListControl_OnWebLibrarySelected; SafeThreadPool.QueueUserWorkItem(o => { // This particular action would BLOCK a very long time on `WebLibraryManager.Instance` as another background // task is busy loading all libraries as part of the WebLibraryManager initialization. WebLibraryManager.Instance.WebLibrariesChanged += Instance_WebLibrariesChanged; WPFDoEvents.InvokeAsyncInUIThread(() => Refresh()); }); }
private void RepopulatePanels() { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); var outbound = pdf_document.PDFDocumentCitationManager.GetOutboundCitations(); var inbound = pdf_document.PDFDocumentCitationManager.GetInboundCitations(); WPFDoEvents.InvokeAsyncInUIThread(() => { WPFDoEvents.AssertThisCodeIsRunningInTheUIThread(); PopulatePanelWithCitations(DocsPanel_Outbound, pdf_document, outbound, Features.Citations_OpenDoc); PopulatePanelWithCitations(DocsPanel_Inbound, pdf_document, inbound, Features.Citations_OpenDoc); }); }
private static void DoInterestingAnalysis_SimilarAuthors(PDFReadingControl pdf_reading_control, PDFDocument pdf_document) { // Populate the similar authors try { List <NameTools.Name> authors = SimilarAuthors.GetAuthorsForPDFDocument(pdf_document); MultiMap <string, PDFDocument> authors_documents = SimilarAuthors.GetDocumentsBySameAuthors(pdf_document.LibraryRef, pdf_document, authors); WPFDoEvents.InvokeAsyncInUIThread(() => { pdf_reading_control.SimilarAuthorsControl.SetItems(authors_documents); }); } catch (Exception ex) { Logging.Error(ex, "There was a problem creating the tag cloud for document {0}", pdf_document.Fingerprint); } }
private static void DoInterestingAnalysis_TagCloud(PDFReadingControl pdf_reading_control, PDFDocument pdf_document) { // Populate the tag cloud try { List <TagCloudEntry> tag_cloud_entries = PDFDocumentTagCloudBuilder.BuildTagCloud(pdf_document.LibraryRef, pdf_document); WPFDoEvents.InvokeAsyncInUIThread(() => { pdf_reading_control.TagCloud.SpecifyEntries(tag_cloud_entries); }); } catch (Exception ex) { Logging.Error(ex, "There was a problem creating the tag cloud for document {0}", pdf_document.Fingerprint); } }
public void SetPDFDocument(PDFDocument doc) { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); pdf_document = doc; WPFDoEvents.InvokeAsyncInUIThread(() => { ObjPDFDocuments.ItemsSource = null; string query = ObjSearchBox.Text; SafeThreadPool.QueueUserWorkItem(o => { ReSearch(doc, query); RepopulatePanels(doc); }); }); }
private void StatusManager_OnStatusEntryUpdate(StatusManager.StatusEntry status_entry) { bool do_invoke = false; //Utilities.LockPerfTimer l1_clk = Utilities.LockPerfChecker.Start(); lock (status_entries_still_to_process_lock) { //l1_clk.LockPerfTimerStop(); status_entries_still_to_process[status_entry.key] = status_entry; if (!status_entries_still_to_process_fresh_thread_running) { status_entries_still_to_process_fresh_thread_running = true; do_invoke = true; } } if (do_invoke) { WPFDoEvents.InvokeAsyncInUIThread(() => StatusManager_OnStatusEntryUpdate_GUI(), DispatcherPriority.Background); } }
private void word_connector_ContextChanged(string context_word, string context_backward, string context_surround) { Logging.Debug特("InCite: ContextChanged"); WPFDoEvents.InvokeAsyncInUIThread(() => { word_connector_ContextChanged_BACKGROUND_UpdateButtonEnabledness(context_word, context_backward, context_surround); }, DispatcherPriority.Background); // Utilities.LockPerfTimer l1_clk = Utilities.LockPerfChecker.Start(); lock (context_thread_lock) { // l1_clk.LockPerfTimerStop(); context_thread_next_context = context_backward; if (!context_thread_running) { context_thread_running = true; SafeThreadPool.QueueUserWorkItem(o => word_connector_ContextChanged_BACKGROUND_FindRecommendations()); } } }
public void RebuildVisual() { WPFDoEvents.AssertThisCodeIsRunningInTheUIThread(); //Logging.Info("+HighlightsRenderer RebuildVisual() on page {0}", page); if (null == pdf_document) { Source = null; return; } if (double.IsNaN(Width) || double.IsNaN(Height)) { Source = null; return; } // We use a smaller image than necessary as we do not need high resolution to represent the highlights double scaled_capped_width = Math.Min(Width, 300); double scaled_capped_height = Height * scaled_capped_width / Width; SafeThreadPool.QueueUserWorkItem(o => { BitmapSource bmp; using (Bitmap raster_bitmap = PDFOverlayRenderer.RenderHighlights((int)scaled_capped_width, (int)scaled_capped_height, pdf_document, page)) { bmp = BitmapImageTools.FromBitmap(raster_bitmap); } WPFDoEvents.InvokeAsyncInUIThread(() => { Source = bmp; }); //Logging.Info("-HighlightsRenderer RebuildVisual() on page {0}", page); }); }
private void drag_area_tracker_OnDragComplete(bool button_left_pressed, bool button_right_pressed, Point mouse_down_point, Point mouse_up_point) { FeatureTrackingManager.Instance.UseFeature(Features.Document_Camera); double width_page = Math.Abs(mouse_up_point.X - mouse_down_point.X); double height_page = Math.Abs(mouse_up_point.Y - mouse_down_point.Y); if (3 <= width_page && 3 <= height_page) { DocPageInfo page_info = new DocPageInfo { pdf_document = @pdf_document, page = @page, ActualHeight = @ActualHeight, ActualWidth = @ActualWidth }; SafeThreadPool.QueueUserWorkItem(o => { // GetSnappedImage() invokes the background renderer, hence run it in a background thread itself: BitmapSource image = GetSnappedImage(page_info, mouse_up_point, mouse_down_point); List <Word> words = GetSnappedWords(page_info, mouse_up_point, mouse_down_point); string raw_text = SelectedWordsToFormattedTextConvertor.ConvertToParagraph(words); string tabled_text = SelectedWordsToFormattedTextConvertor.ConvertToTable(words); WPFDoEvents.InvokeAsyncInUIThread(() => { CameraActionChooserDialog cacd = new CameraActionChooserDialog(); cacd.SetLovelyDetails(image, raw_text, tabled_text); cacd.ShowDialog(); }); }); } else { Logging.Info("Region too small to screen grab"); } }
private void library_OnDocumentsChanged() { WPFDoEvents.InvokeAsyncInUIThread(() => UpdateLibraryStatistics()); }
private void BackgroundThread(object arg) { Daemon daemon = (Daemon)arg; try { // NOTE: while one might wonder why `playing` is not protected by a lock, while it // is used by two threads: this is by design. // // `playing` is only ever changed by a single thread (Main) and any temporary collision // between reading `playing` while the boolean is being changed by the main thread // is NOT A PROBLEM. // Yes, an Exception MAY be thrown then, but we have to reckon with failures inside // the loop anyway (https://github.com/jimmejardine/qiqqa-open-source/issues/42) as // the `playing = false` STOP instruction MAY occur while Dispose()-ing this class // instance: *that* action MAY very well happen while we're *somewhere* inside the // play loop executing stuff... which will surely CRASH with an Exception, e.g. // https://github.com/jimmejardine/qiqqa-open-source/issues/42 // hence we NEED the Exception handling anyway and any unsafe checking of `playing` // is but one potential failure mode, all of whom will be correctly caught by the // outer `try...catch`, hence no critical section lock coding effort for `playing`: while (playing) { int current_wpm = 0; // Interrogate the GUI WPFDoEvents.InvokeInUIThread(() => { current_wpm = (int)SliderWPM.Value; } ); // Sleep a bit to reflect the WPM int sleep_time_ms = (60 * 1000 / (current_wpm + 1)); daemon.Sleep(sleep_time_ms); int current_position = 0; int current_maximum = 0; // Interrogate the GUI WPFDoEvents.InvokeAsyncInUIThread(() => { current_position = (int)SliderLocation.Value; current_maximum = (int)SliderLocation.Maximum; } ); // Can we move onto the next word? if (current_position < current_maximum) { string current_word = words[current_position]; string current_word_left = ""; string current_word_right = ""; for (int i = 1; i <= 3; ++i) { if (current_position - i >= 0 && current_position - i < words.Count) { current_word_left += words[current_position - i] + " "; } if (current_position + i >= 0 && current_position + i < words.Count) { current_word_right += " " + words[current_position + i]; } } ++current_position; WPFDoEvents.InvokeAsyncInUIThread(() => { SliderLocation.Value = current_position; TextCurrentWord.Text = current_word; TextCurrentWordLeft.Text = current_word_left; TextCurrentWordRight.Text = current_word_right; } ); } else { WPFDoEvents.InvokeAsyncInUIThread(() => { TogglePlayPause(force_stop: true); } ); } } } catch (Exception ex) { // all sorts of nasty stuff can happen. If it happens while `Dispose()` // was invoked on the mainline, it's hunky-dory. So we merely rate this // DEBUG level diagnostics. Logging.Debug特(ex, "VERY PROBABLY HARMLESS AND EXPECTED crash in SpeedReader: if you just closed/quit the panel, this is due to Dispose() invocation in the Main thread and expected behaviour."); } }
private static void BackgroundRenderImages_BACKGROUND(FlowDocument flow_document, List <AnnotationWorkGenerator.AnnotationWork> annotation_works, AnnotationReportOptions annotation_report_options) { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); ShutdownableManager.Sleep(annotation_report_options.InitialRenderDelayMilliseconds); PDFDocument last_pdf_document = null; StatusManager.Instance.ClearCancelled("AnnotationReportBackground"); for (int j = 0; j < annotation_works.Count; ++j) { if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Error("Canceling creation of Annotation Report due to signaled application shutdown"); StatusManager.Instance.SetCancelled("AnnotationReportBackground"); } StatusManager.Instance.UpdateStatus("AnnotationReportBackground", "Building annotation report image", j, annotation_works.Count, true); if (StatusManager.Instance.IsCancelled("AnnotationReportBackground")) { Logging.Warn("User canceled annotation report generation"); break; } AnnotationWorkGenerator.AnnotationWork annotation_work = annotation_works[j]; PDFDocument pdf_document = annotation_work.pdf_document; // Clear down our previously caches pages if (null != last_pdf_document && last_pdf_document != pdf_document) { if (last_pdf_document.DocumentExists) { last_pdf_document.FlushCachedPageRenderings(); } } // Remember this PDF document so we can flush it if necessary last_pdf_document = pdf_document; // Now render each image PDFAnnotation pdf_annotation = annotation_work.pdf_annotation; if (null != pdf_annotation) { try { // Clear the waiting for processing text WPFDoEvents.InvokeAsyncInUIThread(() => { annotation_work.processing_error.Text = ""; }); if (pdf_document.DocumentExists) { // Fill in the paragraph text if (null != annotation_work.annotation_paragraph) { WPFDoEvents.InvokeAsyncInUIThread(() => { BuildAnnotationWork_FillAnnotationText(pdf_document, pdf_annotation, annotation_work); }); } if (null != annotation_work.report_floater) { try { System.Drawing.Image annotation_image = PDFAnnotationToImageRenderer.RenderAnnotation(pdf_document, pdf_annotation, 80); BitmapSource cropped_image_page = BitmapImageTools.FromImage(annotation_image); WPFDoEvents.InvokeAsyncInUIThread(() => { annotation_work.report_image.Source = cropped_image_page; annotation_work.report_floater.Width = new FigureLength(cropped_image_page.PixelWidth / 1); }); } catch (Exception ex) { Logging.Warn(ex, "There was a problem while rendering an annotation."); WPFDoEvents.InvokeAsyncInUIThread(() => { annotation_work.report_image.Source = Icons.GetAppIcon(Icons.AnnotationReportImageError); annotation_work.processing_error.Text = "There was a problem while rendering this annotation."; }); } } } else { WPFDoEvents.InvokeAsyncInUIThread(() => { if (null != annotation_work.report_image) { annotation_work.report_image.Source = Icons.GetAppIcon(Icons.AnnotationReportImageError); } annotation_work.processing_error.Text = "Can't show image: The PDF does not exist locally."; }); } } catch (Exception ex) { Logging.Error(ex, "There was an error while rendering page {0} for document {1} for the annotation report", pdf_annotation.Page, pdf_annotation.DocumentFingerprint); WPFDoEvents.InvokeAsyncInUIThread(() => { if (null != annotation_work.report_image) { annotation_work.report_image.Source = Icons.GetAppIcon(Icons.AnnotationReportImageError); } annotation_work.processing_error.Text = "Can't show image: There was an error rendering the metadata image."; }); } } } // And flush the rendering cache of the last document if (null != last_pdf_document) { if (last_pdf_document.DocumentExists) { last_pdf_document.FlushCachedPageRenderings(); } } StatusManager.Instance.ClearStatus("AnnotationReportBackground"); }
private void UpdateLibraryStatistics_Stats_Background_Charts() { // The chart of the recently read and the recently added... const int WEEK_HISTORY = 4 * 3; DateTime NOW = DateTime.UtcNow; // Get the buckets for the past few weeks of READING CountingDictionary <DateTime> date_buckets_read = new CountingDictionary <DateTime>(); { List <DateTime> recently_reads = web_library_detail.library.RecentlyReadManager.GetRecentlyReadDates(); foreach (DateTime recently_read in recently_reads) { for (int week = 1; week < WEEK_HISTORY; ++week) { DateTime cutoff = NOW.AddDays(-7 * week); if (recently_read >= cutoff) { date_buckets_read.TallyOne(cutoff); break; } } } } // Get the buckets for the past few weeks of ADDING CountingDictionary <DateTime> date_buckets_added = new CountingDictionary <DateTime>(); { foreach (PDFDocument pdf_document in web_library_detail.library.PDFDocuments) { for (int week = 1; week < WEEK_HISTORY; ++week) { DateTime cutoff = NOW.AddDays(-7 * week); if (pdf_document.DateAddedToDatabase >= cutoff) { date_buckets_added.TallyOne(cutoff); break; } } } } // Plot the pretty pretty List <ChartItem> chart_items_read = new List <ChartItem>(); List <ChartItem> chart_items_added = new List <ChartItem>(); for (int week = 1; week < WEEK_HISTORY; ++week) { DateTime cutoff = NOW.AddDays(-7 * week); int num_read = date_buckets_read.GetCount(cutoff); int num_added = date_buckets_added.GetCount(cutoff); chart_items_read.Add(new ChartItem { Title = "Read", Timestamp = cutoff, Count = num_read }); chart_items_added.Add(new ChartItem { Title = "Added", Timestamp = cutoff, Count = num_added }); } WPFDoEvents.InvokeAsyncInUIThread(() => UpdateLibraryStatistics_Stats_Background_GUI(chart_items_read, chart_items_added)); }
public static void RestoreDesktop() { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); try { // Get the remembrances if (File.Exists(Filename)) { string[] restore_settings = File.ReadAllLines(Filename); foreach (string restore_setting in restore_settings) { try { if (restore_setting.StartsWith("PDF_LIBRARY")) { string[] parts = restore_setting.Split(','); string library_id = parts[1]; WebLibraryDetail web_library_detail = WebLibraryManager.Instance.GetLibrary(library_id); if (null == web_library_detail) { Logging.Warn("RestoreDesktop: Cannot find library anymore for Id {0}", library_id); } else { WPFDoEvents.InvokeInUIThread(() => MainWindowServiceDispatcher.Instance.OpenLibrary(web_library_detail)); } } else if (restore_setting.StartsWith("PDF_DOCUMENT")) { string[] parts = restore_setting.Split(','); string library_id = parts[1]; string document_fingerprint = parts[2]; WebLibraryDetail web_library_detail = WebLibraryManager.Instance.GetLibrary(library_id); if (null == web_library_detail) { Logging.Warn("RestoreDesktop: Cannot find library anymore for Id {0}", library_id); } else { PDFDocument pdf_document = web_library_detail.Xlibrary.GetDocumentByFingerprint(document_fingerprint); if (null == pdf_document) { Logging.Warn("RestoreDesktop: Cannot find document anymore for fingerprint {0}", document_fingerprint); } else { WPFDoEvents.InvokeAsyncInUIThread(() => { try { MainWindowServiceDispatcher.Instance.OpenDocument(pdf_document); } catch (Exception ex) { Logging.Error(ex, "RestoreDesktop: Error occurred while attempting to restore the view (tab) for document fingerprint {0}, library Id {1}", document_fingerprint, library_id); } }); } } } } catch (Exception ex) { Logging.Warn(ex, "There was a problem restoring desktop with state {0}", restore_setting); } } } } catch (Exception ex) { Logging.Error(ex, "There was a problem restoring the saved desktop state."); } Logging.Warn("Finished restoring desktop."); }
private void DisplayThumbnail() { ImageThumbnail.Source = null; TxtAbstract.Text = ""; if (null == pdf_document) { return; } SafeThreadPool.QueueUserWorkItem(o => { try { if (pdf_document.DocumentExists) { const double IMAGE_PERCENTAGE = 0.5; using (MemoryStream ms = new MemoryStream(SoraxPDFRenderer.GetPageByHeightAsImage(pdf_document.DocumentPath, pdf_document.PDFPassword, page, (int)Math.Round(ImageThumbnail.Height / IMAGE_PERCENTAGE), (int)Math.Round(ImageThumbnail.Width / IMAGE_PERCENTAGE)))) { Bitmap image = (Bitmap)Image.FromStream(ms); PDFOverlayRenderer.RenderAnnotations(image, pdf_document, page, specific_pdf_annotation); PDFOverlayRenderer.RenderHighlights(image, pdf_document, page); PDFOverlayRenderer.RenderInks(image, pdf_document, page); image = image.Clone(new RectangleF { Width = image.Width, Height = (int)Math.Round(image.Height * IMAGE_PERCENTAGE) }, image.PixelFormat); BitmapSource image_page = BitmapImageTools.CreateBitmapSourceFromImage(image); WPFDoEvents.InvokeAsyncInUIThread(() => { ImageThumbnail.Source = image_page; if (null != ImageThumbnail.Source) { ImageThumbnail.Visibility = Visibility.Visible; } else { ImageThumbnail.Visibility = Visibility.Collapsed; } }); } } else { string abstract_text = pdf_document.Abstract; if (PDFAbstractExtraction.CANT_LOCATE != abstract_text) { WPFDoEvents.InvokeAsyncInUIThread(() => { TxtAbstract.Text = abstract_text; }); } } } catch (Exception ex) { Logging.Error(ex, "There was a problem showing the PDF thumbnail"); } }); }
private void LibraryCatalogOverviewControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { // Make the button semi-transparent if our new document is not actually on the harddrive PanelSearchScore.Visibility = Visibility.Collapsed; ListSearchDetails.DataContext = null; ObjLookInsidePanel.Visibility = Visibility.Collapsed; ButtonThemeSwatch.Visibility = Visibility.Collapsed; ObjFavouriteImage.Visibility = Visibility.Collapsed; ButtonOpen.Background = Brushes.Transparent; TextTitle.Foreground = Brushes.Black; TextTitle.FontSize = TextAuthors.FontSize; // No more work if our context is null if (null == PDFDocumentBindable) { return; } // The wizard if ("The Qiqqa Manual" == PDFDocumentBindable.Underlying.TitleCombined) { WizardDPs.SetPointOfInterest(TextTitle, "GuestLibraryQiqqaManualTitle"); WizardDPs.SetPointOfInterest(ButtonOpen, "GuestLibraryQiqqaManualOpenButton"); } else { WizardDPs.ClearPointOfInterest(TextTitle); WizardDPs.ClearPointOfInterest(ButtonOpen); } // Choose the icon depending on the reference type if (PDFDocumentBindable.Underlying.IsVanillaReference) { ButtonOpen.Icon = Icons.GetAppIcon(Icons.LibraryCatalogOpenVanillaReference); ButtonOpen.Opacity = 1.0; } else { ButtonOpen.Icon = Icons.GetAppIcon(Icons.LibraryCatalogOpen); ButtonOpen.Opacity = PDFDocumentBindable.Underlying.DocumentExists ? 1.0 : 0.5; } // Favourite? if (PDFDocumentBindable.Underlying.IsFavourite ?? false) { ObjFavouriteImage.Visibility = Visibility.Visible; } // Colour if (Colors.Transparent != PDFDocumentBindable.Underlying.Color) { ButtonOpen.Background = new SolidColorBrush(ColorTools.MakeTransparentColor(PDFDocumentBindable.Underlying.Color, 64)); } // Rating if (!String.IsNullOrEmpty(PDFDocumentBindable.Underlying.Rating)) { double rating; if (Double.TryParse(PDFDocumentBindable.Underlying.Rating, out rating)) { TextTitle.FontSize = TextAuthors.FontSize + rating; } } // Reading stage switch (PDFDocumentBindable.Underlying.ReadingStage) { case Choices.ReadingStages_TOP_PRIORITY: TextTitle.Foreground = Brushes.DarkRed; break; case Choices.ReadingStages_READ_AGAIN: case Choices.ReadingStages_INTERRUPTED: case Choices.ReadingStages_STARTED_READING: TextTitle.Foreground = Brushes.DarkGreen; break; case Choices.ReadingStages_SKIM_READ: case Choices.ReadingStages_BROWSED: case Choices.ReadingStages_INTEREST_ONLY: TextTitle.Foreground = Brushes.DarkBlue; break; case Choices.ReadingStages_FINISHED_READING: case Choices.ReadingStages_DUPLICATE: TextTitle.Foreground = Brushes.DarkGray; break; case Choices.ReadingStages_UNREAD: TextTitle.Foreground = Brushes.Black; break; default: TextTitle.Foreground = Brushes.Black; break; } // Populate the score if we have them if (null != LibraryCatalogControl) { Dictionary <string, double> search_scores = LibraryCatalogControl.SearchScores; if (null != search_scores) { PanelSearchScore.Visibility = Visibility.Visible; double score; search_scores.TryGetValue(PDFDocumentBindable.Underlying.Fingerprint, out score); string score_string = String.Format("{0:0}%", score * 100); ButtonSearchInside.Caption = "" + score_string + ""; ButtonSearchInside.ToolTip = String.Format("Search score is {0}. Click here to see why...", score_string); ButtonSearchInside.Cursor = Cursors.Hand; ButtonSearchInside.MinWidth = 0; Color color = Color.FromRgb(255, (byte)(255 - 150 * score), 100); ButtonSearchInside.Background = new SolidColorBrush(color); } } // Populate the theme swatch ButtonThemeSwatch.Visibility = Visibility.Visible; ButtonThemeSwatch.Background = ThemeBrushes.GetBrushForDocument(PDFDocumentBindable.Underlying); // Populate the linked documents PDFDocument pdf_document = PDFDocumentBindable.Underlying; SafeThreadPool.QueueUserWorkItem(o => { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); var links = pdf_document.PDFDocumentCitationManager.GetLinkedDocuments(); WPFDoEvents.InvokeAsyncInUIThread(() => { WPFDoEvents.AssertThisCodeIsRunningInTheUIThread(); CitationsUserControl.PopulatePanelWithCitations(DocsPanel_Linked, pdf_document, links, Features.LinkedDocument_Library_OpenDoc, " » ", false); }); }); }
private void ExpeditionPaperThemesControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { // Clear the old ObjSeriesTopics.DataSource = null; TxtPleaseRunExpedition.Visibility = Visibility.Visible; ChartTopics.Visibility = Visibility.Collapsed; AugmentedBindable <PDFDocument> pdf_document_bindable = DataContext as AugmentedBindable <PDFDocument>; if (null == pdf_document_bindable) { return; } PDFDocument pdf_document = pdf_document_bindable.Underlying; SafeThreadPool.QueueUserWorkItem(o => { ExpeditionDataSource eds = pdf_document.LibraryRef.Xlibrary?.ExpeditionManager?.ExpeditionDataSource; if (null == eds) { return; } else { LDAAnalysis lda_analysis = eds.LDAAnalysis; // Draw the pie chart try { if (!eds.docs_index.ContainsKey(pdf_document.Fingerprint)) { return; } int doc_id = eds.docs_index[pdf_document.Fingerprint]; TopicProbability[] topics = lda_analysis.DensityOfTopicsInDocsSorted[doc_id]; int ITEMS_IN_CHART = Math.Min(topics.Length, 3); WPFDoEvents.InvokeAsyncInUIThread(() => { Brush[] brushes = new Brush[ITEMS_IN_CHART + 1]; List <ChartItem> chart_items = new List <ChartItem>(); double remaining_segment_percentage = 1.0; for (int t = 0; t < ITEMS_IN_CHART; ++t) { string topic_name = eds.GetDescriptionForTopic(topics[t].topic); double percentage = topics[t].prob; chart_items.Add(new ChartItem { Topic = topic_name, Percentage = percentage }); brushes[t] = new SolidColorBrush(eds.Colours[topics[t].topic]); remaining_segment_percentage -= percentage; } chart_items.Add(new ChartItem { Topic = "Others", Percentage = remaining_segment_percentage }); brushes[ITEMS_IN_CHART] = new SolidColorBrush(Colors.White); ObjChartTopicsArea.ColorModel.CustomPalette = brushes; ObjChartTopicsArea.ColorModel.Palette = ChartColorPalette.Custom; ObjSeriesTopics.DataSource = chart_items; // Silly ObjSeriesTopics.AnimationDuration = TimeSpan.FromMilliseconds(1000); ObjSeriesTopics.EnableAnimation = false; ObjSeriesTopics.AnimateOneByOne = true; ObjSeriesTopics.AnimateOption = AnimationOptions.Fade; ObjSeriesTopics.EnableAnimation = true; TxtPleaseRunExpedition.Visibility = Visibility.Collapsed; ChartTopics.Visibility = Visibility.Visible; }); } catch (Exception ex) { Logging.Error(ex, "There was a problem while generating the topics chart for document {0}", pdf_document.Fingerprint); } } }); }
public PDFRendererControl(PDFDocument pdf_document, bool remember_last_read_page, ZoomType force_zoom_type) { WPFDoEvents.AssertThisCodeIsRunningInTheUIThread(); Theme.Initialize(); InitializeComponent(); //Unloaded += PDFRendererControl_Unloaded; Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted; pdf_renderer_control_stats = new PDFRendererControlStats(pdf_document); this.remember_last_read_page = remember_last_read_page; ObjPagesPanel.Background = ThemeColours.Background_Brush_Blue_LightToDark; PageRenderArea.SizeChanged += PDFRendererControl_SizeChanged; KeyUp += PDFRendererControl_KeyUp; KeyDown += PDFRendererControl_KeyDown; TextInput += PDFRendererControl_TextInput; PreviewMouseWheel += PDFRendererControl_MouseWheel; ScrollPages.PreviewMouseDown += ScrollPages_PreviewMouseDown; ScrollPages.ScrollChanged += ScrollPages_ScrollChanged; KeyboardNavigation.SetDirectionalNavigation(this, KeyboardNavigationMode.None); KeyboardNavigation.SetDirectionalNavigation(ScrollPages, KeyboardNavigationMode.None); KeyboardNavigation.SetDirectionalNavigation(ObjPagesPanel, KeyboardNavigationMode.None); // Set the initial zoom ZoomType zoom_type = ZoomType.Other; switch (ConfigurationManager.Instance.ConfigurationRecord.GUI_LastPagesUp) { case "1": zoom_type = ZoomType.Zoom1Up; break; case "2": zoom_type = ZoomType.Zoom2Up; break; case "N": zoom_type = ZoomType.ZoomNUp; break; case "W": zoom_type = ZoomType.ZoomWholeUp; break; default: zoom_type = ZoomType.Zoom1Up; break; } // Is the zoom type forced? (e.g. by the metadata panel or the sniffer) if (ZoomType.Other != force_zoom_type) { zoom_type = force_zoom_type; } PageZoom(zoom_type); var doc = pdf_renderer_control_stats.pdf_document; SafeThreadPool.QueueUserWorkItem(o => { // Add the child pages bool add_bells_and_whistles = (doc.PageCount > 0 && doc.PageCount < 50); WPFDoEvents.InvokeAsyncInUIThread(() => { Logging.Info("+Creating child page controls"); for (int page = 1; page <= doc.PageCount; ++page) { PDFRendererPageControl page_control = new PDFRendererPageControl(this, page, add_bells_and_whistles); ObjPagesPanel.Children.Add(page_control); } Logging.Info("-Creating child page controls"); }); }); Logging.Info("+Setting initial viewport"); ReconsiderOperationMode(OperationMode.Hand); SetSearchKeywords(); // Eventually this should move into the ReconsiderOperationMode ScrollPages.Focus(); Logging.Info("-Setting initial viewport"); }
private void Regenerate() { WPFDoEvents.AssertThisCodeIsRunningInTheUIThread(); HashSet <string> parent_fingerprints = null; if (null != PDFDocuments && 0 < PDFDocuments.Count) { parent_fingerprints = new HashSet <string>(); foreach (var pdf_document in PDFDocuments) { parent_fingerprints.Add(pdf_document.Fingerprint); } } string map_y_axis_name = (string)ObjYAxis.SelectedItem; string map_x_axis_name = (string)ObjXAxis.SelectedItem; string identifier_name = (string)ObjIdentifier.SelectedItem; SafeThreadPool.QueueUserWorkItem(o => { MultiMapSet <string, string> map_y_axis = LibraryPivotReportBuilder.GenerateAxisMap(map_y_axis_name, LibraryRef, parent_fingerprints); MultiMapSet <string, string> map_x_axis = LibraryPivotReportBuilder.GenerateAxisMap(map_x_axis_name, LibraryRef, parent_fingerprints); WPFDoEvents.InvokeAsyncInUIThread(() => { LibraryPivotReportBuilder.IdentifierImplementations.IdentifierImplementationDelegate identifier_implementation = LibraryPivotReportBuilder.IdentifierImplementations.GetIdentifierImplementation(identifier_name); LibraryPivotReportBuilder.PivotResult pivot_result = LibraryPivotReportBuilder.GeneratePivot(map_y_axis, map_x_axis); GridControl ObjGridControl = new GridControl(); ObjGridControlHolder.Content = ObjGridControl; ObjGridControl.Model.RowCount = map_y_axis.Count + 2; ObjGridControl.Model.ColumnCount = map_x_axis.Count + 2; // ROW/COLUMN Titles for (int y = 0; y < pivot_result.y_keys.Count; ++y) { ObjGridControl.Model[y + 1, 0].CellValue = pivot_result.y_keys[y]; ObjGridControl.Model[y + 1, 0].CellValueType = typeof(string); } for (int x = 0; x < pivot_result.x_keys.Count; ++x) { ObjGridControl.Model[0, x + 1].CellValue = pivot_result.x_keys[x]; ObjGridControl.Model[0, x + 1].CellValueType = typeof(string); } // Grid contents StatusManager.Instance.ClearCancelled("LibraryPivot"); for (int y = 0; y < pivot_result.y_keys.Count; ++y) { if (General.HasPercentageJustTicked(y, pivot_result.y_keys.Count)) { StatusManager.Instance.UpdateStatus("LibraryPivot", "Building library pivot grid", y, pivot_result.y_keys.Count, true); if (StatusManager.Instance.IsCancelled("LibraryPivot")) { Logging.Warn("User cancelled library pivot grid generation"); break; } } for (int x = 0; x < pivot_result.x_keys.Count; ++x) { identifier_implementation(LibraryRef, pivot_result.common_fingerprints[y, x], ObjGridControl.Model[y + 1, x + 1]); } } StatusManager.Instance.UpdateStatus("LibraryPivot", "Finished library pivot"); // ROW/COLUMN Totals { int y_total = 0; { for (int y = 0; y < pivot_result.y_keys.Count; ++y) { int total = 0; for (int x = 0; x < pivot_result.x_keys.Count; ++x) { if (null != pivot_result.common_fingerprints[y, x]) { total += pivot_result.common_fingerprints[y, x].Count; } } ObjGridControl.Model[y + 1, pivot_result.x_keys.Count + 1].CellValue = total; ObjGridControl.Model[y + 1, pivot_result.x_keys.Count + 1].CellValueType = typeof(int); y_total += total; } } int x_total = 0; { for (int x = 0; x < pivot_result.x_keys.Count; ++x) { int total = 0; for (int y = 0; y < pivot_result.y_keys.Count; ++y) { if (null != pivot_result.common_fingerprints[y, x]) { total += pivot_result.common_fingerprints[y, x].Count; } } ObjGridControl.Model[pivot_result.y_keys.Count + 1, x + 1].CellValue = total; ObjGridControl.Model[pivot_result.y_keys.Count + 1, x + 1].CellValueType = typeof(int); x_total += total; } } int common_total = (x_total + y_total) / 2; if (common_total != x_total || common_total != y_total) { throw new GenericException("X and Y totals do not match?!"); } ObjGridControl.Model[pivot_result.y_keys.Count + 1, pivot_result.x_keys.Count + 1].CellValue = common_total; ObjGridControl.Model[pivot_result.y_keys.Count + 1, pivot_result.x_keys.Count + 1].CellValueType = typeof(int); ObjGridControl.Model[0, pivot_result.x_keys.Count + 1].CellValue = "TOTAL"; ObjGridControl.Model[0, pivot_result.x_keys.Count + 1].CellValueType = typeof(string); ObjGridControl.Model[pivot_result.y_keys.Count + 1, 0].CellValue = "TOTAL"; ObjGridControl.Model[pivot_result.y_keys.Count + 1, 0].CellValueType = typeof(string); } // Store the results for the toolbar buttons last_pivot_result = pivot_result; last_ObjGridControl = ObjGridControl; }); }); }
private void UpdateLibraryStatistics_Stats_Background_CoverFlow() { // The list of recommended items DocumentDisplayWorkManager ddwm = new DocumentDisplayWorkManager(); { { int ITEMS_IN_LIST = 5; // Upcoming reading is: // interrupted // top priority // read again // recently added and no status List <PDFDocument> pdf_documents_all = web_library_detail.library.PDFDocuments; pdf_documents_all.Sort(PDFDocumentListSorters.DateAddedToDatabase); foreach (string reading_stage in new string[] { Choices.ReadingStages_INTERRUPTED, Choices.ReadingStages_TOP_PRIORITY, Choices.ReadingStages_READ_AGAIN }) { foreach (PDFDocument pdf_document in pdf_documents_all) { if (!pdf_document.DocumentExists) { continue; } if (pdf_document.ReadingStage == reading_stage) { if (!ddwm.ContainsPDFDocument(pdf_document)) { ddwm.AddDocumentDisplayWork(DocumentDisplayWork.StarburstColor.Pink, reading_stage, pdf_document); if (ddwm.Count >= ITEMS_IN_LIST) { break; } } } } } } { int ITEMS_IN_LIST = 3; // Recently added { List <PDFDocument> pdf_documents = web_library_detail.library.PDFDocuments; pdf_documents.Sort(PDFDocumentListSorters.DateAddedToDatabase); int num_added = 0; foreach (PDFDocument pdf_document in pdf_documents) { if (!pdf_document.DocumentExists) { continue; } if (!ddwm.ContainsPDFDocument(pdf_document)) { ddwm.AddDocumentDisplayWork(DocumentDisplayWork.StarburstColor.Green, "Added Recently", pdf_document); if (++num_added >= ITEMS_IN_LIST) { break; } } } } // Recently read { List <PDFDocument> pdf_documents = web_library_detail.library.PDFDocuments; pdf_documents.Sort(PDFDocumentListSorters.DateLastRead); int num_added = 0; foreach (PDFDocument pdf_document in pdf_documents) { if (!pdf_document.DocumentExists) { continue; } if (!ddwm.ContainsPDFDocument(pdf_document)) { ddwm.AddDocumentDisplayWork(DocumentDisplayWork.StarburstColor.Blue, "Read Recently", pdf_document); if (++num_added >= ITEMS_IN_LIST) { break; } } } } } // And fill the placeholders WPFDoEvents.InvokeInUIThread(() => UpdateLibraryStatistics_Stats_Background_GUI_AddAllPlaceHolders(ddwm.ddws)); // Now render each document using (Font font = new Font("Times New Roman", 11.0f)) { using (StringFormat string_format = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }) { var color_matrix = new ColorMatrix(); color_matrix.Matrix33 = 0.9f; using (var image_attributes = new ImageAttributes()) { image_attributes.SetColorMatrix(color_matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); foreach (DocumentDisplayWork ddw in ddwm.ddws) { try { using (MemoryStream ms = new MemoryStream(ddw.pdf_document.PDFRenderer.GetPageByHeightAsImage(1, PREVIEW_IMAGE_HEIGHT / PREVIEW_IMAGE_PERCENTAGE))) { Bitmap page_bitmap = (Bitmap)System.Drawing.Image.FromStream(ms); page_bitmap = page_bitmap.Clone(new RectangleF { Width = page_bitmap.Width, Height = (int)Math.Round(page_bitmap.Height * PREVIEW_IMAGE_PERCENTAGE) }, page_bitmap.PixelFormat); using (Graphics g = Graphics.FromImage(page_bitmap)) { int CENTER = 60; int RADIUS = 60; { BitmapImage starburst_bi = null; switch (ddw.starburst_color) { case DocumentDisplayWork.StarburstColor.Blue: starburst_bi = Icons.GetAppIcon(Icons.PageCornerBlue); break; case DocumentDisplayWork.StarburstColor.Green: starburst_bi = Icons.GetAppIcon(Icons.PageCornerGreen); break; case DocumentDisplayWork.StarburstColor.Pink: starburst_bi = Icons.GetAppIcon(Icons.PageCornerPink); break; default: starburst_bi = Icons.GetAppIcon(Icons.PageCornerOrange); break; } Bitmap starburst_image = BitmapImageTools.ConvertBitmapSourceToBitmap(starburst_bi); g.SmoothingMode = SmoothingMode.AntiAlias; g.DrawImage( starburst_image, new Rectangle(CENTER - RADIUS, CENTER - RADIUS, 2 * RADIUS, 2 * RADIUS), 0, 0, starburst_image.Width, starburst_image.Height, GraphicsUnit.Pixel, image_attributes ); } using (Matrix mat = new Matrix()) { mat.RotateAt(-50, new PointF(CENTER / 2, CENTER / 2)); g.Transform = mat; string wrapped_caption = ddw.starburst_caption; wrapped_caption = wrapped_caption.ToLower(); wrapped_caption = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(wrapped_caption); wrapped_caption = wrapped_caption.Replace(" ", "\n"); g.DrawString(wrapped_caption, font, Brushes.Black, new PointF(CENTER / 2, CENTER / 2), string_format); } } BitmapSource page_bitmap_source = BitmapImageTools.CreateBitmapSourceFromImage(page_bitmap); ddw.page_bitmap_source = page_bitmap_source; } WPFDoEvents.InvokeInUIThread(() => UpdateLibraryStatistics_Stats_Background_GUI_FillPlaceHolder(ddw)); } catch (Exception ex) { Logging.Warn(ex, "There was a problem loading a preview image for document {0}", ddw.pdf_document.Fingerprint); } } } } } if (0 == ddwm.ddws.Count) { WPFDoEvents.InvokeAsyncInUIThread(() => { ButtonCoverFlow.IsChecked = false; UpdateLibraryStatistics(); } ); } } }