diff options
Diffstat (limited to 'src')
30 files changed, 647 insertions, 1046 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4cd16f04..6eec86a9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,10 +18,6 @@ SET(organizer_SRCS settings.cpp selfupdater.cpp selectiondialog.cpp - savegameinfowidgetgamebryo.cpp - savegameinfowidget.cpp - savegamegamebryo.cpp - savegame.cpp queryoverwritedialog.cpp profilesdialog.cpp profile.cpp @@ -94,13 +90,7 @@ SET(organizer_SRCS shared/windows_error.cpp shared/error_report.cpp shared/directoryentry.cpp - shared/gameinfo.cpp - shared/oblivioninfo.cpp - shared/fallout3info.cpp - shared/fallout4info.cpp - shared/falloutnvinfo.cpp shared/util.cpp - shared/skyriminfo.cpp shared/appconfig.cpp shared/leaktrace.cpp shared/stackdata.cpp @@ -115,10 +105,6 @@ SET(organizer_HDRS settings.h selfupdater.h selectiondialog.h - savegameinfowidgetgamebryo.h - savegameinfowidget.h - savegamegamebyro.h - savegame.h queryoverwritedialog.h profilesdialog.h profile.h @@ -191,13 +177,7 @@ SET(organizer_HDRS shared/windows_error.h shared/error_report.h shared/directoryentry.h - shared/gameinfo.h - shared/oblivioninfo.h - shared/fallout3info.h - shared/fallout4info.h - shared/falloutnvinfo.h shared/util.h - shared/skyriminfo.h shared/appconfig.h shared/appconfig.inc shared/leaktrace.h @@ -210,7 +190,6 @@ SET(organizer_UIS simpleinstalldialog.ui settingsdialog.ui selectiondialog.ui - savegameinfowidget.ui queryoverwritedialog.ui profilesdialog.ui overwriteinfodialog.ui diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index 6fce2acb..3657a10d 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -22,6 +22,14 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "ui_aboutdialog.h"
#include <utility.h>
+#include <QApplication>
+#include <QLabel>
+#include <QListWidget>
+#include <QListWidgetItem>
+#include <QTextBrowser>
+#include <QVariant>
+#include <Qt>
+
AboutDialog::AboutDialog(const QString &version, QWidget *parent)
: QDialog(parent)
diff --git a/src/aboutdialog.h b/src/aboutdialog.h index c3b38c10..103a0d2f 100644 --- a/src/aboutdialog.h +++ b/src/aboutdialog.h @@ -22,10 +22,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #define ABOUTDIALOG_H
#include <QDialog>
-#include <QListWidgetItem>
+class QListWidgetItem;
+#include <QObject>
+#include <QString>
+
#include <map>
-#include <vector>
-#include <utility>
namespace Ui {
class AboutDialog;
diff --git a/src/activatemodsdialog.cpp b/src/activatemodsdialog.cpp index fd56ae3e..5ef0a4e5 100644 --- a/src/activatemodsdialog.cpp +++ b/src/activatemodsdialog.cpp @@ -21,9 +21,14 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "ui_activatemodsdialog.h"
#include <QComboBox>
+#include <QHeaderView>
#include <QLabel>
+#include <QString>
+#include <QTableWidget>
-ActivateModsDialog::ActivateModsDialog(const std::map<QString, std::vector<QString> > &missingPlugins, QWidget *parent)
+#include <QtGlobal>
+
+ActivateModsDialog::ActivateModsDialog(SaveGameInfo::MissingAssets const &missingAssets, QWidget *parent)
: TutorableDialog("ActivateMods", parent), ui(new Ui::ActivateModsDialog)
{
ui->setupUi(this);
@@ -40,18 +45,17 @@ ActivateModsDialog::ActivateModsDialog(const std::map<QString, std::vector<QStri int row = 0;
- modsTable->setRowCount(missingPlugins.size());
+ modsTable->setRowCount(missingAssets.size());
- for (std::map<QString, std::vector<QString> >::const_iterator espIter = missingPlugins.begin();
- espIter != missingPlugins.end(); ++espIter, ++row) {
- modsTable->setCellWidget(row, 0, new QLabel(espIter->first));
- if (espIter->second.size() == 0) {
+ for (SaveGameInfo::MissingAssets::const_iterator espIter = missingAssets.begin();
+ espIter != missingAssets.end(); ++espIter, ++row) {
+ modsTable->setCellWidget(row, 0, new QLabel(espIter.key()));
+ if (espIter->size() == 0) {
modsTable->setCellWidget(row, 1, new QLabel(tr("not found")));
} else {
QComboBox* combo = new QComboBox();
- for (std::vector<QString>::const_iterator modIter = espIter->second.begin();
- modIter != espIter->second.end(); ++modIter) {
- combo->addItem(*modIter);
+ for (QString const &mod : espIter.value()) {
+ combo->addItem(mod);
}
modsTable->setCellWidget(row, 1, combo);
}
diff --git a/src/activatemodsdialog.h b/src/activatemodsdialog.h index 08dbad8d..f36b5fde 100644 --- a/src/activatemodsdialog.h +++ b/src/activatemodsdialog.h @@ -20,8 +20,14 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #ifndef ACTIVATEMODSDIALOG_H
#define ACTIVATEMODSDIALOG_H
+#include "savegameinfo.h"
#include "tutorabledialog.h"
-#include <map>
+
+#include <QObject>
+
+class QString;
+class QWidget;
+
#include <set>
namespace Ui {
@@ -42,7 +48,7 @@ public: * @param missingPlugins a map containing missing plugins that need to be activated
* @param parent ... Defaults to 0.
**/
- explicit ActivateModsDialog(const std::map<QString, std::vector<QString> > &missingPlugins, QWidget *parent = 0);
+ explicit ActivateModsDialog(SaveGameInfo::MissingAssets const &missingAssets, QWidget *parent = 0);
~ActivateModsDialog();
/**
diff --git a/src/iuserinterface.h b/src/iuserinterface.h index e6b39ee1..19e58c75 100644 --- a/src/iuserinterface.h +++ b/src/iuserinterface.h @@ -7,6 +7,7 @@ #include <ipluginmodpage.h>
#include <delayedfilewriter.h>
+class QSettings;
class IUserInterface
{
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c242bfe6..db7bd682 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -20,7 +20,24 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "mainwindow.h"
#include "ui_mainwindow.h"
+#include "directoryentry.h"
+#include "directoryrefresher.h"
+#include "executableinfo.h"
+#include "executableslist.h"
+#include "guessedvalue.h"
+#include "imodinterface.h"
+#include "iplugingame.h"
+#include "iplugindiagnose.h"
+#include "isavegame.h"
+#include "isavegameinfowidget.h"
+#include "nexusinterface.h"
+#include "organizercore.h"
+#include "pluginlistsortproxy.h"
+#include "previewgenerator.h"
+#include "savegameinfo.h"
#include "spawn.h"
+#include "versioninfo.h"
+
#include "report.h"
#include "modlist.h"
#include "modlistsortproxy.h"
@@ -31,7 +48,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "editexecutablesdialog.h"
#include "categories.h"
#include "categoriesdialog.h"
-#include "utility.h"
#include "modinfodialog.h"
#include "overwriteinfodialog.h"
#include "activatemodsdialog.h"
@@ -41,16 +57,13 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "messagedialog.h"
#include "installationmanager.h"
#include "lockeddialog.h"
-#include "syncoverwritedialog.h"
#include "logbuffer.h"
#include "downloadlistsortproxy.h"
#include "motddialog.h"
#include "filedialogmemory.h"
-#include "questionboxmemory.h"
#include "tutorialmanager.h"
#include "modflagicondelegate.h"
#include "genericicondelegate.h"
-#include "credentialsdialog.h"
#include "selectiondialog.h"
#include "csvbuilder.h"
#include "savetextasdialog.h"
@@ -59,62 +72,86 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "browserdialog.h"
#include "aboutdialog.h"
#include "safewritefile.h"
-//?
-//#include "isavegame.h"
-//#include "savegameinfo.h"
-//?
#include "nxmaccessmanager.h"
-#include <archive.h>
-#include <appconfig.h>
+#include "appconfig.h"
#include <utility.h>
-#include <ipluginproxy.h>
#include <dataarchives.h>
#include <bsainvalidation.h>
-#include <questionboxmemory.h>
#include <taskprogressmanager.h>
-#include <util.h>
#include <scopeguard.h>
#include <usvfs.h>
-#include <QTime>
-#include <QInputDialog>
-#include <QSettings>
-#include <QWhatsThis>
-#include <QProcess>
-#include <QMenu>
+#include <QAbstractItemDelegate>
+#include <QAbstractProxyModel>
+#include <QAction>
+#include <QApplication>
#include <QBuffer>
-#include <QInputDialog>
-#include <QDirIterator>
-#include <QHelpEvent>
-#include <QToolTip>
-#include <QFileDialog>
-#include <QTimer>
-#include <QMessageBox>
+#include <QCheckBox>
+#include <QClipboard>
+#include <QCloseEvent>
+#include <QCoreApplication>
+#include <QCursor>
#include <QDebug>
-#include <QBuffer>
-#include <QWidgetAction>
-#include <QToolButton>
-#include <QGraphicsObject>
-#include <QPluginLoader>
-#include <QRadioButton>
#include <QDesktopWidget>
-#include <QtPlugin>
-#include <QIdentityProxyModel>
-#include <QClipboard>
-#include <QNetworkInterface>
-#include <QNetworkProxy>
-#include <QJsonDocument>
+#include <QDialog>
+#include <QDirIterator>
+#include <QDragEnterEvent>
+#include <QDropEvent>
+#include <QEvent>
+#include <QFileDialog>
+#include <QFont>
+#include <QFuture>
+#include <QHash>
+#include <QIODevice>
+#include <QIcon>
+#include <QInputDialog>
+#include <QItemSelection>
+#include <QItemSelectionModel>
#include <QJsonArray>
+#include <QJsonDocument>
#include <QJsonObject>
-#include <QJsonValue>
+#include <QJsonValueRef>
+#include <QLineEdit>
+#include <QListWidgetItem>
+#include <QMenu>
+#include <QMessageBox>
#include <QMimeData>
+#include <QModelIndex>
+#include <QNetworkProxyFactory>
+#include <QPainter>
+#include <QPixmap>
+#include <QPoint>
+#include <QProcess>
+#include <QProgressDialog>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QRect>
+#include <QRegExp>
+#include <QResizeEvent>
+#include <QSettings>
+#include <QScopedPointer>
+#include <QSizePolicy>
+#include <QSize>
+#include <QTime>
+#include <QTimer>
+#include <QToolButton>
+#include <QToolTip>
+#include <QTranslator>
+#include <QTreeWidget>
+#include <QUrl>
+#include <QVariantList>
+#include <QWhatsThis>
+#include <QWidgetAction>
+
+#include <QtDebug>
+#include <QtGlobal>
+
+
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtConcurrent/QtConcurrentRun>
#else
#include <QtConcurrentRun>
#endif
-#include <QCoreApplication>
-#include <QProgressDialog>
#ifndef Q_MOC_RUN
#include <boost/thread.hpp>
@@ -123,18 +160,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <boost/assign.hpp>
#endif
-#include <Psapi.h>
#include <shlobj.h>
-#include <ShellAPI.h>
-#include <TlHelp32.h>
-#include <sstream>
-#include <regex>
+#include <limits.h>
+#include <exception>
#include <functional>
#include <map>
-#include <ctime>
-#include <wchar.h>
-#include <utility.h>
+#include <regex>
+#include <stdexcept>
+#include <sstream>
+#include <utility>
#ifdef TEST_MODELS
#include "modeltest.h"
@@ -826,37 +861,24 @@ void MainWindow::setBrowserGeometry(const QByteArray &geometry) m_IntegratedBrowser.restoreGeometry(geometry);
}
-
-SaveGameGamebryo *MainWindow::getSaveGame(const QString &name)
-{
- IPluginGame const *game = m_OrganizerCore.managedGame();
- return new SaveGameGamebryo(this, name, game);
-}
-
-
-SaveGameGamebryo *MainWindow::getSaveGame(QListWidgetItem *item)
-{
- try {
- SaveGameGamebryo *saveGame = getSaveGame(item->data(Qt::UserRole).toString());
- saveGame->setParent(item->listWidget());
- return saveGame;
- } catch (const std::exception &e) {
- reportError(tr("failed to read savegame: %1").arg(e.what()));
- return nullptr;
- }
-}
-
-
-void MainWindow::displaySaveGameInfo(const SaveGameGamebryo *save, QPoint pos)
+void MainWindow::displaySaveGameInfo(QListWidgetItem *newItem)
{
+ QString const &save = newItem->data(Qt::UserRole).toString();
if (m_CurrentSaveView == nullptr) {
- m_CurrentSaveView = new SaveGameInfoWidgetGamebryo(save, m_OrganizerCore.pluginList(), this);
- } else {
- m_CurrentSaveView->setSave(save);
+ IPluginGame const *game = m_OrganizerCore.managedGame();
+ SaveGameInfo const *info = game->feature<SaveGameInfo>();
+ if (info != nullptr) {
+ m_CurrentSaveView = info->getSaveGameWidget(this);
+ }
+ if (m_CurrentSaveView == nullptr) {
+ return;
+ }
}
+ m_CurrentSaveView->setSave(save);
QRect screenRect = QApplication::desktop()->availableGeometry(m_CurrentSaveView);
+ QPoint pos = QCursor::pos();
if (pos.x() + m_CurrentSaveView->width() > screenRect.right()) {
pos.rx() -= (m_CurrentSaveView->width() + 2);
} else {
@@ -871,8 +893,9 @@ void MainWindow::displaySaveGameInfo(const SaveGameGamebryo *save, QPoint pos) m_CurrentSaveView->move(pos);
m_CurrentSaveView->show();
+ m_CurrentSaveView->setProperty("displayItem", qVariantFromValue(static_cast<void *>(newItem)));
+
ui->savegameList->activateWindow();
- connect(m_CurrentSaveView, SIGNAL(closeSaveInfo()), this, SLOT(hideSaveGameInfo()));
}
@@ -880,21 +903,15 @@ void MainWindow::saveSelectionChanged(QListWidgetItem *newItem) {
if (newItem == nullptr) {
hideSaveGameInfo();
- } else if ((m_CurrentSaveView == nullptr) || (newItem != m_CurrentSaveView->property("displayItem").value<void*>())) {
- const SaveGameGamebryo *save = getSaveGame(newItem);
- if (save != nullptr) {
- displaySaveGameInfo(save, QCursor::pos());
- m_CurrentSaveView->setProperty("displayItem", qVariantFromValue((void*)newItem));
- }
+ } else if (m_CurrentSaveView == nullptr || newItem != m_CurrentSaveView->property("displayItem").value<void*>()) {
+ displaySaveGameInfo(newItem);
}
}
-
void MainWindow::hideSaveGameInfo()
{
if (m_CurrentSaveView != nullptr) {
- disconnect(m_CurrentSaveView, SIGNAL(closeSaveInfo()), this, SLOT(hideSaveGameInfo()));
m_CurrentSaveView->deleteLater();
m_CurrentSaveView = nullptr;
}
@@ -1258,7 +1275,7 @@ QDir MainWindow::currentSavesDir() const {
QDir savesDir;
if (m_OrganizerCore.currentProfile()->localSavesEnabled()) {
- savesDir.setPath(m_OrganizerCore.currentProfile()->absolutePath() + "/saves");
+ savesDir.setPath(m_OrganizerCore.currentProfile()->savePath());
} else {
wchar_t path[MAX_PATH];
::GetPrivateProfileStringW(
@@ -3002,109 +3019,47 @@ void MainWindow::on_categoriesList_itemSelectionChanged() void MainWindow::deleteSavegame_clicked()
{
- QModelIndexList selectedIndexes = ui->savegameList->selectionModel()->selectedIndexes();
+ SaveGameInfo const *info = m_OrganizerCore.managedGame()->feature<SaveGameInfo>();
QString savesMsgLabel;
QStringList deleteFiles;
int count = 0;
- for (const QModelIndex &idx : selectedIndexes) {
- QString name = idx.data().toString();
- SaveGame *save = new SaveGame(this, idx.data(Qt::UserRole).toString(), m_OrganizerCore.managedGame());
+ for (const QModelIndex &idx : ui->savegameList->selectionModel()->selectedIndexes()) {
+ QString name = idx.data(Qt::UserRole).toString();
if (count < 10) {
savesMsgLabel += "<li>" + QFileInfo(name).completeBaseName() + "</li>";
}
++count;
- deleteFiles << save->saveFiles();
+ if (info == nullptr) {
+ deleteFiles.push_back(name);
+ } else {
+ ISaveGame const *save = info->getSaveGameInfo(name);
+ deleteFiles += save->allFiles();
+ }
}
if (count > 10) {
savesMsgLabel += "<li><i>... " + tr("%1 more").arg(count - 10) + "</i></li>";
}
- if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.", "", selectedIndexes.count())
- .arg(savesMsgLabel),
+ if (QMessageBox::question(this, tr("Confirm"),
+ tr("Are you sure you want to remove the following %n save(s)?<br>"
+ "<ul>%1</ul><br>"
+ "Removed saves will be sent to the Recycle Bin.", "", count)
+ .arg(savesMsgLabel),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
shellDelete(deleteFiles, true); // recycle bin delete.
}
}
-void MainWindow::fixMods_clicked()
+void MainWindow::fixMods_clicked(SaveGameInfo::MissingAssets const &missingAssets)
{
- QListWidgetItem *selectedItem = ui->savegameList->currentItem();
-
- if (selectedItem == nullptr)
- return;
-
- // if required, parse the save game
- if (selectedItem->data(Qt::UserRole).isNull()) {
- QVariant temp;
- SaveGameGamebryo *save = getSaveGame(selectedItem->data(Qt::UserRole).toString());
- save->setParent(selectedItem->listWidget());
- temp.setValue(save);
- selectedItem->setData(Qt::UserRole, temp);
- }
-
- const SaveGameGamebryo *save = getSaveGame(selectedItem);
-
- // collect the list of missing plugins
- std::map<QString, std::vector<QString> > missingPlugins;
-
- for (int i = 0; i < save->numPlugins(); ++i) {
- const QString &pluginName = save->plugin(i);
- if (!m_OrganizerCore.pluginList()->isEnabled(pluginName)) {
- missingPlugins[pluginName] = std::vector<QString>();
- }
- }
-
- // figure out, for each esp/esm, which mod, if any, contains it
- QStringList espFilter("*.esp");
- espFilter.append("*.esm");
-
- // search in data
- {
- QDir dataDir(m_OrganizerCore.managedGame()->dataDirectory());
- QStringList esps = dataDir.entryList(espFilter);
- for (const QString &esp : esps) {
- std::map<QString, std::vector<QString> >::iterator iter = missingPlugins.find(esp);
- if (iter != missingPlugins.end()) {
- iter->second.push_back("<data>");
- }
- }
- }
-
- // search in mods
- for (unsigned int i = 0; i < m_OrganizerCore.currentProfile()->numRegularMods(); ++i) {
- int modIndex = m_OrganizerCore.currentProfile()->modIndexByPriority(i);
- ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
-
- QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter);
- for (const QString &esp : esps) {
- std::map<QString, std::vector<QString> >::iterator iter = missingPlugins.find(esp);
- if (iter != missingPlugins.end()) {
- iter->second.push_back(modInfo->name());
- }
- }
- }
-
- // search in overwrite
- {
- QDir overwriteDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::overwritePath()));
- QStringList esps = overwriteDir.entryList(espFilter);
- for (const QString &esp : esps) {
- std::map<QString, std::vector<QString> >::iterator iter = missingPlugins.find(esp);
- if (iter != missingPlugins.end()) {
- iter->second.push_back("<overwrite>");
- }
- }
- }
-
-
- ActivateModsDialog dialog(missingPlugins, this);
+ ActivateModsDialog dialog(missingAssets, this);
if (dialog.exec() == QDialog::Accepted) {
// activate the required mods, then enable all esps
std::set<QString> modsToActivate = dialog.getModsToActivate();
@@ -3131,13 +3086,25 @@ void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) {
QItemSelectionModel *selection = ui->savegameList->selectionModel();
- if (!selection->hasSelection())
+ if (!selection->hasSelection()) {
return;
+ }
QMenu menu;
+ QAction *action = menu.addAction(tr("Enable Mods..."));
+ action->setEnabled(false);
- if (!(selection->selectedIndexes().count() > 1))
- menu.addAction(tr("Fix Mods..."), this, SLOT(fixMods_clicked()));
+ if (selection->selectedIndexes().count() == 1) {
+ SaveGameInfo const *info = this->m_OrganizerCore.managedGame()->feature<SaveGameInfo>();
+ if (info != nullptr) {
+ QString save = ui->savegameList->currentItem()->data(Qt::UserRole).toString();
+ SaveGameInfo::MissingAssets missing = info->getMissingAssets(save);
+ if (missing.size() != 0) {
+ connect(action, &QAction::triggered, this, [this, missing]{ fixMods_clicked(missing); });
+ action->setEnabled(true);
+ }
+ }
+ }
QString deleteMenuLabel = tr("Delete %n save(s)", "", selection->selectedIndexes().count());
diff --git a/src/mainwindow.h b/src/mainwindow.h index 636fb0a3..4e2e8e21 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -20,50 +20,83 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include <QMainWindow>
-#include <QFileInfo>
-#include <QDir>
-#include <QTreeWidget>
-#include <QListWidgetItem>
-#include <QProcess>
-#include <QProgressBar>
-#include <QTranslator>
-#include <QPluginLoader>
-#include "modlist.h"
-#include "pluginlist.h"
-#include "plugincontainer.h"
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <archive.h>
-#include "directoryrefresher.h"
-#include <imoinfo.h>
-#include "settings.h"
-#include "downloadmanager.h"
-#include "installationmanager.h"
-#include "selfupdater.h"
-#include "savegamegamebyro.h"
-#include "modlistsortproxy.h"
-#include "pluginlistsortproxy.h"
-#include "tutorialcontrol.h"
-#include "savegameinfowidgetgamebryo.h"
-#include "previewgenerator.h"
+#include "bsafolder.h"
#include "browserdialog.h"
+#include "delayedfilewriter.h"
+#include "errorcodes.h"
+#include "imoinfo.h"
#include "iuserinterface.h"
-#include <guessedvalue.h>
-#include <directoryentry.h>
-#include <delayedfilewriter.h>
+#include "modinfo.h"
+#include "modlistsortproxy.h"
+#include "savegameinfo.h"
+#include "tutorialcontrol.h"
+
+//Note the commented headers here can be replaced with forward references,
+//when I get round to cleaning up main.cpp
+struct Executable;
+class CategoryFactory;
+class LockedDialog;
+class OrganizerCore;
+#include "plugincontainer.h" //class PluginContainer;
+class PluginListSortProxy;
+namespace BSA { class Archive; }
+#include "iplugingame.h" //namespace MOBase { class IPluginGame; }
+namespace MOBase { class IPluginModPage; }
+namespace MOBase { class IPluginTool; }
+namespace MOBase { class ISaveGame; }
+
+namespace MOShared { class DirectoryEntry; }
+
+#include <QByteArray>
+#include <QDir>
+#include <QFileInfo>
+#include <QFileSystemWatcher>
+#include <QList>
+#include <QMainWindow>
+#include <QObject>
+#include <QPersistentModelIndex>
+#include <QProcess>
+#include <QString>
+#include <QStringList>
+#include <QTime>
+#include <QTimer>
+#include <QVariant>
+#include <Qt>
+
+class QAction;
+class QAbstractItemModel;
+class QDateTime;
+class QEvent;
+class QFile;
+class QListWidgetItem;
+class QMenu;
+class QModelIndex;
+class QPoint;
+class QProgressBar;
+class QProgressDialog;
+class QTranslator;
+class QTreeWidgetItem;
+class QUrl;
+class QSettings;
+class QWidget;
+
#ifndef Q_MOC_RUN
#include <boost/signals2.hpp>
#endif
+//Sigh - just for HANDLE
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+
+#include <functional>
+#include <set>
+#include <string>
+#include <vector>
+
namespace Ui {
class MainWindow;
}
-class LockedDialog;
-class QToolButton;
-class ModListSortProxy;
-class ModListGroupCategoriesProxy;
class MainWindow : public QMainWindow, public IUserInterface
@@ -217,10 +250,7 @@ private: void setCategoryListVisible(bool visible);
- SaveGameGamebryo *getSaveGame(const QString &name);
- SaveGameGamebryo *getSaveGame(QListWidgetItem *item);
-
- void displaySaveGameInfo(const SaveGameGamebryo *save, QPoint pos);
+ void displaySaveGameInfo(QListWidgetItem *newItem);
HANDLE nextChildProcess();
@@ -293,7 +323,8 @@ private: QTimer m_UpdateProblemsTimer;
QTime m_StartTime;
- SaveGameInfoWidget *m_CurrentSaveView;
+ //SaveGameInfoWidget *m_CurrentSaveView;
+ MOBase::ISaveGameInfoWidget *m_CurrentSaveView;
OrganizerCore &m_OrganizerCore;
PluginContainer &m_PluginContainer;
@@ -352,7 +383,7 @@ private slots: void information_clicked();
// savegame context menu
void deleteSavegame_clicked();
- void fixMods_clicked();
+ void fixMods_clicked(SaveGameInfo::MissingAssets const &missingAssets);
// data-tree context menu
void writeDataToFile();
void openDataFile();
diff --git a/src/modinfo.h b/src/modinfo.h index ae22ccd8..c10232da 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -22,7 +22,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "imodinterface.h"
#include "versioninfo.h"
-//#include <directoryentry.h>
class QDateTime;
class QDir;
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index f9d9b6bd..c689501f 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -193,7 +193,7 @@ void NexusInterface::loginCompleted() void NexusInterface::interpretNexusFileName(const QString &fileName, QString &modName, int &modID, bool query)
{
//Look for something along the lines of modulename-Vn-m + any old rubbish.
- static std::regex exp("^([a-zA-Z0-9_'\"\\-.() ]*?)([-_ ][VvRr]?[0-9_]+)?-([1-9][0-9]+).*\.(zip|rar|7z)");
+ static std::regex exp("^([a-zA-Z0-9_'\"\\-.() ]*?)([-_ ][VvRr]?[0-9_]+)?-([1-9][0-9]+).*\\.(zip|rar|7z)");
static std::regex simpleexp("^([a-zA-Z0-9_]+)");
QByteArray fileNameUTF8 = fileName.toUtf8();
diff --git a/src/organizer.pro b/src/organizer.pro index 1284aa40..0ef2638b 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -27,10 +27,6 @@ SOURCES += \ settings.cpp \
selfupdater.cpp \
selectiondialog.cpp \
- savegameinfowidgetgamebryo.cpp \
- savegameinfowidget.cpp \
- savegamegamebryo.cpp \
- savegame.cpp \
queryoverwritedialog.cpp \
profilesdialog.cpp \
profile.cpp \
@@ -107,10 +103,6 @@ HEADERS += \ settings.h \
selfupdater.h \
selectiondialog.h \
- savegameinfowidgetgamebryo.h \
- savegameinfowidget.h \
- savegamegamebyro.h \
- savegame.h \
queryoverwritedialog.h \
profilesdialog.h \
profile.h \
@@ -183,7 +175,6 @@ FORMS += \ simpleinstalldialog.ui \
settingsdialog.ui \
selectiondialog.ui \
- savegameinfowidget.ui \
queryoverwritedialog.ui \
profilesdialog.ui \
overwriteinfodialog.ui \
diff --git a/src/organizercore.cpp b/src/organizercore.cpp index ecadfb5d..e50f1cd7 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1,15 +1,19 @@ #include "organizercore.h"
+#include "imodinterface.h"
#include "iplugingame.h"
-#include "mainwindow.h"
+#include "iuserinterface.h"
+#include "loadmechanism.h"
#include "messagedialog.h"
+#include "modlistsortproxy.h"
+#include "plugincontainer.h"
+#include "pluginlistsortproxy.h"
#include "logbuffer.h"
#include "credentialsdialog.h"
#include "filedialogmemory.h"
#include "lockeddialog.h"
#include "modinfodialog.h"
#include "spawn.h"
-#include "safewritefile.h"
#include "syncoverwritedialog.h"
#include "nxmaccessmanager.h"
#include <ipluginmodpage.h>
@@ -18,19 +22,29 @@ #include <directoryentry.h>
#include <scopeguard.h>
#include <utility.h>
-#include <appconfig.h>
+#include "appconfig.h"
#include <report.h>
#include <questionboxmemory.h>
-#include <QNetworkInterface>
-#include <QMessageBox>
-#include <QDialogButtonBox>
#include <QApplication>
+#include <QDialogButtonBox>
+#include <QMessageBox>
+#include <QNetworkInterface>
+#include <QProcess>
+#include <QTimer>
+#include <QWidget>
+
+#include <QtDebug>
#include <Psapi.h>
+#include <exception>
#include <functional>
#include <boost/algorithm/string/predicate.hpp>
+#include <memory>
+#include <set>
+#include <utility>
+
using namespace MOShared;
using namespace MOBase;
@@ -953,6 +967,16 @@ ModList *OrganizerCore::modList() return &m_ModList;
}
+QStringList OrganizerCore::modsSortedByProfilePriority() const
+{
+ QStringList res;
+ for (unsigned int i = 0; i < currentProfile()->numRegularMods(); ++i) {
+ int modIndex = currentProfile()->modIndexByPriority(i);
+ res.push_back(ModInfo::getByIndex(modIndex)->name());
+ }
+ return res;
+}
+
void OrganizerCore::spawnBinary(const QFileInfo &binary,
const QString &arguments,
const QDir ¤tDirectory,
diff --git a/src/organizercore.h b/src/organizercore.h index bf6c5a8b..ea37d72c 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -2,31 +2,44 @@ #define ORGANIZERCORE_H
-#include "profile.h"
#include "selfupdater.h"
-#include "iuserinterface.h"
+#include "iuserinterface.h" //should be class IUserInterface;
#include "settings.h"
#include "modlist.h"
+#include "modinfo.h"
#include "pluginlist.h"
#include "directoryrefresher.h"
#include "installationmanager.h"
#include "downloadmanager.h"
-#include "modlistsortproxy.h"
-#include "pluginlistsortproxy.h"
#include "executableslist.h"
#include "usvfsconnector.h"
#include <directoryentry.h>
#include <imoinfo.h>
#include <iplugindiagnose.h>
-#include <iplugingame.h>
#include <versioninfo.h>
-#include <guessedvalue.h>
#include <delayedfilewriter.h>
#include <boost/signals2.hpp>
+
+class ModListSortProxy;
+class PluginListSortProxy;
+class Profile;
+namespace MOBase { template <typename T> class GuessedValue; }
+namespace MOShared { class DirectoryEntry; }
+
+#include <QDir>
+#include <QList>
+#include <QObject>
#include <QSettings>
#include <QString>
+#include <QStringList>
#include <QThread>
+class QNetworkReply;
+class QUrl;
+class QWidget;
+
+#include <functional>
+#include <vector>
class PluginContainer;
@@ -90,7 +103,7 @@ public: m_ExecutablesList = executablesList;
}
- Profile *currentProfile() { return m_CurrentProfile; }
+ Profile *currentProfile() const { return m_CurrentProfile; }
void setCurrentProfile(const QString &profileName);
std::vector<QString> enabledArchives();
@@ -158,6 +171,7 @@ public: bool onAboutToRun(const std::function<bool (const QString &)> &func);
bool onFinishedRun(const std::function<void (const QString &, unsigned int)> &func);
void refreshModList(bool saveChanges = true);
+ QStringList modsSortedByProfilePriority() const;
/**
* @brief return a descriptor of the mappings real file->virtual file
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp index 79ff50e5..fe6809e3 100644 --- a/src/organizerproxy.cpp +++ b/src/organizerproxy.cpp @@ -1,6 +1,7 @@ #include "organizerproxy.h"
-#include <appconfig.h>
+#include "appconfig.h"
+#include "organizercore.h"
#include <QApplication>
@@ -171,7 +172,17 @@ MOBase::IModList *OrganizerProxy::modList() const return m_Proxied->modList();
}
+MOBase::IProfile *OrganizerProxy::profile() const
+{
+ return m_Proxied->currentProfile();
+}
+
MOBase::IPluginGame const *OrganizerProxy::managedGame() const
{
return m_Proxied->managedGame();
}
+
+QStringList OrganizerProxy::modsSortedByProfilePriority() const
+{
+ return m_Proxied->modsSortedByProfilePriority();
+}
diff --git a/src/organizerproxy.h b/src/organizerproxy.h index 02507dd7..77600671 100644 --- a/src/organizerproxy.h +++ b/src/organizerproxy.h @@ -3,7 +3,8 @@ #include <imoinfo.h>
-#include "mainwindow.h"
+
+class OrganizerCore;
class OrganizerProxy : public MOBase::IOrganizer
{
@@ -38,6 +39,7 @@ public: virtual MOBase::IDownloadManager *downloadManager() const;
virtual MOBase::IPluginList *pluginList() const;
virtual MOBase::IModList *modList() const;
+ virtual MOBase::IProfile *profile() const override;
virtual HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = "");
virtual bool waitForApplication(HANDLE handle, LPDWORD exitCode = nullptr) const;
virtual void refreshModList(bool saveChanges);
@@ -48,6 +50,8 @@ public: virtual MOBase::IPluginGame const *managedGame() const;
+ virtual QStringList modsSortedByProfilePriority() const;
+
private:
OrganizerCore *m_Proxied;
diff --git a/src/profile.cpp b/src/profile.cpp index 99a6bd90..f4aab46b 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -19,31 +19,41 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "profile.h" -#include "windows_error.h" #include "modinfo.h" #include "safewritefile.h" #include "settings.h" #include <utility.h> -#include <util.h> #include <error_report.h> -#include <appconfig.h> +#include "appconfig.h" #include <iplugingame.h> #include <report.h> #include <bsainvalidation.h> #include <dataarchives.h> -#include <QMessageBox> #include <QApplication> -#include <QSettings> -#include <QTemporaryFile> +#include <QFile> // for QFile +#include <QFlags> // for operator|, QFlags +#include <QIODevice> // for QIODevice, etc +#include <QMessageBox> +#include <QScopedArrayPointer> +#include <QStringList> // for QStringList +#include <QtDebug> // for qDebug, qWarning, etc +#include <QtGlobal> // for qPrintable + +#include <Windows.h> +#include <assert.h> // for assert +#include <limits.h> // for UINT_MAX, INT_MAX, etc +#include <stddef.h> // for size_t +#include <string.h> // for wcslen + +#include <algorithm> // for max, min +#include <exception> // for exception #include <functional> +#include <set> // for set +#include <utility> // for find #include <stdexcept> -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <shlobj.h> - using namespace MOBase; using namespace MOShared; @@ -690,6 +700,12 @@ QString Profile::absolutePath() const return QDir::cleanPath(m_Directory.absolutePath()); } +QString Profile::savePath() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath("saves")); + +} + void Profile::rename(const QString &newName) { QDir profileDir(Settings::instance().getProfileDirectory()); diff --git a/src/profile.h b/src/profile.h index a7d71251..ece23ef9 100644 --- a/src/profile.h +++ b/src/profile.h @@ -25,12 +25,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <iprofile.h> #include <delayedfilewriter.h> -#include <QString> +#include <QByteArray> #include <QDir> -#include <QSettings> +#include <QObject> +#include <QString> -#include <vector> +#include <boost/shared_ptr.hpp> + +#include <string> #include <tuple> +#include <vector> namespace MOBase { class IPluginGame; } @@ -172,6 +176,15 @@ public: **/ QString absolutePath() const; + /** + * @return path to this profile's save games + **/ + QString savePath() const; + + /** + * @brief rename profile + * @param newName new name of profile + */ void rename(const QString &newName); /** diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp index 49fbda4e..1a47cf74 100644 --- a/src/profilesdialog.cpp +++ b/src/profilesdialog.cpp @@ -19,23 +19,28 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "profilesdialog.h"
#include "ui_profilesdialog.h"
+
+#include "appconfig.h"
+#include "bsainvalidation.h"
+#include "iplugingame.h"
+#include "profile.h"
+#include "profileinputdialog.h"
#include "report.h"
-#include "utility.h"
#include "transfersavesdialog.h"
-#include "profileinputdialog.h"
-#include "mainwindow.h"
-#include "aboutdialog.h"
+#include "utility.h"
#include "settings.h"
-#include <iplugingame.h>
-#include <bsainvalidation.h>
-#include <appconfig.h>
-#include <QListWidgetItem>
+
+#include <QDir>
+#include <QDirIterator>
#include <QInputDialog>
#include <QLineEdit>
-#include <QDirIterator>
+#include <QListWidgetItem>
#include <QMessageBox>
#include <QWhatsThis>
+#include <Windows.h>
+
+#include <exception>
using namespace MOBase;
using namespace MOShared;
diff --git a/src/profilesdialog.h b/src/profilesdialog.h index 073d92b7..0e79b94b 100644 --- a/src/profilesdialog.h +++ b/src/profilesdialog.h @@ -21,17 +21,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #define PROFILESDIALOG_H
#include "tutorabledialog.h"
-#include <QListWidgetItem>
-#include "profile.h"
+class Profile;
+class QListWidget;
+class QListWidgetItem;
+#include <QObject>
+class QString;
-namespace Ui {
- class ProfilesDialog;
-}
+namespace Ui { class ProfilesDialog; }
-namespace MOBase {
- class IPluginGame;
-}
+namespace MOBase { class IPluginGame; }
/**
diff --git a/src/savegame.cpp b/src/savegame.cpp deleted file mode 100644 index 2b125575..00000000 --- a/src/savegame.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "savegame.h"
-
-#include "iplugingame.h"
-#include "scriptextender.h"
-#include "utility.h"
-
-#include <QApplication>
-#include <QDateTime>
-#include <QFile>
-#include <QFileInfo>
-
-#include <limits>
-#include <set>
-
-using namespace MOBase;
-
-SaveGame::SaveGame(QObject *parent, const QString &filename, const MOBase::IPluginGame *game)
- : QObject(parent)
- , m_FileName(filename)
- , m_Game(game)
-{
-}
-
-SaveGame::~SaveGame()
-{
-}
-
-QStringList SaveGame::attachedFiles() const
-{
- QStringList result;
- ScriptExtender const *extender = m_Game->feature<ScriptExtender>();
- if (extender != nullptr) {
- for (QString const &ext : extender->saveGameAttachmentExtensions()) {
- QFileInfo fi(fileName());
- fi.setFile(fi.canonicalPath() + "/" + fi.completeBaseName() + "." + ext);
- if (fi.exists()) {
- result.append(fi.filePath());
- }
- }
- }
-
- return result;
-}
-
-QStringList SaveGame::saveFiles() const
-{
- QStringList result = attachedFiles();
- result.append(fileName());
- return result;
-}
diff --git a/src/savegameinfowidget.cpp b/src/savegameinfowidget.cpp deleted file mode 100644 index 63eefb93..00000000 --- a/src/savegameinfowidget.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "savegameinfowidget.h"
-#include "ui_savegameinfowidget.h"
-#include "utility.h"
-#include "savegame.h"
-#include <QGraphicsDropShadowEffect>
-
-
-SaveGameInfoWidget::SaveGameInfoWidget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::SaveGameInfoWidget)
-{
- ui->setupUi(this);
- this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget);
- setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / qreal(255.0));
- ui->gameFrame->setStyleSheet("background-color: transparent;");
-// installEventFilter(this);
-}
-
-SaveGameInfoWidget::~SaveGameInfoWidget()
-{
- delete ui;
-}
-
-
-void SaveGameInfoWidget::setSave(const SaveGame *saveGame)
-{
- ui->saveNumLabel->setText(QString("%1").arg(saveGame->saveNumber()));
- ui->characterLabel->setText(saveGame->pcName());
- ui->locationLabel->setText(saveGame->pcLocation());
- ui->levelLabel->setText(QString("%1").arg(saveGame->pcLevel()));
- ui->dateLabel->setText(MOBase::ToString(saveGame->creationTime()));
- ui->screenshotLabel->setPixmap(QPixmap::fromImage(saveGame->screenshot()));
- if (ui->gameFrame->layout() != nullptr) {
- QLayoutItem *item = nullptr;
- while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) {
- delete item->widget();
- delete item;
- }
- ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize);
- }
-}
-
-QFrame *SaveGameInfoWidget::getGameFrame()
-{
- return ui->gameFrame;
-}
diff --git a/src/savegameinfowidget.h b/src/savegameinfowidget.h deleted file mode 100644 index dfb0f8b1..00000000 --- a/src/savegameinfowidget.h +++ /dev/null @@ -1,61 +0,0 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef SAVEGAMEINFOWIDGET_H
-#define SAVEGAMEINFOWIDGET_H
-
-#include <QWidget>
-#include <QFrame>
-
-namespace Ui {
-class SaveGameInfoWidget;
-}
-
-class SaveGame;
-
-class SaveGameInfoWidget : public QWidget
-{
- Q_OBJECT
-
-public:
-
- explicit SaveGameInfoWidget(QWidget *parent = 0);
- ~SaveGameInfoWidget();
-
- virtual void setSave(const SaveGame *saveGame);
-
-signals:
-
- void closeSaveInfo();
-
-protected:
-
-// virtual bool eventFilter(QObject *object, QEvent *event);
-
- QFrame *getGameFrame();
-
-private:
-
-private:
-
- Ui::SaveGameInfoWidget *ui;
-
-};
-
-#endif // SAVEGAMEINFOWIDGET_H
diff --git a/src/savegameinfowidget.ui b/src/savegameinfowidget.ui deleted file mode 100644 index e2e9588c..00000000 --- a/src/savegameinfowidget.ui +++ /dev/null @@ -1,209 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>SaveGameInfoWidget</class>
- <widget class="QWidget" name="SaveGameInfoWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>300</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <property name="toolTip">
- <string notr="true"/>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Save #</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Character</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_4">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Level</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_3">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Location</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_5">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Date</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="saveNumLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="characterLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="levelLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="locationLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QLabel" name="dateLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QFrame" name="gameFrame">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="screenshotLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/savegameinfowidgetgamebryo.cpp b/src/savegameinfowidgetgamebryo.cpp deleted file mode 100644 index c97e5810..00000000 --- a/src/savegameinfowidgetgamebryo.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "savegamegamebyro.h"
-#include "savegameinfowidgetgamebryo.h"
-#include <QLabel>
-#include <QVBoxLayout>
-
-
-SaveGameInfoWidgetGamebryo::SaveGameInfoWidgetGamebryo(const SaveGame *saveGame, PluginList *pluginList, QWidget *parent)
- : SaveGameInfoWidget(parent), m_PluginList(pluginList)
-{
- QVBoxLayout *gameLayout = new QVBoxLayout();
- gameLayout->setMargin(0);
- gameLayout->setSpacing(2);
- getGameFrame()->setLayout(gameLayout);
- setSave(saveGame);
-}
-
-
-void SaveGameInfoWidgetGamebryo::setSave(const SaveGame *saveGame)
-{
- SaveGameInfoWidget::setSave(saveGame);
- const SaveGameGamebryo *gamebryoSave = qobject_cast<const SaveGameGamebryo*>(saveGame);
- QLayout *layout = getGameFrame()->layout();
- QLabel *header = new QLabel(tr("Missing ESPs"));
- QFont headerFont = header->font();
- QFont contentFont = headerFont;
- headerFont.setItalic(true);
- contentFont.setBold(true);
- contentFont.setPointSize(7);
- header->setFont(headerFont);
- layout->addWidget(header);
- int count = 0;
- for (int i = 0; i < gamebryoSave->numPlugins(); ++i) {
- const QString &pluginName = gamebryoSave->plugin(i);
- if (m_PluginList->isEnabled(pluginName)) {
- continue;
- } else {
- ++count;
- }
-
- if (count > 10) {
- break;
- }
-
- QLabel *pluginLabel = new QLabel(gamebryoSave->plugin(i));
- pluginLabel->setIndent(10);
- pluginLabel->setFont(contentFont);
- layout->addWidget(pluginLabel);
- }
- if (count > 10) {
- QLabel *dotDotLabel = new QLabel("...");
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
- if (count == 0) {
- QLabel *dotDotLabel = new QLabel(tr("None"));
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
-}
diff --git a/src/savegameinfowidgetgamebryo.h b/src/savegameinfowidgetgamebryo.h deleted file mode 100644 index 149a8885..00000000 --- a/src/savegameinfowidgetgamebryo.h +++ /dev/null @@ -1,44 +0,0 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef SAVEGAMEINFOWIDGETGAMEBRYO_H
-#define SAVEGAMEINFOWIDGETGAMEBRYO_H
-
-
-#include "savegameinfowidget.h"
-#include "pluginlist.h"
-
-
-class SaveGame;
-
-class SaveGameInfoWidgetGamebryo : public SaveGameInfoWidget
-{
-public:
-
- explicit SaveGameInfoWidgetGamebryo(const SaveGame *saveGame, PluginList *pluginList, QWidget *parent = 0);
-
- virtual void setSave(const SaveGame *saveGame);
-
-private:
-
- PluginList *m_PluginList;
-
-};
-
-#endif // SAVEGAMEINFOWIDGETGAMEBRYO_H
diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp index ae75b9cb..7733ae80 100644 --- a/src/selfupdater.cpp +++ b/src/selfupdater.cpp @@ -19,6 +19,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "selfupdater.h"
+#include "archive.h"
+#include "callback.h"
#include "utility.h"
#include "installationmanager.h"
#include "iplugingame.h"
@@ -30,15 +32,36 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <report.h>
#include <util.h>
+#include <QApplication>
+#include <QCoreApplication>
+#include <QDir>
+#include <QFileInfo>
+#include <QLibrary>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
-#include <QDir>
-#include <QLibrary>
+#include <QNetworkReply>
#include <QProcess>
-#include <QApplication>
+#include <QProgressDialog>
+#include <QRegExp>
+#include <QStringList>
+#include <QTimer>
+#include <QUrl>
+#include <QVariantList>
+#include <QVariantMap>
+
+#include <Qt>
+#include <QtDebug>
+#include <QtAlgorithms>
+
#include <boost/bind.hpp>
+#include <Windows.h> //for VS_FIXEDFILEINFO, GetLastError
+
+#include <exception>
+#include <map>
+#include <stddef.h> //for size_t
+#include <stdexcept>
using namespace MOBase;
using namespace MOShared;
diff --git a/src/selfupdater.h b/src/selfupdater.h index 0a31b0f3..37021b42 100644 --- a/src/selfupdater.h +++ b/src/selfupdater.h @@ -21,19 +21,20 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #define SELFUPDATER_H
-#include <archive.h>
#include <versioninfo.h>
-#include <QObject>
-#include <QNetworkReply>
-#include <QFile>
-#include <QProgressDialog>
-
-#include <windows.h>
-
+class Archive;
+class NexusInterface;
namespace MOBase { class IPluginGame; }
-class NexusInterface;
+#include <QFile>
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QtGlobal> //for qint64
+
+class QNetworkReply;
+class QProgressDialog;
/**
diff --git a/src/shared/shared.pro b/src/shared/shared.pro index a64e781d..517e1e86 100644 --- a/src/shared/shared.pro +++ b/src/shared/shared.pro @@ -21,12 +21,7 @@ SOURCES += \ windows_error.cpp \
error_report.cpp \
directoryentry.cpp \
- gameinfo.cpp \
- oblivioninfo.cpp \
- fallout3info.cpp \
- falloutnvinfo.cpp \
util.cpp \
- skyriminfo.cpp \
appconfig.cpp \
leaktrace.cpp \
stackdata.cpp
@@ -36,12 +31,7 @@ HEADERS += \ windows_error.h \
error_report.h \
directoryentry.h \
- gameinfo.h \
- oblivioninfo.h \
- fallout3info.h \
- falloutnvinfo.h \
util.h \
- skyriminfo.h \
appconfig.h \
appconfig.inc \
leaktrace.h \
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;
}
diff --git a/src/transfersavesdialog.h b/src/transfersavesdialog.h index e2c556b4..6961e8c6 100644 --- a/src/transfersavesdialog.h +++ b/src/transfersavesdialog.h @@ -23,10 +23,19 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "tutorabledialog.h"
#include "profile.h"
+class QListWidget;
+#include <QObject>
+class QPushButton;
+#include <QString>
+class QWidget;
+
+#include <memory>
+#include <map>
+#include <vector>
+
namespace Ui { class TransferSavesDialog; }
namespace MOBase { class IPluginGame; }
-
-class SaveGame;
+namespace MOBase { class ISaveGame; }
class TransferSavesDialog : public MOBase::TutorableDialog
{
@@ -76,9 +85,23 @@ private: MOBase::IPluginGame const *m_GamePlugin;
- std::vector<SaveGame*> m_GlobalSaves;
- std::vector<SaveGame*> m_LocalSaves;
+ typedef std::unique_ptr<MOBase::ISaveGame const> SaveListItem;
+ typedef std::vector<SaveListItem> SaveList;
+ typedef std::map<QString, SaveList> SaveCollection;
+ SaveCollection m_GlobalSaves;
+ SaveCollection m_LocalSaves;
+
+ void refreshSaves(SaveCollection &saveCollection, const QString &savedir);
+ void refreshCharacters(SaveCollection const &saveCollection,
+ QListWidget *charList,
+ QPushButton *copy,
+ QPushButton *move);
+ bool transferCharacters(
+ QString const &character, char const *message, SaveList &saves,
+ QString const &dest,
+ const std::function<bool(const QString &, const QString &)> &method,
+ char const *errmsg);
};
#endif // TRANSFERSAVESDIALOG_H
|
