summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2020-08-14 19:44:31 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2020-11-03 11:39:07 -0500
commitf7e9724eb1a817bdef372f87ebf96e9692db2bc9 (patch)
treeeb4f287b499331bdce0b306709f7a1af08a2a563 /src
parentf67dc91aa1f00eb2005d8e576c24739df91802ce (diff)
delete instance
Diffstat (limited to 'src')
-rw-r--r--src/instancemanagerdialog.cpp268
-rw-r--r--src/instancemanagerdialog.h7
-rw-r--r--src/instancemanagerdialog.ui24
3 files changed, 265 insertions, 34 deletions
diff --git a/src/instancemanagerdialog.cpp b/src/instancemanagerdialog.cpp
index 99ade7ad..5f42f409 100644
--- a/src/instancemanagerdialog.cpp
+++ b/src/instancemanagerdialog.cpp
@@ -6,9 +6,11 @@
#include "selectiondialog.h"
#include "plugincontainer.h"
#include "shared/appconfig.h"
+#include <utility.h>
+#include <report.h>
#include <iplugingame.h>
-namespace shell = MOBase::shell;
+using namespace MOBase;
void openInstanceManager(PluginContainer& pc, QWidget* parent)
{
@@ -54,7 +56,7 @@ public:
QString gamePath() const
{
if (auto n=m_settings.game().directory()) {
- return *n;
+ return QDir::toNativeSeparators(*n);
} else {
return {};
}
@@ -62,12 +64,12 @@ public:
QString location() const
{
- return m_dir.path();
+ return QDir::toNativeSeparators(m_dir.path());
}
QString baseDirectory() const
{
- return m_settings.paths().base();
+ return QDir::toNativeSeparators(m_settings.paths().base());
}
bool isPortable() const
@@ -75,6 +77,19 @@ public:
return m_portable;
}
+ bool isActive() const
+ {
+ auto& m = InstanceManager::instance();
+
+ if (m_portable && m.currentInstance() == "") {
+ return true;
+ } else if (m.currentInstance() == name()) {
+ return true;
+ }
+
+ return false;
+ }
+
private:
QDir m_dir;
bool m_portable;
@@ -90,6 +105,7 @@ InstanceManagerDialog::InstanceManagerDialog(
m_model(nullptr)
{
ui->setupUi(this);
+
ui->splitter->setSizes({200, 1});
ui->splitter->setStretchFactor(0, 0);
ui->splitter->setStretchFactor(1, 1);
@@ -114,6 +130,7 @@ InstanceManagerDialog::InstanceManagerDialog(
connect(ui->exploreLocation, &QPushButton::clicked, [&]{ exploreLocation(); });
connect(ui->exploreBaseDirectory, &QPushButton::clicked, [&]{ exploreBaseDirectory(); });
connect(ui->exploreGame, &QPushButton::clicked, [&]{ exploreGame(); });
+ connect(ui->deleteInstance, &QPushButton::clicked, [&]{ deleteInstance(); });
connect(ui->switchToInstance, &QPushButton::clicked, [&]{ openSelectedInstance(); });
connect(ui->close, &QPushButton::clicked, [&]{ close(); });
@@ -137,29 +154,51 @@ void InstanceManagerDialog::updateInstances()
void InstanceManagerDialog::updateList()
{
+ const auto prevSelIndex = singleSelectionIndex();
+ const auto* prevSel = singleSelection();
+
m_model->clear();
- for (auto&& ii : m_instances) {
- m_model->appendRow(new QStandardItem(ii->name()));
+ const std::size_t NoSel = -1;
+ std::size_t sel = NoSel;
+
+ for (std::size_t i=0; i<m_instances.size(); ++i) {
+ const auto& ii = *m_instances[i];
+ m_model->appendRow(new QStandardItem(ii.name()));
+
+ if (&ii == prevSel) {
+ sel = i;
+ }
}
- if (!m_instances.empty()) {
- select(0);
+
+ if (m_instances.empty()) {
+ select(-1);
+ } else {
+ if (sel == NoSel) {
+ if (prevSelIndex >= m_instances.size()) {
+ sel = m_instances.size() - 1;
+ } else {
+ sel = prevSelIndex;
+ }
+ }
+
+ select(sel);
}
}
void InstanceManagerDialog::select(std::size_t i)
{
- if (i >= m_instances.size()) {
- return;
- }
-
- const auto& ii = m_instances[i];
- fillData(*ii);
+ if (i < m_instances.size()) {
+ const auto& ii = m_instances[i];
+ fillData(*ii);
- ui->list->selectionModel()->select(
- m_filter.mapFromSource(m_filter.sourceModel()->index(i, 0)),
- QItemSelectionModel::ClearAndSelect);
+ ui->list->selectionModel()->select(
+ m_filter.mapFromSource(m_filter.sourceModel()->index(i, 0)),
+ QItemSelectionModel::ClearAndSelect);
+ } else {
+ clearData();
+ }
}
void InstanceManagerDialog::openSelectedInstance()
@@ -180,9 +219,9 @@ void InstanceManagerDialog::rename()
}
auto& m = InstanceManager::instance();
- if (m.currentInstance() == i->name()) {
+ if (i->isActive()) {
QMessageBox::information(this,
- tr("Rename instance"), tr("The active instance cannot be renamed"));
+ tr("Rename instance"), tr("The active instance cannot be renamed."));
return;
}
@@ -234,7 +273,7 @@ void InstanceManagerDialog::rename()
const QString newName = m.sanitizeInstanceName(text->text());
- const QString src = QDir::toNativeSeparators(i->location());
+ const QString src = i->location();
const QString dest = QDir::toNativeSeparators(
QFileInfo(i->location()).dir().path() + "/" + newName);
@@ -247,8 +286,6 @@ void InstanceManagerDialog::rename()
return;
}
-
-
}
void InstanceManagerDialog::exploreLocation()
@@ -272,6 +309,160 @@ void InstanceManagerDialog::exploreGame()
}
}
+void InstanceManagerDialog::deleteInstance()
+{
+ const auto* i = singleSelection();
+ if (!i) {
+ return;
+ }
+
+ auto& m = InstanceManager::instance();
+ if (i->isActive()) {
+ QMessageBox::information(this,
+ tr("Deleting instance"), tr("The active instance cannot be deleted."));
+ return;
+ }
+
+ if (i->isPortable()) {
+ deletePortable(*i);
+ } else {
+ deleteGlobal(*i);
+ }
+
+ updateInstances();
+ updateList();
+}
+
+bool InstanceManagerDialog::deletePortable(const InstanceInfo& i)
+{
+ const auto Recycle = QMessageBox::Save;
+ const auto Delete = QMessageBox::Yes;
+ const auto Cancel = QMessageBox::Cancel;
+
+ const std::vector<std::wstring> fileNames = {
+ AppConfig::iniFileName(),
+ };
+
+ const std::vector<std::wstring> dirNames = {
+ AppConfig::dumpsDir(),
+ AppConfig::downloadPath(),
+ AppConfig::logPath(),
+ AppConfig::modsPath(),
+ AppConfig::overwritePath(),
+ AppConfig::profilesPath(),
+ AppConfig::cachePath()
+ };
+
+ QStringList files;
+ for (const auto& n : fileNames) {
+ files.push_back(QDir::toNativeSeparators(
+ i.location() + "/" + QString::fromStdWString(n)));
+ }
+
+ QStringList dirs;
+ for (const auto& n : dirNames) {
+ dirs.push_back(QDir::toNativeSeparators(
+ i.location() + "/" + QString::fromStdWString(n)));
+ }
+
+ QString details = QObject::tr("These files will be deleted:");
+ for (const auto& f : files) {
+ details += "\n - " + f;
+ }
+
+ details += "\n\n" + QObject::tr("These folders will be deleted:");
+ for (const auto& d : dirs) {
+ details += "\n - " + d;
+ }
+
+
+ QStringList all;
+ all.append(files);
+ all.append(dirs);
+
+
+ const auto r = MOBase::TaskDialog(this)
+ .title(("Deleting portable instance"))
+ .main(tr("This will delete the data of the portable instance."))
+ .content(tr(
+ "The data is in %1. Only the relevant files and folders will be "
+ "deleted. The Mod Organizer installation itself will be untouched.")
+ .arg(i.location()))
+ .details(details)
+ .icon(QMessageBox::Warning)
+ .button({tr("Move the data to the recycle bin"), Recycle})
+ .button({tr("Delete the data permanently"), Delete})
+ .button({tr("Cancel"), Cancel})
+ .exec();
+
+ switch (r)
+ {
+ case Recycle:
+ return doDelete(all, true);
+
+ case Delete:
+ return doDelete(all, false);
+
+ case Cancel: // fall-through
+ default:
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool InstanceManagerDialog::deleteGlobal(const InstanceInfo& i)
+{
+ const auto Recycle = QMessageBox::Save;
+ const auto Delete = QMessageBox::Yes;
+ const auto Cancel = QMessageBox::Cancel;
+
+ const auto r = MOBase::TaskDialog(this)
+ .title(tr("Deleting instance"))
+ .main(tr("The instance folder will be deleted."))
+ .content(i.location())
+ .icon(QMessageBox::Warning)
+ .button({tr("Move the folder to the recycle bin"), Recycle})
+ .button({tr("Delete the folder permanently"), Delete})
+ .button({tr("Cancel"), Cancel})
+ .exec();
+
+ switch (r)
+ {
+ case Recycle:
+ return doDelete(QStringList(i.location()), true);
+
+ case Delete:
+ return doDelete(QStringList(i.location()), false);
+
+ case Cancel: // fall-through
+ default:
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool InstanceManagerDialog::doDelete(const QStringList& files, bool recycle)
+{
+ if (MOBase::shellDelete(files, recycle, this)) {
+ return true;
+ }
+
+ const auto e = GetLastError();
+ if (e == ERROR_CANCELLED) {
+ log::debug("deletion cancelled by user");
+ } else {
+ log::error("failed to delete, {}", formatSystemMessage(e));
+ }
+
+ return false;
+}
+
void InstanceManagerDialog::onSelection()
{
const auto i = singleSelectionIndex();
@@ -327,6 +518,7 @@ void InstanceManagerDialog::fillData(const InstanceInfo& ii)
ui->baseDirectory->setText(ii.baseDirectory());
ui->gameName->setText(ii.gameName());
ui->gameDir->setText(ii.gamePath());
+ setButtonsEnabled(true);
const auto& m = InstanceManager::instance();
@@ -348,4 +540,36 @@ void InstanceManagerDialog::fillData(const InstanceInfo& ii)
ui->convertToPortable->setToolTip("");
}
}
+
+
+ // these are not currently implemented; the ui sets them correctly above,
+ // but force them hidden for now
+ ui->convertToPortable->setVisible(false);
+ ui->convertToGlobal->setVisible(false);
+}
+
+void InstanceManagerDialog::clearData()
+{
+ ui->name->clear();
+ ui->location->clear();
+ ui->baseDirectory->clear();
+ ui->gameName->clear();
+ ui->gameDir->clear();
+
+ setButtonsEnabled(false);
+
+ ui->convertToPortable->setVisible(false);
+ ui->convertToGlobal->setVisible(false);
+}
+
+void InstanceManagerDialog::setButtonsEnabled(bool b)
+{
+ ui->rename->setEnabled(b);
+ ui->exploreLocation->setEnabled(b);
+ ui->exploreBaseDirectory->setEnabled(b);
+ ui->exploreGame->setEnabled(b);
+ ui->convertToPortable->setEnabled(b);
+ ui->convertToGlobal->setEnabled(b);
+ ui->deleteInstance->setEnabled(b);
+ ui->switchToInstance->setEnabled(b);
}
diff --git a/src/instancemanagerdialog.h b/src/instancemanagerdialog.h
index d102facb..3daa0800 100644
--- a/src/instancemanagerdialog.h
+++ b/src/instancemanagerdialog.h
@@ -26,6 +26,7 @@ public:
void exploreLocation();
void exploreBaseDirectory();
void exploreGame();
+ void deleteInstance();
private:
static const std::size_t NoSelection = -1;
@@ -47,6 +48,12 @@ private:
void updateList();
void fillData(const InstanceInfo& ii);
+ void clearData();
+ void setButtonsEnabled(bool b);
+
+ bool deletePortable(const InstanceInfo& ii);
+ bool deleteGlobal(const InstanceInfo& ii);
+ bool doDelete(const QStringList& files, bool recycle);
};
#endif // MODORGANIZER_INSTANCEMANAGERDIALOG_INCLUDED
diff --git a/src/instancemanagerdialog.ui b/src/instancemanagerdialog.ui
index 8bf28ed6..a8e5e2b7 100644
--- a/src/instancemanagerdialog.ui
+++ b/src/instancemanagerdialog.ui
@@ -305,18 +305,7 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="deleteInstance">
- <property name="text">
- <string>Delete instance</string>
- </property>
- <property name="icon">
- <iconset resource="resources.qrc">
- <normaloff>:/MO/gui/remove</normaloff>:/MO/gui/remove</iconset>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
+ <spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@@ -328,6 +317,17 @@
</property>
</spacer>
</item>
+ <item>
+ <widget class="QPushButton" name="deleteInstance">
+ <property name="text">
+ <string>Delete instance</string>
+ </property>
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/MO/gui/remove</normaloff>:/MO/gui/remove</iconset>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>