I like this idea! What if layout-module-remove is used on a module that
a different module depends on? e.g., AMS Theorems (Extended) depends on
AMS Theorems. If I have both added and I try to remove AMS Theorems,
what happens? Do we need a layoutModuleCanBeRemoved helper function?
Actually there must already be some code because "delete" is greyed out
if I do this in the GUI.

Scott

You are right, module dependencies were not taken into account in first version of the patch. Here is the updated patch that forbids removing modules that have dependents.

Yuriy

From f62034cbd7ed6469f20a2605a965074817e8d270 Mon Sep 17 00:00:00 2001
From: Yuriy Skalko <yuriy.ska...@gmail.com>
Date: Fri, 22 Oct 2021 02:30:06 +0300
Subject: [PATCH] Add LFUN for removing LyX modules

---
 src/BufferParams.cpp     | 12 ++++++++++++
 src/BufferParams.h       |  4 ++++
 src/BufferView.cpp       | 19 +++++++++++++++++++
 src/FuncCode.h           |  1 +
 src/LayoutModuleList.cpp | 12 ++++++++++++
 src/LayoutModuleList.h   |  5 +++++
 src/LyXAction.cpp        | 10 ++++++++++
 7 files changed, 63 insertions(+)

diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp
index bbbce16bef..90f52a38fb 100644
--- a/src/BufferParams.cpp
+++ b/src/BufferParams.cpp
@@ -2580,6 +2580,12 @@ bool BufferParams::layoutModuleCanBeAdded(string const & 
modName) const
 }
 
 
+bool BufferParams::layoutModuleCanBeRemoved(string const & modName) const
+{
+       return layout_modules_.moduleCanBeRemoved(modName, baseClass());
+}
+
+
 docstring BufferParams::getLocalLayout(bool forced) const
 {
        if (forced)
@@ -2608,6 +2614,12 @@ bool BufferParams::addLayoutModule(string const & 
modName)
 }
 
 
+void BufferParams::removeLayoutModule(string const & modName)
+{
+       layout_modules_.remove(modName);
+}
+
+
 string BufferParams::bufferFormat() const
 {
        return documentClass().outputFormat();
diff --git a/src/BufferParams.h b/src/BufferParams.h
index 52d8219cb4..fb9364f333 100644
--- a/src/BufferParams.h
+++ b/src/BufferParams.h
@@ -175,10 +175,14 @@ public:
        /// if you want to check for compatibility.
        /// \return true if module was successfully added.
        bool addLayoutModule(std::string const & modName);
+       ///
+       void removeLayoutModule(std::string const & modName);
        /// checks to make sure module's requriements are satisfied, that it 
does
        /// not conflict with already-present modules, isn't already loaded, 
etc.
        bool layoutModuleCanBeAdded(std::string const & modName) const;
        ///
+       bool layoutModuleCanBeRemoved(std::string const & modName) const;
+       ///
        void addRemovedModule(std::string const & modName)
                        { removed_modules_.push_back(modName); }
        /// Clear the list
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index ac9a8235db..e4fc04df4d 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -1156,6 +1156,7 @@ bool BufferView::getStatus(FuncRequest const & cmd, 
FuncStatus & flag)
        case LFUN_BUFFER_PARAMS_APPLY:
        case LFUN_LAYOUT_MODULES_CLEAR:
        case LFUN_LAYOUT_MODULE_ADD:
+       case LFUN_LAYOUT_MODULE_REMOVE:
        case LFUN_LAYOUT_RELOAD:
        case LFUN_TEXTCLASS_APPLY:
        case LFUN_TEXTCLASS_LOAD:
@@ -1400,6 +1401,24 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
                break;
        }
 
+       case LFUN_LAYOUT_MODULE_REMOVE: {
+               BufferParams const & params = buffer_.params();
+               if (!params.layoutModuleCanBeRemoved(argument)) {
+                       LYXERR0("Module `" << argument <<
+                               "' cannot be removed, it is required by another 
active module.");
+                       break;
+               }
+               // FIXME: this modifies the document in 
cap::switchBetweenClasses
+               //  without calling recordUndo. Fix this before using
+               //  recordUndoBufferParams().
+               cur.recordUndoFullBuffer();
+               buffer_.params().removeLayoutModule(argument);
+               makeDocumentClass();
+               dr.screenUpdate(Update::Force);
+               dr.forceBufferUpdate();
+               break;
+       }
+
        case LFUN_TEXTCLASS_APPLY: {
                // since this shortcircuits, the second call is made only if
                // the first fails
diff --git a/src/FuncCode.h b/src/FuncCode.h
index 20231eb164..2a3221641d 100644
--- a/src/FuncCode.h
+++ b/src/FuncCode.h
@@ -502,6 +502,7 @@ enum FuncCode
        LFUN_SPELLING_REMOVE_LOCAL,     // jspitzm 20210307
        LFUN_FINISHED_DOWN,             // lasgouttes 20210629
        LFUN_FINISHED_UP,               // lasgouttes 20210629
+       LFUN_LAYOUT_MODULE_REMOVE,      // yuriy 20211021
        LFUN_LASTACTION                 // end of the table
 };
 
diff --git a/src/LayoutModuleList.cpp b/src/LayoutModuleList.cpp
index b2e9067ed2..040931df70 100644
--- a/src/LayoutModuleList.cpp
+++ b/src/LayoutModuleList.cpp
@@ -99,6 +99,18 @@ bool LayoutModuleList::moduleCanBeAdded(string const & 
modName,
 }
 
 
+bool LayoutModuleList::moduleCanBeRemoved(string const & modName,
+               LayoutFile const * const lay) const
+{
+       for (string const & mod : *this) {
+               vector<string> reqs = theModuleList[mod]->getRequiredModules();
+               if (find(reqs.begin(), reqs.end(), modName) != reqs.end())
+                       return false;
+       }
+       return true;
+}
+
+
 bool LayoutModuleList::moduleConflicts(string const & modName,
                                        LayoutFile const * const lay) const
 {
diff --git a/src/LayoutModuleList.h b/src/LayoutModuleList.h
index 868c1cf945..eaa8ac1820 100644
--- a/src/LayoutModuleList.h
+++ b/src/LayoutModuleList.h
@@ -51,6 +51,8 @@ public:
        ///
        void push_back(std::string const & str) { lml_.push_back(str); }
        ///
+       void remove(std::string const & str) { lml_.remove(str); }
+       ///
        size_t size() const { return lml_.size(); }
        /// This is needed in GuiDocument. It seems better than an
        /// implicit conversion.
@@ -59,6 +61,9 @@ public:
        /// not conflict with already-present modules, isn't already loaded, 
etc.
        bool moduleCanBeAdded(std::string const & modName,
                        LayoutFile const * const lay) const;
+       ///
+       bool moduleCanBeRemoved(std::string const & modName,
+                       LayoutFile const * const lay) const;
        /// Like !moduleCanBeAdded(), but does not check requirements
        bool moduleConflicts(std::string const & modName,
                        LayoutFile const * const lay) const;
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 254060e789..e2d6cd3cca 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -2477,6 +2477,16 @@ void LyXAction::init()
  */
                { LFUN_LAYOUT_MODULE_ADD, "layout-module-add", NoInternal, 
Layout },
 
+/*!
+ * \var lyx::FuncCode lyx::LFUN_LAYOUT_MODULE_REMOVE
+ * \li Action: Removes a module.
+ * \li Notion: Removes a module from the list of included modules for the 
current buffer.
+ * \li Syntax: layout-module-remove <MODULE>
+ * \li Params: <MODULE>: the module to be removed
+ * \endvar
+ */
+               { LFUN_LAYOUT_MODULE_REMOVE, "layout-module-remove", 
NoInternal, Layout },
+
 /*!
  * \var lyx::FuncCode lyx::LFUN_LAYOUT_PARAGRAPH
  * \li Action: Launches the paragraph settings dialog.
-- 
2.28.0.windows.1

-- 
lyx-devel mailing list
lyx-devel@lists.lyx.org
http://lists.lyx.org/mailman/listinfo/lyx-devel

Reply via email to