diff --git a/Viewer/ecflowUI/src/ChangeNotify.cpp b/Viewer/ecflowUI/src/ChangeNotify.cpp index 2b46a0b60..0b811174d 100644 --- a/Viewer/ecflowUI/src/ChangeNotify.cpp +++ b/Viewer/ecflowUI/src/ChangeNotify.cpp @@ -63,6 +63,12 @@ ChangeNotify::ChangeNotify(const std::string& id) items[id] = this; } +ChangeNotify::~ChangeNotify() { + delete data_; + delete model_; + delete proxyModel_; +} + ChangeNotifyModel* ChangeNotify::model() const { return model_; // proxyModel_; } diff --git a/Viewer/ecflowUI/src/ChangeNotify.hpp b/Viewer/ecflowUI/src/ChangeNotify.hpp index 13ed2d238..97c51d6a9 100644 --- a/Viewer/ecflowUI/src/ChangeNotify.hpp +++ b/Viewer/ecflowUI/src/ChangeNotify.hpp @@ -31,6 +31,7 @@ class ChangeNotify : public VPropertyObserver { explicit ChangeNotify(const std::string& id); ChangeNotify(const ChangeNotify&) = delete; ChangeNotify& operator=(const ChangeNotify&) = delete; + ~ChangeNotify() override; const std::string& id() const { return id_; } VNodeList* data() const { return data_; } diff --git a/Viewer/ecflowUI/src/InfoPresenter.hpp b/Viewer/ecflowUI/src/InfoPresenter.hpp index e9cc8c3af..b88a1b6a1 100644 --- a/Viewer/ecflowUI/src/InfoPresenter.hpp +++ b/Viewer/ecflowUI/src/InfoPresenter.hpp @@ -25,7 +25,7 @@ class VReply; class InfoPresenter { public: InfoPresenter() = default; - virtual ~InfoPresenter() = default; + virtual ~InfoPresenter(); virtual void infoReady(VReply*) {} virtual void infoFailed(VReply*) {} virtual void infoProgress(VReply*) {} diff --git a/Viewer/ecflowUI/src/InfoProvider.cpp b/Viewer/ecflowUI/src/InfoProvider.cpp index 901fb7144..10284e016 100644 --- a/Viewer/ecflowUI/src/InfoProvider.cpp +++ b/Viewer/ecflowUI/src/InfoProvider.cpp @@ -21,6 +21,12 @@ #include "ecflow/node/EcfFile.hpp" #include "ecflow/node/Submittable.hpp" +InfoPresenter::~InfoPresenter() { + // The following takes care of deleting the provider used by this presenter. + // The provider is typically created in the ctor of derived class (e.g. WhyItemWidget) + delete infoProvider_; +} + InfoProvider::InfoProvider(InfoPresenter* owner, VTask::Type taskType) : owner_(owner), reply_(new VReply(this)), @@ -30,8 +36,8 @@ InfoProvider::InfoProvider(InfoPresenter* owner, VTask::Type taskType) } InfoProvider::~InfoProvider() { - delete reply_; clearInternal(); + delete reply_; } void InfoProvider::clearInternal() { diff --git a/Viewer/ecflowUI/src/InfoProvider.hpp b/Viewer/ecflowUI/src/InfoProvider.hpp index c5cc22997..a5fb17bd5 100644 --- a/Viewer/ecflowUI/src/InfoProvider.hpp +++ b/Viewer/ecflowUI/src/InfoProvider.hpp @@ -24,7 +24,9 @@ class InfoProvider : public VTaskObserver, public VInfoVisitor { InfoProvider(InfoPresenter* owner, VTask::Type); ~InfoProvider() override; InfoProvider(const InfoProvider&) = delete; + InfoProvider(InfoProvider&&) = delete; InfoProvider& operator=(const InfoProvider&) = delete; + InfoProvider& operator=(InfoProvider&&) = delete; void info(VInfo_ptr); void command(VTask::Type); diff --git a/Viewer/ecflowUI/src/LogLoadWidget.cpp b/Viewer/ecflowUI/src/LogLoadWidget.cpp index 769e306c3..394637a1c 100644 --- a/Viewer/ecflowUI/src/LogLoadWidget.cpp +++ b/Viewer/ecflowUI/src/LogLoadWidget.cpp @@ -169,7 +169,9 @@ LogLoadWidget::LogLoadWidget(QWidget* /*parent*/) : ui_(new Ui::LogLoadWidget) { slotExpandFileInfo(expandSt); } -LogLoadWidget::~LogLoadWidget() = default; +LogLoadWidget::~LogLoadWidget() { + delete ui_; +} // void LogLoadWidget::initSplitter() //{ diff --git a/Viewer/ecflowUI/src/ModelColumn.cpp b/Viewer/ecflowUI/src/ModelColumn.cpp index 3e792c1c0..8dfe7546c 100644 --- a/Viewer/ecflowUI/src/ModelColumn.cpp +++ b/Viewer/ecflowUI/src/ModelColumn.cpp @@ -20,16 +20,56 @@ #include "VProperty.hpp" #include "VSettingsLoader.hpp" -static std::map defs; +class ColumnDefinitions { +public: + using storage_t = std::map; + + ColumnDefinitions(): storage_{} {} + ~ColumnDefinitions() { + for(auto item: storage_) { + delete item.second; + } + } + + void insert(const std::string& k, ModelColumn* v) { + storage_[k] = v; + } + + auto find(const std::string& k) const { + return storage_.find(k); + } + + auto end() { + return storage_.end(); + } + + template + void for_each(F&& f) { + for(auto item: storage_) { + f(item.first, item.second); + } + } + +private: + storage_t storage_; +}; + +static ColumnDefinitions defs; ModelColumn::ModelColumn(const std::string& id) : id_(id), diagStart_(-1), diagEnd_(-1) { - defs[id_] = this; + defs.insert(id_, this); +} + +ModelColumn::~ModelColumn() { + for(auto && item: items_) { + delete item; + } } ModelColumn* ModelColumn::def(const std::string& id) { - auto it = defs.find(id); - if (it != defs.end()) + if (auto it = defs.find(id); it != defs.end()) { return it->second; + } return nullptr; } @@ -211,6 +251,9 @@ void ModelColumn::load(VProperty* group) { Q_ASSERT(group); auto* m = new ModelColumn(group->strName()); + // Attention: Each ModelColumn object self-registers in `defs`! + // This means that the newly created object will live until `defs` (with static allocation) is released. + for (int i = 0; i < group->children().size(); i++) { VProperty* p = group->children().at(i); m->loadItem(p); @@ -222,9 +265,7 @@ void ModelColumn::load(VProperty* group) { // Called via VSettingsLoader after the users settings are read void ModelColumn::loadSettings() { - for (auto& def : defs) { - def.second->loadUserSettings(); - } + defs.for_each([](auto&& k, auto&& v){v->loadUserSettings();}); } // Load user defined settings diff --git a/Viewer/ecflowUI/src/ModelColumn.hpp b/Viewer/ecflowUI/src/ModelColumn.hpp index c473375ef..ce4bb3e62 100644 --- a/Viewer/ecflowUI/src/ModelColumn.hpp +++ b/Viewer/ecflowUI/src/ModelColumn.hpp @@ -42,6 +42,7 @@ class ModelColumn : public QObject { Q_OBJECT public: explicit ModelColumn(const std::string& id); + ~ModelColumn() override; int count() const { return items_.size(); } int indexOf(QString) const; diff --git a/Viewer/ecflowUI/src/NodeQuery.cpp b/Viewer/ecflowUI/src/NodeQuery.cpp index 337474a3e..d3b04ffc1 100644 --- a/Viewer/ecflowUI/src/NodeQuery.cpp +++ b/Viewer/ecflowUI/src/NodeQuery.cpp @@ -77,6 +77,7 @@ NodeQuery::NodeQuery(const std::string& name, bool ignoreMaxNum) NodeQuery::~NodeQuery() { qDeleteAll(options_); + qDeleteAll(attrGroup_); } NodeQuery* NodeQuery::clone() { diff --git a/Viewer/ecflowUI/src/NodeQuery.hpp b/Viewer/ecflowUI/src/NodeQuery.hpp index 29b50d16c..b95f6fd02 100644 --- a/Viewer/ecflowUI/src/NodeQuery.hpp +++ b/Viewer/ecflowUI/src/NodeQuery.hpp @@ -33,6 +33,7 @@ class NodeQueryAttrGroup { : name_(name), types_(types), options_(options) {} + virtual ~NodeQueryAttrGroup() = default; QString name() const { return name_; } virtual bool hasType(VAttributeType* t) const { return types_.contains(t); } @@ -41,14 +42,15 @@ class NodeQueryAttrGroup { protected: QString name_; - QList types_; - QList options_; + QList types_; // This is a non-owning container + QList options_; // This is a non-owning container }; class NodeQueryVarAttrGroup : public NodeQueryAttrGroup { public: NodeQueryVarAttrGroup(QString name, QList types, QList options) : NodeQueryAttrGroup(name, types, options) {} + ~NodeQueryVarAttrGroup() override = default; bool hasType(VAttributeType*) const override; }; diff --git a/Viewer/ecflowUI/src/OutputDirWidget.cpp b/Viewer/ecflowUI/src/OutputDirWidget.cpp index 40a487f04..6a1e3584e 100644 --- a/Viewer/ecflowUI/src/OutputDirWidget.cpp +++ b/Viewer/ecflowUI/src/OutputDirWidget.cpp @@ -370,6 +370,10 @@ OutputDirWidget::OutputDirWidget(QWidget* parent) : QWidget(parent), ui_(new Ui: transitionTo(new DirWidgetEmptyState(this, nullptr)); } +OutputDirWidget::~OutputDirWidget() { + delete ui_; +} + // must be called externally void OutputDirWidget::showIt(bool st) { if (st) { diff --git a/Viewer/ecflowUI/src/OutputDirWidget.hpp b/Viewer/ecflowUI/src/OutputDirWidget.hpp index b13678c9b..93b38a8eb 100644 --- a/Viewer/ecflowUI/src/OutputDirWidget.hpp +++ b/Viewer/ecflowUI/src/OutputDirWidget.hpp @@ -43,6 +43,7 @@ class OutputDirWidget : public QWidget { public: explicit OutputDirWidget(QWidget* parent); + ~OutputDirWidget() override; void clear(); void load(VReply* reply, const std::string& joboutFile); diff --git a/Viewer/ecflowUI/src/OutputFetchInfo.cpp b/Viewer/ecflowUI/src/OutputFetchInfo.cpp index c33986c16..83b07b377 100644 --- a/Viewer/ecflowUI/src/OutputFetchInfo.cpp +++ b/Viewer/ecflowUI/src/OutputFetchInfo.cpp @@ -45,6 +45,10 @@ OutputFetchInfo::OutputFetchInfo(QWidget* parent) : QWidget(parent), ui_(new Ui: connect(bGroup_, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(buttonClicked(QAbstractButton*))); } +OutputFetchInfo::~OutputFetchInfo() { + delete ui_; +} + void OutputFetchInfo::buttonClicked(QAbstractButton* b) { ui_->stackedWidget->setCurrentIndex((b == ui_->infoTb) ? 0 : 1); } diff --git a/Viewer/ecflowUI/src/OutputFetchInfo.hpp b/Viewer/ecflowUI/src/OutputFetchInfo.hpp index c063bc56c..ee1e83aab 100644 --- a/Viewer/ecflowUI/src/OutputFetchInfo.hpp +++ b/Viewer/ecflowUI/src/OutputFetchInfo.hpp @@ -30,6 +30,8 @@ class OutputFetchInfo : public QWidget { Q_OBJECT public: explicit OutputFetchInfo(QWidget* parent); + ~OutputFetchInfo() override; + void clearInfo(); void setInfo(VReply*, VInfo_ptr info = nullptr); void setError(QString); diff --git a/Viewer/ecflowUI/src/PlainTextWidget.cpp b/Viewer/ecflowUI/src/PlainTextWidget.cpp index 20cf30125..8df899ea0 100644 --- a/Viewer/ecflowUI/src/PlainTextWidget.cpp +++ b/Viewer/ecflowUI/src/PlainTextWidget.cpp @@ -33,6 +33,10 @@ PlainTextWidget::PlainTextWidget(QWidget* /*parent*/) : ui_(new Ui::PlainTextWid connect(ui_->fontSizeDownTb, SIGNAL(clicked()), this, SLOT(slotFontSizeDown())); } +PlainTextWidget::~PlainTextWidget() { + delete ui_; +} + void PlainTextWidget::setPlainText(QString t) { ui_->textEdit->setPlainText(t); } diff --git a/Viewer/ecflowUI/src/PlainTextWidget.hpp b/Viewer/ecflowUI/src/PlainTextWidget.hpp index 50840cac3..88c5bb625 100644 --- a/Viewer/ecflowUI/src/PlainTextWidget.hpp +++ b/Viewer/ecflowUI/src/PlainTextWidget.hpp @@ -22,7 +22,7 @@ class PlainTextWidget : public QWidget { public: explicit PlainTextWidget(QWidget* parent = nullptr); - ~PlainTextWidget() override = default; + ~PlainTextWidget() override; void setPlainText(QString); void setTitle(QString); diff --git a/Viewer/ecflowUI/src/TimelineView.cpp b/Viewer/ecflowUI/src/TimelineView.cpp index 6fb651724..13faf68d8 100644 --- a/Viewer/ecflowUI/src/TimelineView.cpp +++ b/Viewer/ecflowUI/src/TimelineView.cpp @@ -73,7 +73,9 @@ TimelineDelegate::TimelineDelegate(TimelineModel* model, QWidget* parent) updateSettings(); } -TimelineDelegate::~TimelineDelegate() = default; +TimelineDelegate::~TimelineDelegate() { + delete prop_; +} void TimelineDelegate::notifyChange(VProperty*) { updateSettings(); diff --git a/Viewer/ecflowUI/src/TimelineWidget.cpp b/Viewer/ecflowUI/src/TimelineWidget.cpp index 1c898e0c2..ad087d78d 100644 --- a/Viewer/ecflowUI/src/TimelineWidget.cpp +++ b/Viewer/ecflowUI/src/TimelineWidget.cpp @@ -222,8 +222,8 @@ TimelineWidget::TimelineWidget(QWidget* /*parent*/) } TimelineWidget::~TimelineWidget() { - if (data_) - delete data_; + delete data_; + delete ui_; } // a complete clear diff --git a/Viewer/ecflowUI/src/TreeNodeWidget.cpp b/Viewer/ecflowUI/src/TreeNodeWidget.cpp index 8fbdb2553..ed7e10c42 100644 --- a/Viewer/ecflowUI/src/TreeNodeWidget.cpp +++ b/Viewer/ecflowUI/src/TreeNodeWidget.cpp @@ -86,7 +86,11 @@ TreeNodeWidget::TreeNodeWidget(ServerFilter* serverFilter, QWidget* parent) WidgetNameProvider::nameChildren(this); } -TreeNodeWidget::~TreeNodeWidget() = default; +TreeNodeWidget::~TreeNodeWidget() { + delete stateFilterMenu_; + delete attrFilterMenu_; + delete iconFilterMenu_; +} void TreeNodeWidget::setViewLayoutMode(TreeNodeWidget::ViewLayoutMode mode) { if (view_ && viewLayoutMode_ == mode) diff --git a/Viewer/ecflowUI/src/TriggerGraphWidget.cpp b/Viewer/ecflowUI/src/TriggerGraphWidget.cpp index 909c1c910..c3747b3cd 100644 --- a/Viewer/ecflowUI/src/TriggerGraphWidget.cpp +++ b/Viewer/ecflowUI/src/TriggerGraphWidget.cpp @@ -47,6 +47,7 @@ TriggerGraphWidget::TriggerGraphWidget(QWidget* parent) : QWidget(parent), ui_(n TriggerGraphWidget::~TriggerGraphWidget() { clear(); + delete ui_; } void TriggerGraphWidget::clear(bool keepConfig) { diff --git a/Viewer/ecflowUI/src/VConfigLoader.cpp b/Viewer/ecflowUI/src/VConfigLoader.cpp index b34710464..07dab5f34 100644 --- a/Viewer/ecflowUI/src/VConfigLoader.cpp +++ b/Viewer/ecflowUI/src/VConfigLoader.cpp @@ -11,14 +11,16 @@ #include "VConfigLoader.hpp" #include +#include using Map = std::multimap; -static Map* makers = nullptr; +static std::unique_ptr makers = nullptr; VConfigLoader::VConfigLoader(const std::string& name) { - if (makers == nullptr) - makers = new Map(); + if (!makers) { + makers = std::make_unique(); + } makers->insert(Map::value_type(name, this)); } diff --git a/Viewer/ecflowUI/src/WhyItemWidget.cpp b/Viewer/ecflowUI/src/WhyItemWidget.cpp index 14971e0b0..e2ac311b7 100644 --- a/Viewer/ecflowUI/src/WhyItemWidget.cpp +++ b/Viewer/ecflowUI/src/WhyItemWidget.cpp @@ -39,7 +39,7 @@ WhyItemWidget::WhyItemWidget(QWidget* parent) : HtmlItemWidget(parent) { fileLabel_->hide(); // Will be used for ECFLOW-901 - infoProvider_ = new WhyProvider(this); + infoProvider_ = new WhyProvider(this); // populating InfoPresenter::infoProvider_, with the deletion later handled by InfoPresenter itself textEdit_->setProperty("trigger", "1"); textEdit_->setFontProperty(VConfig::instance()->find("panel.why.font")); diff --git a/Viewer/ecflowUI/src/WhyItemWidget.hpp b/Viewer/ecflowUI/src/WhyItemWidget.hpp index f70614768..6f6e74fb9 100644 --- a/Viewer/ecflowUI/src/WhyItemWidget.hpp +++ b/Viewer/ecflowUI/src/WhyItemWidget.hpp @@ -24,8 +24,13 @@ class WhyItemWidget : public HtmlItemWidget, public InfoPanelItem { public: explicit WhyItemWidget(QWidget* parent = nullptr); + WhyItemWidget(const WhyItemWidget&) = delete; + WhyItemWidget(WhyItemWidget&&) = delete; ~WhyItemWidget() override; + WhyItemWidget& operator=(const WhyItemWidget&) = delete; + WhyItemWidget& operator=(WhyItemWidget&&) = delete; + void reload(VInfo_ptr) override; QWidget* realWidget() override; void clearContents() override; diff --git a/Viewer/libViewer/src/IconProvider.cpp b/Viewer/libViewer/src/IconProvider.cpp index 3a04d750e..bae92b905 100644 --- a/Viewer/libViewer/src/IconProvider.cpp +++ b/Viewer/libViewer/src/IconProvider.cpp @@ -108,6 +108,17 @@ QPixmap UnknownIconItem::unknown(int /*size*/) { IconProvider::IconProvider() = default; +IconProvider::~IconProvider() { + // Important! + // + // The life time of the singleton instance 'iconProvider' is used to manage the life time of loaded Icons. + // This means that when the application closes, after main() has finished, the destruction of the instance clears the Icons. + // + for(auto icon : icons_) { + delete icon.second; + } +} + QString IconProvider::path(int id) { auto it = iconsById_.find(id); if (it != iconsById_.end()) diff --git a/Viewer/libViewer/src/IconProvider.hpp b/Viewer/libViewer/src/IconProvider.hpp index 0e4c7a601..16557fa6b 100644 --- a/Viewer/libViewer/src/IconProvider.hpp +++ b/Viewer/libViewer/src/IconProvider.hpp @@ -45,6 +45,7 @@ class UnknownIconItem : public IconItem { class IconProvider { public: IconProvider(); + ~IconProvider(); static int add(QString path, QString name); diff --git a/libs/client/src/ecflow/client/ClientOptions.hpp b/libs/client/src/ecflow/client/ClientOptions.hpp index 18a218e6f..97a636a77 100644 --- a/libs/client/src/ecflow/client/ClientOptions.hpp +++ b/libs/client/src/ecflow/client/ClientOptions.hpp @@ -30,11 +30,12 @@ class CommandLine; class ClientOptions { public: - ClientOptions(const ClientOptions&) = delete; - const ClientOptions& operator=(const ClientOptions&) = delete; - /// Will create command register, & ask each cmd to describe their arguments ClientOptions(); + ClientOptions(const ClientOptions&) = delete; + ClientOptions(ClientOptions&&) = delete; + ClientOptions& operator=(const ClientOptions&) = delete; + ClientOptions& operator=(ClientOptions&&) = delete; ~ClientOptions(); /// parse the arguments and create the client request that is to be sent diff --git a/libs/node/src/ecflow/node/ExprDuplicate.cpp b/libs/node/src/ecflow/node/ExprDuplicate.cpp index d0f82eb4d..a4eab4090 100644 --- a/libs/node/src/ecflow/node/ExprDuplicate.cpp +++ b/libs/node/src/ecflow/node/ExprDuplicate.cpp @@ -16,32 +16,24 @@ #include "ecflow/core/Ecf.hpp" #include "ecflow/node/ExprAst.hpp" -using namespace std; +using expression_cache_t = std::unordered_map>; + +static expression_cache_t duplicate_expr; -static std::unordered_map duplicate_expr; -typedef std::unordered_map my_map; ExprDuplicate::~ExprDuplicate() { - // cout << "ExprDuplicate::~ExprDuplicate: server(" << Ecf::server() << ") " << duplicate_expr.size() << " - // *****************************************************************\n"; - for (my_map::value_type i : duplicate_expr) { - // cout << " deleting: " << i.first << " :" << i.second << "\n"; - delete i.second; - i.second = NULL; - } duplicate_expr.clear(); } void ExprDuplicate::dump(const std::string& msg) { - cout << "ExprDuplicate::dump server(" << Ecf::server() << ") " << msg << "\n"; - for (const my_map::value_type& i : duplicate_expr) { - cout << " " << i.first << " :" << i.second << "\n"; + std::cout << "ExprDuplicate::dump server(" << Ecf::server() << ") " << msg << "\n"; + for (const auto& i : duplicate_expr) { + std::cout << " " << i.first << " :" << i.second.get() << "\n"; } } std::unique_ptr ExprDuplicate::find(const std::string& expr) { - my_map::const_iterator it = duplicate_expr.find(expr); - if (it != duplicate_expr.end()) { + if (auto it = duplicate_expr.find(expr); it != duplicate_expr.end()) { return std::unique_ptr((*it).second->clone()); } return std::unique_ptr(); @@ -49,9 +41,6 @@ std::unique_ptr ExprDuplicate::find(const std::string& expr) { void ExprDuplicate::add(const std::string& expr, AstTop* ast) { assert(!expr.empty() && ast); - AstTop* clone = ast->clone(); - duplicate_expr.insert(std::make_pair(expr, clone)); - - // cout << "ExprDuplicate::add: server(" << Ecf::server() << ") " << expr << " :" << clone << " " << - // duplicate_expr.size() << "\n"; + auto clone = std::unique_ptr(ast->clone()); + duplicate_expr.emplace(expr, std::move(clone)); }