From 420d363937ccdff8f006744ece8982ce53926ad1 Mon Sep 17 00:00:00 2001 From: RobBuchanan <106311829+RobBuchananCompPhys@users.noreply.github.com> Date: Mon, 13 May 2024 09:37:23 +0100 Subject: [PATCH] fix: Remove atom type and master term from forcefield tab (#1889) --- src/classes/coreData.cpp | 86 ++++++++++- src/classes/coreData.h | 11 +- src/gui/forcefieldTab.cpp | 190 ++++++++++++++++++++++++- src/gui/forcefieldTab.h | 4 + src/gui/models/masterAngleModel.cpp | 6 + src/gui/models/masterAngleModel.h | 1 + src/gui/models/masterBondModel.cpp | 6 + src/gui/models/masterBondModel.h | 1 + src/gui/models/masterImproperModel.cpp | 6 + src/gui/models/masterImproperModel.h | 1 + src/gui/models/masterTorsionModel.cpp | 6 + src/gui/models/masterTorsionModel.h | 1 + src/keywords/store.h | 7 + 13 files changed, 318 insertions(+), 8 deletions(-) diff --git a/src/classes/coreData.cpp b/src/classes/coreData.cpp index 575e42fd92..906d9504f2 100644 --- a/src/classes/coreData.cpp +++ b/src/classes/coreData.cpp @@ -53,9 +53,11 @@ std::shared_ptr CoreData::addAtomType(Elements::Element Z) } // Remove specified AtomType -void CoreData::removeAtomType(const std::shared_ptr &at) +void CoreData::removeAtomType(std::shared_ptr &at) { - atomTypes_.erase(std::remove(atomTypes_.begin(), atomTypes_.end(), at)); + removeReferencesTo(at); + + atomTypes_.erase(std::remove(atomTypes_.begin(), atomTypes_.end(), at), atomTypes_.end()); } // Return number of AtomTypes in list @@ -156,6 +158,20 @@ MasterBond &CoreData::addMasterBond(std::string_view name) return *masters_.bonds.emplace_back(std::make_shared(name)); } +// Remove specified master Bond +void CoreData::removeMasterBond(const std::shared_ptr &bond) +{ + // Detach from master term + for (auto &species : species_) + { + for (auto &b : species->bonds()) + if (b.masterTerm() == bond.get()) + b.detachFromMasterTerm(); + } + + masters_.bonds.erase(std::remove(masters_.bonds.begin(), masters_.bonds.end(), bond), masters_.bonds.end()); +} + // Return number of master Bond parameters in list int CoreData::nMasterBonds() const { return masters_.bonds.size(); } @@ -198,6 +214,20 @@ MasterAngle &CoreData::addMasterAngle(std::string_view name) return *masters_.angles.emplace_back(std::make_shared(name)); } +// Remove specified master Angle +void CoreData::removeMasterAngle(const std::shared_ptr &angle) +{ + // Detach from master term + for (auto &species : species_) + { + for (auto &a : species->angles()) + if (a.masterTerm() == angle.get()) + a.detachFromMasterTerm(); + } + + masters_.angles.erase(std::remove(masters_.angles.begin(), masters_.angles.end(), angle), masters_.angles.end()); +} + // Return number of master Angle parameters in list int CoreData::nMasterAngles() const { return masters_.angles.size(); } @@ -240,6 +270,20 @@ MasterTorsion &CoreData::addMasterTorsion(std::string_view name) return *masters_.torsions.emplace_back(std::make_shared(name)); } +// Remove specified MasterTorsion +void CoreData::removeMasterTorsion(const std::shared_ptr &torsion) +{ + // Detach from master term + for (auto &species : species_) + { + for (auto &t : species->torsions()) + if (t.masterTerm() == torsion.get()) + t.detachFromMasterTerm(); + } + + masters_.torsions.erase(std::remove(masters_.torsions.begin(), masters_.torsions.end(), torsion), masters_.torsions.end()); +} + // Return number of master Torsion parameters in list int CoreData::nMasterTorsions() const { return masters_.torsions.size(); } @@ -282,6 +326,21 @@ MasterImproper &CoreData::addMasterImproper(std::string_view name) return *masters_.impropers.emplace_back(std::make_shared(name)); } +// Remove specified master Improper +void CoreData::removeMasterImproper(const std::shared_ptr &improper) +{ + // Detach from master term + for (auto &species : species_) + { + for (auto &i : species->impropers()) + if (i.masterTerm() == improper.get()) + i.detachFromMasterTerm(); + } + + masters_.impropers.erase(std::remove(masters_.impropers.begin(), masters_.impropers.end(), improper), + masters_.impropers.end()); +} + // Return number of master Improper parameters in list int CoreData::nMasterImpropers() const { return masters_.impropers.size(); } @@ -677,6 +736,14 @@ template void objectNoLongerValid(CoreData *coreData, O *object) mod->keywords().objectNoLongerValid(object); } +template void objectNoLongerValid(CoreData *coreData, std::shared_ptr

object) +{ + // Loop over all keyword objects and call their local functions + for (auto &layer : coreData->processingLayers()) + for (auto &mod : layer->modules()) + mod->keywords().objectNoLongerValid(object); +} + // Remove all references to the specified data void CoreData::removeReferencesTo(Module *data) { objectNoLongerValid(this, data); } void CoreData::removeReferencesTo(Isotopologue *data) { objectNoLongerValid(this, data); } @@ -691,6 +758,21 @@ void CoreData::removeReferencesTo(Species *data) cfg->empty(); } void CoreData::removeReferencesTo(SpeciesSite *data) { objectNoLongerValid(this, data); } +void CoreData::removeReferencesTo(std::shared_ptr data) +{ + for (auto &species : species_) + { + for (auto &atom : species->atoms()) + { + if (atom.atomType() == data) + { + atom.setAtomType(nullptr); + } + } + } + + objectNoLongerValid(this, data); +} /* * Modules diff --git a/src/classes/coreData.h b/src/classes/coreData.h index bf7b46619e..9d4cb702ba 100644 --- a/src/classes/coreData.h +++ b/src/classes/coreData.h @@ -46,7 +46,7 @@ class CoreData // Add new AtomType std::shared_ptr addAtomType(Elements::Element Z); // Remove specified AtomType - void removeAtomType(const std::shared_ptr &at); + void removeAtomType(std::shared_ptr &at); // Return number of AtomTypes in list int nAtomTypes() const; // Return core AtomTypes list @@ -114,6 +114,8 @@ class CoreData void deserialiseMaster(const SerialisedValue &node); // Add new master Bond parameters MasterBond &addMasterBond(std::string_view name); + // Remove specified master Bond + void removeMasterBond(const std::shared_ptr &bond); // Return number of master Bond parameters in list int nMasterBonds() const; // Return list of master Bond parameters @@ -124,6 +126,8 @@ class CoreData OptionalReferenceWrapper getMasterBond(std::string_view name) const; // Add new master Angle parameters MasterAngle &addMasterAngle(std::string_view name); + // Remove specified master Angle + void removeMasterAngle(const std::shared_ptr &angle); // Return number of master Angles parameters in list int nMasterAngles() const; // Return list of master Angle parameters @@ -134,6 +138,8 @@ class CoreData OptionalReferenceWrapper getMasterAngle(std::string_view name) const; // Add new master Torsion parameters MasterTorsion &addMasterTorsion(std::string_view name); + // Remove specified master Torsion + void removeMasterTorsion(const std::shared_ptr &torsion); // Return number of master Torsions parameters in list int nMasterTorsions() const; // Return list of master Torsion parameters @@ -144,6 +150,8 @@ class CoreData OptionalReferenceWrapper getMasterTorsion(std::string_view name) const; // Add new master Improper parameters MasterImproper &addMasterImproper(std::string_view name); + // Remove specified master Impropers + void removeMasterImproper(const std::shared_ptr &improper); // Return number of master Impropers parameters in list int nMasterImpropers() const; // Return list of master Improper parameters @@ -274,4 +282,5 @@ class CoreData void removeReferencesTo(Module *data); void removeReferencesTo(Species *data); void removeReferencesTo(SpeciesSite *data); + void removeReferencesTo(std::shared_ptr data); }; diff --git a/src/gui/forcefieldTab.cpp b/src/gui/forcefieldTab.cpp index c023d30fe9..1996ca50e0 100644 --- a/src/gui/forcefieldTab.cpp +++ b/src/gui/forcefieldTab.cpp @@ -15,6 +15,7 @@ #include "gui/widgets/elementSelector.h" #include "main/dissolve.h" #include +#include ForcefieldTab::ForcefieldTab(DissolveWindow *dissolveWindow, Dissolve &dissolve, MainTabsWidget *parent, const QString title) : MainTab(dissolveWindow, dissolve, parent, title, this), atomTypesModel_(dissolve.coreData()), @@ -67,6 +68,15 @@ ForcefieldTab::ForcefieldTab(DissolveWindow *dissolveWindow, Dissolve &dissolve, SLOT(masterTorsionsDataChanged(const QModelIndex &, const QModelIndex &))); connect(&masterImpropersTableModel_, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(masterImpropersDataChanged(const QModelIndex &, const QModelIndex &))); + connect(ui_.MasterBondsTable->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(masterBondsSelectionChanged(const QItemSelection &, const QItemSelection &))); + connect(ui_.MasterAnglesTable->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(masterAnglesSelectionChanged(const QItemSelection &, const QItemSelection &))); + connect(ui_.MasterTorsionsTable->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(masterTorsionsSelectionChanged(const QItemSelection &, const QItemSelection &))); + connect(ui_.MasterImpropersTable->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, + SLOT(masterImpropersSelectionChanged(const QItemSelection &, const QItemSelection &))); /* * Atom Types @@ -283,10 +293,40 @@ void ForcefieldTab::on_AtomTypeAddButton_clicked(bool checked) dissolveWindow_->setModified(); } -void ForcefieldTab::on_AtomTypeRemoveButton_clicked(bool checked) { Messenger::error("NOT IMPLEMENTED YET.\n"); } +void ForcefieldTab::on_AtomTypeRemoveButton_clicked(bool checked) +{ + auto index = ui_.AtomTypesTable->currentIndex(); + if (!index.isValid()) + return; + + QMessageBox queryBox; + queryBox.setWindowTitle(QString("Remove Atom Type")); + queryBox.setText(QString("Are you sure? This operation cannot be undone!\n")); + queryBox.setInformativeText("Proceed?"); + queryBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + queryBox.setDefaultButton(QMessageBox::No); + + if (queryBox.exec() != QMessageBox::Yes) + return; + + // Get selected atomtype + auto at = atomTypesModel_.rawData(index); + if (!at) + return; + + dissolve_.coreData().removeAtomType(at); + + Locker refreshLocker(refreshLock_); + + atomTypesModel_.setData(dissolve_.coreData().atomTypes()); + ui_.AtomTypesTable->resizeColumnsToContents(); + + dissolveWindow_->setModified(); +} void ForcefieldTab::atomTypeSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) { + ui_.AtomTypeRemoveButton->setEnabled(!current.empty()); ui_.AtomTypeDuplicateButton->setEnabled(!current.empty()); } @@ -470,6 +510,26 @@ void ForcefieldTab::masterImpropersDataChanged(const QModelIndex &, const QModel dissolveWindow_->setModified(); } +void ForcefieldTab::masterBondsSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) +{ + ui_.MasterTermRemoveBondButton->setEnabled(!current.empty()); +} + +void ForcefieldTab::masterAnglesSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) +{ + ui_.MasterTermRemoveAngleButton->setEnabled(!current.empty()); +} + +void ForcefieldTab::masterTorsionsSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) +{ + ui_.MasterTermRemoveTorsionButton->setEnabled(!current.empty()); +} + +void ForcefieldTab::masterImpropersSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) +{ + ui_.MasterTermRemoveImproperButton->setEnabled(!current.empty()); +} + void ForcefieldTab::on_MasterTermAddBondButton_clicked(bool checked) { dissolve_.coreData().addMasterBond( @@ -479,7 +539,37 @@ void ForcefieldTab::on_MasterTermAddBondButton_clicked(bool checked) dissolveWindow_->setModified(); } -void ForcefieldTab::on_MasterTermRemoveBondButton_clicked(bool checked) { Messenger::error("NOT IMPLEMENTED YET.\n"); } +void ForcefieldTab::on_MasterTermRemoveBondButton_clicked(bool checked) +{ + auto index = ui_.MasterBondsTable->currentIndex(); + if (!index.isValid()) + return; + + QMessageBox queryBox; + queryBox.setWindowTitle(QString("Remove Master Bond")); + queryBox.setText(QString("Are you sure? This operation cannot be undone!\n") + + QString("Any uses of this term in species will be converted to a local definition.")); + queryBox.setInformativeText("Proceed?"); + queryBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + queryBox.setDefaultButton(QMessageBox::No); + + if (queryBox.exec() != QMessageBox::Yes) + return; + + // Get selected master bond + auto bond = masterBondsTableModel_.rawData(index); + if (!bond) + return; + + dissolve_.coreData().removeMasterBond(bond); + + Locker refreshLocker(refreshLock_); + + masterBondsTableModel_.setSourceData(dissolve_.coreData().masterBonds()); + ui_.MasterBondsTable->resizeColumnsToContents(); + + dissolveWindow_->setModified(); +} void ForcefieldTab::on_MasterTermAddAngleButton_clicked(bool checked) { @@ -490,7 +580,37 @@ void ForcefieldTab::on_MasterTermAddAngleButton_clicked(bool checked) dissolveWindow_->setModified(); } -void ForcefieldTab::on_MasterTermRemoveAngleButton_clicked(bool checked) { Messenger::error("NOT IMPLEMENTED YET.\n"); } +void ForcefieldTab::on_MasterTermRemoveAngleButton_clicked(bool checked) +{ + auto index = ui_.MasterAnglesTable->currentIndex(); + if (!index.isValid()) + return; + + QMessageBox queryBox; + queryBox.setWindowTitle(QString("Remove Master Angle")); + queryBox.setText(QString("Are you sure? This operation cannot be undone!\n") + + QString("Any uses of this term in species will be converted to a local definition.")); + queryBox.setInformativeText("Proceed?"); + queryBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + queryBox.setDefaultButton(QMessageBox::No); + + if (queryBox.exec() != QMessageBox::Yes) + return; + + // Get selected master angle + auto angle = masterAnglesTableModel_.rawData(index); + if (!angle) + return; + + dissolve_.coreData().removeMasterAngle(angle); + + Locker refreshLocker(refreshLock_); + + masterAnglesTableModel_.setSourceData(dissolve_.coreData().masterAngles()); + ui_.MasterAnglesTable->resizeColumnsToContents(); + + dissolveWindow_->setModified(); +} void ForcefieldTab::on_MasterTermAddTorsionButton_clicked(bool checked) { @@ -501,7 +621,37 @@ void ForcefieldTab::on_MasterTermAddTorsionButton_clicked(bool checked) dissolveWindow_->setModified(); } -void ForcefieldTab::on_MasterTermRemoveTorsionButton_clicked(bool checked) { Messenger::error("NOT IMPLEMENTED YET.\n"); } +void ForcefieldTab::on_MasterTermRemoveTorsionButton_clicked(bool checked) +{ + auto index = ui_.MasterTorsionsTable->currentIndex(); + if (!index.isValid()) + return; + + QMessageBox queryBox; + queryBox.setWindowTitle(QString("Remove Master Torsion")); + queryBox.setText(QString("Are you sure? This operation cannot be undone!\n") + + QString("Any uses of this term in species will be converted to a local definition.")); + queryBox.setInformativeText("Proceed?"); + queryBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + queryBox.setDefaultButton(QMessageBox::No); + + if (queryBox.exec() != QMessageBox::Yes) + return; + + // Get selected master torsion + auto torsion = masterTorsionsTableModel_.rawData(index); + if (!torsion) + return; + + dissolve_.coreData().removeMasterTorsion(torsion); + + Locker refreshLocker(refreshLock_); + + masterTorsionsTableModel_.setSourceData(dissolve_.coreData().masterTorsions()); + ui_.MasterTorsionsTable->resizeColumnsToContents(); + + dissolveWindow_->setModified(); +} void ForcefieldTab::on_MasterTermAddImproperButton_clicked(bool checked) { @@ -512,4 +662,34 @@ void ForcefieldTab::on_MasterTermAddImproperButton_clicked(bool checked) dissolveWindow_->setModified(); } -void ForcefieldTab::on_MasterTermRemoveImproperButton_clicked(bool checked) { Messenger::error("NOT IMPLEMENTED YET.\n"); } +void ForcefieldTab::on_MasterTermRemoveImproperButton_clicked(bool checked) +{ + auto index = ui_.MasterImpropersTable->currentIndex(); + if (!index.isValid()) + return; + + QMessageBox queryBox; + queryBox.setWindowTitle(QString("Remove Master Improper")); + queryBox.setText(QString("Are you sure? This operation cannot be undone!\n") + + QString("Any uses of this term in species will be converted to a local definition.")); + queryBox.setInformativeText("Proceed?"); + queryBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + queryBox.setDefaultButton(QMessageBox::No); + + if (queryBox.exec() != QMessageBox::Yes) + return; + + // Get selected master improper + auto improper = masterImpropersTableModel_.rawData(index); + if (!improper) + return; + + dissolve_.coreData().removeMasterImproper(improper); + + Locker refreshLocker(refreshLock_); + + masterImpropersTableModel_.setSourceData(dissolve_.coreData().masterImpropers()); + ui_.MasterImpropersTable->resizeColumnsToContents(); + + dissolveWindow_->setModified(); +} diff --git a/src/gui/forcefieldTab.h b/src/gui/forcefieldTab.h index 937c551a59..cc98c39ab8 100644 --- a/src/gui/forcefieldTab.h +++ b/src/gui/forcefieldTab.h @@ -108,6 +108,10 @@ class ForcefieldTab : public QWidget, public MainTab void masterAnglesDataChanged(const QModelIndex &, const QModelIndex &); void masterTorsionsDataChanged(const QModelIndex &, const QModelIndex &); void masterImpropersDataChanged(const QModelIndex &, const QModelIndex &); + void masterBondsSelectionChanged(const QItemSelection &, const QItemSelection &); + void masterAnglesSelectionChanged(const QItemSelection &, const QItemSelection &); + void masterTorsionsSelectionChanged(const QItemSelection &, const QItemSelection &); + void masterImpropersSelectionChanged(const QItemSelection &, const QItemSelection &); void on_MasterTermAddBondButton_clicked(bool checked); void on_MasterTermRemoveBondButton_clicked(bool checked); void on_MasterTermAddAngleButton_clicked(bool checked); diff --git a/src/gui/models/masterAngleModel.cpp b/src/gui/models/masterAngleModel.cpp index f1c5d399ad..ca3497db20 100644 --- a/src/gui/models/masterAngleModel.cpp +++ b/src/gui/models/masterAngleModel.cpp @@ -94,3 +94,9 @@ bool MasterAngleModel::setTermData(int row, MasterTermModelData::DataType dataTy return true; } + +const std::shared_ptr &MasterAngleModel::rawData(const QModelIndex &index) const +{ + assert(sourceData_); + return sourceData_->get()[index.row()]; +} \ No newline at end of file diff --git a/src/gui/models/masterAngleModel.h b/src/gui/models/masterAngleModel.h index 1e861eba5b..87aebbbfdf 100644 --- a/src/gui/models/masterAngleModel.h +++ b/src/gui/models/masterAngleModel.h @@ -39,6 +39,7 @@ class MasterAngleModel : public MasterTermModel int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant getTermData(int row, MasterTermModelData::DataType dataType) const override; bool setTermData(int row, MasterTermModelData::DataType dataType, const QVariant &value) override; + const std::shared_ptr &rawData(const QModelIndex &index) const; private: ModelUpdater modelUpdater; diff --git a/src/gui/models/masterBondModel.cpp b/src/gui/models/masterBondModel.cpp index b8b1a00451..b178e795e4 100644 --- a/src/gui/models/masterBondModel.cpp +++ b/src/gui/models/masterBondModel.cpp @@ -94,3 +94,9 @@ bool MasterBondModel::setTermData(int row, MasterTermModelData::DataType dataTyp return true; } + +const std::shared_ptr &MasterBondModel::rawData(const QModelIndex &index) const +{ + assert(sourceData_); + return sourceData_->get()[index.row()]; +} \ No newline at end of file diff --git a/src/gui/models/masterBondModel.h b/src/gui/models/masterBondModel.h index 833d08149f..31139a6d32 100644 --- a/src/gui/models/masterBondModel.h +++ b/src/gui/models/masterBondModel.h @@ -39,6 +39,7 @@ class MasterBondModel : public MasterTermModel int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant getTermData(int row, MasterTermModelData::DataType dataType) const override; bool setTermData(int row, MasterTermModelData::DataType dataType, const QVariant &value) override; + const std::shared_ptr &rawData(const QModelIndex &index) const; private: ModelUpdater modelUpdater; diff --git a/src/gui/models/masterImproperModel.cpp b/src/gui/models/masterImproperModel.cpp index 6b0f28ec8a..12cabde84d 100644 --- a/src/gui/models/masterImproperModel.cpp +++ b/src/gui/models/masterImproperModel.cpp @@ -94,3 +94,9 @@ bool MasterImproperModel::setTermData(int row, MasterTermModelData::DataType dat return true; } + +const std::shared_ptr &MasterImproperModel::rawData(const QModelIndex &index) const +{ + assert(sourceData_); + return sourceData_->get()[index.row()]; +} \ No newline at end of file diff --git a/src/gui/models/masterImproperModel.h b/src/gui/models/masterImproperModel.h index 1fe32386f6..6499dda1e8 100644 --- a/src/gui/models/masterImproperModel.h +++ b/src/gui/models/masterImproperModel.h @@ -39,6 +39,7 @@ class MasterImproperModel : public MasterTermModel int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant getTermData(int row, MasterTermModelData::DataType dataType) const override; bool setTermData(int row, MasterTermModelData::DataType dataType, const QVariant &value) override; + const std::shared_ptr &rawData(const QModelIndex &index) const; private: ModelUpdater modelUpdater; diff --git a/src/gui/models/masterTorsionModel.cpp b/src/gui/models/masterTorsionModel.cpp index 0e07ee6dbe..38e683d4bb 100644 --- a/src/gui/models/masterTorsionModel.cpp +++ b/src/gui/models/masterTorsionModel.cpp @@ -106,3 +106,9 @@ bool MasterTorsionModel::setTermData(int row, MasterTermModelData::DataType data return true; } + +const std::shared_ptr &MasterTorsionModel::rawData(const QModelIndex &index) const +{ + assert(sourceData_); + return sourceData_->get()[index.row()]; +} \ No newline at end of file diff --git a/src/gui/models/masterTorsionModel.h b/src/gui/models/masterTorsionModel.h index 4907699489..838ed24f81 100644 --- a/src/gui/models/masterTorsionModel.h +++ b/src/gui/models/masterTorsionModel.h @@ -40,6 +40,7 @@ class MasterTorsionModel : public MasterTermModel int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant getTermData(int row, MasterTermModelData::DataType dataType) const override; bool setTermData(int row, MasterTermModelData::DataType dataType, const QVariant &value) override; + const std::shared_ptr &rawData(const QModelIndex &index) const; private: ModelUpdater modelUpdater; diff --git a/src/keywords/store.h b/src/keywords/store.h index fb5c938513..a943f8e44d 100644 --- a/src/keywords/store.h +++ b/src/keywords/store.h @@ -291,4 +291,11 @@ class KeywordStore for (auto *kwd : allKeywords_) kwd->removeReferencesTo(object); } + + template void objectNoLongerValid(std::shared_ptr

object) + { + // Loop over all keyword objects and call their local functions + for (auto *kwd : allKeywords_) + kwd->removeReferencesTo(object); + } };