change: make Mod a QObject used as a pointer
Prevents problems when copying it around! Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
@ -700,24 +700,24 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr
|
||||
{
|
||||
out << QString("%1:").arg(label);
|
||||
auto modList = model.allMods();
|
||||
std::sort(modList.begin(), modList.end(), [](Mod &a, Mod &b) {
|
||||
auto aName = a.fileinfo().completeBaseName();
|
||||
auto bName = b.fileinfo().completeBaseName();
|
||||
std::sort(modList.begin(), modList.end(), [](Mod::Ptr a, Mod::Ptr b) {
|
||||
auto aName = a->fileinfo().completeBaseName();
|
||||
auto bName = b->fileinfo().completeBaseName();
|
||||
return aName.localeAwareCompare(bName) < 0;
|
||||
});
|
||||
for(auto & mod: modList)
|
||||
for(auto mod: modList)
|
||||
{
|
||||
if(mod.type() == Mod::MOD_FOLDER)
|
||||
if(mod->type() == Mod::MOD_FOLDER)
|
||||
{
|
||||
out << u8" [📁] " + mod.fileinfo().completeBaseName() + " (folder)";
|
||||
out << u8" [📁] " + mod->fileinfo().completeBaseName() + " (folder)";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(mod.enabled()) {
|
||||
out << u8" [✔️] " + mod.fileinfo().completeBaseName();
|
||||
if(mod->enabled()) {
|
||||
out << u8" [✔️]" + mod->fileinfo().completeBaseName();
|
||||
}
|
||||
else {
|
||||
out << u8" [❌] " + mod.fileinfo().completeBaseName() + " (disabled)";
|
||||
out << u8" [❌] " + mod->fileinfo().completeBaseName() + " (disabled)";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1136,16 +1136,16 @@ std::shared_ptr<GameOptions> MinecraftInstance::gameOptionsModel() const
|
||||
return m_game_options;
|
||||
}
|
||||
|
||||
QList< Mod > MinecraftInstance::getJarMods() const
|
||||
QList<Mod*> MinecraftInstance::getJarMods() const
|
||||
{
|
||||
auto profile = m_components->getProfile();
|
||||
QList<Mod> mods;
|
||||
QList<Mod*> mods;
|
||||
for (auto jarmod : profile->getJarMods())
|
||||
{
|
||||
QStringList jar, temp1, temp2, temp3;
|
||||
jarmod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, jarmodsPath().absolutePath());
|
||||
// QString filePath = jarmodsPath().absoluteFilePath(jarmod->filename(currentSystem));
|
||||
mods.push_back(Mod(QFileInfo(jar[0])));
|
||||
mods.push_back(new Mod(QFileInfo(jar[0])));
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override;
|
||||
QStringList extraArguments() const override;
|
||||
QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override;
|
||||
QList<Mod> getJarMods() const;
|
||||
QList<Mod*> getJarMods() const;
|
||||
QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin);
|
||||
/// get arguments passed to java
|
||||
QStringList javaArguments() const;
|
||||
|
@ -39,10 +39,12 @@
|
||||
#include <QFileInfo>
|
||||
#include <QList>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include "ModDetails.h"
|
||||
|
||||
class Mod
|
||||
class Mod : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ModType
|
||||
{
|
||||
@ -53,6 +55,8 @@ public:
|
||||
MOD_LITEMOD, //!< The mod is a litemod
|
||||
};
|
||||
|
||||
using Ptr = shared_qobject_ptr<Mod>;
|
||||
|
||||
Mod() = default;
|
||||
Mod(const QFileInfo &file);
|
||||
explicit Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata);
|
||||
|
@ -134,7 +134,7 @@ void ModFolderModel::finishUpdate()
|
||||
QSet<QString> newSet(newList.begin(), newList.end());
|
||||
#else
|
||||
QSet<QString> currentSet = modsIndex.keys().toSet();
|
||||
auto & newMods = m_update->mods;
|
||||
auto& newMods = m_update->mods;
|
||||
QSet<QString> newSet = newMods.keys().toSet();
|
||||
#endif
|
||||
|
||||
@ -142,19 +142,20 @@ void ModFolderModel::finishUpdate()
|
||||
{
|
||||
QSet<QString> kept = currentSet;
|
||||
kept.intersect(newSet);
|
||||
for(auto & keptMod: kept) {
|
||||
auto & newMod = newMods[keptMod];
|
||||
for(auto& keptMod : kept) {
|
||||
auto* newMod = newMods[keptMod];
|
||||
auto row = modsIndex[keptMod];
|
||||
auto & currentMod = mods[row];
|
||||
if(newMod.dateTimeChanged() == currentMod.dateTimeChanged()) {
|
||||
auto currentMod = mods[row];
|
||||
if(newMod->dateTimeChanged() == currentMod->dateTimeChanged()) {
|
||||
// no significant change, ignore...
|
||||
continue;
|
||||
}
|
||||
auto & oldMod = mods[row];
|
||||
if(oldMod.isResolving()) {
|
||||
activeTickets.remove(oldMod.resolutionTicket());
|
||||
auto oldMod = mods[row];
|
||||
if(oldMod->isResolving()) {
|
||||
activeTickets.remove(oldMod->resolutionTicket());
|
||||
}
|
||||
oldMod = newMod;
|
||||
|
||||
mods[row] = newMod;
|
||||
resolveMod(mods[row]);
|
||||
emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1));
|
||||
}
|
||||
@ -173,9 +174,10 @@ void ModFolderModel::finishUpdate()
|
||||
int removedIndex = *iter;
|
||||
beginRemoveRows(QModelIndex(), removedIndex, removedIndex);
|
||||
auto removedIter = mods.begin() + removedIndex;
|
||||
if(removedIter->isResolving()) {
|
||||
activeTickets.remove(removedIter->resolutionTicket());
|
||||
if((*removedIter)->isResolving()) {
|
||||
activeTickets.remove((*removedIter)->resolutionTicket());
|
||||
}
|
||||
|
||||
mods.erase(removedIter);
|
||||
endRemoveRows();
|
||||
}
|
||||
@ -201,8 +203,8 @@ void ModFolderModel::finishUpdate()
|
||||
{
|
||||
modsIndex.clear();
|
||||
int idx = 0;
|
||||
for(auto & mod: mods) {
|
||||
modsIndex[mod.internal_id()] = idx;
|
||||
for(auto mod: mods) {
|
||||
modsIndex[mod->internal_id()] = idx;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
@ -217,17 +219,17 @@ void ModFolderModel::finishUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
void ModFolderModel::resolveMod(Mod& m)
|
||||
void ModFolderModel::resolveMod(Mod::Ptr m)
|
||||
{
|
||||
if(!m.shouldResolve()) {
|
||||
if(!m->shouldResolve()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto task = new LocalModParseTask(nextResolutionTicket, m.type(), m.fileinfo());
|
||||
auto task = new LocalModParseTask(nextResolutionTicket, m->type(), m->fileinfo());
|
||||
auto result = task->result();
|
||||
result->id = m.internal_id();
|
||||
result->id = m->internal_id();
|
||||
activeTickets.insert(nextResolutionTicket, result);
|
||||
m.setResolving(true, nextResolutionTicket);
|
||||
m->setResolving(true, nextResolutionTicket);
|
||||
nextResolutionTicket++;
|
||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
||||
connect(task, &LocalModParseTask::finished, this, &ModFolderModel::finishModParse);
|
||||
@ -243,8 +245,8 @@ void ModFolderModel::finishModParse(int token)
|
||||
auto result = *iter;
|
||||
activeTickets.remove(token);
|
||||
int row = modsIndex[result->id];
|
||||
auto & mod = mods[row];
|
||||
mod.finishResolvingWithDetails(result->details);
|
||||
auto mod = mods[row];
|
||||
mod->finishResolvingWithDetails(result->details);
|
||||
emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1));
|
||||
}
|
||||
|
||||
@ -269,9 +271,9 @@ bool ModFolderModel::isValid()
|
||||
return m_dir.exists() && m_dir.isReadable();
|
||||
}
|
||||
|
||||
auto ModFolderModel::selectedMods(QModelIndexList& indexes) -> std::list<Mod>
|
||||
auto ModFolderModel::selectedMods(QModelIndexList& indexes) -> std::list<Mod::Ptr>
|
||||
{
|
||||
std::list<Mod> selected_mods;
|
||||
std::list<Mod::Ptr> selected_mods;
|
||||
for (auto i : indexes) {
|
||||
if(i.column() != 0)
|
||||
continue;
|
||||
@ -370,9 +372,9 @@ bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadat
|
||||
{
|
||||
|
||||
for(auto mod : allMods()){
|
||||
if(mod.fileinfo().fileName() == filename){
|
||||
if(mod->fileinfo().fileName() == filename){
|
||||
auto index_dir = indexDir();
|
||||
mod.destroy(index_dir, preserve_metadata);
|
||||
mod->destroy(index_dir, preserve_metadata);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -413,9 +415,9 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes)
|
||||
if(i.column() != 0) {
|
||||
continue;
|
||||
}
|
||||
Mod &m = mods[i.row()];
|
||||
auto m = mods[i.row()];
|
||||
auto index_dir = indexDir();
|
||||
m.destroy(index_dir);
|
||||
m->destroy(index_dir);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -442,9 +444,9 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const
|
||||
switch (column)
|
||||
{
|
||||
case NameColumn:
|
||||
return mods[row].name();
|
||||
return mods[row]->name();
|
||||
case VersionColumn: {
|
||||
switch(mods[row].type()) {
|
||||
switch(mods[row]->type()) {
|
||||
case Mod::MOD_FOLDER:
|
||||
return tr("Folder");
|
||||
case Mod::MOD_SINGLEFILE:
|
||||
@ -452,23 +454,23 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return mods[row].version();
|
||||
return mods[row]->version();
|
||||
}
|
||||
case DateColumn:
|
||||
return mods[row].dateTimeChanged();
|
||||
return mods[row]->dateTimeChanged();
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return mods[row].internal_id();
|
||||
return mods[row]->internal_id();
|
||||
|
||||
case Qt::CheckStateRole:
|
||||
switch (column)
|
||||
{
|
||||
case ActiveColumn:
|
||||
return mods[row].enabled() ? Qt::Checked : Qt::Unchecked;
|
||||
return mods[row]->enabled() ? Qt::Checked : Qt::Unchecked;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@ -508,20 +510,20 @@ bool ModFolderModel::setModStatus(int row, ModFolderModel::ModStatusAction actio
|
||||
break;
|
||||
case Toggle:
|
||||
default:
|
||||
desiredStatus = !mod.enabled();
|
||||
desiredStatus = !mod->enabled();
|
||||
break;
|
||||
}
|
||||
|
||||
if(desiredStatus == mod.enabled()) {
|
||||
if(desiredStatus == mod->enabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// preserve the row, but change its ID
|
||||
auto oldId = mod.internal_id();
|
||||
if(!mod.enable(!mod.enabled())) {
|
||||
auto oldId = mod->internal_id();
|
||||
if(!mod->enable(!mod->enabled())) {
|
||||
return false;
|
||||
}
|
||||
auto newId = mod.internal_id();
|
||||
auto newId = mod->internal_id();
|
||||
if(modsIndex.contains(newId)) {
|
||||
// NOTE: this could handle a corner case, where we are overwriting a file, because the same 'mod' exists both enabled and disabled
|
||||
// But is it necessary?
|
||||
|
@ -101,13 +101,13 @@ public:
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
Mod &operator[](size_t index)
|
||||
Mod& operator[](size_t index)
|
||||
{
|
||||
return mods[index];
|
||||
return *mods[index];
|
||||
}
|
||||
const Mod &at(size_t index) const
|
||||
const Mod& at(size_t index) const
|
||||
{
|
||||
return mods.at(index);
|
||||
return *mods.at(index);
|
||||
}
|
||||
|
||||
/// Reloads the mod list and returns true if the list changed.
|
||||
@ -141,12 +141,12 @@ public:
|
||||
return { QString("%1/.index").arg(dir().absolutePath()) };
|
||||
}
|
||||
|
||||
const QList<Mod> & allMods()
|
||||
const QList<Mod::Ptr>& allMods()
|
||||
{
|
||||
return mods;
|
||||
}
|
||||
|
||||
auto selectedMods(QModelIndexList& indexes) -> std::list<Mod>;
|
||||
auto selectedMods(QModelIndexList& indexes) -> std::list<Mod::Ptr>;
|
||||
|
||||
public slots:
|
||||
void disableInteraction(bool disabled);
|
||||
@ -161,7 +161,7 @@ signals:
|
||||
void updateFinished();
|
||||
|
||||
private:
|
||||
void resolveMod(Mod& m);
|
||||
void resolveMod(Mod::Ptr m);
|
||||
bool setModStatus(int index, ModStatusAction action);
|
||||
|
||||
protected:
|
||||
@ -175,5 +175,5 @@ protected:
|
||||
QMap<QString, int> modsIndex;
|
||||
QMap<int, LocalModParseTask::ResultPtr> activeTickets;
|
||||
int nextResolutionTicket = 0;
|
||||
QList<Mod> mods;
|
||||
QList<Mod::Ptr> mods;
|
||||
};
|
||||
|
@ -53,33 +53,33 @@ void ModFolderLoadTask::run()
|
||||
// Read JAR files that don't have metadata
|
||||
m_mods_dir.refresh();
|
||||
for (auto entry : m_mods_dir.entryInfoList()) {
|
||||
Mod mod(entry);
|
||||
auto* mod = new Mod(entry);
|
||||
|
||||
if (mod.enabled()) {
|
||||
if (m_result->mods.contains(mod.internal_id())) {
|
||||
m_result->mods[mod.internal_id()].setStatus(ModStatus::Installed);
|
||||
if (mod->enabled()) {
|
||||
if (m_result->mods.contains(mod->internal_id())) {
|
||||
m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed);
|
||||
}
|
||||
else {
|
||||
m_result->mods[mod.internal_id()] = mod;
|
||||
m_result->mods[mod.internal_id()].setStatus(ModStatus::NoMetadata);
|
||||
m_result->mods[mod->internal_id()] = mod;
|
||||
m_result->mods[mod->internal_id()]->setStatus(ModStatus::NoMetadata);
|
||||
}
|
||||
}
|
||||
else {
|
||||
QString chopped_id = mod.internal_id().chopped(9);
|
||||
QString chopped_id = mod->internal_id().chopped(9);
|
||||
if (m_result->mods.contains(chopped_id)) {
|
||||
m_result->mods[mod.internal_id()] = mod;
|
||||
m_result->mods[mod->internal_id()] = mod;
|
||||
|
||||
auto metadata = m_result->mods[chopped_id].metadata();
|
||||
auto metadata = m_result->mods[chopped_id]->metadata();
|
||||
if (metadata) {
|
||||
mod.setMetadata(*metadata);
|
||||
mod->setMetadata(*metadata);
|
||||
|
||||
m_result->mods[mod.internal_id()].setStatus(ModStatus::Installed);
|
||||
m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed);
|
||||
m_result->mods.remove(chopped_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_result->mods[mod.internal_id()] = mod;
|
||||
m_result->mods[mod.internal_id()].setStatus(ModStatus::NoMetadata);
|
||||
m_result->mods[mod->internal_id()] = mod;
|
||||
m_result->mods[mod->internal_id()]->setStatus(ModStatus::NoMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,8 +97,8 @@ void ModFolderLoadTask::getFromMetadata()
|
||||
return;
|
||||
}
|
||||
|
||||
Mod mod(m_mods_dir, metadata);
|
||||
mod.setStatus(ModStatus::NotInstalled);
|
||||
m_result->mods[mod.internal_id()] = mod;
|
||||
auto* mod = new Mod(m_mods_dir, metadata);
|
||||
mod->setStatus(ModStatus::NotInstalled);
|
||||
m_result->mods[mod->internal_id()] = mod;
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class ModFolderLoadTask : public QObject, public QRunnable
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct Result {
|
||||
QMap<QString, Mod> mods;
|
||||
QMap<QString, Mod*> mods;
|
||||
};
|
||||
using ResultPtr = std::shared_ptr<Result>;
|
||||
ResultPtr result() const {
|
||||
|
Reference in New Issue
Block a user