SCRATCH things and stuff, related to grou saving
This commit is contained in:
parent
12f2716f31
commit
7b439c85c0
@ -99,16 +99,11 @@ void BaseInstance::iconUpdated(QString key)
|
|||||||
void BaseInstance::invalidate()
|
void BaseInstance::invalidate()
|
||||||
{
|
{
|
||||||
changeStatus(Status::Gone);
|
changeStatus(Status::Gone);
|
||||||
|
m_group = QString();
|
||||||
|
emit groupChanged();
|
||||||
qDebug() << "Instance" << id() << "has been invalidated.";
|
qDebug() << "Instance" << id() << "has been invalidated.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::nuke()
|
|
||||||
{
|
|
||||||
changeStatus(Status::Gone);
|
|
||||||
qDebug() << "Instance" << id() << "has been deleted by MultiMC.";
|
|
||||||
FS::deletePath(instanceRoot());
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstance::changeStatus(BaseInstance::Status newStatus)
|
void BaseInstance::changeStatus(BaseInstance::Status newStatus)
|
||||||
{
|
{
|
||||||
Status status = currentStatus();
|
Status status = currentStatus();
|
||||||
|
@ -72,10 +72,6 @@ public:
|
|||||||
virtual void init() = 0;
|
virtual void init() = 0;
|
||||||
virtual void saveNow() = 0;
|
virtual void saveNow() = 0;
|
||||||
|
|
||||||
/// nuke thoroughly - deletes the instance contents, notifies the list/model which is
|
|
||||||
/// responsible of cleaning up the husk
|
|
||||||
void nuke();
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* the instance has been invalidated - it is no longer tracked by MultiMC for some reason,
|
* the instance has been invalidated - it is no longer tracked by MultiMC for some reason,
|
||||||
* but it has not necessarily been deleted.
|
* but it has not necessarily been deleted.
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "multimc_logic_export.h"
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
using InstanceId = QString;
|
using InstanceId = QString;
|
||||||
|
using GroupId = QString;
|
||||||
using InstanceLocator = std::pair<InstancePtr, int>;
|
using InstanceLocator = std::pair<InstancePtr, int>;
|
||||||
|
|
||||||
enum class InstCreateError
|
enum class InstCreateError
|
||||||
|
@ -48,6 +48,7 @@ FolderInstanceProvider::FolderInstanceProvider(SettingsObjectPtr settings, const
|
|||||||
|
|
||||||
QList< InstanceId > FolderInstanceProvider::discoverInstances()
|
QList< InstanceId > FolderInstanceProvider::discoverInstances()
|
||||||
{
|
{
|
||||||
|
qDebug() << "Discovering instances in" << m_instDir;
|
||||||
QList<InstanceId> out;
|
QList<InstanceId> out;
|
||||||
QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden, QDirIterator::FollowSymlinks);
|
QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden, QDirIterator::FollowSymlinks);
|
||||||
while (iter.hasNext())
|
while (iter.hasNext())
|
||||||
@ -71,6 +72,8 @@ QList< InstanceId > FolderInstanceProvider::discoverInstances()
|
|||||||
out.append(id);
|
out.append(id);
|
||||||
qDebug() << "Found instance ID" << id;
|
qDebug() << "Found instance ID" << id;
|
||||||
}
|
}
|
||||||
|
instanceSet = out.toSet();
|
||||||
|
m_instancesProbed = true;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +118,12 @@ InstancePtr FolderInstanceProvider::loadInstance(const InstanceId& id)
|
|||||||
|
|
||||||
void FolderInstanceProvider::saveGroupList()
|
void FolderInstanceProvider::saveGroupList()
|
||||||
{
|
{
|
||||||
|
qDebug() << "Will save group list now.";
|
||||||
|
if(!m_instancesProbed)
|
||||||
|
{
|
||||||
|
qDebug() << "Group saving prevented because we don't know the full list of instances yet.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
WatchLock foo(m_watcher, m_instDir);
|
WatchLock foo(m_watcher, m_instDir);
|
||||||
QString groupFileName = m_instDir + "/instgroups.json";
|
QString groupFileName = m_instDir + "/instgroups.json";
|
||||||
QMap<QString, QSet<QString>> reverseGroupMap;
|
QMap<QString, QSet<QString>> reverseGroupMap;
|
||||||
@ -124,6 +133,11 @@ void FolderInstanceProvider::saveGroupList()
|
|||||||
QString group = iter.value();
|
QString group = iter.value();
|
||||||
if (group.isEmpty())
|
if (group.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
if(!instanceSet.contains(id))
|
||||||
|
{
|
||||||
|
qDebug() << "Skipping saving missing instance" << id << "to groups list.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!reverseGroupMap.count(group))
|
if (!reverseGroupMap.count(group))
|
||||||
{
|
{
|
||||||
@ -159,6 +173,7 @@ void FolderInstanceProvider::saveGroupList()
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
FS::write(groupFileName, doc.toJson());
|
FS::write(groupFileName, doc.toJson());
|
||||||
|
qDebug() << "Group list saved.";
|
||||||
}
|
}
|
||||||
catch (const FS::FileSystemException &e)
|
catch (const FS::FileSystemException &e)
|
||||||
{
|
{
|
||||||
@ -168,6 +183,7 @@ void FolderInstanceProvider::saveGroupList()
|
|||||||
|
|
||||||
void FolderInstanceProvider::loadGroupList()
|
void FolderInstanceProvider::loadGroupList()
|
||||||
{
|
{
|
||||||
|
qDebug() << "Will load group list now.";
|
||||||
QSet<QString> groupSet;
|
QSet<QString> groupSet;
|
||||||
|
|
||||||
QString groupFileName = m_instDir + "/instgroups.json";
|
QString groupFileName = m_instDir + "/instgroups.json";
|
||||||
@ -262,6 +278,7 @@ void FolderInstanceProvider::loadGroupList()
|
|||||||
}
|
}
|
||||||
m_groupsLoaded = true;
|
m_groupsLoaded = true;
|
||||||
emit groupsChanged(groupSet);
|
emit groupsChanged(groupSet);
|
||||||
|
qDebug() << "Group list loaded.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderInstanceProvider::groupChanged()
|
void FolderInstanceProvider::groupChanged()
|
||||||
@ -309,6 +326,7 @@ static void clamp(T& current, T min, T max)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
// List of numbers from min to max. Next is exponent times bigger than previous.
|
// List of numbers from min to max. Next is exponent times bigger than previous.
|
||||||
class ExponentialSeries
|
class ExponentialSeries
|
||||||
{
|
{
|
||||||
@ -335,12 +353,8 @@ public:
|
|||||||
unsigned m_max;
|
unsigned m_max;
|
||||||
unsigned m_exponent;
|
unsigned m_exponent;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* WHY: the whole reason why this uses an exponential backoff retry scheme is antivirus on Windows.
|
|
||||||
* Basically, it starts messing things up while MultiMC is extracting/creating instances
|
|
||||||
* and causes that horrible failure that is NTFS to lock files in place because they are open.
|
|
||||||
*/
|
|
||||||
class FolderInstanceStaging : public Task
|
class FolderInstanceStaging : public Task
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -405,6 +419,11 @@ private slots:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*
|
||||||
|
* WHY: the whole reason why this uses an exponential backoff retry scheme is antivirus on Windows.
|
||||||
|
* Basically, it starts messing things up while MultiMC is extracting/creating instances
|
||||||
|
* and causes that horrible failure that is NTFS to lock files in place because they are open.
|
||||||
|
*/
|
||||||
ExponentialSeries backoff;
|
ExponentialSeries backoff;
|
||||||
QString m_stagingPath;
|
QString m_stagingPath;
|
||||||
FolderInstanceProvider * m_parent;
|
FolderInstanceProvider * m_parent;
|
||||||
@ -449,6 +468,7 @@ bool FolderInstanceProvider::commitStagedInstance(const QString& path, const QSt
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
groupMap[instID] = groupName;
|
groupMap[instID] = groupName;
|
||||||
|
instanceSet.insert(instID);
|
||||||
emit groupsChanged({groupName});
|
emit groupsChanged({groupName});
|
||||||
emit instancesChanged();
|
emit instancesChanged();
|
||||||
}
|
}
|
||||||
|
@ -19,24 +19,6 @@ public:
|
|||||||
/// used by InstanceList to (re)load an instance with the given @id.
|
/// used by InstanceList to (re)load an instance with the given @id.
|
||||||
InstancePtr loadInstance(const InstanceId& id) override;
|
InstancePtr loadInstance(const InstanceId& id) override;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// create instance in this provider
|
|
||||||
Task * creationTask(BaseVersionPtr version, const QString &instName, const QString &instGroup, const QString &instIcon);
|
|
||||||
|
|
||||||
// copy instance to this provider
|
|
||||||
Task * copyTask(const InstancePtr &oldInstance, const QString& instName, const QString& instGroup, const QString& instIcon, bool copySaves);
|
|
||||||
|
|
||||||
// import zipped instance into this provider
|
|
||||||
Task * zipImportTask(const QUrl sourceUrl, const QString &instName, const QString &instGroup, const QString &instIcon);
|
|
||||||
|
|
||||||
//create FtbInstance
|
|
||||||
Task * ftbCreationTask(FtbPackDownloader *downloader, const QString &instName, const QString &instGroup, const QString &instIcon);
|
|
||||||
|
|
||||||
// migrate an instance to the current format
|
|
||||||
Task * legacyUpgradeTask(const InstancePtr& oldInstance);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Wrap an instance creation task in some more task machinery and make it ready to be used
|
// Wrap an instance creation task in some more task machinery and make it ready to be used
|
||||||
Task * wrapInstanceTask(InstanceTask * task);
|
Task * wrapInstanceTask(InstanceTask * task);
|
||||||
|
|
||||||
@ -70,6 +52,8 @@ private: /* methods */
|
|||||||
private: /* data */
|
private: /* data */
|
||||||
QString m_instDir;
|
QString m_instDir;
|
||||||
QFileSystemWatcher * m_watcher;
|
QFileSystemWatcher * m_watcher;
|
||||||
QMap<QString, QString> groupMap;
|
QMap<InstanceId, GroupId> groupMap;
|
||||||
|
QSet<InstanceId> instanceSet;
|
||||||
bool m_groupsLoaded = false;
|
bool m_groupsLoaded = false;
|
||||||
|
bool m_instancesProbed = false;
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
|
|
||||||
#include "FolderInstanceProvider.h"
|
#include "FolderInstanceProvider.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
InstanceList::InstanceList(QObject *parent)
|
InstanceList::InstanceList(QObject *parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
@ -118,6 +119,25 @@ void InstanceList::deleteGroup(const QString& name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstanceList::deleteInstance(const InstanceId& id)
|
||||||
|
{
|
||||||
|
auto inst = getInstanceById(id);
|
||||||
|
if(!inst)
|
||||||
|
{
|
||||||
|
qDebug() << "Cannot delete instance" << id << " No such instance is present.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Will delete instance" << id;
|
||||||
|
if(!FS::deletePath(inst->instanceRoot()))
|
||||||
|
{
|
||||||
|
qWarning() << "Deletion of instance" << id << "has not been completely successful ...";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Instance" << id << "has been deleted by MultiMC.";
|
||||||
|
}
|
||||||
|
|
||||||
static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr> &list)
|
static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr> &list)
|
||||||
{
|
{
|
||||||
QMap<InstanceId, InstanceLocator> out;
|
QMap<InstanceId, InstanceLocator> out;
|
||||||
|
@ -80,7 +80,8 @@ public:
|
|||||||
QModelIndex getInstanceIndexById(const QString &id) const;
|
QModelIndex getInstanceIndexById(const QString &id) const;
|
||||||
QStringList getGroups();
|
QStringList getGroups();
|
||||||
|
|
||||||
void deleteGroup(const QString & name);
|
void deleteGroup(const GroupId & name);
|
||||||
|
void deleteInstance(const InstanceId & id);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataIsInvalid();
|
void dataIsInvalid();
|
||||||
|
@ -1617,7 +1617,7 @@ void MainWindow::on_actionDeleteInstance_triggered()
|
|||||||
)->exec();
|
)->exec();
|
||||||
if (response == QMessageBox::Yes)
|
if (response == QMessageBox::Yes)
|
||||||
{
|
{
|
||||||
m_selectedInstance->nuke();
|
MMC->instances()->deleteInstance(m_selectedInstance->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +64,6 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
|
|||||||
ui->groupBox->setCurrentIndex(index);
|
ui->groupBox->setCurrentIndex(index);
|
||||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||||
|
|
||||||
m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
||||||
m_buttons->button(QDialogButtonBox::Ok)->setDefault(true);
|
|
||||||
|
|
||||||
|
|
||||||
m_container = new PageContainer(this);
|
m_container = new PageContainer(this);
|
||||||
@ -73,8 +71,25 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
|
|||||||
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
||||||
ui->verticalLayout->insertWidget(2, m_container);
|
ui->verticalLayout->insertWidget(2, m_container);
|
||||||
|
|
||||||
|
m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
m_container->addButtons(m_buttons);
|
m_container->addButtons(m_buttons);
|
||||||
m_buttons->setFocus();
|
|
||||||
|
// Bonk Qt over its stupid head and make sure it understands which button is the default one...
|
||||||
|
// See: https://stackoverflow.com/questions/24556831/qbuttonbox-set-default-button
|
||||||
|
auto OkButton = m_buttons->button(QDialogButtonBox::Ok);
|
||||||
|
OkButton->setDefault(true);
|
||||||
|
OkButton->setAutoDefault(true);
|
||||||
|
connect(OkButton, &QPushButton::clicked, this, &NewInstanceDialog::accept);
|
||||||
|
|
||||||
|
auto CancelButton = m_buttons->button(QDialogButtonBox::Cancel);
|
||||||
|
CancelButton->setDefault(false);
|
||||||
|
CancelButton->setAutoDefault(false);
|
||||||
|
connect(CancelButton, &QPushButton::clicked, this, &NewInstanceDialog::reject);
|
||||||
|
|
||||||
|
auto HelpButton = m_buttons->button(QDialogButtonBox::Help);
|
||||||
|
HelpButton->setDefault(false);
|
||||||
|
HelpButton->setAutoDefault(false);
|
||||||
|
connect(HelpButton, &QPushButton::clicked, m_container, &PageContainer::help);
|
||||||
|
|
||||||
if(!url.isEmpty())
|
if(!url.isEmpty())
|
||||||
{
|
{
|
||||||
@ -82,14 +97,9 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
|
|||||||
importPage->setUrl(url);
|
importPage->setUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(m_buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &NewInstanceDialog::accept);
|
|
||||||
connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &NewInstanceDialog::reject);
|
|
||||||
connect(m_buttons->button(QDialogButtonBox::Help), &QPushButton::clicked, m_container, &PageContainer::help);
|
|
||||||
|
|
||||||
updateDialogState();
|
updateDialogState();
|
||||||
|
|
||||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("NewInstanceGeometry").toByteArray()));
|
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("NewInstanceGeometry").toByteArray()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewInstanceDialog::reject()
|
void NewInstanceDialog::reject()
|
||||||
@ -160,7 +170,11 @@ InstanceTask * NewInstanceDialog::extractTask()
|
|||||||
void NewInstanceDialog::updateDialogState()
|
void NewInstanceDialog::updateDialogState()
|
||||||
{
|
{
|
||||||
auto allowOK = creationTask && !instName().isEmpty();
|
auto allowOK = creationTask && !instName().isEmpty();
|
||||||
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
auto OkButton = m_buttons->button(QDialogButtonBox::Ok);
|
||||||
|
if(OkButton->isEnabled() != allowOK)
|
||||||
|
{
|
||||||
|
OkButton->setEnabled(allowOK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString NewInstanceDialog::instName() const
|
QString NewInstanceDialog::instName() const
|
||||||
|
Loading…
Reference in New Issue
Block a user