diff options
Diffstat (limited to 'src/transfersavesdialog.cpp')
| -rw-r--r-- | src/transfersavesdialog.cpp | 411 |
1 files changed, 215 insertions, 196 deletions
diff --git a/src/transfersavesdialog.cpp b/src/transfersavesdialog.cpp index 838d12ce..e130b1ae 100644 --- a/src/transfersavesdialog.cpp +++ b/src/transfersavesdialog.cpp @@ -21,19 +21,83 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "ui_transfersavesdialog.h"
#include "iplugingame.h"
-#include "savegamegamebyro.h"
-#include "utility.h"
+#include "isavegame.h"
+#include "savegameinfo.h"
+#include <utility.h>
+#include <QtDebug>
+#include <QDateTime>
#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QFlags>
+#include <QLabel>
+#include <QListWidget>
+#include <QListWidgetItem>
#include <QMessageBox>
-
-#include <Shlwapi.h>
-#include <shlobj.h>
-
+#include <QPushButton>
+#include <QStringList>
using namespace MOBase;
using namespace MOShared;
+//These two classes give the save-transfer box a smidgin of useful info even
+//if save game isn't supported yet.
+namespace {
+
+class DummySave : public ISaveGame
+{
+public:
+ DummySave(QString const &filename) :
+ m_File(filename)
+ {}
+
+ ~DummySave() {}
+
+ virtual QString getFilename() const override
+ {
+ return m_File;
+ }
+
+ virtual QDateTime getCreationTime() const override
+ {
+ return QFileInfo(m_File).created();
+ }
+
+ virtual QString getSaveGroupIdentifier() const override
+ {
+ return m_File;
+ }
+
+ virtual QStringList allFiles() const override
+ {
+ return { m_File };
+ }
+
+private:
+ QString m_File;
+};
+
+class DummyInfo : public SaveGameInfo
+{
+public:
+ virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override
+ {
+ return new DummySave(file);
+ }
+
+ virtual MissingAssets getMissingAssets(QString const &) const override
+ {
+ return {};
+ }
+
+ MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override
+ {
+ return nullptr;
+ }
+};
+
+} //end anonymous namespace
TransferSavesDialog::TransferSavesDialog(const Profile &profile, IPluginGame const *gamePlugin, QWidget *parent)
: TutorableDialog("TransferSaves", parent)
@@ -42,6 +106,7 @@ TransferSavesDialog::TransferSavesDialog(const Profile &profile, IPluginGame con , m_GamePlugin(gamePlugin)
{
ui->setupUi(this);
+ ui->label_2->setText(tr("Characters for profile %1").arg(m_Profile.name()));
refreshGlobalSaves();
refreshLocalSaves();
refreshGlobalCharacters();
@@ -53,85 +118,27 @@ TransferSavesDialog::~TransferSavesDialog() delete ui;
}
-
void TransferSavesDialog::refreshGlobalSaves()
{
- m_GlobalSaves.clear();
- QDir savesDir(m_GamePlugin->savesDirectory());
- savesDir.setNameFilters(QStringList() << QString("*.%1").arg(m_GamePlugin->savegameExtension()));
-
- QStringList files = savesDir.entryList(QDir::Files, QDir::Time);
-
- for (const QString &filename : files) {
- SaveGameGamebryo *save = new SaveGameGamebryo(this, savesDir.absoluteFilePath(filename), m_GamePlugin);
- save->setParent(this);
- m_GlobalSaves.push_back(save);
- }
+ refreshSaves(m_GlobalSaves, m_GamePlugin->savesDirectory().absolutePath());
}
void TransferSavesDialog::refreshLocalSaves()
{
- m_LocalSaves.clear();
-
- QDir savesDir(m_Profile.absolutePath() + "/saves");
-
- savesDir.setNameFilters(QStringList() << QString("*.%1").arg(m_GamePlugin->savegameExtension()));
-
- QStringList files = savesDir.entryList(QDir::Files, QDir::Time);
-
- for (const QString &filename : files) {
- SaveGameGamebryo *save = new SaveGameGamebryo(this, savesDir.absoluteFilePath(filename), m_GamePlugin);
-
- save->setParent(this);
- m_LocalSaves.push_back(save);
- }
+ refreshSaves(m_LocalSaves, m_Profile.savePath());
}
void TransferSavesDialog::refreshGlobalCharacters()
{
- std::set<QString> characters;
- for (std::vector<SaveGame*>::const_iterator iter = m_GlobalSaves.begin();
- iter != m_GlobalSaves.end(); ++iter) {
- characters.insert((*iter)->pcName());
- }
- ui->globalCharacterList->clear();
- for (std::set<QString>::const_iterator iter = characters.begin();
- iter != characters.end(); ++iter) {
- ui->globalCharacterList->addItem(*iter);
- }
- if (ui->globalCharacterList->count() > 0) {
- ui->globalCharacterList->setCurrentRow(0);
- ui->copyToLocalBtn->setEnabled(true);
- ui->moveToLocalBtn->setEnabled(true);
- } else {
- ui->copyToLocalBtn->setEnabled(false);
- ui->moveToLocalBtn->setEnabled(false);
- }
+ refreshCharacters(m_GlobalSaves, ui->globalCharacterList, ui->copyToLocalBtn, ui->moveToLocalBtn);
}
void TransferSavesDialog::refreshLocalCharacters()
{
- std::set<QString> characters;
- for (std::vector<SaveGame*>::const_iterator iter = m_LocalSaves.begin();
- iter != m_LocalSaves.end(); ++iter) {
- characters.insert((*iter)->pcName());
- }
- ui->localCharacterList->clear();
- for (std::set<QString>::const_iterator iter = characters.begin();
- iter != characters.end(); ++iter) {
- ui->localCharacterList->addItem(*iter);
- }
- if (ui->localCharacterList->count() > 0) {
- ui->localCharacterList->setCurrentRow(0);
- ui->copyToGlobalBtn->setEnabled(true);
- ui->moveToGlobalBtn->setEnabled(true);
- } else {
- ui->copyToGlobalBtn->setEnabled(false);
- ui->moveToGlobalBtn->setEnabled(false);
- }
+ refreshCharacters(m_LocalSaves, ui->localCharacterList, ui->copyToGlobalBtn, ui->moveToGlobalBtn);
}
@@ -153,144 +160,75 @@ bool TransferSavesDialog::testOverwrite(OverwriteMode &overwriteMode, const QStr return res == QMessageBox::Yes;
}
+
+#define MOVE_SAVES "Move all save games of character \"%1\""
+#define COPY_SAVES "Copy all save games of character \"%1\""
+
+#define TO_PROFILE "to the profile?"
+#define TO_GLOBAL "to the global location? Please be aware that this will mess up the running number of save games."
+
void TransferSavesDialog::on_moveToLocalBtn_clicked()
{
- QString selectedCharacter = ui->globalCharacterList->currentItem()->text();
- if (QMessageBox::question(this, tr("Confirm"),
- tr("Move all save games of character \"%1\" to the profile?").arg(selectedCharacter),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- QString destination = m_Profile.absolutePath() + "/saves";
- OverwriteMode overwriteMode = OVERWRITE_ASK;
-
- for (std::vector<SaveGame*>::const_iterator iter = m_GlobalSaves.begin();
- iter != m_GlobalSaves.end(); ++iter) {
- if ((*iter)->pcName() == selectedCharacter) {
- QStringList files = (*iter)->saveFiles();
- for (const QString &file : files) {
- QFileInfo fileInfo(file);
- QString destinationFile = destination + "/" + fileInfo.fileName();
- if (QFile::exists(destinationFile)) {
- if (testOverwrite(overwriteMode, destinationFile)) {
- QFile::remove(destinationFile);
- } else {
- continue;
- }
- }
- if (!shellMove(fileInfo.absoluteFilePath(), destinationFile)) {
- qCritical("failed to move %s to %s: %lu",
- fileInfo.absoluteFilePath().toUtf8().constData(),
- destinationFile.toUtf8().constData(),
- ::GetLastError());
- }
- }
- }
- }
+ QString character = ui->globalCharacterList->currentItem()->text();
+ if (transferCharacters(
+ character, MOVE_SAVES TO_PROFILE, m_GlobalSaves[character],
+ m_Profile.savePath(),
+ [this](const QString &source, const QString &destination) -> bool {
+ return shellMove(source, destination, this);
+ },
+ "Failed to move %s to %s")) {
+ refreshGlobalSaves();
+ refreshGlobalCharacters();
+ refreshLocalSaves();
+ refreshLocalCharacters();
}
- refreshGlobalSaves();
- refreshGlobalCharacters();
- refreshLocalSaves();
- refreshLocalCharacters();
}
void TransferSavesDialog::on_copyToLocalBtn_clicked()
{
- QString selectedCharacter = ui->globalCharacterList->currentItem()->text();
- if (QMessageBox::question(this, tr("Confirm"),
- tr("Copy all save games of character \"%1\" to the profile?").arg(selectedCharacter),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- QString destination = m_Profile.absolutePath() + "/saves";
- OverwriteMode overwriteMode = OVERWRITE_ASK;
- for (std::vector<SaveGame*>::const_iterator iter = m_GlobalSaves.begin();
- iter != m_GlobalSaves.end(); ++iter) {
- if ((*iter)->pcName() == selectedCharacter) {
- QStringList files = (*iter)->saveFiles();
- QStringList destinations;
- for (const QString &file : files) {
- QFileInfo fileInfo(file);
- destinations.append(destination + "/" + fileInfo.fileName());
- }
- shellCopy(files, destinations, this);
- }
- }
+ QString character = ui->globalCharacterList->currentItem()->text();
+ if (transferCharacters(
+ character, COPY_SAVES TO_PROFILE, m_GlobalSaves[character],
+ m_Profile.savePath(),
+ [this](const QString &source, const QString &destination) -> bool {
+ return shellCopy(source, destination, this);
+ },
+ "Failed to copy %s to %s")) {
+ refreshLocalSaves();
+ refreshLocalCharacters();
}
- refreshLocalSaves();
- refreshLocalCharacters();
}
void TransferSavesDialog::on_moveToGlobalBtn_clicked()
{
- QString selectedCharacter = ui->localCharacterList->currentItem()->text();
- if (QMessageBox::question(this, tr("Confirm"),
- tr("Move all save games of character \"%1\" to the global location? Please be aware "
- "that this will mess up the running number of save games.").arg(selectedCharacter),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
-
- QDir destination = m_GamePlugin->savesDirectory();
- OverwriteMode overwriteMode = OVERWRITE_ASK;
- for (std::vector<SaveGame*>::const_iterator iter = m_LocalSaves.begin();
- iter != m_LocalSaves.end(); ++iter) {
- if ((*iter)->pcName() == selectedCharacter) {
- QStringList files = (*iter)->saveFiles();
- for (const QString &file : files) {
- QFileInfo fileInfo(file);
- QString destinationFile = destination.filePath(fileInfo.fileName());
- if (QFile::exists(destinationFile)) {
- if (testOverwrite(overwriteMode, destinationFile)) {
- QFile::remove(destinationFile);
- } else {
- continue;
- }
- }
- if (!shellMove(fileInfo.absoluteFilePath(), destinationFile)) {
- qCritical("failed to move %s to %s",
- fileInfo.absoluteFilePath().toUtf8().constData(),
- destinationFile.toUtf8().constData());
- }
- }
- }
- }
+ QString character = ui->localCharacterList->currentItem()->text();
+ if (transferCharacters(
+ character, MOVE_SAVES TO_GLOBAL, m_LocalSaves[character],
+ m_GamePlugin->savesDirectory().absolutePath(),
+ [this](const QString &source, const QString &destination) -> bool {
+ return shellMove(source, destination, this);
+ },
+ "Failed to move %s to %s")) {
+ refreshGlobalSaves();
+ refreshGlobalCharacters();
+ refreshLocalSaves();
+ refreshLocalCharacters();
}
- refreshGlobalSaves();
- refreshGlobalCharacters();
- refreshLocalSaves();
- refreshLocalCharacters();
}
void TransferSavesDialog::on_copyToGlobalBtn_clicked()
{
- QString selectedCharacter = ui->localCharacterList->currentItem()->text();
- if (QMessageBox::question(this, tr("Confirm"),
- tr("Copy all save games of character \"%1\" to the global location? Please be aware "
- "that this will mess up the running number of save games.").arg(selectedCharacter),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
-
- QDir destination = m_GamePlugin->savesDirectory();
- OverwriteMode overwriteMode = OVERWRITE_ASK;
- for (std::vector<SaveGame*>::const_iterator iter = m_LocalSaves.begin();
- iter != m_LocalSaves.end(); ++iter) {
- if ((*iter)->pcName() == selectedCharacter) {
- QStringList files = (*iter)->saveFiles();
- for (const QString &file : files) {
- QFileInfo fileInfo(file);
- QString destinationFile = destination.filePath(fileInfo.fileName());
- if (QFile::exists(destinationFile)) {
- if (testOverwrite(overwriteMode, destinationFile)) {
- QFile::remove(destinationFile);
- } else {
- continue;
- }
- }
- if (!shellCopy(fileInfo.absoluteFilePath(), destinationFile)) {
- qCritical("failed to copy %s to %s",
- fileInfo.absoluteFilePath().toUtf8().constData(),
- destinationFile.toUtf8().constData());
- }
- }
- }
- }
+ QString character = ui->localCharacterList->currentItem()->text();
+ if (transferCharacters(
+ character, COPY_SAVES TO_GLOBAL, m_LocalSaves[character],
+ m_GamePlugin->savesDirectory().absolutePath(),
+ [this](const QString &source, const QString &destination) -> bool {
+ return shellCopy(source, destination, this);
+ },
+ "Failed to copy %s to %s")) {
+ refreshGlobalSaves();
+ refreshGlobalCharacters();
}
- refreshGlobalSaves();
- refreshGlobalCharacters();
}
void TransferSavesDialog::on_doneButton_clicked()
@@ -301,10 +239,12 @@ void TransferSavesDialog::on_doneButton_clicked() void TransferSavesDialog::on_globalCharacterList_currentTextChanged(const QString ¤tText)
{
ui->globalSavesList->clear();
- for (std::vector<SaveGame*>::const_iterator iter = m_GlobalSaves.begin();
- iter != m_GlobalSaves.end(); ++iter) {
- if ((*iter)->pcName() == currentText) {
- ui->globalSavesList->addItem(QFileInfo((*iter)->fileName()).fileName());
+ //sadly this can get called while we're resetting the list, with an invalid
+ //name, so we have to check.
+ SaveCollection::const_iterator saveList = m_GlobalSaves.find(currentText);
+ if (saveList != m_GlobalSaves.end()) {
+ for (SaveListItem const &save : saveList->second) {
+ ui->globalSavesList->addItem(QFileInfo(save->getFilename()).fileName());
}
}
}
@@ -312,10 +252,89 @@ void TransferSavesDialog::on_globalCharacterList_currentTextChanged(const QStrin void TransferSavesDialog::on_localCharacterList_currentTextChanged(const QString ¤tText)
{
ui->localSavesList->clear();
- for (std::vector<SaveGame*>::const_iterator iter = m_LocalSaves.begin();
- iter != m_LocalSaves.end(); ++iter) {
- if ((*iter)->pcName() == currentText) {
- ui->localSavesList->addItem(QFileInfo((*iter)->fileName()).fileName());
+ //sadly this can get called while we're resetting the list, with an invalid
+ //name, so we have to check.
+ SaveCollection::const_iterator saveList = m_LocalSaves.find(currentText);
+ if (saveList != m_LocalSaves.end()) {
+ for (SaveListItem const &save : saveList->second) {
+ ui->localSavesList->addItem(QFileInfo(save->getFilename()).fileName());
+ }
+ }
+}
+
+void TransferSavesDialog::refreshSaves(SaveCollection &saveCollection, QString const &savedir)
+{
+ saveCollection.clear();
+ QDir savesDir(savedir);
+ savesDir.setNameFilters(QStringList() << QString("*.%1").arg(m_GamePlugin->savegameExtension()));
+
+ SaveGameInfo const *info = m_GamePlugin->feature<SaveGameInfo>();
+ if (info == nullptr) {
+ static DummyInfo dummyInfo;
+ info = &dummyInfo;
+ }
+
+ QStringList files = savesDir.entryList(QDir::Files, QDir::Time);
+ for (const QString &filename : files) {
+ QString file = savesDir.absoluteFilePath(filename);
+ MOBase::ISaveGame const *save = info->getSaveGameInfo(file);
+ saveCollection[save->getSaveGroupIdentifier()].push_back(
+ std::unique_ptr<MOBase::ISaveGame const>(save));
+ }
+}
+
+void TransferSavesDialog::refreshCharacters(const SaveCollection &saveCollection,
+ QListWidget *charList, QPushButton *copy, QPushButton *move)
+{
+ charList->clear();
+ for (SaveCollection::value_type const &val : saveCollection) {
+ charList->addItem(val.first);
+ }
+ if (charList->count() > 0) {
+ charList->setCurrentRow(0);
+ copy->setEnabled(true);
+ move->setEnabled(true);
+ } else {
+ copy->setEnabled(false);
+ move->setEnabled(false);
+ }
+}
+
+bool TransferSavesDialog::transferCharacters(
+ QString const &character, char const *message, SaveList &saves,
+ QString const &dest,
+ const std::function<bool(const QString &, const QString &)> &method,
+ char const *errmsg)
+{
+ if (QMessageBox::question(this, tr("Confirm"),
+ tr(message).arg(character),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
+ return false;
+ }
+
+ OverwriteMode overwriteMode = OVERWRITE_ASK;
+
+ QDir destination(dest);
+ for (SaveListItem const &save : saves) {
+ for (QString source : save->allFiles()) {
+ QFileInfo sourceFile(source);
+ QString destinationFile(destination.absoluteFilePath(sourceFile.fileName()));
+
+ //If the file is already there, let them skip (or not).
+ if (QFile::exists(destinationFile)) {
+ if (! testOverwrite(overwriteMode, destinationFile)) {
+ continue;
+ }
+ //OK, they want to remove it.
+ QFile::remove(destinationFile);
+ }
+
+ if (!method(sourceFile.absoluteFilePath(), destinationFile)) {
+ qCritical(errmsg,
+ sourceFile.absoluteFilePath().toUtf8().constData(),
+ destinationFile.toUtf8().constData());
+ }
}
}
+ return true;
}
|
