]> git.lyx.org Git - lyx.git/commitdiff
Fixup LFUN_REFERENCE_TO_PARAGRAPH for captions in other buffers
authorJuergen Spitzmueller <spitz@lyx.org>
Tue, 30 Jul 2024 10:36:20 +0000 (12:36 +0200)
committerJuergen Spitzmueller <spitz@lyx.org>
Tue, 30 Jul 2024 10:36:20 +0000 (12:36 +0200)
The movement to the caption is now done in the LFUN function itself,
as we need the DocIterator in the caption

This greatly simplifies the code in the TocWidget and shifts all the
complexity to the LFUN itself

src/BufferView.cpp
src/LyXAction.cpp
src/TocBackend.h
src/TocBuilder.cpp
src/frontends/qt/TocWidget.cpp

index 19f98554fe7aab3384d939174028804dffff9833..b7ef6fac94471393ebadbd5aa89e19b2f6bbeefe 100644 (file)
@@ -1293,8 +1293,15 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
 
        case LFUN_REFERENCE_TO_PARAGRAPH: {
-               int const id = convert<int>(cmd.getArg(0));
-               flag.setEnabled(id >= 0);
+               vector<string> const pids = getVectorFromString(cmd.getArg(0));
+               for (string const & s : pids) {
+                       int const id = convert<int>(s);
+                       if (id < 0) {
+                               flag.setEnabled(false);
+                               break;
+                       }
+               }
+               flag.setEnabled(true);
                break;
        }
 
@@ -1658,42 +1665,59 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
        }
 
        case LFUN_REFERENCE_TO_PARAGRAPH: {
-               int const id = convert<int>(cmd.getArg(0));
+               vector<string> const pids = getVectorFromString(cmd.getArg(0));
+               string const type = cmd.getArg(1);
+               int id = convert<int>(pids.front());
                if (id < 0)
                        break;
-               string const type = cmd.getArg(1);
                int i = 0;
                for (Buffer * b = &buffer_; i == 0 || b != &buffer_;
                        b = theBufferList().next(b)) {
-                       DocIterator const dit = b->getParFromID(id);
+                       DocIterator dit = b->getParFromID(id);
                        if (dit.empty()) {
                                LYXERR(Debug::INFO, "No matching paragraph found! [" << id << "].");
                                ++i;
                                continue;
                        }
-                       string const label = dit.innerParagraph().getLabelForXRef();
+                       string label = dit.innerParagraph().getLabelForXRef();
                        if (!label.empty()) {
                                // if the paragraph has a label, we refer to this
                                string const arg = (type.empty()) ? label : label + " " + type;
                                lyx::dispatch(FuncRequest(LFUN_REFERENCE_INSERT, arg));
                                break;
                        } else {
-                               // if there is not a label yet, go to the paragraph ...
+                               // if there is not a label yet, or we do not see it
+                               // (since it is in a different buffer),
+                               // go to the paragraph (including nested insets) ...
                                lyx::dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
-                               lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_GOTO, cmd.argument()));
-                               // ... insert the label
-                               // we do not want to open the dialog, hence we
-                               // do not employ LFUN_LABEL_INSERT
-                               InsetCommandParams p(LABEL_CODE);
-                               docstring const label = dit.getPossibleLabel();
-                               p["name"] = label;
-                               string const data = InsetCommand::params2string(p);
-                               lyx::dispatch(FuncRequest(LFUN_INSET_INSERT, data));
+                               for (string const & s : pids) {
+                                       id = convert<int>(s);
+                                       if (id < 0)
+                                               break;
+                                       dit = b->getParFromID(id);
+                                       lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_GOTO, s));
+                               }
+                               // ... and try again if we find a label ...
+                               label = dit.innerParagraph().getLabelForXRef();
+                               string arg;
+                               if (!label.empty()) {
+                                       // if the paragraph has a label, we refer to this
+                                       arg = (type.empty()) ? label : label + " " + type;
+                               } else {
+                                       // ... 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));
+                                       arg = (type.empty()) ? to_utf8(new_label)
+                                                            : to_utf8(new_label) + " " + type;
+                               }
                                // ... and go back to the original position
                                lyx::dispatch(FuncRequest(LFUN_BOOKMARK_GOTO, "0"));
                                // ... to insert the ref
-                               string const arg = (type.empty()) ? to_utf8(label)
-                                                                 : to_utf8(label) + " " + type;
                                lyx::dispatch(FuncRequest(LFUN_REFERENCE_INSERT, arg));
                                break;
                        }
index bbc518d02df93eee230871db3af417336775efdf..e07f260b25b39248c7c7d0a792f6c186c5ef4fc6 100644 (file)
@@ -3537,8 +3537,9 @@ void LyXAction::init()
  * \li Notion: The function checks of the paragraph already has a label.
  *             If so, it uses that. Otherwise it inserts a label and uses this.
  * \li Syntax: reference-to-paragraph <PAR_ID> [<TYPE>]
- * \li Params: <PAR_ID>:  paragraph id \n
-              <TYPE>: cross-references type
+ * \li Params: <PAR_IDs>: paragraph ids, might be a comma-separated list\n
+ *                        if it is in a nested inset\n
+ *             <TYPE>: cross-references type
  * \li Origin: spitz, 28 Jul 2024
  * \endvar
  */
index 7ad36fec66399b92f23c77b9166915bd24b2fea1..68eb825c6d5888120885fecafeef62462bdd3902 100644 (file)
@@ -75,17 +75,22 @@ public:
        ///
        docstring const & prettyStr() const { return pretty_str_; }
        ///
-       void prettyStr (docstring const & s) { pretty_str_ = s; }
+       void prettyStr(docstring const & s) { pretty_str_ = s; }
        ///
        bool isOutput() const { return output_; }
        ///
        bool isMissing() const { return missing_; }
        ///
        void setAction(FuncRequest const & a) { action_ = a; }
+       /// return comma-separated list of all par IDs (including nested insets)
+       /// this is used by captioned elements
+       docstring const parIDs() const { return par_ids_; }
+       ///
+       void setParIDs(docstring const & ids) { par_ids_ = ids; }
 
        /// custom action, or the default one (paragraph-goto) if not customised
        FuncRequest action() const;
-       ///
+       /// return only main par ID
        int id() const;
        /// String for display, e.g. it has a mark if output is inactive
        docstring const asString() const;
@@ -105,6 +110,8 @@ private:
        bool missing_;
        /// Custom action
        FuncRequest action_;
+       /// Paragraph IDs including nested insets (comma-separated).
+       docstring par_ids_;
 };
 
 
index aff19bc2b1d570275e9c2e9d682d21d715e50299..1cfeddc4508d2a69cb620cd5dec490b255250027 100644 (file)
@@ -46,10 +46,13 @@ void TocBuilder::captionItem(DocIterator const & dit, docstring const & s,
                              bool output_active)
 {
        // first show the float before moving to the caption
+       docstring parids = dit.paragraphGotoArgument(true);
        docstring arg = "paragraph-goto " + dit.paragraphGotoArgument();
-       if (!stack_.empty())
+       if (!stack_.empty()) {
                arg = "paragraph-goto " +
                        (*toc_)[stack_.top().pos].dit().paragraphGotoArgument() + ";" + arg;
+               parids = (*toc_)[stack_.top().pos].dit().paragraphGotoArgument(true) + "," + parids;
+       }
        FuncRequest func(LFUN_COMMAND_SEQUENCE, arg);
 
        if (!stack_.empty() && !stack_.top().is_captioned) {
@@ -58,6 +61,7 @@ void TocBuilder::captionItem(DocIterator const & dit, docstring const & s,
                TocItem & captionable = (*toc_)[stack_.top().pos];
                captionable.str(s);
                captionable.setAction(func);
+               captionable.setParIDs(parids);
                stack_.top().is_captioned = true;
        } else {
                // This is a new entry.
index 16a9e0a883f2e98a7a2fcd7c475fe74b248f86fa..04fd599857e6906764d29ad92b354d87f445f326 100644 (file)
@@ -254,39 +254,11 @@ void TocWidget::doDispatch(Cursor & cur, FuncRequest const & cmd,
                docstring const type = cmd.argument();
                TocItem const & item =
                        gui_view_.tocModels().currentItem(current_type_, index);
-               if (item.action().action() == LFUN_PARAGRAPH_GOTO) {
-                       // easy case
-                       docstring const id = item.dit().paragraphGotoArgument(true);
-                       docstring const arg = (type.empty()) ? id : id + " " + type;
-                       dispatch(FuncRequest(cmd, arg));
-                       break;
-               }
-               // Captions etc.
-               // Here we cannot employ LFUN_REFERENCE_TO_PARAGRAPH
-               // as it won't land in the inset. Seo we do it ourselves;
-               // 1. save current position
-               lyx::dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
-               // go to the item
-               sendDispatch(item.action());
-               // check if it has a label
-               docstring label = from_utf8(cur.innerParagraph().getLabelForXRef());
-               if (label.empty()) {
-                       // 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);
-                       label = cur.getPossibleLabel();
-                       p["name"] = label;
-                       string const data = InsetCommand::params2string(p);
-                       lyx::dispatch(FuncRequest(LFUN_INSET_INSERT, data));
-               }
-               // now go back to the original position ...
-               lyx::dispatch(FuncRequest(LFUN_BOOKMARK_GOTO, "0"));
-               // ... to insert the ref
-               docstring const arg = (type.empty()) ? label
-                                                 : label + from_ascii(" ") + type;
-               lyx::dispatch(FuncRequest(LFUN_REFERENCE_INSERT, arg));
+               docstring const id = (item.parIDs().empty())
+                               ? item.dit().paragraphGotoArgument(true)
+                               : item.parIDs();
+               docstring const arg = (type.empty()) ? id : id + " " + type;
+               dispatch(FuncRequest(cmd, arg));
                break;
        }