From ba176e5e9b639ac0770192987833a3b40e71409a Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 13 Dec 2015 18:30:40 +0000 Subject: Remove dependency of TransferSave on SaveGameBryo, part of fix for #418 Added a method to Profile class to get location of save games for the profile. I haven't added this to IProfile as am in two minds. Aside from this have done cleanups of issues suggested by include-what-you-use, and some OCD sorting of #includes --- src/transfersavesdialog.cpp | 409 ++++++++++++++++++++++---------------------- 1 file changed, 206 insertions(+), 203 deletions(-) (limited to 'src/transfersavesdialog.cpp') diff --git a/src/transfersavesdialog.cpp b/src/transfersavesdialog.cpp index 48fc4548..710a33b9 100644 --- a/src/transfersavesdialog.cpp +++ b/src/transfersavesdialog.cpp @@ -21,19 +21,70 @@ along with Mod Organizer. If not, see . #include "ui_transfersavesdialog.h" #include "iplugingame.h" -#include "savegamegamebyro.h" -#include "utility.h" +#include "isavegame.h" +#include "savegameinfo.h" +#include "scriptextender.h" +#include +#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include -#include -#include - +class QWidget; //Do we /really/ need this? 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 getIdentifier() 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); + } +}; + +} //end anonymous namespace TransferSavesDialog::TransferSavesDialog(const Profile &profile, IPluginGame const *gamePlugin, QWidget *parent) : TutorableDialog("TransferSaves", parent) @@ -42,6 +93,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,84 +105,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); - - foreach (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 characters; - for (std::vector::const_iterator iter = m_GlobalSaves.begin(); - iter != m_GlobalSaves.end(); ++iter) { - characters.insert((*iter)->pcName()); - } - ui->globalCharacterList->clear(); - for (std::set::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 characters; - for (std::vector::const_iterator iter = m_LocalSaves.begin(); - iter != m_LocalSaves.end(); ++iter) { - characters.insert((*iter)->pcName()); - } - ui->localCharacterList->clear(); - for (std::set::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); } @@ -152,153 +147,71 @@ 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("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::const_iterator iter = m_GlobalSaves.begin(); - iter != m_GlobalSaves.end(); ++iter) { - if ((*iter)->pcName() == selectedCharacter) { - QStringList files = (*iter)->saveFiles(); - foreach (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 (!QFile::rename(fileInfo.absoluteFilePath(), destinationFile)) { - qCritical("failed to move %s to %s", - fileInfo.absoluteFilePath().toUtf8().constData(), - destinationFile.toUtf8().constData()); - } - } - } - } + QString character = ui->globalCharacterList->currentItem()->text(); + if (transferCharacters(character, + MOVE_SAVES TO_PROFILE, + m_GlobalSaves[character], + m_Profile.savePath(), + QFile::rename, + "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::const_iterator iter = m_GlobalSaves.begin(); - iter != m_GlobalSaves.end(); ++iter) { - if ((*iter)->pcName() == selectedCharacter) { - QStringList files = (*iter)->saveFiles(); - foreach (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 (!QFile::copy(fileInfo.absoluteFilePath(), destinationFile)) { - qCritical("failed to copy %s to %s", - fileInfo.absoluteFilePath().toUtf8().constData(), - destinationFile.toUtf8().constData()); - } - } - } - } + QString character = ui->globalCharacterList->currentItem()->text(); + if (transferCharacters(character, + COPY_SAVES TO_PROFILE, + m_GlobalSaves[character], + m_Profile.savePath(), + QFile::copy, + "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::const_iterator iter = m_LocalSaves.begin(); - iter != m_LocalSaves.end(); ++iter) { - if ((*iter)->pcName() == selectedCharacter) { - QStringList files = (*iter)->saveFiles(); - foreach (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 (!QFile::rename(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(), + QFile::rename, + "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::const_iterator iter = m_LocalSaves.begin(); - iter != m_LocalSaves.end(); ++iter) { - if ((*iter)->pcName() == selectedCharacter) { - QStringList files = (*iter)->saveFiles(); - foreach (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 (!QFile::copy(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(), + QFile::copy, + "Failed to copy %s to %s")) { + refreshGlobalSaves(); + refreshGlobalCharacters(); } - refreshGlobalSaves(); - refreshGlobalCharacters(); } void TransferSavesDialog::on_doneButton_clicked() @@ -309,10 +222,12 @@ void TransferSavesDialog::on_doneButton_clicked() void TransferSavesDialog::on_globalCharacterList_currentTextChanged(const QString ¤tText) { ui->globalSavesList->clear(); - for (std::vector::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()); } } } @@ -320,10 +235,98 @@ void TransferSavesDialog::on_globalCharacterList_currentTextChanged(const QStrin void TransferSavesDialog::on_localCharacterList_currentTextChanged(const QString ¤tText) { ui->localSavesList->clear(); - for (std::vector::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(); + 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->getIdentifier()].push_back( + std::unique_ptr(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, + bool (method)(QString const &, QString const &), + 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; + + QStringList extensions = { m_GamePlugin->savegameExtension() }; + { + ScriptExtender *ext = m_GamePlugin->feature(); + if (ext != nullptr) { + extensions += ext->saveGameAttachmentExtensions(); + } + } + QDir destination(dest); + for (SaveListItem const &save : saves) { + QFileInfo const saveFile = save->getFilename(); + for (QString const &ext : extensions) { + QFileInfo sourceFile(saveFile.absoluteDir().absoluteFilePath(saveFile.completeBaseName() + "." + ext)); + 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; } -- cgit v1.3.1