Introduce "inverted" branch insets: These are branches whose content

is output when a branch is NOT activated. Fixes bug #7698.

At the moment, inversion is controlled through the branch settings
dialog. There is no provision for inserting inverted insets directly,
or for changing them from the context menu. Both of these could be
done, of course. The latter would need LFUN_BRANCH_TOGGLE_INVERTED.
This commit is contained in:
Richard Heck 2016-07-11 23:56:32 -04:00
parent ed87044d91
commit 5df323a0dd
7 changed files with 146 additions and 26 deletions

View File

@ -11,6 +11,10 @@ adjustments are made to tex2lyx and bugs are fixed in lyx2lyx.
----------------------- -----------------------
2016-07-11 Richard Heck <rgheck@lyx.org>
* Format incremented to 511
Added "inverted" branches
2016-06-19 Georg Baum <Georg.Baum@post.rwth-aachen.de> 2016-06-19 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* Format incremented to 510 * Format incremented to 510
Removed external date inset Removed external date inset

View File

@ -93,6 +93,88 @@ def convert_dateinset(document):
continue continue
def convert_ibranches(document):
' Add "inverted 0" to branch insets'
i = 0
while True:
i = find_token(document.body, "\\begin_inset Branch", i)
if i == -1:
return
document.body.insert(i + 1, "inverted 0")
i += 1
def revert_ibranches(document):
' Convert inverted branches to explicit anti-branches'
# Get list of branches
ourbranches = {}
i = 0
while True:
i = find_token(document.header, "\\branch", i)
if i == -1:
break
branch = document.header[i][8:].strip()
if document.header[i+1].startswith("\\selected "):
#document.warning(document.header[i+1])
#document.warning(document.header[i+1][10])
selected = int(document.header[i+1][10])
else:
document.warning("Malformed LyX document: No selection indicator for branch " + branch)
selected = 1
# the value tells us whether the branch is selected
ourbranches[document.header[i][8:].strip()] = selected
i += 1
# Figure out what inverted branches, if any, have been used
# and convert them to "Anti-OldBranch"
ibranches = {}
i = 0
while True:
i = find_token(document.body, "\\begin_inset Branch", i)
if i == -1:
break
if not document.body[i+1].startswith("inverted "):
document.warning("Malformed LyX document: Missing 'inverted' tag!")
i += 1
continue
inverted = document.body[i+1][9]
#document.warning(document.body[i+1])
if inverted == "1":
branch = document.body[i][20:].strip()
#document.warning(branch)
if not branch in ibranches:
antibranch = "Anti-" + branch
while antibranch in ibranches:
antibranch = "x" + antibranch
ibranches[branch] = antibranch
else:
antibranch = ibranches[branch]
#document.warning(antibranch)
document.body[i] = "\\begin_inset Branch " + antibranch
# remove "inverted" key
del document.body[i+1]
i += 1
# now we need to add the new branches to the header
for old, new in ibranches.iteritems():
i = find_token(document.header, "\\branch " + old, 0)
if i == -1:
document.warning("Can't find branch %s even though we found it before!" % (old))
continue
j = find_token(document.header, "\\end_branch", i)
if j == -1:
document.warning("Malformed LyX document! Can't find end of branch " + old)
continue
# ourbranches[old] - 1 inverts the selection status of the old branch
lines = ["\\branch " + new,
"\\selected " + str(ourbranches[old] - 1)]
# these are the old lines telling us color, etc.
lines += document.header[i+2 : j+1]
document.header[i:i] = lines
## ##
# Conversion hub # Conversion hub
@ -101,10 +183,12 @@ def convert_dateinset(document):
supported_versions = ["2.3.0", "2.3"] supported_versions = ["2.3.0", "2.3"]
convert = [ convert = [
[509, [convert_microtype]], [509, [convert_microtype]],
[510, [convert_dateinset]] [510, [convert_dateinset]],
[511, [convert_ibranches]]
] ]
revert = [ revert = [
[510, [revert_ibranches]],
[509, []], [509, []],
[508, [revert_microtype]] [508, [revert_microtype]]
] ]

View File

@ -33,6 +33,7 @@ GuiBranch::GuiBranch(QWidget * parent) : InsetParamsWidget(parent)
{ {
setupUi(this); setupUi(this);
connect(branchCO, SIGNAL(activated(int)), this, SIGNAL(changed())); connect(branchCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
connect(invertedCB, SIGNAL(clicked()), this, SIGNAL(changed()));
} }
@ -55,12 +56,13 @@ void GuiBranch::paramsToDialog(Inset const * inset)
id = count; id = count;
} }
branchCO->setCurrentIndex(id); branchCO->setCurrentIndex(id);
invertedCB->setChecked(ib->params().inverted);
} }
docstring GuiBranch::dialogToParams() const docstring GuiBranch::dialogToParams() const
{ {
InsetBranchParams params(qstring_to_ucs4(branchCO->currentText())); InsetBranchParams params(qstring_to_ucs4(branchCO->currentText()), invertedCB->isChecked());
return from_utf8(InsetBranch::params2string(params)); return from_utf8(InsetBranch::params2string(params));
} }
@ -68,6 +70,7 @@ docstring GuiBranch::dialogToParams() const
bool GuiBranch::checkWidgets(bool readonly) const bool GuiBranch::checkWidgets(bool readonly) const
{ {
branchCO->setEnabled(!readonly); branchCO->setEnabled(!readonly);
invertedCB->setEnabled(!readonly);
return InsetParamsWidget::checkWidgets(); return InsetParamsWidget::checkWidgets();
} }

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>BranchUi</class> <class>BranchUi</class>
<widget class="QWidget" name="BranchUi"> <widget class="QWidget" name="BranchUi">
@ -6,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>259</width> <width>259</width>
<height>38</height> <height>62</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -30,6 +31,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="invertedCB">
<property name="text">
<string>Inverted</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>

View File

@ -74,7 +74,8 @@ docstring InsetBranch::toolTip(BufferView const & bv, int, int) const
masterstatus : masterstatus :
support::bformat(_("master: %1$s, child: %2$s"), support::bformat(_("master: %1$s, child: %2$s"),
masterstatus, childstatus); masterstatus, childstatus);
docstring const heading = docstring const heading = params_.inverted ?
support::bformat(_("Branch, inverted (%1$s): %2$s"), status, params_.branch) :
support::bformat(_("Branch (%1$s): %2$s"), status, params_.branch); support::bformat(_("Branch (%1$s): %2$s"), status, params_.branch);
if (isOpen(bv)) if (isOpen(bv))
return heading; return heading;
@ -86,6 +87,8 @@ docstring const InsetBranch::buttonLabel(BufferView const &) const
{ {
static char_type const tick = 0x2714; // ✔ U+2714 HEAVY CHECK MARK static char_type const tick = 0x2714; // ✔ U+2714 HEAVY CHECK MARK
static char_type const cross = 0x2716; // ✖ U+2716 HEAVY MULTIPLICATION X static char_type const cross = 0x2716; // ✖ U+2716 HEAVY MULTIPLICATION X
static char_type const itick = 0x271A; // ✚ U+271A HEAVY GREEK CROSS
static char_type const icross = 0x274E; // ❎ U+274E NEGATIVE SQUARED CROSS MARK
Buffer const & realbuffer = *buffer().masterBuffer(); Buffer const & realbuffer = *buffer().masterBuffer();
BranchList const & branchlist = realbuffer.params().branchlist(); BranchList const & branchlist = realbuffer.params().branchlist();
@ -95,9 +98,14 @@ docstring const InsetBranch::buttonLabel(BufferView const &) const
bool const master_selected = isBranchSelected(); bool const master_selected = isBranchSelected();
bool const child_selected = isBranchSelected(true); bool const child_selected = isBranchSelected(true);
docstring symb = docstring(1, master_selected ? tick : cross); docstring symb = docstring(1, master_selected ?
if (inchild && master_selected != child_selected) (params_.inverted ? icross : tick) :
symb += child_selected ? tick : cross; (params_.inverted ? itick: cross));
if (inchild && master_selected != child_selected) {
symb += child_selected ?
(params_.inverted ? icross : tick) :
(params_.inverted ? itick: cross);
}
if (decoration() == InsetLayout::MINIMALISTIC) if (decoration() == InsetLayout::MINIMALISTIC)
return symb + params_.branch; return symb + params_.branch;
@ -113,7 +121,7 @@ docstring const InsetBranch::buttonLabel(BufferView const &) const
s = _("Branch (undefined): "); s = _("Branch (undefined): ");
s += params_.branch; s += params_.branch;
return symb + s; return symb + s;
} }
@ -138,6 +146,7 @@ void InsetBranch::doDispatch(Cursor & cur, FuncRequest & cmd)
cur.recordUndoInset(this); cur.recordUndoInset(this);
params_.branch = params.branch; params_.branch = params.branch;
params_.inverted = params.inverted;
// what we really want here is a TOC update, but that means // what we really want here is a TOC update, but that means
// a full buffer update // a full buffer update
cur.forceBufferUpdate(); cur.forceBufferUpdate();
@ -261,7 +270,7 @@ bool InsetBranch::isBranchSelected(bool const child) const
void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const
{ {
if (isBranchSelected()) if (isBranchActive())
InsetText::latex(os, runparams); InsetText::latex(os, runparams);
} }
@ -269,7 +278,7 @@ void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const
int InsetBranch::plaintext(odocstringstream & os, int InsetBranch::plaintext(odocstringstream & os,
OutputParams const & runparams, size_t max_length) const OutputParams const & runparams, size_t max_length) const
{ {
if (!isBranchSelected()) if (!isBranchActive())
return 0; return 0;
int len = InsetText::plaintext(os, runparams, max_length); int len = InsetText::plaintext(os, runparams, max_length);
@ -280,13 +289,13 @@ int InsetBranch::plaintext(odocstringstream & os,
int InsetBranch::docbook(odocstream & os, int InsetBranch::docbook(odocstream & os,
OutputParams const & runparams) const OutputParams const & runparams) const
{ {
return isBranchSelected() ? InsetText::docbook(os, runparams) : 0; return isBranchActive() ? InsetText::docbook(os, runparams) : 0;
} }
docstring InsetBranch::xhtml(XHTMLStream & xs, OutputParams const & rp) const docstring InsetBranch::xhtml(XHTMLStream & xs, OutputParams const & rp) const
{ {
if (isBranchSelected()) { if (isBranchActive()) {
OutputParams newrp = rp; OutputParams newrp = rp;
newrp.par_begin = 0; newrp.par_begin = 0;
newrp.par_end = text().paragraphs().size(); newrp.par_end = text().paragraphs().size();
@ -298,7 +307,7 @@ docstring InsetBranch::xhtml(XHTMLStream & xs, OutputParams const & rp) const
void InsetBranch::toString(odocstream & os) const void InsetBranch::toString(odocstream & os) const
{ {
if (isBranchSelected()) if (isBranchActive())
InsetCollapsable::toString(os); InsetCollapsable::toString(os);
} }
@ -306,14 +315,14 @@ void InsetBranch::toString(odocstream & os) const
void InsetBranch::forOutliner(docstring & os, size_t const maxlen, void InsetBranch::forOutliner(docstring & os, size_t const maxlen,
bool const shorten) const bool const shorten) const
{ {
if (isBranchSelected()) if (isBranchActive())
InsetCollapsable::forOutliner(os, maxlen, shorten); InsetCollapsable::forOutliner(os, maxlen, shorten);
} }
void InsetBranch::validate(LaTeXFeatures & features) const void InsetBranch::validate(LaTeXFeatures & features) const
{ {
if (isBranchSelected()) if (isBranchActive())
InsetCollapsable::validate(features); InsetCollapsable::validate(features);
} }
@ -327,7 +336,7 @@ string InsetBranch::contextMenuName() const
bool InsetBranch::isMacroScope() const bool InsetBranch::isMacroScope() const
{ {
// Its own scope if not selected by buffer // Its own scope if not selected by buffer
return !isBranchSelected(); return !isBranchActive();
} }
@ -361,26 +370,30 @@ void InsetBranch::addToToc(DocIterator const & cpit, bool output_active,
docstring str; docstring str;
text().forOutliner(str, TOC_ENTRY_LENGTH); text().forOutliner(str, TOC_ENTRY_LENGTH);
str = params_.branch + ": " + str; str = params_.branch + (params_.inverted ? " (-):" : ": ") + str;
shared_ptr<Toc> toc = buffer().tocBackend().toc("branch"); shared_ptr<Toc> toc = buffer().tocBackend().toc("branch");
toc->push_back(TocItem(pit, 0, str, output_active)); toc->push_back(TocItem(pit, 0, str, output_active));
// Proceed with the rest of the inset. // Proceed with the rest of the inset.
bool const doing_output = output_active && isBranchSelected(); bool const doing_output = output_active && isBranchActive();
InsetCollapsable::addToToc(cpit, doing_output, utype); InsetCollapsable::addToToc(cpit, doing_output, utype);
} }
void InsetBranchParams::write(ostream & os) const void InsetBranchParams::write(ostream & os) const
{ {
os << to_utf8(branch); os << to_utf8(branch)
<< '\n'
<< "inverted "
<< inverted;
} }
void InsetBranchParams::read(Lexer & lex) void InsetBranchParams::read(Lexer & lex)
{ {
lex.eatLine(); lex >> branch;
branch = lex.getDocString(); lex >> "inverted" >> inverted;
} }
} // namespace lyx } // namespace lyx

View File

@ -20,13 +20,17 @@ class InsetBranchParams {
public: public:
/// ///
explicit InsetBranchParams(docstring const & b = docstring()) explicit InsetBranchParams(docstring const & b = docstring())
: branch(b) {} : branch(b), inverted(false) {}
InsetBranchParams(docstring const & b, bool i)
: branch(b), inverted(i) {}
/// ///
void write(std::ostream & os) const; void write(std::ostream & os) const;
/// ///
void read(Lexer & lex); void read(Lexer & lex);
/// ///
docstring branch; docstring branch;
///
bool inverted;
}; };
@ -52,6 +56,8 @@ public:
docstring branch() const { return params_.branch; } docstring branch() const { return params_.branch; }
/// ///
void rename(docstring const & newname) { params_.branch = newname; } void rename(docstring const & newname) { params_.branch = newname; }
///
InsetBranchParams const & params() const { return params_; }
private: private:
/// ///
@ -85,14 +91,16 @@ private:
void addToToc(DocIterator const & di, bool output_active, void addToToc(DocIterator const & di, bool output_active,
UpdateType utype) const; UpdateType utype) const;
/// ///
InsetBranchParams const & params() const { return params_; }
///
void setParams(InsetBranchParams const & params) { params_ = params; } void setParams(InsetBranchParams const & params) { params_ = params; }
/** \returns true if params_.branch is listed as 'selected' in /** \returns true if params_.branch is listed as 'selected' in
\c buffer. \p child only checks within child documents. \c buffer. \p child only checks within child documents.
*/ */
bool isBranchSelected(bool const child = false) const; bool isBranchSelected(bool const child = false) const;
///
bool isBranchActive(bool const child = false) const
// XOR
{ return isBranchSelected(child) != params_.inverted; }
/*! /*!
* Is the content of this inset part of the output document? * Is the content of this inset part of the output document?
* *

View File

@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in // Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own. // independent branches. Instead add your own.
#define LYX_FORMAT_LYX 510 // gb: date inset #define LYX_FORMAT_LYX 511 // rgh: inverted branches
#define LYX_FORMAT_TEX2LYX 510 #define LYX_FORMAT_TEX2LYX 511
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER #ifndef _MSC_VER