commit 1b82fc4d8eb50dac7eef743a0ac95002f5709589
Author: Juergen Spitzmueller <[email protected]>
Date: Sun Oct 12 13:47:06 2025 +0200
Implement LFUN_REFERENCE_TO_PARAGRAPH for mathed (#13206)
This allows to enter references to numbered math formulae directly
from the outliner (or the list of existing equations in the cross
ref dialog), whether they already have a label or not (as for text
elements).
---
lib/ui/stdcontext.inc | 9 ++++++
src/BufferView.cpp | 72 ++++++++++++++++++++++++++++++--------------
src/TocBuilder.cpp | 28 +++++++++++++++--
src/TocBuilder.h | 4 ++-
src/frontends/qt/GuiRef.cpp | 5 ++-
src/mathed/InsetMathHull.cpp | 19 ++++++------
src/mathed/InsetMathHull.h | 2 +-
7 files changed, 101 insertions(+), 38 deletions(-)
diff --git a/lib/ui/stdcontext.inc b/lib/ui/stdcontext.inc
index ad8571d0ed..316be4031b 100644
--- a/lib/ui/stdcontext.inc
+++ b/lib/ui/stdcontext.inc
@@ -593,6 +593,15 @@ Menuset
End
+#
+# Toc Equation context menu
+#
+
+ Menu "context-toc-equation"
+ SubMenu "Insert Cross-Reference to this Item|C"
"context-toc-ref-to-par"
+ End
+
+
#
# Toc Footnotes context menu
#
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 20d7b0bbfe..eec356939e 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -53,6 +53,7 @@
#include "insets/InsetRef.h"
#include "insets/InsetText.h"
+#include "mathed/InsetMathHull.h"
#include "mathed/InsetMathNest.h"
#include "mathed/InsetMathRef.h"
#include "mathed/MathData.h"
@@ -1723,6 +1724,7 @@ void BufferView::dispatch(FuncRequest const & cmd,
DispatchResult & dr)
vector<string> const pids = getVectorFromString(cmd.getArg(0));
string const type = cmd.getArg(1);
int id = convert<int>(pids.back());
+ row_type row = -1;
inserted_label_.clear();
if (id < 0)
break;
@@ -1735,43 +1737,69 @@ void BufferView::dispatch(FuncRequest const & cmd,
DispatchResult & dr)
++i;
continue;
}
- string label = dit.innerParagraph().getLabelForXRef();
+ string label;
+ if (dit.nextInset() && dit.nextInset()->asInsetMath()
&& dit.nextInset()->asInsetMath()->asHullInset()) {
+ row = convert<row_type>(pids.front());
+ label =
to_utf8(dit.nextInset()->asInsetMath()->asHullInset()->label(row));
+ } else
+ label = dit.innerParagraph().getLabelForXRef();
if (!label.empty()) {
// if the paragraph has a label, we use this
if (type == "forrefdialog")
+ // only store the label for the dialog
to take it
inserted_label_ = label;
else {
+ // insert a reference to the label
(e.g., from outliner)
string const arg = (type.empty()) ?
label : label + " " + type;
lyx::dispatch(FuncRequest(LFUN_REFERENCE_INSERT, arg));
cur.forceBufferUpdate();
}
break;
} else {
- // if there is not a label yet
- // go to the paragraph (including nested
insets) ...
- lyx::dispatch(FuncRequest(LFUN_BOOKMARK_SAVE,
"0"));
- for (string const & s : pids) {
- id = convert<int>(s);
- if (id < 0)
- break;
- dit = b->getParFromID(id);
-
lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_GOTO, s));
+ // if there is not a label yet, insert one
+ // this categorically differes in texted and
mathed
+ docstring new_label;
+ if (dit.nextInset() &&
dit.nextInset()->asInsetMath() &&
dit.nextInset()->asInsetMath()->asHullInset()) {
+ // in mathed, we set the label via
InsetMathHull::label()
+ // but we need to assure it is unique
+ new_label = from_ascii("eq:equation");
+ int j = 1;
+ while (buffer().activeLabel(new_label))
{
+ new_label = new_label + '-' +
convert<docstring>(j);
+ ++j;
+ }
+ // record undo for the math inset next
to dit
+
cur.buffer()->undo().recordUndoInset(CursorData(dit), dit.nextInset());
+ // insert the label to the desired row
of the hull inset
+
dit.nextInset()->asInsetMath()->asHullInset()->label(row, new_label, true);
+ // needed to get the new label into the
buffer list
+ cur.buffer()->updateBuffer();
+ } else {
+ // in texted, go to the paragraph
(including nested insets) ...
+
lyx::dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
+ for (string const & s : pids) {
+ id = convert<int>(s);
+ if (id < 0)
+ break;
+ dit = b->getParFromID(id);
+
lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_GOTO, s));
+ }
+ // insert a new label
+ // we do not want to open the dialog,
hence we
+ // do not employ LFUN_LABEL_INSERT
+ InsetCommandParams p(LABEL_CODE);
+ new_label = dit.getPossibleLabel();
+ p["name"] = new_label;
+ string const data =
InsetCommand::params2string(p);
+
lyx::dispatch(FuncRequest(LFUN_INSET_INSERT, data));
+ // ... go back to the original position
+
lyx::dispatch(FuncRequest(LFUN_BOOKMARK_GOTO, "0"));
}
- // ... if not, insert a new label
- // we do not want to open the dialog, hence we
- // do not employ LFUN_LABEL_INSERT
- InsetCommandParams p(LABEL_CODE);
- docstring const new_label =
dit.getPossibleLabel();
- p["name"] = new_label;
- string const data =
InsetCommand::params2string(p);
- lyx::dispatch(FuncRequest(LFUN_INSET_INSERT,
data));
- // ... go back to the original position
- lyx::dispatch(FuncRequest(LFUN_BOOKMARK_GOTO,
"0"));
if (type == "forrefdialog")
- // ... and save for the ref dialog to
insert
+ // save for the ref dialog to insert
inserted_label_ = to_utf8(new_label);
else {
- // ... or insert the ref directly (from
outliner)
+ // or insert the ref directly (from
outliner)
string const arg = (type.empty()) ?
to_utf8(new_label)
:
to_utf8(new_label) + " " + type;
lyx::dispatch(FuncRequest(LFUN_REFERENCE_INSERT, arg));
diff --git a/src/TocBuilder.cpp b/src/TocBuilder.cpp
index fb688bd58e..458a95db66 100644
--- a/src/TocBuilder.cpp
+++ b/src/TocBuilder.cpp
@@ -15,6 +15,7 @@
#include "DocIterator.h"
#include "TocBackend.h"
+#include "support/convert.h"
#include "support/lassert.h"
using namespace std;
@@ -32,9 +33,16 @@ TocBuilder::TocBuilder(shared_ptr<Toc> const & toc)
}
void TocBuilder::pushItem(DocIterator const & dit, docstring const & s,
- bool output_active, bool is_captioned)
+ bool output_active, bool is_captioned, int row)
{
- toc_->push_back(TocItem(dit, stack_.size(), s, output_active));
+ TocItem item(dit, stack_.size(), s, output_active);
+ if (row != -1) {
+ docstring parID = item.parIDs();
+ if (!stack_.empty())
+ parID =
(*toc_)[stack_.top().pos].dit().paragraphGotoArgument(true);
+ item.setParIDs(convert<docstring>(row) + ',' + parID);
+ }
+ toc_->push_back(item);
frame f = {
toc_->size() - 1, //pos
is_captioned, //is_captioned
@@ -87,6 +95,22 @@ void TocBuilder::argumentItem(docstring const & arg_str)
stack_.top().is_captioned = true;
}
+void TocBuilder::mathMultilineItem(docstring const & arg_str, Toc::size_type
row)
+{
+ if (stack_.empty() || arg_str.empty())
+ return;
+ TocItem & item = (*toc_)[stack_.top().pos];
+ docstring const & str = item.str();
+ string const & delim =
+ (str.empty() || !stack_.top().is_captioned) ? "" : ", ";
+ item.str(str + from_ascii(delim) + arg_str);
+ docstring parID = item.parIDs();
+ if (!stack_.empty())
+ parID =
(*toc_)[stack_.top().pos].dit().paragraphGotoArgument(true);
+ item.setParIDs(convert<docstring>(row) + ',' + parID);
+ stack_.top().is_captioned = true;
+}
+
void TocBuilder::pop()
{
if (!stack_.empty())
diff --git a/src/TocBuilder.h b/src/TocBuilder.h
index af9c41cb24..23d5fe8329 100644
--- a/src/TocBuilder.h
+++ b/src/TocBuilder.h
@@ -31,7 +31,7 @@ public:
/// Open a level.
/// When entering a float or flex or paragraph (with AddToToc)
void pushItem(DocIterator const & dit, docstring const & s,
- bool output_active, bool is_captioned = false);
+ bool output_active, bool is_captioned = false, int row =
-1);
/// Edit entry at current level. Add new entry if already captioned.
/// When encountering a float caption
void captionItem(DocIterator const & dit, docstring const & s,
@@ -39,6 +39,8 @@ public:
/// Edit entry at current level (always).
/// When encountering an argument (with isTocCaption) for flex or
paragraph
void argumentItem(docstring const & arg_str);
+ ///
+ void mathMultilineItem(docstring const & arg_str, Toc::size_type row);
/// Close a level.
/// When exiting a float or flex or paragraph
void pop();
diff --git a/src/frontends/qt/GuiRef.cpp b/src/frontends/qt/GuiRef.cpp
index 295294ae51..23e4ddbae4 100644
--- a/src/frontends/qt/GuiRef.cpp
+++ b/src/frontends/qt/GuiRef.cpp
@@ -554,9 +554,8 @@ void GuiRef::updateTargets()
targetCO->addItem(toqstr(translateIfPossible(name.second)), toqstr(name.first));
}
}
-// FIXME This does not work yet with REFERENCE_TO_PARAGRAPH
-// if (isTargetAvailable("equation"))
-// targetCO->addItem(qt_("Equations"), "equation");
+ if (isTargetAvailable("equation"))
+ targetCO->addItem(qt_("Equations"), "equation");
// restore previous setting
int const i = targetCO->findData(target);
if (i != -1)
diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp
index b9d76279af..5d8e3b4abd 100644
--- a/src/mathed/InsetMathHull.cpp
+++ b/src/mathed/InsetMathHull.cpp
@@ -354,8 +354,8 @@ void InsetMathHull::addToToc(DocIterator const & pit, bool
output_active,
TocBuilder & b = backend.builder("equation");
b.pushItem(pit, docstring(), output_active);
if (first != last)
- b.argumentItem(bformat(from_ascii("(%1$s-%2$s)"),
- numbers_[first], numbers_[last]));
+ b.mathMultilineItem(bformat(from_ascii("(%1$s-%2$s)"),
+ numbers_[first], numbers_[last]), 0);
odocstringstream ods;
Encoding const * enc = encodings.fromLyXName("utf8");
@@ -373,7 +373,7 @@ void InsetMathHull::addToToc(DocIterator const & pit, bool
output_active,
if (first == last) {
// this is the only equation
plaintext(ods, ops, max_length);
- b.argumentItem(label + " " + ods.str());
+ b.mathMultilineItem(label + " " + ods.str(), row);
} else {
// insert as sub-items
otexrowstream ots(ods);
@@ -387,7 +387,7 @@ void InsetMathHull::addToToc(DocIterator const & pit, bool
output_active,
break;
}
}
- b.pushItem(pit, label+ " " + d, output_active);
+ b.pushItem(pit, label+ " " + d, output_active, false,
row);
// clear the stringstream
odocstringstream().swap(ods);
b.pop();
@@ -1002,7 +1002,7 @@ docstring InsetMathHull::label(row_type row) const
}
-void InsetMathHull::label(row_type row, docstring const & label)
+void InsetMathHull::label(row_type row, docstring const & label, bool const
init)
{
//lyxerr << "setting label '" << label << "' for row " << row << endl;
if (labels_[row]) {
@@ -1022,6 +1022,9 @@ void InsetMathHull::label(row_type row, docstring const &
label)
labels_[row] = new InsetLabel(buffer_, p);
if (buffer_)
labels_[row]->setBuffer(buffer());
+ if (init)
+ // Newly created inset so initialize it.
+ labels_[row]->initView();
}
@@ -2101,11 +2104,9 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest
& cmd)
if (labels_[r])
// The label will take care of the
reference update.
label(r, str);
- else {
- label(r, str);
+ else
// Newly created inset so initialize it.
- labels_[r]->initView();
- }
+ label(r, str, true);
}
cur.forceBufferUpdate();
break;
diff --git a/src/mathed/InsetMathHull.h b/src/mathed/InsetMathHull.h
index e25e516e0c..b5cfe92f03 100644
--- a/src/mathed/InsetMathHull.h
+++ b/src/mathed/InsetMathHull.h
@@ -71,7 +71,7 @@ public:
///
docstring label(row_type row) const;
///
- void label(row_type row, docstring const & label);
+ void label(row_type row, docstring const & label, bool const init =
false);
///
std::vector<InsetLabel *> const & getLabels() { return labels_; }
///
--
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs