]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Attempt to fix bug #13017.
[lyx.git] / src / Buffer.cpp
index a7f6588f4b4a100ac143e13941ecf1bbe0a3edd5..7522dce4343938d433bf26fed31bada34d1be385 100644 (file)
@@ -802,6 +802,12 @@ Undo & Buffer::undo()
 }
 
 
+Undo const & Buffer::undo() const
+{
+       return d->undo_;
+}
+
+
 void Buffer::setChild(DocIterator const & dit, Buffer * child)
 {
        d->children_positions[child] = dit;
@@ -2416,7 +2422,7 @@ void Buffer::validate(LaTeXFeatures & features) const
 }
 
 
-void Buffer::getLabelList(vector<std::pair<docstring, docstring>> & list) const
+void Buffer::getLabelList(vector<std::tuple<docstring, docstring, docstring>> & list) const
 {
        // If this is a child document, use the master's list instead.
        if (parent()) {
@@ -2427,8 +2433,9 @@ void Buffer::getLabelList(vector<std::pair<docstring, docstring>> & list) const
        list.clear();
        shared_ptr<Toc> toc = d->toc_backend.toc("label");
        for (auto const & tocit : *toc) {
-               if (tocit.depth() == 0)
-                       list.push_back(make_pair(tocit.str(), tocit.asString()));
+               if (tocit.depth() == 0) {
+                       list.push_back(make_tuple(tocit.str(), tocit.asString(), tocit.prettyStr()));
+               }
        }
 }
 
@@ -2682,6 +2689,11 @@ bool Buffer::citeLabelsValid() const
 
 void Buffer::removeBiblioTempFiles() const
 {
+       if (theApp()->isBufferBusy(this)) {
+               removeBiblioTemps = true;
+               return;
+       }
+
        // We remove files that contain LaTeX commands specific to the
        // particular bibliographic style being used, in order to avoid
        // LaTeX errors when we switch style.
@@ -2695,6 +2707,7 @@ void Buffer::removeBiblioTempFiles() const
        Buffer const * const pbuf = parent();
        if (pbuf)
                pbuf->removeBiblioTempFiles();
+       removeBiblioTemps = false;
 }
 
 
@@ -2713,6 +2726,24 @@ void Buffer::markDepClean(string const & name)
 }
 
 
+bool Buffer::branchActivationEnabled(FuncCode act, docstring const & branch) const
+{
+       bool const master = act == LFUN_BRANCH_MASTER_ACTIVATE
+                           || act == LFUN_BRANCH_MASTER_DEACTIVATE;
+       bool const activate = act == LFUN_BRANCH_ACTIVATE
+                           || act == LFUN_BRANCH_MASTER_ACTIVATE;
+       Buffer const * buf = master ? masterBuffer() : this;
+       Branch const * our_branch = buf->params().branchlist().find(branch);
+       // Can be disabled if
+       // - this is  a _MASTER_ command and there is no master
+       // - the relevant buffer does not know the branch
+       // - the branch is already in the desired state
+       return ((!master || parent() != nullptr)
+               && !branch.empty() && our_branch
+               && our_branch->isSelected() != activate);
+}
+
+
 bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) const
 {
        if (isInternal()) {
@@ -2764,15 +2795,12 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) const
        case LFUN_BRANCH_ACTIVATE:
        case LFUN_BRANCH_DEACTIVATE:
        case LFUN_BRANCH_MASTER_ACTIVATE:
-       case LFUN_BRANCH_MASTER_DEACTIVATE: {
-               bool const master = (cmd.action() == LFUN_BRANCH_MASTER_ACTIVATE
-                                    || cmd.action() == LFUN_BRANCH_MASTER_DEACTIVATE);
-               BranchList const & branchList = master ? masterBuffer()->params().branchlist()
-                       : params().branchlist();
-               docstring const & branchName = cmd.argument();
-               flag.setEnabled(!branchName.empty() && branchList.find(branchName));
+       case LFUN_BRANCH_MASTER_DEACTIVATE:
+               // Let a branch inset handle that
+               if (cmd.argument().empty())
+                       return false;
+               flag.setEnabled(branchActivationEnabled(cmd.action(), cmd.argument()));
                break;
-       }
 
        case LFUN_BRANCH_ADD:
        case LFUN_BRANCHES_RENAME:
@@ -2817,6 +2845,53 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) const
 }
 
 
+bool Buffer::branchActivationDispatch(FuncCode act, docstring const & branch)
+{
+       bool const master = (act == LFUN_BRANCH_MASTER_ACTIVATE
+                            || act == LFUN_BRANCH_MASTER_DEACTIVATE);
+       bool const activate = (act == LFUN_BRANCH_ACTIVATE
+                              || act == LFUN_BRANCH_MASTER_ACTIVATE);
+       Buffer * buf = master ? const_cast<Buffer *>(masterBuffer()) : this;
+       Branch * our_branch = buf->params().branchlist().find(branch);
+
+       // See comment in branchActivationStatus
+       if ((master && parent() == nullptr)
+            || !our_branch
+            || our_branch->isSelected() == activate)
+               return false;
+
+       if (master && !buf->hasGuiDelegate()
+           && (!theApp() || !theApp()->unhide(buf)))
+               // at least issue a warning for now (ugly, but better than dataloss).
+               frontend::Alert::warning(_("Branch state changes in master document"),
+                   lyx::support::bformat(_("The state of the branch '%1$s' "
+                       "was changed in the master file. "
+                       "Please make sure to save the master."), branch), true);
+
+       UndoGroupHelper ugh(buf);
+       buf->undo().recordUndoBufferParams(CursorData());
+       our_branch->setSelected(activate);
+       // cur.forceBufferUpdate() is not enough)
+       buf->updateBuffer();
+
+       // if branch exists in a descendant, update previews.
+       // TODO: only needed if "Show preview" is enabled in the included inset.
+       bool exists_in_desc = false;
+       for (auto const & it : buf->getDescendants()) {
+               if (it->params().branchlist().find(branch))
+                       exists_in_desc = true;
+       }
+       if (exists_in_desc) {
+               // TODO: ideally we would only update the previews of the
+               // specific children that have this branch directly or
+               // in one of their descendants
+               buf->removePreviews();
+               buf->updatePreviews();
+       }
+       return true;
+}
+
+
 void Buffer::dispatch(string const & command, DispatchResult & result)
 {
        return dispatch(lyxaction.lookupFunc(command), result);
@@ -2828,6 +2903,7 @@ void Buffer::dispatch(string const & command, DispatchResult & result)
 // whether we have a GUI or not. The boolean use_gui holds this information.
 void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
 {
+       LYXERR(Debug::ACTION, "Buffer::dispatch: cmd: " << func);
        if (isInternal()) {
                // FIXME? if there is an Buffer LFUN that can be dispatched even
                // if internal, put a switch '(cmd.action())' here.
@@ -2926,35 +3002,15 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
        case LFUN_BRANCH_DEACTIVATE:
        case LFUN_BRANCH_MASTER_ACTIVATE:
        case LFUN_BRANCH_MASTER_DEACTIVATE: {
-               bool const master = (func.action() == LFUN_BRANCH_MASTER_ACTIVATE
-                                    || func.action() == LFUN_BRANCH_MASTER_DEACTIVATE);
-               Buffer * buf = master ? const_cast<Buffer *>(masterBuffer())
-                                     : this;
-
-               docstring const & branch_name = func.argument();
-               // the case without a branch name is handled elsewhere
-               if (branch_name.empty()) {
-                       dispatched = false;
-                       break;
-               }
-               Branch * branch = buf->params().branchlist().find(branch_name);
-               if (!branch) {
-                       LYXERR0("Branch " << branch_name << " does not exist.");
-                       dr.setError(true);
-                       docstring const msg =
-                               bformat(_("Branch \"%1$s\" does not exist."), branch_name);
-                       dr.setMessage(msg);
-                       break;
+               // Let a branch inset handle that
+               if (func.argument().empty()) {
+                       dr.dispatched(false);
+                       return;
                }
-               bool const activate = (func.action() == LFUN_BRANCH_ACTIVATE
-                                      || func.action() == LFUN_BRANCH_MASTER_ACTIVATE);
-               if (branch->isSelected() != activate) {
-                       buf->undo().recordUndoBufferParams(CursorData());
-                       branch->setSelected(activate);
-                       dr.setError(false);
+               bool const res = branchActivationDispatch(func.action(), func.argument());
+               dr.setError(!res);
+               if (res)
                        dr.screenUpdate(Update::Force);
-                       dr.forceBufferUpdate();
-               }
                break;
        }
 
@@ -5292,6 +5348,10 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const
 
 void Buffer::updateBuffer(ParIterator & parit, UpdateType utype, bool const deleted) const
 {
+       // if fomatted references are shown in workarea update buffer accordingly
+       if (params().use_formatted_ref)
+               utype = OutputUpdate;
+
        pushIncludedBuffer(this);
        // LASSERT: Is it safe to continue here, or should we just return?
        LASSERT(parit.pit() == 0, /**/);
@@ -5661,15 +5721,24 @@ void Buffer::Impl::fileExternallyModified(bool const exists)
                       "checksum unchanged: " << filename);
                return;
        }
+       lyx_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;
+               externally_modified_ = true;
        // Update external modification notification.
        // Dirty buffers must be visible at all times.
-       if (wa_ && wa_->unhide(owner_))
+       if (wa_ && wa_->unhide(owner_)) {
                wa_->updateTitles();
+               if (!exists) {
+                       frontend::Alert::warning(
+                               _("File deleted from disk"),
+                               bformat(_("The file\n  %1$s\n"
+                                          "has been deleted from disk!"),
+                                       from_utf8(filename.absFileName())));
+               }
+       }
        else
                // Unable to unhide the buffer (e.g. no GUI or not current View)
                lyx_clean = true;