feat: track instance copies that use links
confirm deleations when other instances link to it Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
3ec92acfe7
commit
1ca2c59f2e
@ -40,6 +40,8 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include "settings/INISettingsObject.h"
|
#include "settings/INISettingsObject.h"
|
||||||
#include "settings/Setting.h"
|
#include "settings/Setting.h"
|
||||||
@ -64,6 +66,8 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
|
|||||||
m_settings->registerSetting("totalTimePlayed", 0);
|
m_settings->registerSetting("totalTimePlayed", 0);
|
||||||
m_settings->registerSetting("lastTimePlayed", 0);
|
m_settings->registerSetting("lastTimePlayed", 0);
|
||||||
|
|
||||||
|
m_settings->registerSetting("linkedInstancesList", "[]");
|
||||||
|
|
||||||
// Game time override
|
// Game time override
|
||||||
auto gameTimeOverride = m_settings->registerSetting("OverrideGameTime", false);
|
auto gameTimeOverride = m_settings->registerSetting("OverrideGameTime", false);
|
||||||
m_settings->registerOverride(globalSettings->getSetting("ShowGameTime"), gameTimeOverride);
|
m_settings->registerOverride(globalSettings->getSetting("ShowGameTime"), gameTimeOverride);
|
||||||
@ -182,6 +186,38 @@ bool BaseInstance::shouldStopOnConsoleOverflow() const
|
|||||||
return m_settings->get("ConsoleOverflowStop").toBool();
|
return m_settings->get("ConsoleOverflowStop").toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList BaseInstance::getLinkedInstances() const
|
||||||
|
{
|
||||||
|
return m_settings->getList<QString>("linkedInstancesList");
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseInstance::setLinkedInstances(const QStringList& list)
|
||||||
|
{
|
||||||
|
auto linkedInstancesList = m_settings->getList<QString>("linkedInstancesList");
|
||||||
|
m_settings->setList("linkedInstancesList", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseInstance::addLinkedInstanceId(const QString& id)
|
||||||
|
{
|
||||||
|
auto linkedInstancesList = m_settings->getList<QString>("linkedInstancesList");
|
||||||
|
linkedInstancesList.append(id);
|
||||||
|
setLinkedInstances(linkedInstancesList);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseInstance::removeLinkedInstanceId(const QString& id)
|
||||||
|
{
|
||||||
|
auto linkedInstancesList = m_settings->getList<QString>("linkedInstancesList");
|
||||||
|
int numRemoved = linkedInstancesList.removeAll(id);
|
||||||
|
setLinkedInstances(linkedInstancesList);
|
||||||
|
return numRemoved > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseInstance::isLinkedToInstanceId(const QString& id) const
|
||||||
|
{
|
||||||
|
auto linkedInstancesList = m_settings->getList<QString>("linkedInstancesList");
|
||||||
|
return linkedInstancesList.contains(id);
|
||||||
|
}
|
||||||
|
|
||||||
void BaseInstance::iconUpdated(QString key)
|
void BaseInstance::iconUpdated(QString key)
|
||||||
{
|
{
|
||||||
if(iconKey() == key)
|
if(iconKey() == key)
|
||||||
|
@ -282,6 +282,12 @@ public:
|
|||||||
int getConsoleMaxLines() const;
|
int getConsoleMaxLines() const;
|
||||||
bool shouldStopOnConsoleOverflow() const;
|
bool shouldStopOnConsoleOverflow() const;
|
||||||
|
|
||||||
|
QStringList getLinkedInstances() const;
|
||||||
|
void setLinkedInstances(const QStringList& list);
|
||||||
|
void addLinkedInstanceId(const QString& id);
|
||||||
|
bool removeLinkedInstanceId(const QString& id);
|
||||||
|
bool isLinkedToInstanceId(const QString& id) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void changeStatus(Status newStatus);
|
void changeStatus(Status newStatus);
|
||||||
|
|
||||||
|
@ -137,6 +137,8 @@ void InstanceCopyTask::copyFinished()
|
|||||||
if(!m_keepPlaytime) {
|
if(!m_keepPlaytime) {
|
||||||
inst->resetTimePlayed();
|
inst->resetTimePlayed();
|
||||||
}
|
}
|
||||||
|
if (m_useLinks)
|
||||||
|
inst->addLinkedInstanceId(m_origInstance->id());
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +129,16 @@ QMimeData* InstanceList::mimeData(const QModelIndexList& indexes) const
|
|||||||
return mimeData;
|
return mimeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList InstanceList::getLinkedInstancesById(const QString &id) const
|
||||||
|
{
|
||||||
|
QStringList linkedInstances;
|
||||||
|
for (auto inst : m_instances) {
|
||||||
|
if (inst->isLinkedToInstanceId(id))
|
||||||
|
linkedInstances.append(inst->id());
|
||||||
|
}
|
||||||
|
return linkedInstances;
|
||||||
|
}
|
||||||
|
|
||||||
int InstanceList::rowCount(const QModelIndex& parent) const
|
int InstanceList::rowCount(const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
|
@ -154,6 +154,8 @@ public:
|
|||||||
QStringList mimeTypes() const override;
|
QStringList mimeTypes() const override;
|
||||||
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||||
|
|
||||||
|
QStringList getLinkedInstancesById(const QString &id) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataIsInvalid();
|
void dataIsInvalid();
|
||||||
void instancesChanged();
|
void instancesChanged();
|
||||||
|
@ -183,3 +183,21 @@ void INIFile::set(QString key, QVariant val)
|
|||||||
{
|
{
|
||||||
this->operator[](key) = val;
|
this->operator[](key) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void INIFile::setList(QString key, QVariantList val)
|
||||||
|
{
|
||||||
|
QString stringList = QJsonDocument(QVariant(val).toJsonArray()).toJson(QJsonDocument::Compact);
|
||||||
|
|
||||||
|
this->operator[](key) = stringList;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList INIFile::getList(QString key, QVariantList def) const
|
||||||
|
{
|
||||||
|
if (this->contains(key)) {
|
||||||
|
auto src = this->operator[](key);
|
||||||
|
|
||||||
|
return QJsonDocument::fromJson(src.toByteArray()).toVariant().toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
// Sectionless INI parser (for instance config files)
|
// Sectionless INI parser (for instance config files)
|
||||||
class INIFile : public QMap<QString, QVariant>
|
class INIFile : public QMap<QString, QVariant>
|
||||||
{
|
{
|
||||||
@ -33,4 +36,36 @@ public:
|
|||||||
void set(QString key, QVariant val);
|
void set(QString key, QVariant val);
|
||||||
static QString unescape(QString orig);
|
static QString unescape(QString orig);
|
||||||
static QString escape(QString orig);
|
static QString escape(QString orig);
|
||||||
|
|
||||||
|
void setList(QString key, QVariantList val);
|
||||||
|
template <typename T> void setList(QString key, QList<T> val)
|
||||||
|
{
|
||||||
|
QVariantList variantList;
|
||||||
|
variantList.reserve(val.size());
|
||||||
|
for (const T& v : val)
|
||||||
|
{
|
||||||
|
variantList.append(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setList(key, variantList);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList getList(QString key, QVariantList def) const;
|
||||||
|
template <typename T> QList<T> getList(QString key, QList<T> def) const
|
||||||
|
{
|
||||||
|
if (this->contains(key)) {
|
||||||
|
QVariant src = this->operator[](key);
|
||||||
|
QVariantList variantList = QJsonDocument::fromJson(src.toByteArray()).toVariant().toList();
|
||||||
|
|
||||||
|
QList<T>TList;
|
||||||
|
TList.reserve(variantList.size());
|
||||||
|
for (const QVariant& v : variantList)
|
||||||
|
{
|
||||||
|
TList.append(v.value<T>());
|
||||||
|
}
|
||||||
|
return TList;
|
||||||
|
}
|
||||||
|
|
||||||
|
return def;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -121,6 +121,19 @@ bool SettingsObject::contains(const QString &id)
|
|||||||
return m_settings.contains(id);
|
return m_settings.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SettingsObject::setList(const QString &id, QVariantList value)
|
||||||
|
{
|
||||||
|
QString stringList = QJsonDocument(QVariant(value).toJsonArray()).toJson(QJsonDocument::Compact);
|
||||||
|
|
||||||
|
return set(id, stringList);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList SettingsObject::getList(const QString &id)
|
||||||
|
{
|
||||||
|
QVariant value = this->get(id);
|
||||||
|
return QJsonDocument::fromJson(value.toByteArray()).toVariant().toList();
|
||||||
|
}
|
||||||
|
|
||||||
bool SettingsObject::reload()
|
bool SettingsObject::reload()
|
||||||
{
|
{
|
||||||
for (auto setting : m_settings.values())
|
for (auto setting : m_settings.values())
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class Setting;
|
class Setting;
|
||||||
@ -142,6 +144,45 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool contains(const QString &id);
|
bool contains(const QString &id);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the value of the setting with the given ID with a json list.
|
||||||
|
* If no setting with the given ID exists, returns false
|
||||||
|
* \param id The ID of the setting to change.
|
||||||
|
* \param value The new value of the setting.
|
||||||
|
*/
|
||||||
|
bool setList(const QString &id, QVariantList value);
|
||||||
|
template <typename T> bool setList(const QString &id, QList<T> val)
|
||||||
|
{
|
||||||
|
QVariantList variantList;
|
||||||
|
variantList.reserve(val.size());
|
||||||
|
for (const T& v : val)
|
||||||
|
{
|
||||||
|
variantList.append(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setList(id, variantList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets the value of the setting with the given ID as if it were a json list.
|
||||||
|
* \param id The ID of the setting to change.
|
||||||
|
* \return The setting's value as a QVariantList.
|
||||||
|
* If no setting with the given ID exists, returns an empty QVariantList.
|
||||||
|
*/
|
||||||
|
QVariantList getList(const QString &id);
|
||||||
|
template <typename T> QList<T> getList(const QString &id)
|
||||||
|
{
|
||||||
|
QVariantList variantList = this->getList(id);
|
||||||
|
|
||||||
|
QList<T>TList;
|
||||||
|
TList.reserve(variantList.size());
|
||||||
|
for (const QVariant& v : variantList)
|
||||||
|
{
|
||||||
|
TList.append(v.value<T>());
|
||||||
|
}
|
||||||
|
return TList;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Reloads the settings and emit signals for changed settings
|
* \brief Reloads the settings and emit signals for changed settings
|
||||||
* \return True if reloading was successful
|
* \return True if reloading was successful
|
||||||
|
@ -1337,6 +1337,20 @@ void MainWindow::on_actionDeleteInstance_triggered()
|
|||||||
if (response != QMessageBox::Yes)
|
if (response != QMessageBox::Yes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto linkedInstances = APPLICATION->instances()->getLinkedInstancesById(id);
|
||||||
|
if (!linkedInstances.empty()) {
|
||||||
|
response = CustomMessageBox::selectable(
|
||||||
|
this, tr("There are linked instances"),
|
||||||
|
tr("The folowing Instance(s) might reference files in this instance:\n\n"
|
||||||
|
"%1\n\n"
|
||||||
|
"Deleting it could break the other instance(s), \n\n"
|
||||||
|
"Are you sure?").arg(linkedInstances.join("\n")),
|
||||||
|
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No
|
||||||
|
)->exec();
|
||||||
|
if (response != QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (APPLICATION->instances()->trashInstance(id)) {
|
if (APPLICATION->instances()->trashInstance(id)) {
|
||||||
ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
|
ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QVariant>
|
||||||
#include <settings/INIFile.h>
|
#include <settings/INIFile.h>
|
||||||
|
|
||||||
|
|
||||||
class IniFileTest : public QObject
|
class IniFileTest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -52,8 +55,39 @@ slots:
|
|||||||
// load
|
// load
|
||||||
INIFile f2;
|
INIFile f2;
|
||||||
f2.loadFile(filename);
|
f2.loadFile(filename);
|
||||||
QCOMPARE(a, f2.get("a","NOT SET").toString());
|
QCOMPARE(f2.get("a","NOT SET").toString(), a);
|
||||||
QCOMPARE(b, f2.get("b","NOT SET").toString());
|
QCOMPARE(f2.get("b","NOT SET").toString(), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_SaveLoadLists()
|
||||||
|
{
|
||||||
|
QString slist_strings = "[\"a\",\"b\",\"c\"]";
|
||||||
|
QStringList list_strings = {"a", "b", "c"};
|
||||||
|
|
||||||
|
QString slist_numbers = "[1,2,3,10]";
|
||||||
|
QList<int> list_numbers = {1, 2, 3, 10};
|
||||||
|
|
||||||
|
QString filename = "test_SaveLoadLists.ini";
|
||||||
|
|
||||||
|
INIFile f;
|
||||||
|
f.setList("list_strings", list_strings);
|
||||||
|
f.setList("list_numbers", list_numbers);
|
||||||
|
f.saveFile(filename);
|
||||||
|
|
||||||
|
// load
|
||||||
|
INIFile f2;
|
||||||
|
f2.loadFile(filename);
|
||||||
|
|
||||||
|
QStringList out_list_strings = f2.getList<QString>("list_strings", QStringList());
|
||||||
|
qDebug() << "OutStringList" << out_list_strings;
|
||||||
|
|
||||||
|
QList<int> out_list_numbers = f2.getList<int>("list_numbers", QList<int>());
|
||||||
|
qDebug() << "OutNumbersList" << out_list_numbers;
|
||||||
|
|
||||||
|
QCOMPARE(f2.get("list_strings","NOT SET").toString(), slist_strings);
|
||||||
|
QCOMPARE(out_list_strings, list_strings);
|
||||||
|
QCOMPARE(f2.get("list_numbers","NOT SET").toString(), slist_numbers);
|
||||||
|
QCOMPARE(out_list_numbers, list_numbers);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user