X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetBranch.cpp;h=ad7cbc5cdc21fb6f83efc517a2be06a1842790b8;hb=c0adb03a7ae15cf6409ee3cb64f4cc91c24c052e;hp=01cd795bd9ff4cf622d50c37048247625b852cab;hpb=832d6cd7e1017b11058048a9dc6930ec08aee30c;p=lyx.git diff --git a/src/insets/InsetBranch.cpp b/src/insets/InsetBranch.cpp index 01cd795bd9..ad7cbc5cdc 100644 --- a/src/insets/InsetBranch.cpp +++ b/src/insets/InsetBranch.cpp @@ -17,12 +17,12 @@ #include "BufferView.h" #include "BranchList.h" #include "ColorSet.h" -#include "Counters.h" #include "Cursor.h" #include "DispatchResult.h" #include "FuncRequest.h" #include "FuncStatus.h" #include "Lexer.h" +#include "LyX.h" #include "OutputParams.h" #include "output_xhtml.h" #include "TextClass.h" @@ -32,6 +32,7 @@ #include "support/gettext.h" #include "support/lstrings.h" +#include "frontends/alert.h" #include "frontends/Application.h" #include @@ -42,7 +43,7 @@ using namespace std; namespace lyx { InsetBranch::InsetBranch(Buffer * buf, InsetBranchParams const & params) - : InsetCollapsable(buf, InsetText::DefaultLayout), params_(params) + : InsetCollapsible(buf, InsetText::DefaultLayout), params_(params) {} @@ -51,50 +52,80 @@ void InsetBranch::write(ostream & os) const os << "Branch "; params_.write(os); os << '\n'; - InsetCollapsable::write(os); + InsetCollapsible::write(os); } void InsetBranch::read(Lexer & lex) { params_.read(lex); - InsetCollapsable::read(lex); + InsetCollapsible::read(lex); } docstring InsetBranch::toolTip(BufferView const & bv, int, int) const { - docstring const status = isBranchSelected() ? + docstring const masterstatus = isBranchSelected() ? _("active") : _("non-active"); - docstring const heading = - support::bformat(_("Branch (%1$s): %2$s"), status, params_.branch); + docstring const childstatus = isBranchSelected(true) ? + _("active") : _("non-active"); + docstring const status = (masterstatus == childstatus) ? + masterstatus : + support::bformat(_("master %1$s, child %2$s"), + masterstatus, childstatus); + + docstring const masteron = producesOutput() ? + _("on") : _("off"); + docstring const childon = + (isBranchSelected(true) != params_.inverted) ? + _("on") : _("off"); + docstring const onoff = (masteron == childon) ? + masteron : + support::bformat(_("master %1$s, child %2$s"), + masteron, childon); + + docstring const heading = + support::bformat(_("Branch Name: %1$s\nBranch Status: %2$s\nInset Status: %3$s"), + params_.branch, status, onoff); + if (isOpen(bv)) return heading; return toolTipText(heading + from_ascii("\n")); } -docstring const InsetBranch::buttonLabel(BufferView const & bv) const +docstring const InsetBranch::buttonLabel(BufferView const &) const { - docstring s = _("Branch: ") + params_.branch; + static char_type const tick = 0x2714; // ✔ U+2714 HEAVY CHECK MARK + static char_type const cross = 0x2716; // ✖ U+2716 HEAVY MULTIPLICATION X + Buffer const & realbuffer = *buffer().masterBuffer(); BranchList const & branchlist = realbuffer.params().branchlist(); - if (!branchlist.find(params_.branch) - && buffer().params().branchlist().find(params_.branch)) - s = _("Branch (child only): ") + params_.branch; - else if (!branchlist.find(params_.branch)) - s = _("Branch (undefined): ") + params_.branch; - if (!params_.branch.empty()) { - // FIXME UNICODE - ColorCode c = lcolor.getFromLyXName(to_utf8(params_.branch)); - if (c == Color_none) - s = _("Undef: ") + s; - } - s = char_type(isBranchSelected() ? 0x2714 : 0x2716) + s; - if (decoration() == InsetLayout::CLASSIC) - return isOpen(bv) ? s : getNewLabel(s); - else - return params_.branch + ": " + getNewLabel(s); + bool const inmaster = branchlist.find(params_.branch); + bool const inchild = buffer().params().branchlist().find(params_.branch); + + bool const master_selected = producesOutput(); + bool const child_selected = isBranchSelected(true) != params_.inverted; + + docstring symb = docstring(1, master_selected ? tick : cross); + if (inchild && master_selected != child_selected) + symb += (child_selected ? tick : cross); + + if (decoration() == InsetLayout::MINIMALISTIC) + return symb + params_.branch; + + docstring s; + if (inmaster && inchild) + s = _("Branch: "); + else if (inchild) // && !inmaster + s = _("Branch (child): "); + else if (inmaster) // && !inchild + s = _("Branch (master): "); + else // !inmaster && !inchild + s = _("Branch (undefined): "); + s += params_.branch; + + return symb + s; } @@ -117,41 +148,84 @@ void InsetBranch::doDispatch(Cursor & cur, FuncRequest & cmd) InsetBranchParams params; InsetBranch::string2params(to_utf8(cmd.argument()), params); - cur.recordUndoInset(ATOMIC_UNDO, this); + cur.recordUndoInset(this); params_.branch = params.branch; + params_.inverted = params.inverted; // what we really want here is a TOC update, but that means // a full buffer update cur.forceBufferUpdate(); break; } case LFUN_BRANCH_ACTIVATE: - case LFUN_BRANCH_DEACTIVATE: { - // FIXME: I do not like this cast, but have no other idea... - Buffer const * buf = buffer().masterBuffer(); - BranchList const & branchlist = buf->params().branchlist(); - Branch * our_branch = const_cast(branchlist.find(params_.branch)); - if (!our_branch) { - // child only? - our_branch = buffer().params().branchlist().find(params_.branch); - if (!our_branch) - break; - } - bool const activate = (cmd.action() == 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); + Buffer * buf = master ? const_cast(buffer().masterBuffer()) + : &buffer(); + + Branch * our_branch = buf->params().branchlist().find(params_.branch); + if (!our_branch) + break; + + bool const activate = (cmd.action() == LFUN_BRANCH_ACTIVATE + || cmd.action() == LFUN_BRANCH_MASTER_ACTIVATE); if (our_branch->isSelected() != activate) { + // FIXME If the branch is in the master document, we cannot + // call recordUndo..., because the master may be hidden, and + // the code presently assumes that hidden documents can never + // be dirty. See GuiView::closeBufferAll(), for example. + // An option would be to check if the master is hidden. + // If it is, unhide. + if (!master) + buffer().undo().recordUndoBufferParams(cur); + else + // 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."), params_.branch), true); our_branch->setSelected(activate); - cur.forceBufferUpdate(); + // 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(params_.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(); } break; } + case LFUN_BRANCH_INVERT: + cur.recordUndoInset(this); + params_.inverted = !params_.inverted; + // what we really want here is a TOC update, but that means + // a full buffer update + cur.forceBufferUpdate(); + break; + case LFUN_BRANCH_ADD: + lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, params_.branch)); + break; case LFUN_INSET_TOGGLE: if (cmd.argument() == "assign") setStatus(cur, isBranchSelected() ? Open : Collapsed); else - InsetCollapsable::doDispatch(cur, cmd); + InsetCollapsible::doDispatch(cur, cmd); break; default: - InsetCollapsable::doDispatch(cur, cmd); + InsetCollapsible::doDispatch(cur, cmd); break; } } @@ -160,36 +234,58 @@ void InsetBranch::doDispatch(Cursor & cur, FuncRequest & cmd) bool InsetBranch::getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus & flag) const { + bool const known_branch = + buffer().params().branchlist().find(params_.branch); + switch (cmd.action()) { case LFUN_INSET_MODIFY: flag.setEnabled(true); break; case LFUN_BRANCH_ACTIVATE: - flag.setEnabled(!isBranchSelected()); + flag.setEnabled(known_branch && !isBranchSelected(true)); + break; + + case LFUN_BRANCH_INVERT: + flag.setEnabled(true); + flag.setOnOff(params_.inverted); + break; + + case LFUN_BRANCH_ADD: + flag.setEnabled(!known_branch); break; case LFUN_BRANCH_DEACTIVATE: - flag.setEnabled(isBranchSelected()); + flag.setEnabled(isBranchSelected(true)); + break; + + case LFUN_BRANCH_MASTER_ACTIVATE: + flag.setEnabled(buffer().parent() + && buffer().masterBuffer()->params().branchlist().find(params_.branch) + && !isBranchSelected()); + break; + + case LFUN_BRANCH_MASTER_DEACTIVATE: + flag.setEnabled(buffer().parent() && isBranchSelected()); break; case LFUN_INSET_TOGGLE: if (cmd.argument() == "assign") flag.setEnabled(true); else - return InsetCollapsable::getStatus(cur, cmd, flag); + return InsetCollapsible::getStatus(cur, cmd, flag); break; default: - return InsetCollapsable::getStatus(cur, cmd, flag); + return InsetCollapsible::getStatus(cur, cmd, flag); } return true; } -bool InsetBranch::isBranchSelected() const +bool InsetBranch::isBranchSelected(bool const child) const { - Buffer const & realbuffer = *buffer().masterBuffer(); + Buffer const & realbuffer = child ? buffer() : *buffer().masterBuffer(); BranchList const & branchlist = realbuffer.params().branchlist(); Branch const * ourBranch = branchlist.find(params_.branch); @@ -203,65 +299,84 @@ bool InsetBranch::isBranchSelected() const } -int InsetBranch::latex(odocstream & os, OutputParams const & runparams) const +bool InsetBranch::producesOutput() const { - return isBranchSelected() ? InsetText::latex(os, runparams) : 0; + return isBranchSelected() != params_.inverted; } -int InsetBranch::plaintext(odocstream & os, - OutputParams const & runparams) const +void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const { - if (!isBranchSelected()) - return 0; + if (producesOutput()) { + OutputParams rp = runparams; + rp.inbranch = true; + InsetText::latex(os, rp); + } +} - os << '[' << buffer().B_("branch") << ' ' << params_.branch << ":\n"; - InsetText::plaintext(os, runparams); - os << "\n]"; - return PLAINTEXT_NEWLINE + 1; // one char on a separate line +int InsetBranch::plaintext(odocstringstream & os, + OutputParams const & runparams, size_t max_length) const +{ + if (!producesOutput()) + return 0; + + int len = InsetText::plaintext(os, runparams, max_length); + return len; } int InsetBranch::docbook(odocstream & os, OutputParams const & runparams) const { - return isBranchSelected() ? InsetText::docbook(os, runparams) : 0; + return producesOutput() ? InsetText::docbook(os, runparams) : 0; } docstring InsetBranch::xhtml(XHTMLStream & xs, OutputParams const & rp) const { - if (isBranchSelected()) - return InsetText::xhtml(xs, rp); + if (producesOutput()) { + OutputParams newrp = rp; + newrp.par_begin = 0; + newrp.par_end = text().paragraphs().size(); + xhtmlParagraphs(text(), buffer(), xs, newrp); + } return docstring(); } void InsetBranch::toString(odocstream & os) const { - if (isBranchSelected()) - InsetCollapsable::toString(os); + if (producesOutput()) + InsetCollapsible::toString(os); +} + + +void InsetBranch::forOutliner(docstring & os, size_t const maxlen, + bool const shorten) const +{ + if (producesOutput()) + InsetCollapsible::forOutliner(os, maxlen, shorten); } void InsetBranch::validate(LaTeXFeatures & features) const { - if (isBranchSelected()) - InsetCollapsable::validate(features); + if (producesOutput()) + InsetCollapsible::validate(features); } -docstring InsetBranch::contextMenuName() const +string InsetBranch::contextMenuName() const { - return from_ascii("context-branch"); + return "context-branch"; } -bool InsetBranch::isMacroScope() const +bool InsetBranch::isMacroScope() const { // Its own scope if not selected by buffer - return !isBranchSelected(); + return !producesOutput(); } @@ -287,28 +402,29 @@ void InsetBranch::string2params(string const & in, InsetBranchParams & params) } -void InsetBranch::addToToc(DocIterator const & cpit) +void InsetBranch::updateBuffer(ParIterator const & it, UpdateType utype, bool const deleted) { - DocIterator pit = cpit; - pit.push_back(CursorSlice(*this)); - - Toc & toc = buffer().tocBackend().toc("branch"); - docstring const str = params_.branch + ": " + text().getPar(0).asString(); - toc.push_back(TocItem(pit, 0, str, toolTipText())); - // Proceed with the rest of the inset. - InsetCollapsable::addToToc(cpit); + setLabel(params_.branch + (params_.inverted ? " (-)" : "")); + InsetCollapsible::updateBuffer(it, utype, deleted); } void InsetBranchParams::write(ostream & os) const { - os << to_utf8(branch); + os << to_utf8(branch) + << '\n' + << "inverted " + << inverted; } void InsetBranchParams::read(Lexer & lex) { - lex >> branch; + // There may be a space in branch name + // if we wanted to use lex>>, the branch name should be properly in quotes + lex.eatLine(); + branch = lex.getDocString(); + lex >> "inverted" >> inverted; } } // namespace lyx