X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=inline;f=src%2FBuffer.cpp;h=61b89200c17a7b784205965985077d02fdb2e9a6;hb=28be7d552f62cc02fa86d7f79201d089bfb2d7b5;hp=5c46fb3d45ad7ac5436d1c2d7d36e0859c14c280;hpb=656bc46892c2041437111dfff697957530e75ec2;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 5c46fb3d45..61b89200c1 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -379,14 +379,11 @@ public: // Make sure the file monitor monitors the good file. void refreshFileMonitor(); - /// has it been notified of an external modification? - bool isExternallyModified() const { return externally_modified_; } - /// Notify or clear of external modification - void fileExternallyModified(bool modified) const; + void fileExternallyModified(bool exists); - /// Block notifications of external modifications - FileMonitorBlocker blockFileMonitor() { return file_monitor_->block(10); } + /// has been externally modified? Can be reset by the user. + mutable bool externally_modified_; private: /// So we can force access via the accessors. @@ -396,9 +393,6 @@ private: int char_count_; int blank_count_; - /// has been externally modified? Can be reset by the user. - mutable bool externally_modified_; - FileMonitorPtr file_monitor_; }; @@ -440,9 +434,8 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_, bibfile_cache_valid_(false), cite_labels_valid_(false), preview_error_(false), inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer), clone_list_(0), doing_export(false), - tracked_changes_present_(0), parent_buffer(0), - word_count_(0), char_count_(0), blank_count_(0), - externally_modified_(false) + tracked_changes_present_(0), externally_modified_(false), parent_buffer(0), + word_count_(0), char_count_(0), blank_count_(0) { refreshFileMonitor(); if (!cloned_buffer_) { @@ -553,7 +546,11 @@ Buffer::~Buffer() if (!isClean()) { docstring msg = _("LyX attempted to close a document that had unsaved changes!\n"); - msg += emergencyWrite(); + try { + msg += emergencyWrite(); + } catch (...) { + msg += " " + _("Save failed! Document is lost."); + } Alert::warning(_("Attempting to close changed document!"), msg); } @@ -725,7 +722,7 @@ BufferParams const & Buffer::masterParams() const double Buffer::fontScalingFactor() const { return isExporting() ? 75.0 * params().html_math_img_scale - : 0.01 * lyxrc.dpi * lyxrc.zoom * lyxrc.preview_scale_factor * params().display_pixel_ratio; + : 0.01 * lyxrc.dpi * lyxrc.currentZoom * lyxrc.preview_scale_factor * params().display_pixel_ratio; } @@ -834,7 +831,7 @@ string Buffer::logName(LogType * type) const FileName const bname( addName(path, onlyFileName( changeExtension(filename, - formats.extension(params().bufferFormat()) + ".out")))); + theFormats().extension(params().bufferFormat()) + ".out")))); // Also consider the master buffer log file FileName masterfname = fname; @@ -1085,7 +1082,7 @@ bool Buffer::readDocument(Lexer & lex) bool Buffer::importString(string const & format, docstring const & contents, ErrorList & errorList) { - Format const * fmt = formats.getFormat(format); + Format const * fmt = theFormats().getFormat(format); if (!fmt) return false; // It is important to use the correct extension here, since some @@ -1199,7 +1196,7 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn) d->file_fully_loaded = true; d->read_only = !d->filename.isWritable(); - params().compressed = formats.isZippedFile(d->filename); + params().compressed = theFormats().isZippedFile(d->filename); saveCheckSum(); return ReadSuccess; } @@ -1313,7 +1310,7 @@ Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, command << os::python() << ' ' << quoteName(lyx2lyx.toFilesystemEncoding()) << " -t " << convert(LYX_FORMAT) - << " -o " << quoteName(tmpfile.toFilesystemEncoding()) + << " -o " << quoteName(tmpfile.toSafeFilesystemEncoding()) << ' ' << quoteName(fn.toSafeFilesystemEncoding()); string const command_str = command.str(); @@ -1379,7 +1376,6 @@ FileName Buffer::getBackupName() const { // Should probably be moved to somewhere else: BufferView? GuiView? bool Buffer::save() const { - FileMonitorBlocker block = d->blockFileMonitor(); docstring const file = makeDisplayPath(absFileName(), 20); d->filename.refresh(); @@ -1606,7 +1602,7 @@ docstring Buffer::emergencyWrite() return user_message; } - user_message += " " + _("Save failed! Bummer. Document is lost."); + user_message += " " + _("Save failed! Document is lost."); // Don't try again. markClean(); return user_message; @@ -1741,6 +1737,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname, catch (exception const & e) { errorList.push_back(ErrorItem(_("conversion failed"), _(e.what()))); + lyxerr << e.what() << endl; failed_export = true; } catch (...) { @@ -2535,7 +2532,7 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) switch (cmd.action()) { case LFUN_BUFFER_TOGGLE_READ_ONLY: - flag.setOnOff(isReadonly()); + flag.setOnOff(hasReadonlyFlag()); break; // FIXME: There is need for a command-line import. @@ -2659,7 +2656,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) dr.setMessage(log); } else - setReadonly(!isReadonly()); + setReadonly(!hasReadonlyFlag()); break; case LFUN_BUFFER_EXPORT: { @@ -2688,7 +2685,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) case LFUN_BUFFER_EXPORT_CUSTOM: { string format_name; string command = split(argument, format_name, ' '); - Format const * format = formats.getFormat(format_name); + Format const * format = theFormats().getFormat(format_name); if (!format) { lyxerr << "Format \"" << format_name << "\" not recognized!" @@ -2847,7 +2844,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) } case LFUN_BUFFER_VIEW_CACHE: - if (!formats.view(*this, d->preview_file_, + if (!theFormats().view(*this, d->preview_file_, d->preview_format_)) dr.setMessage(_("Error viewing the output file.")); break; @@ -3262,12 +3259,18 @@ void Buffer::setLayoutPos(string const & path) } -bool Buffer::isReadonly() const +bool Buffer::hasReadonlyFlag() const { return d->read_only; } +bool Buffer::isReadonly() const +{ + return hasReadonlyFlag() || notifiesExternalModification(); +} + + void Buffer::setParent(Buffer const * buffer) { // Avoids recursive include. @@ -3938,6 +3941,7 @@ unique_ptr Buffer::getSourceCode(odocstream & os, string const & format, ots.texrow().newlines(2); if (master) runparams.is_child = true; + updateBuffer(); writeLaTeXSource(ots, string(), runparams, output); texrow = ots.releaseTexRow(); } @@ -4144,7 +4148,7 @@ void Buffer::moveAutosaveFile(support::FileName const & oldauto) const bool Buffer::autoSave() const { Buffer const * buf = d->cloned_buffer_ ? d->cloned_buffer_ : this; - if (buf->d->bak_clean || isReadonly()) + if (buf->d->bak_clean || hasReadonlyFlag()) return true; message(_("Autosaving current document...")); @@ -4274,7 +4278,7 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir // file (not for previewing). Alert::error(_("Couldn't export file"), bformat( _("No information for exporting the format %1$s."), - formats.prettyName(format))); + theFormats().prettyName(format))); } return ExportNoPathToFormat; } @@ -4304,7 +4308,7 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir string filename = latexName(false); filename = addName(temppath(), filename); filename = changeExtension(filename, - formats.extension(backend_format)); + theFormats().extension(backend_format)); LYXERR(Debug::FILES, "filename=" << filename); // Plain text backend @@ -4350,7 +4354,7 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir string const error_type = (format == "program") ? "Build" : params().bufferFormat(); ErrorList & error_list = d->errorLists[error_type]; - string const ext = formats.extension(format); + string const ext = theFormats().extension(format); FileName const tmp_result_file(changeExtension(filename, ext)); bool const success = converters.convert(this, FileName(filename), tmp_result_file, FileName(absFileName()), backend_format, format, @@ -4418,7 +4422,7 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir vector::const_iterator it = files.begin(); vector::const_iterator const en = files.end(); for (; it != en && status != CANCEL; ++it) { - string const fmt = formats.getFormatFromFile(it->sourceName); + string const fmt = theFormats().getFormatFromFile(it->sourceName); string fixedName = it->exportName; if (!runparams.export_folder.empty()) { // Relative pathnames starting with ../ will be sanitized @@ -4454,13 +4458,13 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir } else { message(bformat(_("Document exported as %1$s " "to file `%2$s'"), - formats.prettyName(format), + theFormats().prettyName(format), makeDisplayPath(result_file))); } } else { // This must be a dummy converter like fax (bug 1888) message(bformat(_("Document exported as %1$s"), - formats.prettyName(format))); + theFormats().prettyName(format))); } return success ? ExportSuccess : ExportConverterError; @@ -4499,7 +4503,7 @@ Buffer::ExportStatus Buffer::preview(string const & format, bool includeall) con return status; if (previewFile.exists()) - return formats.view(*this, previewFile, format) ? + return theFormats().view(*this, previewFile, format) ? PreviewSuccess : PreviewError; // Successful export but no output file? @@ -4541,7 +4545,7 @@ Buffer::ReadStatus Buffer::loadEmergency() ReadStatus const ret_llf = loadThisLyXFile(emergencyFile); bool const success = (ret_llf == ReadSuccess); if (success) { - if (isReadonly()) { + if (hasReadonlyFlag()) { Alert::warning(_("File is read-only"), bformat(_("An emergency file is successfully loaded, " "but the original file %1$s is marked read-only. " @@ -4604,7 +4608,7 @@ Buffer::ReadStatus Buffer::loadAutosave() ReadStatus const ret_llf = loadThisLyXFile(autosaveFile); // the file is not saved if we load the autosave file. if (ret_llf == ReadSuccess) { - if (isReadonly()) { + if (hasReadonlyFlag()) { Alert::warning(_("File is read-only"), bformat(_("A backup file is successfully loaded, " "but the original file %1$s is marked read-only. " @@ -4751,16 +4755,17 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const ParIterator parit = cbuf.par_iterator_begin(); updateBuffer(parit, utype); - /// FIXME: Perf - /// Update the tocBackend for any buffer. The outliner uses the master's, - /// and the navigation menu uses the child's. - cbuf.tocBackend().update(true, utype); - if (master != this) + // If this document has siblings, then update the TocBackend later. The + // reason is to ensure that later siblings are up to date when e.g. the + // broken or not status of references is computed. The update is called + // in InsetInclude::addToToc. return; d->bibinfo_cache_valid_ = true; d->cite_labels_valid_ = true; + /// FIXME: Perf + cbuf.tocBackend().update(true, utype); if (scope == UpdateMaster) cbuf.structureChanged(); } @@ -5311,38 +5316,57 @@ void Buffer::updateChangesPresent() const void Buffer::Impl::refreshFileMonitor() { - if (file_monitor_ && file_monitor_->filename() == filename.absFileName()) - return file_monitor_->refresh(); + if (file_monitor_ && file_monitor_->filename() == filename.absFileName()) { + file_monitor_->refresh(); + return; + } // The previous file monitor is invalid // This also destroys the previous file monitor and all its connections file_monitor_ = FileSystemWatcher::monitor(filename); - fileExternallyModified(false); // file_monitor_ will be destroyed with *this, so it is not going to call a // destroyed object method. - file_monitor_->connect([this](){ fileExternallyModified(true); }); + file_monitor_->connect([this](bool exists) { + fileExternallyModified(exists); + }); } -void Buffer::Impl::fileExternallyModified(bool modified) const +void Buffer::Impl::fileExternallyModified(bool const exists) { - if (modified) - lyx_clean = bak_clean = false; - externally_modified_ = modified; - if (wa_) + // ignore notifications after our own saving operations + if (checksum_ == filename.checksum()) { + LYXERR(Debug::FILES, "External modification but " + "checksum unchanged: " << filename); + return; + } + lyx_clean = bak_clean = false; + // If the file has been deleted, only mark the file as dirty since it is + // pointless to prompt for reloading. If later a file is moved into this + // location, then the externally modified warning will appear then. + if (exists) + externally_modified_ = true; + // Update external modification notification. + // Dirty buffers must be visible at all times. + if (wa_ && wa_->unhide(owner_)) wa_->updateTitles(); + else + // Unable to unhide the buffer (e.g. no GUI or not current View) + lyx_clean = true; } bool Buffer::notifiesExternalModification() const { - return d->isExternallyModified(); + return d->externally_modified_; } void Buffer::clearExternalModification() const { - d->fileExternallyModified(false); + d->externally_modified_ = false; + if (d->wa_) + d->wa_->updateTitles(); }