# HG changeset patch # User Teemu Piippo # Date 1488713617 -7200 # Node ID c2e0db52ea072eee077e125730f9e93e83d1fa1a # Parent 393babf1319d95d54a25a71e648ffcacc871bd6d Added a new type ResourceVector which manages object lifetimes, and used it to remove a bit of memory management. diff -r 393babf1319d -r c2e0db52ea07 CMakeLists.txt --- a/CMakeLists.txt Sun Mar 05 01:57:56 2017 +0200 +++ b/CMakeLists.txt Sun Mar 05 13:33:37 2017 +0200 @@ -151,6 +151,7 @@ src/toolsets/toolset.h src/toolsets/viewtoolset.h src/types/matrix.h + src/types/resourcevector.h ) set (LDFORGE_FORMS diff -r 393babf1319d -r c2e0db52ea07 src/mainwindow.cpp --- a/src/mainwindow.cpp Sun Mar 05 01:57:56 2017 +0200 +++ b/src/mainwindow.cpp Sun Mar 05 13:33:37 2017 +0200 @@ -215,22 +215,17 @@ // void MainWindow::updateRecentFilesMenu() { - // First, clear any items in the recent files menu - for (QAction* recent : m_recentFiles) - delete recent; - m_recentFiles.clear(); - QAction* first = nullptr; + QAction* previous = nullptr; for (const QVariant& it : m_config.recentFiles()) { QString file = it.toString(); - QAction* recent = new QAction (getIcon ("open-recent"), file, this); - connect (recent, SIGNAL (triggered()), this, SLOT (recentFileClicked())); - ui.menuOpenRecent->insertAction (first, recent); - m_recentFiles << recent; - first = recent; + QAction* recentFileAction = m_recentFiles.append(getIcon("open-recent"), file, this); + connect(recentFileAction, SIGNAL(triggered()), this, SLOT(recentFileClicked())); + ui.menuOpenRecent->insertAction(previous, recentFileAction); + previous = recentFileAction; } } diff -r 393babf1319d -r c2e0db52ea07 src/mainwindow.h --- a/src/mainwindow.h Sun Mar 05 01:57:56 2017 +0200 +++ b/src/mainwindow.h Sun Mar 05 13:33:37 2017 +0200 @@ -27,6 +27,7 @@ #include "linetypes/modelobject.h" #include "colors.h" #include "doublemap.h" +#include "types/resourcevector.h" class MessageManager; class QToolButton; @@ -156,7 +157,7 @@ QVector m_sel; QVector m_quickColors; QList m_colorButtons; - QList m_recentFiles; + ResourceVector m_recentFiles; class Ui_MainWindow& ui; QTabBar* m_tabs; bool m_updatingTabs; diff -r 393babf1319d -r c2e0db52ea07 src/types/resourcevector.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/types/resourcevector.h Sun Mar 05 13:33:37 2017 +0200 @@ -0,0 +1,153 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2017 Teemu Piippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +/* + * A vector that allocates elements on the heap and manages their lifetime. + */ +template +class ResourceVector +{ +public: + ~ResourceVector(); + void append(T) = delete; + template + T* append(Args&&... args); + T** const begin() const; + T** const end() const; + template + T* insert(int position, Args&&... args); + void clear(); + void removeAt(int position); + T* operator[](int position) const; + int size() const; + +private: + QVector _data; +}; + +template +int countof(const ResourceVector& vector); + +/* + * Frees the resources when the vector is deleted. + */ +template +ResourceVector::~ResourceVector() +{ + clear(); +} + +/* + * Creates a new resource and adds it to the end of this vector. + */ +template +template +T* ResourceVector::append(Args&&... args) +{ + _data.append(new TT {args...}); + return _data[size() - 1]; +} + +/* + * Returns an iterator to the beginning of this vector. + */ +template +T** const ResourceVector::begin() const +{ + return _data.cbegin(); +} + +/* + * Returns an iterator to the end of this vector. + */ +template +T** const ResourceVector::end() const +{ + return _data.cend(); +} + +/* + * Creates a new resource and inserts it to the specified position in this vector. + */ +template +template +T* ResourceVector::insert(int position, Args&&... args) +{ + _data.insert(position, new TT {args...}); +} + +/* + * Deletes all resources in this vector. + */ +template +void ResourceVector::clear() +{ + for (T* element : _data) + delete element; + + _data.clear(); +} + +/* + * Removes the resource at the provided position. Throws an exception if the index is out of range. + */ +template +void ResourceVector::removeAt(int position) +{ + if (position < _data.size()) + { + delete _data[position]; + _data.removeAt(position); + } + else + { + throw std::domain_error {"index out of range"}; + } +} + +/* + * Returns the resource at the provided position. Throws an exception if the index is out of range. + */ +template +T* ResourceVector::operator[](int position) const +{ + if (position < _data.size()) + return _data[position]; + else + throw std::domain_error {"index out of range"}; +} + +/* + * Returns the amount of resources in this vector. + */ +template +int ResourceVector::size() const +{ + return _data.size(); +} + +/* + * countof() overload for resource vectors. Returns the amount of resources in the given vector. + */ +template +int countof(const ResourceVector& vector) +{ + return vector.size(); +}