private void CreateBundle(string target_directory)
        {
            string target_filename_bundle_manifest = Path.GetFullPath(Path.Combine(target_directory, manifest.Id + Common.EXT_BUNDLE_MANIFEST));
            string target_filename_bundle          = Path.GetFullPath(Path.Combine(target_directory, manifest.Id + Common.EXT_BUNDLE));

            // Check that the details of the manifest are reasonable
            try
            {
                new Uri(manifest.BaseUrl);
            }
            catch (Exception)
            {
                MessageBoxes.Warn("Your base URL of '{0}' is invalid.  Please correct it and try again.", manifest.BaseUrl);
                return;
            }

            // Smash out the manifest
            string json = manifest.ToJSON();

            File.WriteAllText(target_filename_bundle_manifest, json);

            // Smash out the bundle
            string source_directory = Path.GetFullPath(Path.Combine(library.LIBRARY_BASE_PATH, @"*"));
            string directory_exclusion_parameter = (manifest.IncludesPDFs ? "" : "-xr!documents");
            string parameters = String.Format("a -tzip -mm=Deflate -mmt=on -mx9 \"{0}\" \"{1}\" {2}", target_filename_bundle, source_directory, directory_exclusion_parameter);

            // Watch the zipper
            SafeThreadPool.QueueUserWorkItem(o => TailZIPProcess(manifest, parameters));
        }
        // -------------------------------------------------------------------------------------------------------------------------------------------------------

        internal void Sync(SyncControlGridItemSet sync_control_grid_item_set)
        {
            Logging.Info("Syncing");

            foreach (SyncControlGridItem sync_control_grid_item_temp in sync_control_grid_item_set.grid_items)
            {
                // Needed for passing to background thread...
                SyncControlGridItem sync_control_grid_item = sync_control_grid_item_temp;

                if (sync_control_grid_item.library_sync_detail.web_library_detail.library.sync_in_progress)
                {
                    if (!sync_control_grid_item_set.sync_request.suppress_already_in_progress_notification)
                    {
                        MessageBoxes.Info("A sync operation is already in progress for library {0}.  Please wait for it to finish before trying to sync again.", sync_control_grid_item.library_sync_detail.web_library_detail.library.WebLibraryDetail.Title);
                    }
                    else
                    {
                        Logging.Info("A sync operation is already in progress for library {0}.  This has been suppressed from the GUI.", sync_control_grid_item.library_sync_detail.web_library_detail.library.WebLibraryDetail.Title);
                    }
                }
                else
                {
                    if (sync_control_grid_item.SyncMetadata || sync_control_grid_item.SyncDocuments)
                    {
                        sync_control_grid_item.library_sync_detail.web_library_detail.library.sync_in_progress = true;
                        SafeThreadPool.QueueUserWorkItem(o => Sync_BACKGROUND(sync_control_grid_item));
                    }
                }
            }
        }
Example #3
0
        private void ButtonJoinCreate_Click(object sender, RoutedEventArgs e)
        {
            FeatureTrackingManager.Instance.UseFeature(Features.StartPage_CreateIntranetLibrary);

            if (String.IsNullOrEmpty(TxtPath.Text))
            {
                MessageBoxes.Error("Please enter a path to your Intranet Library.");
                return;
            }

            string db_base_path   = TxtPath.Text;
            string db_title       = TxtTitle.Text;
            string db_description = TxtDescription.Text;

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                bool validation_successful = EnsureIntranetLibraryExists(db_base_path, db_title, db_description);

                if (validation_successful)
                {
                    WPFDoEvents.InvokeInUIThread(() =>
                    {
                        Close();
                    });
                }
            });
        }
        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 void MenuForceOCR_Click(object sender, RoutedEventArgs e)
        {
            popup.Close();

            string   language  = "";
            MenuItem menu_item = sender as MenuItem;

            if (null != menu_item)
            {
                language = menu_item.Name.Substring(menu_item.Name.Length - 3, 3);
            }

            FeatureTrackingManager.Instance.UseFeature(
                Features.Library_ForceOCR,
                "language", language
                );

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                foreach (var pdf_document in pdf_documents)
                {
                    if (pdf_document.DocumentExists)
                    {
                        pdf_document.ForceOCRText(language);
                    }
                }
            });
        }
        private void MoveGuestPreviewPDFDocument(WebLibraryDetail web_library_detail)
        {
            PDFDocument source_pdf_document = pdf_renderer_control_stats.pdf_document;

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                PDFDocument cloned_pdf_document = ImportingIntoLibrary.ClonePDFDocumentsFromOtherLibrary_SYNCHRONOUS(source_pdf_document, web_library_detail.library, false);

                WPFDoEvents.InvokeInUIThread(() =>
                {
                    // Open the new
                    if (null != cloned_pdf_document)
                    {
                        MainWindowServiceDispatcher.Instance.OpenDocument(cloned_pdf_document);
                    }
                    else
                    {
                        MessageBoxes.Warn("There was a problem moving this document to another library.");
                    }

                    // Close the old
                    MainWindowServiceDispatcher.Instance.ClosePDFReadingControl(this);

                    // Delete the old
                    if (cloned_pdf_document != source_pdf_document)
                    {
                        source_pdf_document.Deleted = true;
                        source_pdf_document.Bindable.NotifyPropertyChanged(nameof(source_pdf_document.Deleted));
                    }
                });
            });
        }
        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.");
                });
            });
        }
        public static void Export(WebLibraryDetail web_library_detail, List <PDFDocument> pdf_documents)
        {
            FeatureTrackingManager.Instance.UseFeature(Features.Library_Export);

            // Get the directory
            string initial_directory = null;

            if (null == initial_directory)
            {
                initial_directory = Path.GetDirectoryName(ConfigurationManager.Instance.ConfigurationRecord.System_LastLibraryExportFolder);
            }
            if (null == initial_directory)
            {
                initial_directory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            }

            using (CommonOpenFileDialog dialog = new CommonOpenFileDialog())
            {
                dialog.IsFolderPicker   = true;
                dialog.Title            = "Please select the folder to which you wish to export your entire Qiqqa library.";
                dialog.DefaultDirectory = initial_directory;
                CommonFileDialogResult result = dialog.ShowDialog();
                if (result == CommonFileDialogResult.Ok)
                {
                    // Remember the filename for next time
                    string base_path = dialog.FileName;
                    ConfigurationManager.Instance.ConfigurationRecord.System_LastLibraryExportFolder = base_path;
                    ConfigurationManager.Instance.ConfigurationRecord_Bindable.NotifyPropertyChanged(nameof(ConfigurationManager.Instance.ConfigurationRecord.System_LastLibraryExportFolder));

                    SafeThreadPool.QueueUserWorkItem(o => Export(web_library_detail, pdf_documents, base_path));
                }
            }
        }
 public static void ClonePDFDocumentsFromOtherLibrary_ASYNCHRONOUS(PDFDocument existing_pdf_document, WebLibraryDetail web_library_detail)
 {
     SafeThreadPool.QueueUserWorkItem(o =>
     {
         ClonePDFDocumentsFromOtherLibrary_SYNCHRONOUS(existing_pdf_document, web_library_detail);
     });
 }
        public void RequestSync(SyncRequest sync_request)
        {
            bool user_wants_intervention = KeyboardTools.IsCTRLDown() || !ConfigurationManager.Instance.ConfigurationRecord.SyncTermsAccepted;

            WPFDoEvents.SetHourglassCursor();

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                GlobalSyncDetail global_sync_detail = GenerateGlobalSyncDetail();
                WPFDoEvents.InvokeInUIThread(() =>
                {
                    WPFDoEvents.ResetHourglassCursor();

                    SyncControlGridItemSet scgis = new SyncControlGridItemSet(sync_request, global_sync_detail);
                    scgis.AutoTick();

                    if (scgis.CanRunWithoutIntervention() && !user_wants_intervention)
                    {
                        Sync(scgis);
                    }
                    else
                    {
                        SyncControl sync_control = new SyncControl();
                        sync_control.SetSyncParameters(scgis);
                        sync_control.Show();
                    }
                });
            });
        }
Example #11
0
        private void StartMainApplication()
        {
            WPFDoEvents.AssertThisCodeIsRunningInTheUIThread();
            WPFDoEvents.SetHourglassCursor();

            // Initialise the web browser
            try
            {
                StatusManager.Instance.UpdateStatus("AppStart", "Installing browser components");
                GeckoInstaller.CheckForInstall();
                StatusManager.Instance.UpdateStatus("AppStart", "Initialising browser components");
                GeckoManager.Initialise();
                GeckoManager.RegisterPDFInterceptor();
            }
            catch (Exception ex)
            {
                Logging.Error(ex, "Problem initialising GeckoFX.");
            }

            // Fire up Qiqqa!
            StatusManager.Instance.UpdateStatus("AppStart", "Starting background processes");
            SafeThreadPool.QueueUserWorkItem(o =>
            {
                StartDaemonSingletons();
            });

            StatusManager.Instance.UpdateStatus("AppStart", "Launching Qiqqa!");
            FireStartUseFeature();
            MainWindow window = new MainWindow();

            window.Show();

            Hide();
        }
Example #12
0
        public void Shutdown()
        {
            Logging.Info("Stopping MaintainableManager");

            // signal everyone it's STOP time ASAP:
            lock (do_maintenance_delegate_wrappers_lock)
            {
                foreach (DoMaintenanceDelegateWrapper do_maintenance_delegate_wrapper in do_maintenance_delegate_wrappers)
                {
                    do_maintenance_delegate_wrapper?.daemon.Stop();
                }
            }

            // Then go and wait for all to really terminate.
            shutdown_cleanup_action = new WaitCallback(o =>
            {
                Logging.Debug("+Stopping MaintainableManager tasks (async wait callback)");

                if (!CleanupOnShutdown())
                {
                    // queue another cleanup task round to check again
                    SafeThreadPool.QueueUserWorkItem(shutdown_cleanup_action, skip_task_at_app_shutdown: false);
                }
            });
            SafeThreadPool.QueueUserWorkItem(shutdown_cleanup_action, skip_task_at_app_shutdown: false);
        }
Example #13
0
 public static void ClonePDFDocumentsFromOtherLibrary_ASYNCHRONOUS(PDFDocument existing_pdf_document, Library library, bool suppress_signal_that_docs_have_changed)
 {
     SafeThreadPool.QueueUserWorkItem(o =>
     {
         ClonePDFDocumentsFromOtherLibrary_SYNCHRONOUS(existing_pdf_document, library, suppress_signal_that_docs_have_changed);
     });
 }
Example #14
0
        public static void Export(Library library, List <PDFDocument> pdf_documents)
        {
            FeatureTrackingManager.Instance.UseFeature(Features.Library_Export);

            // Get the directory
            string initial_directory = null;

            if (null == initial_directory)
            {
                initial_directory = Path.GetDirectoryName(ConfigurationManager.Instance.ConfigurationRecord.System_LastLibraryExportFolder);
            }
            if (null == initial_directory)
            {
                initial_directory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            }

            using (FolderBrowserDialog dlg = new FolderBrowserDialog
            {
                Description = "Please select the folder to which you wish to export your entire Qiqqa library.",
                SelectedPath = initial_directory,
                ShowNewFolderButton = true
            })
            {
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    // Remember the filename for next time
                    string base_path = dlg.SelectedPath;
                    ConfigurationManager.Instance.ConfigurationRecord.System_LastLibraryExportFolder = base_path;
                    ConfigurationManager.Instance.ConfigurationRecord_Bindable.NotifyPropertyChanged(() => ConfigurationManager.Instance.ConfigurationRecord.System_LastLibraryExportFolder);

                    SafeThreadPool.QueueUserWorkItem(o => Export(library, pdf_documents, base_path));
                }
            }
        }
        internal void RefreshSyncControl(SyncControlGridItemSet scgis_previous, SyncControl sync_control)
        {
            WPFDoEvents.SetHourglassCursor();

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                //
                // Explicitly instruct the sync info collector to perform a swift scan, which DOES NOT include
                // collecting the precise size of every document in every Qiqqa library (which itself is a *significant*
                // file system load when you have any reasonably large libraries like I do.          [GHo]
                //
                // TODO: fetch and cache document filesizes in the background, so we can improve on the accuracy of
                // our numbers in a future call to this method.
                //
                GlobalSyncDetail global_sync_detail = GenerateGlobalSyncDetail(tally_library_storage_size: false);
                WPFDoEvents.InvokeInUIThread(() =>
                {
                    WPFDoEvents.ResetHourglassCursor();

                    SyncControlGridItemSet scgis = new SyncControlGridItemSet(scgis_previous.sync_request, global_sync_detail);
                    scgis.AutoTick();
                    sync_control.SetSyncParameters(scgis);
                });
            });
        }
        void CreateBundle(string target_directory)
        {
            string target_filename_bundle_manifest = target_directory + "\\" + manifest.Id + Common.EXT_BUNDLE_MANIFEST;
            string target_filename_bundle          = target_directory + "\\" + manifest.Id + Common.EXT_BUNDLE;

            // Check that the details of the manifest are reasonable
            {
                try
                {
                    new Uri(this.manifest.BaseUrl);
                }
                catch (Exception)
                {
                    MessageBoxes.Warn("Your base URL of '{0}' is invalid.  Please correct it and try again.", this.manifest.BaseUrl);
                    return;
                }
            }

            // Smash out he manifest
            string json = this.manifest.ToJSON();

            File.WriteAllText(target_filename_bundle_manifest, json);

            // Smash out the bundle
            string  source_directory = library.LIBRARY_BASE_PATH + "\\*";
            string  directory_exclusion_parameter = manifest.IncludesPDFs ? "" : String.Format("-xr!documents", source_directory);
            string  parameters  = String.Format("a -tzip -mm=Deflate -mmt=on -mx9 \"{0}\" \"{1}\" {2}", target_filename_bundle, source_directory, directory_exclusion_parameter);
            Process zip_process = Process.Start(ConfigurationManager.Instance.Program7ZIP, parameters);

            // Watch the zipper
            SafeThreadPool.QueueUserWorkItem(o => TailZIPProcess(manifest, zip_process));
        }
Example #17
0
 public void NotifyOfChangeToWebLibraryDetail()
 {
     SafeThreadPool.QueueUserWorkItem(o =>
     {
         SaveKnownWebLibraries();
     },
                                      skip_task_at_app_shutdown: false);
 }
Example #18
0
        private void ObjSearchBox_OnSoftSearch()
        {
            var    doc   = this.pdf_document;
            string query = ObjSearchBox.Text;

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                ReSearch(doc, query);
            });
        }
        private void ObjTooManyAnnotationsButton_Click(object sender, RoutedEventArgs e)
        {
            ObjTooManyAnnotationsButton.Visibility = Visibility.Collapsed;

            PDFDocument pdf_document = (PDFDocument)ObjTooManyAnnotationsButton.Tag;

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                PopulateWithAnnotationReport(pdf_document);
            });
        }
 void ButtonRefreshTags_Click(object sender, RoutedEventArgs e)
 {
     if (null != library)
     {
         SafeThreadPool.QueueUserWorkItem(o => library.AITagManager.Regenerate(null));
     }
     else
     {
         MessageBoxes.Warn("Please select a Library before trying to refresh its AutoTags.");
     }
 }
Example #21
0
 private void ButtonGarbageCollect_Click(object sender, RoutedEventArgs e)
 {
     SafeThreadPool.QueueUserWorkItem(o =>
     {
         Logging.Info("+Before Garbage Collect: Memory load: {0} Bytes", GC.GetTotalMemory(false));
         GC.WaitForPendingFinalizers();
         GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
         GC.WaitForPendingFinalizers();
         GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
         Logging.Info("-After Garbage Collect: Memory load: {0} Bytes", GC.GetTotalMemory(true));
     });
 }
Example #22
0
        public static void DoInterestingAnalysis(PDFReadingControl pdf_reading_control, PDFRendererControl pdf_renderer_control, PDFRendererControlStats pdf_renderer_control_stats)
        {
            pdf_reading_control.OnlineDatabaseLookupControl.PDFDocument = pdf_renderer_control_stats.pdf_document;

            Thread.Sleep(1000);

            // Uncomment once ready
            SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_DuplicatesAndCitations(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
            SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_GoogleScholar(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
            SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_TagCloud(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
            SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_SimilarAuthors(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
        }
Example #23
0
        public void CauseAllPDFPagesToBeOCRed()
        {
            // jobqueue this one too - saves us one PDF access + parse action inline when invoked in the UI thread by OpenDocument()
            int pgcount = PageCount;

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                for (int i = pgcount; i >= 1; --i)
                {
                    GetOCRText(i);
                }
            });
        }
        void ButtonRefresh_Click(object sender, RoutedEventArgs e)
        {
            if (null == library)
            {
                MessageBoxes.Warn("You need to first choose a library against which to run Qiqqa Expedition.");
                return;
            }

            int num_topics = Convert.ToInt32(TextExpeditionNumThemes.Text);
            bool add_autotags = ObjAddAutoTags.IsChecked ?? true;
            bool add_tags = ObjAddTags.IsChecked ?? true;
            SafeThreadPool.QueueUserWorkItem(o => library.ExpeditionManager.RebuildExpedition(num_topics, add_autotags, add_tags, OnRebuildExpeditionComplete));
        }
        private void HyperlinkForget_OnClick(object sender, MouseButtonEventArgs e)
        {
            WebLibraryDetail web_library_detail = DataContext as WebLibraryDetail;

            if (null != web_library_detail)
            {
                SafeThreadPool.QueueUserWorkItem(o =>
                {
                    WebLibraryManager.Instance.ForgetKnownWebLibraryFromIntranet(web_library_detail);
                });
            }
            e.Handled = true;
        }
Example #26
0
        private void CmdExport_Click(object sender, RoutedEventArgs e)
        {
            SafeThreadPool.QueueUserWorkItem(o =>
            {
                WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread();

                DateTime start_time = DateTime.Now;

                MultiMapSet <string, string> tags_with_fingerprints_ALL = GetNodeItems(web_library_detail, null);
                StringBuilder sb = new StringBuilder();

                sb.AppendLine("------------------------------------------------------------------------");
                sb.AppendFormat("{0} report\r\n", description_title);
                sb.AppendLine("------------------------------------------------------------------------");
                sb.AppendLine("Generated by Qiqqa (http://www.qiqqa.com)");
                sb.AppendLine(String.Format("On {0} {1}", start_time.ToLongDateString(), start_time.ToLongTimeString()));
                sb.AppendLine("------------------------------------------------------------------------");

                sb.AppendLine();
                sb.AppendLine();
                sb.AppendLine();
                sb.AppendLine("------------------------------------------------------------------------");
                sb.AppendFormat("{0}:\r\n", description_title);
                sb.AppendLine("------------------------------------------------------------------------");
                sb.AppendLine();

                foreach (var pair in tags_with_fingerprints_ALL)
                {
                    sb.AppendLine(pair.Key);
                }

                sb.AppendLine();
                sb.AppendLine();
                sb.AppendLine();
                sb.AppendLine("------------------------------------------------------------------------");
                sb.AppendFormat("{0} with associated fingerprints:\r\n", description_title);
                sb.AppendLine("------------------------------------------------------------------------");
                sb.AppendLine();
                foreach (var pair in tags_with_fingerprints_ALL)
                {
                    foreach (var value in pair.Value)
                    {
                        sb.AppendFormat("{0}\t{1}\r\n", pair.Key, value);
                    }
                }

                string filename = TempFile.GenerateTempFilename("txt");
                File.WriteAllText(filename, sb.ToString());
                Process.Start(filename);
            });
        }
        private void MenuClearOCR_Click(object sender, RoutedEventArgs e)
        {
            popup.Close();

            FeatureTrackingManager.Instance.UseFeature(Features.Library_ClearOCR);

            SafeThreadPool.QueueUserWorkItem(o =>
            {
                foreach (var pdf_document in pdf_documents)
                {
                    pdf_document.ClearOCRText();
                }
            });
        }
Example #28
0
        void ButtonGrabWebPage_Click(object sender, RoutedEventArgs e)
        {
            if (null == CurrentUri)
            {
                MessageBoxes.Error("You need to have navigated to a web page before trying to export to PDF.");
                return;
            }

            string title = CurrentTitle;
            string url   = CurrentUri.ToString();

            // This was the code that does the magic locally on the client...
            SafeThreadPool.QueueUserWorkItem(o => HTMLToPDFConversion.GrabWebPage(title, url));
        }
        private void UseAsBibTeX(string text)
        {
            SafeThreadPool.QueueUserWorkItem(o => PostBibTeXToAggregator(text));

            if (null != pdf_document)
            {
                pdf_document.BibTex = text;
                pdf_document.Bindable.NotifyPropertyChanged(() => pdf_document.BibTex);
            }
            else
            {
                MessageBoxes.Error("Please first select a PDF in your library before trying to search for BibTeX.");
            }
        }
        public static void DoInterestingAnalysis(PDFReadingControl pdf_reading_control, PDFRendererControl pdf_renderer_control, PDFRendererControlStats pdf_renderer_control_stats)
        {
            pdf_reading_control.OnlineDatabaseLookupControl.PDFDocument = pdf_renderer_control_stats.pdf_document;

            Thread.Sleep(1000);

            SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_DuplicatesAndCitations(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
            // Only bother Google Scholar with a query when we want to:
            if (ConfigurationManager.IsEnabled(nameof(DoInterestingAnalysis_GoogleScholar)))
            {
                SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_GoogleScholar(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
            }
            SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_TagCloud(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
            SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_SimilarAuthors(pdf_reading_control, pdf_renderer_control, pdf_renderer_control_stats));
        }