X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fgraphics%2FPreviewLoader.cpp;h=d9133d9a7dc09763938061fd92963d71d839aa59;hb=38c2cde0d8695ac5287bae218c4a33a2acf18ef8;hp=1715b5df3c8d53e1c48e2a0cfb4ad8c5d31165e0;hpb=306b136cc005a1aeb9a6861ee0ac6fe2a2dd53e3;p=lyx.git diff --git a/src/graphics/PreviewLoader.cpp b/src/graphics/PreviewLoader.cpp index 1715b5df3c..d9133d9a7d 100644 --- a/src/graphics/PreviewLoader.cpp +++ b/src/graphics/PreviewLoader.cpp @@ -25,6 +25,7 @@ #include "output.h" #include "OutputParams.h" #include "TexRow.h" +#include "texstream.h" #include "frontends/Application.h" // hexName @@ -37,12 +38,16 @@ #include "support/ForkedCalls.h" #include "support/lstrings.h" -#include "support/bind.h" #include "support/TempFile.h" -#include +#include #include #include +#include +#include +#include + +#include using namespace std; using namespace lyx::support; @@ -68,35 +73,6 @@ FileName const unique_tex_filename(FileName const & bufferpath) } -lyx::Converter const * setConverter(string const & from) -{ - typedef vector FmtList; - typedef lyx::graphics::Cache GCache; - FmtList const & loadableFormats = GCache::get().loadableFormats(); - FmtList::const_iterator it = loadableFormats.begin(); - FmtList::const_iterator const end = loadableFormats.end(); - - for (; it != end; ++it) { - string const to = *it; - if (from == to) - continue; - - lyx::Converter const * ptr = lyx::theConverters().getConverter(from, to); - if (ptr) - return ptr; - } - - // FIXME THREAD - static bool first = true; - if (first) { - first = false; - LYXERR0("PreviewLoader::startLoading()\n" - << "No converter from \"" << from << "\" format has been defined."); - } - return 0; -} - - void setAscentFractions(vector & ascent_fractions, FileName const & metrics_file) { @@ -184,14 +160,13 @@ typedef map InProgressProcesses; typedef InProgressProcesses::value_type InProgressProcess; -} // namespace anon - +} // namespace namespace lyx { namespace graphics { -class PreviewLoader::Impl : public boost::signals::trackable { +class PreviewLoader::Impl { public: /// Impl(PreviewLoader & p, Buffer const & b); @@ -205,19 +180,19 @@ public: void add(string const & latex_snippet); /// void remove(string const & latex_snippet); - /// Record math macro definitions added to the loader - void addMacroDef(docstring const & latex_snippet); - /// Has a math macro definition already been added to the loader? - bool hasMacroDef(docstring const & latex_snippet) const; /// \p wait whether to wait for the process to complete or, instead, /// to do it in the background. void startLoading(bool wait = false); + /// + void refreshPreviews(); /// Emit this signal when an image is ready for display. - boost::signal imageReady; + signals2::signal imageReady; Buffer const & buffer() const { return buffer_; } + lyx::Converter const * setConverter(string const & from); + private: /// Called by the ForkedCall process that generated the bitmap files. void finishedGenerating(pid_t, int); @@ -229,7 +204,7 @@ private: /** cache_ allows easy retrieval of already-generated images * using the LaTeX snippet as the identifier. */ - typedef shared_ptr PreviewImagePtr; + typedef std::shared_ptr PreviewImagePtr; /// typedef map Cache; /// @@ -242,22 +217,28 @@ private: /** in_progress_ stores all forked processes so that we can proceed * thereafter. - The map uses the conversion commands as its identifiers. */ InProgressProcesses in_progress_; - /// - set macrodefs_; - /// PreviewLoader & parent_; /// Buffer const & buffer_; /// mutable int font_scaling_factor_; + /// + mutable int fg_color_; + /// + mutable int bg_color_; + /// + QTimer * delay_refresh_; + /// + bool finished_generating_; /// We don't own this static lyx::Converter const * pconverter_; + + Trackable trackable_; }; @@ -303,25 +284,19 @@ void PreviewLoader::remove(string const & latex_snippet) const } -void PreviewLoader::addMacroDef(docstring const & latex_snippet) const -{ - pimpl_->addMacroDef(latex_snippet); -} - - -bool PreviewLoader::hasMacroDef(docstring const & latex_snippet) const +void PreviewLoader::startLoading(bool wait) const { - return pimpl_->hasMacroDef(latex_snippet); + pimpl_->startLoading(wait); } -void PreviewLoader::startLoading(bool wait) const +void PreviewLoader::refreshPreviews() { - pimpl_->startLoading(wait); + pimpl_->refreshPreviews(); } -boost::signals::connection PreviewLoader::connect(slot_type const & slot) const +signals2::connection PreviewLoader::connect(slot const & slot) const { return pimpl_->imageReady.connect(slot); } @@ -402,23 +377,66 @@ void InProgress::stop() const } } -} // namespace anon +} // namespace namespace lyx { namespace graphics { PreviewLoader::Impl::Impl(PreviewLoader & p, Buffer const & b) - : parent_(p), buffer_(b) + : parent_(p), buffer_(b), finished_generating_(true) { font_scaling_factor_ = int(buffer_.fontScalingFactor()); + if (theApp()) { + fg_color_ = strtol(theApp()->hexName(foregroundColor()).c_str(), 0, 16); + bg_color_ = strtol(theApp()->hexName(backgroundColor()).c_str(), 0, 16); + } else { + fg_color_ = 0x0; + bg_color_ = 0xffffff; + } if (!pconverter_) pconverter_ = setConverter("lyxpreview"); + + delay_refresh_ = new QTimer(&parent_); + delay_refresh_->setSingleShot(true); + QObject::connect(delay_refresh_, SIGNAL(timeout()), + &parent_, SLOT(refreshPreviews())); +} + + +lyx::Converter const * PreviewLoader::Impl::setConverter(string const & from) +{ + typedef vector FmtList; + FmtList const & loadableFormats = graphics::Cache::get().loadableFormats(); + FmtList::const_iterator it = loadableFormats.begin(); + FmtList::const_iterator const end = loadableFormats.end(); + + for (; it != end; ++it) { + string const to = *it; + if (from == to) + continue; + + lyx::Converter const * ptr = lyx::theConverters().getConverter(from, to); + if (ptr) + return ptr; + } + + // Show the error only once. This is thread-safe. + static nullptr_t no_conv = [&]{ + LYXERR0("PreviewLoader::startLoading()\n" + << "No converter from \"" << from + << "\" format has been defined."); + return nullptr; + } (); + + return no_conv; } PreviewLoader::Impl::~Impl() { + delete delay_refresh_; + InProgressProcesses::iterator ipit = in_progress_.begin(); InProgressProcesses::iterator ipend = in_progress_.end(); @@ -431,20 +449,45 @@ PreviewImage const * PreviewLoader::Impl::preview(string const & latex_snippet) const { int fs = int(buffer_.fontScalingFactor()); - if (font_scaling_factor_ != fs) { - // Refresh all previews on zoom changes - font_scaling_factor_ = fs; - Cache::const_iterator cit = cache_.begin(); - Cache::const_iterator cend = cache_.end(); - while (cit != cend) - parent_.remove((cit++)->first); - buffer_.updatePreviews(); + int fg = 0x0; + int bg = 0xffffff; + if (theApp()) { + fg = strtol(theApp()->hexName(foregroundColor()).c_str(), 0, 16); + bg = strtol(theApp()->hexName(backgroundColor()).c_str(), 0, 16); + } + if (font_scaling_factor_ != fs || fg_color_ != fg || bg_color_ != bg) { + // Schedule refresh of all previews on zoom or color changes. + // The previews are regenerated only after the zoom factor + // has not been changed for about 1 second. + fg_color_ = fg; + bg_color_ = bg; + delay_refresh_->start(1000); } + // Don't try to access the cache until we are done. + if (delay_refresh_->isActive() || !finished_generating_) + return 0; Cache::const_iterator it = cache_.find(latex_snippet); return (it == cache_.end()) ? 0 : it->second.get(); } +void PreviewLoader::Impl::refreshPreviews() +{ + font_scaling_factor_ = int(buffer_.fontScalingFactor()); + // Reschedule refresh until the previous process completed. + if (!finished_generating_) { + delay_refresh_->start(1000); + return; + } + Cache::const_iterator cit = cache_.begin(); + Cache::const_iterator cend = cache_.end(); + while (cit != cend) + parent_.remove((cit++)->first); + finished_generating_ = false; + buffer_.updatePreviews(); +} + + namespace { class FindSnippet { @@ -462,7 +505,7 @@ private: string const snippet_; }; -} // namespace anon +} // namespace PreviewLoader::Status PreviewLoader::Impl::status(string const & latex_snippet) const @@ -524,7 +567,7 @@ private: string const & snippet_; }; -} // namespace anon +} // namespace void PreviewLoader::Impl::remove(string const & latex_snippet) @@ -551,18 +594,6 @@ void PreviewLoader::Impl::remove(string const & latex_snippet) } -void PreviewLoader::Impl::addMacroDef(docstring const & latex_snippet) -{ - macrodefs_.insert(latex_snippet); -} - - -bool PreviewLoader::Impl::hasMacroDef(docstring const & latex_snippet) const -{ - return macrodefs_.find(latex_snippet) != macrodefs_.end(); -} - - void PreviewLoader::Impl::startLoading(bool wait) { if (pending_.empty() || !pconverter_) @@ -598,8 +629,7 @@ void PreviewLoader::Impl::startLoading(bool wait) return; } - TexRow texrow; - otexstream os(of, texrow); + otexstream os(of); OutputParams runparams(&enc); LaTeXFeatures features(buffer_, buffer_.params(), runparams); @@ -613,6 +643,11 @@ void PreviewLoader::Impl::startLoading(bool wait) } of << "\\batchmode\n"; + // Set \jobname of previews to the document name (see bug 9627) + of << "\\def\\jobname{" + << from_utf8(changeExtension(buffer_.latexName(true), "")) + << "}\n"; + LYXERR(Debug::LATEX, "Format = " << buffer_.params().getDefaultOutputFormat()); string latexparam = ""; bool docformat = !buffer_.params().default_output_format.empty() @@ -672,22 +707,17 @@ void PreviewLoader::Impl::startLoading(bool wait) << " " << quoteName(latexfile.toFilesystemEncoding()) << " --dpi " << font_scaling_factor_; - // FIXME XHTML + // FIXME XHTML // The colors should be customizable. if (!buffer_.isExporting()) { ColorCode const fg = PreviewLoader::foregroundColor(); ColorCode const bg = PreviewLoader::backgroundColor(); - cs << " --fg " << theApp()->hexName(fg) + cs << " --fg " << theApp()->hexName(fg) << " --bg " << theApp()->hexName(bg); } cs << latexparam; - if (buffer_.params().bibtex_command != "default") - cs << " --bibtex=" << quoteName(buffer_.params().bibtex_command); - else if (buffer_.params().encoding().package() == Encoding::japanese) - cs << " --bibtex=" << quoteName(lyxrc.jbibtex_command); - else - cs << " --bibtex=" << quoteName(lyxrc.bibtex_command); + cs << " --bibtex=" << quoteName(buffer_.params().bibtexCommand()); if (buffer_.params().bufferFormat() == "lilypond-book") cs << " --lilypond"; @@ -696,8 +726,8 @@ void PreviewLoader::Impl::startLoading(bool wait) if (wait) { ForkedCall call(buffer_.filePath(), buffer_.layoutPos()); int ret = call.startScript(ForkedProcess::Wait, command); - // FIXME THREAD - static int fake = (2^20) + 1; + // PID_MAX_LIMIT is 2^22 so we start one after that + static atomic_int fake((1 << 22) + 1); int pid = fake++; inprogress.pid = pid; inprogress.command = command; @@ -707,9 +737,10 @@ void PreviewLoader::Impl::startLoading(bool wait) } // Initiate the conversion from LaTeX to bitmap images files. - ForkedCall::SignalTypePtr - convert_ptr(new ForkedCall::SignalType); - convert_ptr->connect(bind(&Impl::finishedGenerating, this, _1, _2)); + ForkedCall::sigPtr convert_ptr = make_shared(); + convert_ptr->connect(ForkedProcess::slot([this](pid_t pid, int retval){ + finishedGenerating(pid, retval); + }).track_foreign(trackable_.p())); ForkedCall call(buffer_.filePath()); int ret = call.startScript(command, convert_ptr); @@ -739,6 +770,7 @@ void PreviewLoader::Impl::finishedGenerating(pid_t pid, int retval) if (git == in_progress_.end()) { lyxerr << "PreviewLoader::finishedGenerating(): unable to find " "data for PID " << pid << endl; + finished_generating_ = true; return; } @@ -747,8 +779,11 @@ void PreviewLoader::Impl::finishedGenerating(pid_t pid, int retval) LYXERR(Debug::GRAPHICS, "PreviewLoader::finishedInProgress(" << retval << "): processing " << status << " for " << command); - if (retval > 0) + if (retval > 0) { + in_progress_.erase(git); + finished_generating_ = true; return; + } // Read the metrics file, if it exists vector ascent_fractions(git->second.snippets.size()); @@ -789,6 +824,7 @@ void PreviewLoader::Impl::finishedGenerating(pid_t pid, int retval) for (; nit != nend; ++nit) { imageReady(*nit->get()); } + finished_generating_ = true; } @@ -851,3 +887,5 @@ void PreviewLoader::Impl::dumpData(odocstream & os, } // namespace graphics } // namespace lyx + +#include "moc_PreviewLoader.cpp"