fix(memory leak): IndexedPack too large to live inside a qlist without pointers ()
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
e61d8e4dc8
commit
aae892dfd1
@ -23,6 +23,7 @@
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include <memory>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
@ -83,6 +84,8 @@ struct ExtraPackData {
|
||||
};
|
||||
|
||||
struct IndexedPack {
|
||||
using Ptr = std::shared_ptr<IndexedPack>;
|
||||
|
||||
QVariant addonId;
|
||||
ResourceProvider provider;
|
||||
QString name;
|
||||
|
@ -36,7 +36,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
|
||||
|
||||
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
|
||||
{
|
||||
auto& pack = m_packs[entry.row()];
|
||||
auto& pack = *m_packs[entry.row()];
|
||||
auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
|
||||
|
||||
Q_ASSERT(profile);
|
||||
@ -51,7 +51,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
|
||||
|
||||
ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)
|
||||
{
|
||||
auto& pack = m_packs[entry.row()];
|
||||
auto& pack = *m_packs[entry.row()];
|
||||
return { pack };
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QPixmapCache>
|
||||
#include <QUrl>
|
||||
#include <memory>
|
||||
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
@ -45,16 +46,16 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
|
||||
auto pack = m_packs.at(pos);
|
||||
switch (role) {
|
||||
case Qt::ToolTipRole: {
|
||||
if (pack.description.length() > 100) {
|
||||
if (pack->description.length() > 100) {
|
||||
// some magic to prevent to long tooltips and replace html linebreaks
|
||||
QString edit = pack.description.left(97);
|
||||
QString edit = pack->description.left(97);
|
||||
edit = edit.left(edit.lastIndexOf("<br>")).left(edit.lastIndexOf(" ")).append("...");
|
||||
return edit;
|
||||
}
|
||||
return pack.description;
|
||||
return pack->description;
|
||||
}
|
||||
case Qt::DecorationRole: {
|
||||
if (auto icon_or_none = const_cast<ResourceModel*>(this)->getIcon(const_cast<QModelIndex&>(index), pack.logoUrl);
|
||||
if (auto icon_or_none = const_cast<ResourceModel*>(this)->getIcon(const_cast<QModelIndex&>(index), pack->logoUrl);
|
||||
icon_or_none.has_value())
|
||||
return icon_or_none.value();
|
||||
|
||||
@ -64,16 +65,16 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
|
||||
return QSize(0, 58);
|
||||
case Qt::UserRole: {
|
||||
QVariant v;
|
||||
v.setValue(pack);
|
||||
v.setValue(*pack);
|
||||
return v;
|
||||
}
|
||||
// Custom data
|
||||
case UserDataTypes::TITLE:
|
||||
return pack.name;
|
||||
return pack->name;
|
||||
case UserDataTypes::DESCRIPTION:
|
||||
return pack.description;
|
||||
return pack->description;
|
||||
case UserDataTypes::SELECTED:
|
||||
return pack.isAnyVersionSelected();
|
||||
return pack->isAnyVersionSelected();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -102,7 +103,7 @@ bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int
|
||||
if (pos >= m_packs.size() || pos < 0 || !index.isValid())
|
||||
return false;
|
||||
|
||||
m_packs[pos] = value.value<ModPlatform::IndexedPack>();
|
||||
m_packs[pos] = std::make_shared<ModPlatform::IndexedPack>(value.value<ModPlatform::IndexedPack>());
|
||||
emit dataChanged(index, index);
|
||||
|
||||
return true;
|
||||
@ -161,7 +162,7 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
||||
if (!hasActiveInfoJob())
|
||||
m_current_info_job.clear();
|
||||
|
||||
if (!pack.versionsLoaded) {
|
||||
if (!pack->versionsLoaded) {
|
||||
auto args{ createVersionsArguments(entry) };
|
||||
auto callbacks{ createVersionsCallbacks(entry) };
|
||||
|
||||
@ -177,7 +178,7 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
||||
runInfoJob(job);
|
||||
}
|
||||
|
||||
if (!pack.extraDataLoaded) {
|
||||
if (!pack->extraDataLoaded) {
|
||||
auto args{ createInfoArguments(entry) };
|
||||
auto callbacks{ createInfoCallbacks(entry) };
|
||||
|
||||
@ -326,15 +327,15 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra
|
||||
|
||||
void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
|
||||
{
|
||||
QList<ModPlatform::IndexedPack> newList;
|
||||
QList<ModPlatform::IndexedPack::Ptr> newList;
|
||||
auto packs = documentToArray(doc);
|
||||
|
||||
for (auto packRaw : packs) {
|
||||
auto packObj = packRaw.toObject();
|
||||
|
||||
ModPlatform::IndexedPack pack;
|
||||
ModPlatform::IndexedPack::Ptr pack = std::make_shared<ModPlatform::IndexedPack>();
|
||||
try {
|
||||
loadIndexedPack(pack, packObj);
|
||||
loadIndexedPack(*pack, packObj);
|
||||
newList.append(pack);
|
||||
} catch (const JSONValidationError& e) {
|
||||
qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause();
|
||||
|
@ -123,7 +123,7 @@ class ResourceModel : public QAbstractListModel {
|
||||
QSet<QUrl> m_currently_running_icon_actions;
|
||||
QSet<QUrl> m_failed_icon_actions;
|
||||
|
||||
QList<ModPlatform::IndexedPack> m_packs;
|
||||
QList<ModPlatform::IndexedPack::Ptr> m_packs;
|
||||
|
||||
// HACK: We need this to prevent callbacks from calling the model after it has already been deleted.
|
||||
// This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better?
|
||||
|
@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ResourcePackResourceModel::createSearchArguments()
|
||||
ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(QModelIndex& entry)
|
||||
{
|
||||
auto& pack = m_packs[entry.row()];
|
||||
return { pack };
|
||||
return { *pack };
|
||||
}
|
||||
|
||||
ResourceAPI::ProjectInfoArgs ResourcePackResourceModel::createInfoArguments(QModelIndex& entry)
|
||||
{
|
||||
auto& pack = m_packs[entry.row()];
|
||||
return { pack };
|
||||
return { *pack };
|
||||
}
|
||||
|
||||
void ResourcePackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
|
||||
|
@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ShaderPackResourceModel::createSearchArguments()
|
||||
ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(QModelIndex& entry)
|
||||
{
|
||||
auto& pack = m_packs[entry.row()];
|
||||
return { pack };
|
||||
return { *pack };
|
||||
}
|
||||
|
||||
ResourceAPI::ProjectInfoArgs ShaderPackResourceModel::createInfoArguments(QModelIndex& entry)
|
||||
{
|
||||
auto& pack = m_packs[entry.row()];
|
||||
return { pack };
|
||||
return { *pack };
|
||||
}
|
||||
|
||||
void ShaderPackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
|
||||
|
@ -75,9 +75,9 @@ class ResourceModelTest : public QObject {
|
||||
auto search_json = DummyResourceAPI::searchRequestResult();
|
||||
auto processed_response = model->documentToArray(search_json).first().toObject();
|
||||
|
||||
QVERIFY(processed_pack.addonId.toString() == Json::requireString(processed_response, "project_id"));
|
||||
QVERIFY(processed_pack.description == Json::requireString(processed_response, "description"));
|
||||
QVERIFY(processed_pack.authors.first().name == Json::requireString(processed_response, "author"));
|
||||
QVERIFY(processed_pack->addonId.toString() == Json::requireString(processed_response, "project_id"));
|
||||
QVERIFY(processed_pack->description == Json::requireString(processed_response, "description"));
|
||||
QVERIFY(processed_pack->authors.first().name == Json::requireString(processed_response, "author"));
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user