From 62b0c07a93bbf244dbf8ae4bc73f008cfa1fc84d Mon Sep 17 00:00:00 2001 From: TheBloke Date: Mon, 7 Jul 2014 21:39:27 +0100 Subject: Added 'make install' steps in ModOrganizer.pro - Added config to install required libraries to output(d) directory If the user adds a Deploy step, that runs 'jom install', he will have the necessary libraries copied to output(d)\dlls These libraries are - 7z.dll Qt4 Core Declarative Gui Network OpenGL Script Sql Svg Webkit Xml XmlPatterns Different set configured for Qt5, e.g. adding Widgets, Qml, Quick In a debug build, the 'd' DLLs will be used instead. Qt4 libraries are copied from system Qt4 installation directory. This allows the Qt-Creator user to hit "Run" in Qt-C and end up with a complete install, including all DLLs; no manual Exporer copying required. This therefore removes the need for post-build steps 10 & 11 in Readme.txt. Future thought - Update all current POST_LINK (x)copy steps to make install? Fixed DESTDIR in ModOrganizer.pro It was pointing to source/output(d) before, should be ..\output(d) It was not used before so didn't matter, but is now referenced for install. --- src/ModOrganizer.pro | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro index 4624ffec..b345d64b 100644 --- a/src/ModOrganizer.pro +++ b/src/ModOrganizer.pro @@ -21,7 +21,31 @@ hookdll.depends = shared organizer.depends = shared uibase plugins loot_cli CONFIG(debug, debug|release) { - DESTDIR = outputd + DESTDIR = $$PWD/../outputd } else { - DESTDIR = output + DESTDIR = $$PWD/../output } + +STATICDATAPATH = $${DESTDIR}\\..\\tools\\static_data\\dlls +DLLSPATH = $${DESTDIR}\\dlls + +otherlibs.path = $$DLLSPATH +otherlibs.files += $${STATICDATAPATH}\\7z.dll + +qtlibs.path = $$DLLSPATH + +equals(QT_MAJOR_VERSION, 5) { + QTLIBNAMES += Core Gui Network OpenGL Script Sql Svg Qml Quick Webkit Widgets Xml XmlPatterns +} else { + QTLIBNAMES += Core Declarative Gui Network OpenGL Script Sql Svg Webkit Xml XmlPatterns +} + +QTLIBSUFFIX = $${QT_MAJOR_VERSION}.dll +CONFIG(debug, debug|release): QTLIBSUFFIX = "d$${QTLIBSUFFIX}" # Can't use Debug: .. here, it ignores the line - no idea why, as it works in BossDummy.pro + +for(QTNAME, QTLIBNAMES) { + QTFILE = Qt$${QTNAME} + qtlibs.files += $$[QT_INSTALL_BINS]\\$${QTFILE}$${QTLIBSUFFIX} +} + +INSTALLS += qtlibs otherlibs -- cgit v1.3.1 From a49ed5c33c01d4964523eafb790284fcebc0563d Mon Sep 17 00:00:00 2001 From: TheBloke Date: Mon, 7 Jul 2014 21:51:35 +0100 Subject: organizer.pro - tiny tweak to Qt5 version check Directly checking QT_MAJOR_VERSION instead of pattern matching on QT_VERSION --- src/organizer.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/organizer.pro b/src/organizer.pro index de0f70af..bed1ca47 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -5,7 +5,7 @@ #------------------------------------------------- -contains(QT_VERSION, "^5.*") { +equals(QT_MAJOR_VERSION, 5) { QT += core gui widgets network xml sql xmlpatterns qml quick script webkit } else { QT += core gui network xml declarative script sql xmlpatterns webkit -- cgit v1.3.1 From 2b5748003d2ae4de1b897041f92df3e0495b2825 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Mon, 7 Jul 2014 23:32:18 +0100 Subject: .pro files - formatting/consistency fixes Many small formatting changes to the majority of .pro files Consistent style for Qt version checking, using greaterThan(QT_MAJOR_VERSION, 4) This seems safest, as would continue to work for a future Qt 6 etc. Note that this makes redudundant the commit before this one, to organizer.pro Consistent indenting Moved some file configuration sections to be together with related sections Moved some installation-related sections (e.g. OUTDIR/DSTDIR) to be at the bottom, immediately before the related POST_LINK install lines. Similarly, in some cases separated out CONFIG(debug,.. checks into separate LIB/INCLUDE sections (high in file) and installation directory sections (low in file) --- src/organizer.pro | 100 ++++++++++++++++++++++++++------------------------ src/shared/shared.pro | 4 +- 2 files changed, 54 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/organizer.pro b/src/organizer.pro index bed1ca47..5be205b4 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -5,15 +5,15 @@ #------------------------------------------------- -equals(QT_MAJOR_VERSION, 5) { +TARGET = ModOrganizer +TEMPLATE = app + +greaterThan(QT_MAJOR_VERSION, 4) { QT += core gui widgets network xml sql xmlpatterns qml quick script webkit } else { QT += core gui network xml declarative script sql xmlpatterns webkit } -TARGET = ModOrganizer -TEMPLATE = app - SOURCES += \ transfersavesdialog.cpp \ syncoverwritedialog.cpp \ @@ -202,24 +202,60 @@ FORMS += \ browserdialog.ui \ aboutdialog.ui +RESOURCES += \ + resources.qrc \ + stylesheet_resource.qrc + +RC_FILE += \ + app_icon.rc + +OTHER_FILES += \ + version.rc \ + tutorials/firststeps.qml \ + tutorials/tutorials.js \ + tutorials/tutorial_firststeps_main.js \ + tutorials/tutorials_settingsdialog.qml \ + tutorials/tutorials_mainwindow.qml \ + tutorials/Highlight.qml \ + tutorials/TutorialDescription.qml \ + tutorials/TutorialOverlay.qml \ + tutorials/tutorials_nexusdialog.qml \ + tutorials/tutorials_modinfodialog.qml \ + tutorials/tutorial_firststeps_modinfo.js \ + tutorials/tutorial_conflictresolution_main.js \ + tutorials/tutorial_conflictresolution_modinfo.js \ + app_icon.rc \ + dark.qss \ + stylesheets/dark.qss \ + tutorials/tutorial_window_installer.js \ + tutorials/tutorials_installdialog.qml \ + tutorials/tutorial_firststeps_settings.js + + +# leak detection with vld +#INCLUDEPATH += "E:/Visual Leak Detector/include" +#LIBS += -L"E:/Visual Leak Detector/lib/Win32" +#DEFINES += LEAK_CHECK_WITH_VLD + +#SOURCES += modeltest.cpp +#HEADERS += modeltest.h +#DEFINES += TEST_MODELS + + INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk ../boss_modified/boss-api "$(BOOSTPATH)" LIBS += -L"$(BOOSTPATH)/stage/lib" CONFIG(debug, debug|release) { - OUTDIR = $$OUT_PWD/debug - DSTDIR = $$PWD/../../outputd LIBS += -L$$OUT_PWD/../shared/debug LIBS += -L$$OUT_PWD/../bsatk/debug LIBS += -L$$OUT_PWD/../uibase/debug LIBS += -L$$OUT_PWD/../boss_modified/debug LIBS += -lDbgHelp } else { - OUTDIR = $$OUT_PWD/release - DSTDIR = $$PWD/../../output LIBS += -L$$OUT_PWD/../shared/release LIBS += -L$$OUT_PWD/../bsatk/release - LIBS += -L$$OUT_PWD/../uibase/release + LIBS += -L$$OUT_PWD/../uibase/release LIBS += -L$$OUT_PWD/../boss_modified/release QMAKE_CXXFLAGS += /Zi /GL # QMAKE_CXXFLAGS -= -O2 @@ -275,6 +311,13 @@ DEFINES += BOOST_DISABLE_ASSERTS NDEBUG HGID = $$system(hg id -i) DEFINES += HGID=\\\"$${HGID}\\\" +CONFIG(debug, debug|release) { + OUTDIR = $$OUT_PWD/debug + DSTDIR = $$PWD/../../outputd +} else { + OUTDIR = $$OUT_PWD/release + DSTDIR = $$PWD/../../output +} SRCDIR = $$PWD SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g @@ -294,42 +337,3 @@ CONFIG(debug, debug|release) { } else { QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) } - -RESOURCES += \ - resources.qrc \ - stylesheet_resource.qrc - -RC_FILE += \ - app_icon.rc - -OTHER_FILES += \ - version.rc \ - tutorials/firststeps.qml \ - tutorials/tutorials.js \ - tutorials/tutorial_firststeps_main.js \ - tutorials/tutorials_settingsdialog.qml \ - tutorials/tutorials_mainwindow.qml \ - tutorials/Highlight.qml \ - tutorials/TutorialDescription.qml \ - tutorials/TutorialOverlay.qml \ - tutorials/tutorials_nexusdialog.qml \ - tutorials/tutorials_modinfodialog.qml \ - tutorials/tutorial_firststeps_modinfo.js \ - tutorials/tutorial_conflictresolution_main.js \ - tutorials/tutorial_conflictresolution_modinfo.js \ - app_icon.rc \ - dark.qss \ - stylesheets/dark.qss \ - tutorials/tutorial_window_installer.js \ - tutorials/tutorials_installdialog.qml \ - tutorials/tutorial_firststeps_settings.js - - -# leak detection with vld -#INCLUDEPATH += "E:/Visual Leak Detector/include" -#LIBS += -L"E:/Visual Leak Detector/lib/Win32" -#DEFINES += LEAK_CHECK_WITH_VLD - -#SOURCES += modeltest.cpp -#HEADERS += modeltest.h -#DEFINES += TEST_MODELS diff --git a/src/shared/shared.pro b/src/shared/shared.pro index 992fd7f2..5f327fa3 100644 --- a/src/shared/shared.pro +++ b/src/shared/shared.pro @@ -21,11 +21,11 @@ INCLUDEPATH += ../bsatk "$(BOOSTPATH)" CONFIG(debug, debug|release) { LIBS += -L$$OUT_PWD/../bsatk/debug - LIBS += -lDbgHelp + LIBS += -lDbgHelp QMAKE_CXXFLAGS_DEBUG -= -Zi QMAKE_CXXFLAGS += -Z7 } else { - LIBS += -L$$OUT_PWD/../bsatk/release + LIBS += -L$$OUT_PWD/../bsatk/release } LIBS += -lbsatk -- cgit v1.3.1 From 0046d8710e895a158b7e49678eae1514c5b7dc88 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Tue, 8 Jul 2014 04:01:24 +0100 Subject: Compilation dependency tracking enabled for organizer, hook, bsaExtractor, shared Previously, qmake did not detect when code was changed in the static libraries So for example, changing code in shared/*.cpp and then Build, would not cause a re-link and re-deploy of ModOrganizer.exe. This has been fixed by adding PRE_TARGETDEPS references to each project that depend on static libraries provided by other sub-projects. These checks are conditional on debug|release, to point to the correct lib. List of currently configured static library dependency checks - organizer - mo_shared.lib, bsatk.lib hookdll - mo_shared.lib, bsatk.lib shared - bsatk.lib bsaExtractor - bsatk.lib I have tested to confirm that changing a shared file results in re-linking and re-deplomyent of both ModOrganizer.exe and hook.dll. Note that dependencies have not been configured for DLLs, as these are loaded dynamically and so recompilation is not required. But there could be an argument for configuring DLLs as dependencies too - as if you make a change in DLL code, you might want all clients of the DLL to be recompiled to check that they have not been broken by the changes? The downside of that would be extra re-compilation every time. --- src/organizer.pro | 4 ++++ src/shared/shared.pro | 2 ++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/organizer.pro b/src/organizer.pro index 5be205b4..e013aab7 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -252,6 +252,8 @@ CONFIG(debug, debug|release) { LIBS += -L$$OUT_PWD/../uibase/debug LIBS += -L$$OUT_PWD/../boss_modified/debug LIBS += -lDbgHelp + PRE_TARGETDEPS += $$OUT_PWD/../shared/debug/mo_shared.lib \ + $$OUT_PWD/../bsatk/debug/bsatk.lib } else { LIBS += -L$$OUT_PWD/../shared/release LIBS += -L$$OUT_PWD/../bsatk/release @@ -260,6 +262,8 @@ CONFIG(debug, debug|release) { QMAKE_CXXFLAGS += /Zi /GL # QMAKE_CXXFLAGS -= -O2 QMAKE_LFLAGS += /DEBUG /LTCG /OPT:REF /OPT:ICF + PRE_TARGETDEPS += $$OUT_PWD/../shared/release/mo_shared.lib \ + $$OUT_PWD/../bsatk/release/bsatk.lib } #QMAKE_CXXFLAGS_WARN_ON -= -W3 diff --git a/src/shared/shared.pro b/src/shared/shared.pro index 5f327fa3..c5925c24 100644 --- a/src/shared/shared.pro +++ b/src/shared/shared.pro @@ -24,8 +24,10 @@ CONFIG(debug, debug|release) { LIBS += -lDbgHelp QMAKE_CXXFLAGS_DEBUG -= -Zi QMAKE_CXXFLAGS += -Z7 + PRE_TARGETDEPS += $$OUT_PWD/../bsatk/debug/bsatk.lib } else { LIBS += -L$$OUT_PWD/../bsatk/release + PRE_TARGETDEPS += $$OUT_PWD/../bsatk/release/bsatk.lib } LIBS += -lbsatk -- cgit v1.3.1 From 46a32ff3b7bcf6bd4ccc9470c7712a4bbd429a48 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Tue, 8 Jul 2014 04:05:33 +0100 Subject: Additional 'make install' step - install boost_python DLL to output(d)\DLLs Extended the new ModOrganizer.pro 'make install' steps, to now also copy $$(BOOSTPATH)\stage\lib\boost_python-vc*-mt-1*.dll This is the final install step required, so that now ModOrganizer.exe works fully when a Qt-Creator "Run" step is performed. The wildcard should pick up the right version of the library regardless of MSVC compiler version used. Updated Qt5 version check to the standardised greaterThan check. --- src/ModOrganizer.pro | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro index b345d64b..859f4caf 100644 --- a/src/ModOrganizer.pro +++ b/src/ModOrganizer.pro @@ -30,11 +30,12 @@ STATICDATAPATH = $${DESTDIR}\\..\\tools\\static_data\\dlls DLLSPATH = $${DESTDIR}\\dlls otherlibs.path = $$DLLSPATH -otherlibs.files += $${STATICDATAPATH}\\7z.dll +otherlibs.files += $${STATICDATAPATH}\\7z.dll \ + $$(BOOSTPATH)\\stage\\lib\\boost_python-vc*-mt-1*.dll qtlibs.path = $$DLLSPATH -equals(QT_MAJOR_VERSION, 5) { +greaterThan(QT_MAJOR_VERSION, 4) { QTLIBNAMES += Core Gui Network OpenGL Script Sql Svg Qml Quick Webkit Widgets Xml XmlPatterns } else { QTLIBNAMES += Core Declarative Gui Network OpenGL Script Sql Svg Webkit Xml XmlPatterns -- cgit v1.3.1 From d93df95dcfcaf0170f7fb273e9955ef6070fbaa5 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Fri, 11 Jul 2014 01:29:33 +0100 Subject: - Save game management: re-factored getting of filenames including .skse -- New - SaveGame->saveFiles(), returns all filenames for save (eg. ess + skse) -- Moved - SaveGameGameBryo->attachedFiles() to SaveGame->attachedFiles() -- This allows the getting of save file names with just a SaveGame object, not a GameBryo object, which would do a full file read including plugins and image etc. -- Therefore SaveGame is no longer abstract. - Transfer Saves: re-factored to use new SaveGame->saveFiles() method -- Removed - TransferSavesDialog->getFilesToProcess, now redundant as information is now provided by SaveGame class itself. --- src/savegame.cpp | 148 +++++++++++++++++------------- src/savegame.h | 219 ++++++++++++++++++++++---------------------- src/savegamegamebryo.cpp | 11 +-- src/savegamegamebyro.h | 171 +++++++++++++++++----------------- src/transfersavesdialog.cpp | 15 +-- src/transfersavesdialog.h | 1 - 6 files changed, 283 insertions(+), 282 deletions(-) (limited to 'src') diff --git a/src/savegame.cpp b/src/savegame.cpp index 0ddd5fd2..d09f291c 100644 --- a/src/savegame.cpp +++ b/src/savegame.cpp @@ -17,68 +17,86 @@ You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see . */ -#include "savegame.h" -#include -#include -#include -#include "gameinfo.h" -#include -#include -#include - - -SaveGame::SaveGame(QObject *parent) - : QObject(parent), m_FileName(), m_PCName(), m_PCLevel(0), m_PCLocation(), m_SaveNumber(0), m_Screenshot() -{ -} - - -SaveGame::SaveGame(QObject *parent, const QString &filename) - : QObject(parent), m_FileName(filename), m_PCName(), m_PCLevel(0), m_PCLocation(), m_SaveNumber(0), m_Screenshot() -{ -} - - -SaveGame::SaveGame(const SaveGame& reference) - : m_FileName(reference.m_FileName), m_PCName(reference.m_PCName), m_PCLevel(reference.m_PCLevel), - m_PCLocation(reference.m_PCLocation), m_SaveNumber(reference.m_SaveNumber), - m_Screenshot(reference.m_Screenshot) -{ -} - - -SaveGame& SaveGame::operator=(const SaveGame &reference) -{ - if (&reference != this) { - m_FileName = reference.m_FileName; - m_PCName = reference.m_PCName; - m_PCLevel = reference.m_PCLevel; - m_PCLocation = reference.m_PCLocation; - m_SaveNumber = reference.m_SaveNumber; - m_Screenshot = reference.m_Screenshot; - } - return *this; -} - - -SaveGame::~SaveGame() -{ -} - - -void SaveGame::setCreationTime(const QString &fileName) -{ - QFileInfo creationTime(fileName); - QDateTime modified = creationTime.lastModified(); - memset(&m_CreationTime, 0, sizeof(SYSTEMTIME)); - - m_CreationTime.wDay = static_cast(modified.date().day()); - m_CreationTime.wDayOfWeek = static_cast(modified.date().dayOfWeek()); - m_CreationTime.wMonth = static_cast(modified.date().month()); - m_CreationTime.wYear =static_cast( modified.date().year()); - - m_CreationTime.wHour = static_cast(modified.time().hour()); - m_CreationTime.wMinute = static_cast(modified.time().minute()); - m_CreationTime.wSecond = static_cast(modified.time().second()); - m_CreationTime.wMilliseconds = static_cast(modified.time().msec()); -} +#include "savegame.h" +#include +#include +#include +#include "gameinfo.h" +#include +#include +#include + + +SaveGame::SaveGame(QObject *parent) + : QObject(parent), m_FileName(), m_PCName(), m_PCLevel(0), m_PCLocation(), m_SaveNumber(0), m_Screenshot() +{ +} + + +SaveGame::SaveGame(QObject *parent, const QString &filename) + : QObject(parent), m_FileName(filename), m_PCName(), m_PCLevel(0), m_PCLocation(), m_SaveNumber(0), m_Screenshot() +{ +} + + +SaveGame::SaveGame(const SaveGame& reference) + : m_FileName(reference.m_FileName), m_PCName(reference.m_PCName), m_PCLevel(reference.m_PCLevel), + m_PCLocation(reference.m_PCLocation), m_SaveNumber(reference.m_SaveNumber), + m_Screenshot(reference.m_Screenshot) +{ +} + + +SaveGame& SaveGame::operator=(const SaveGame &reference) +{ + if (&reference != this) { + m_FileName = reference.m_FileName; + m_PCName = reference.m_PCName; + m_PCLevel = reference.m_PCLevel; + m_PCLocation = reference.m_PCLocation; + m_SaveNumber = reference.m_SaveNumber; + m_Screenshot = reference.m_Screenshot; + } + return *this; +} + + +SaveGame::~SaveGame() +{ +} + +QStringList SaveGame::attachedFiles() const +{ + QStringList result; + QString seFileFile = fileName().mid(0).replace(".ess", ".skse"); + QFileInfo seFile(seFileFile); + if (seFile.exists()) { + result.append(seFile.absoluteFilePath()); + } + return result; +} + +QStringList SaveGame::saveFiles() const +{ + QStringList result = attachedFiles(); + result.append(fileName()); + return result; +} + + +void SaveGame::setCreationTime(const QString &fileName) +{ + QFileInfo creationTime(fileName); + QDateTime modified = creationTime.lastModified(); + memset(&m_CreationTime, 0, sizeof(SYSTEMTIME)); + + m_CreationTime.wDay = static_cast(modified.date().day()); + m_CreationTime.wDayOfWeek = static_cast(modified.date().dayOfWeek()); + m_CreationTime.wMonth = static_cast(modified.date().month()); + m_CreationTime.wYear =static_cast( modified.date().year()); + + m_CreationTime.wHour = static_cast(modified.time().hour()); + m_CreationTime.wMinute = static_cast(modified.time().minute()); + m_CreationTime.wSecond = static_cast(modified.time().second()); + m_CreationTime.wMilliseconds = static_cast(modified.time().msec()); +} diff --git a/src/savegame.h b/src/savegame.h index e3eb8546..9a5f7036 100644 --- a/src/savegame.h +++ b/src/savegame.h @@ -17,110 +17,115 @@ You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see . */ -#ifndef SAVEGAME_H -#define SAVEGAME_H - - -#include -#include -#include -#include -#include -#include - -#define WIN32_LEAN_AND_MEAN -#include - - -/** - * @brief represents a single save game - **/ -class SaveGame : public QObject { - -Q_OBJECT - -public: - - /** - * @brief construct an empty object - **/ - SaveGame(QObject *parent = 0); - - /** - * @brief construct a save game and immediately read out information from the file - * - * @param filename absolute path of the save game file - **/ - SaveGame(QObject *parent, const QString &filename); - - SaveGame(const SaveGame& reference); - - SaveGame& operator=(const SaveGame &reference); - - ~SaveGame(); - - /** - * @brief read out information from a savegame - * - * @param fileName absolute path of the save game file - **/ - virtual void readFile(const QString &fileName) = 0; - - /** - * @return filename of this savegame - */ - const QString &fileName() const { return m_FileName; } - - /** - * @return a list of additional files that belong to this savegame - */ - virtual QStringList attachedFiles() const { return QStringList(); } - - /** - * @return name of the player character - **/ - const QString &pcName() const { return m_PCName; } - - /** - * @return level of the player character - **/ - unsigned short pcLevel() const { return m_PCLevel; } - - /** - * @return location of the player character - **/ - const QString &pcLocation() const { return m_PCLocation; } - - /** - * @return index of the save game - **/ - unsigned long saveNumber() const { return m_SaveNumber; } - - /** - * @return creation time of the save game - **/ - SYSTEMTIME creationTime() const { return m_CreationTime; } - - /** - * @return screenshot in the savegame - **/ - const QImage &screenshot() const { return m_Screenshot; } - -private: - - void setCreationTime(const QString &fileName); - -protected: - - QString m_FileName; - QString m_PCName; - unsigned short m_PCLevel; - QString m_PCLocation; - unsigned long m_SaveNumber; - SYSTEMTIME m_CreationTime; - QImage m_Screenshot; - -}; - - -#endif // SAVEGAME_H +#ifndef SAVEGAME_H +#define SAVEGAME_H + + +#include +#include +#include +#include +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include + + +/** + * @brief represents a single save game + **/ +class SaveGame : public QObject { + +Q_OBJECT + +public: + + /** + * @brief construct an empty object + **/ + SaveGame(QObject *parent = 0); + + /** + * @brief construct a save game and immediately read out information from the file + * + * @param filename absolute path of the save game file + **/ + SaveGame(QObject *parent, const QString &filename); + + SaveGame(const SaveGame& reference); + + SaveGame& operator=(const SaveGame &reference); + + ~SaveGame(); + + /** + * @brief read out information from a savegame + * + * @param fileName absolute path of the save game file + **/ + virtual void readFile(const QString) { } + + /** + * @return filename of this savegame + */ + const QString &fileName() const { return m_FileName; } + + /** + * @return a list of additional files that belong to this savegame + */ + virtual QStringList attachedFiles() const; + + /** + * @return a list of all files that belong to this savegame + */ + virtual QStringList saveFiles() const; + + /** + * @return name of the player character + **/ + const QString &pcName() const { return m_PCName; } + + /** + * @return level of the player character + **/ + unsigned short pcLevel() const { return m_PCLevel; } + + /** + * @return location of the player character + **/ + const QString &pcLocation() const { return m_PCLocation; } + + /** + * @return index of the save game + **/ + unsigned long saveNumber() const { return m_SaveNumber; } + + /** + * @return creation time of the save game + **/ + SYSTEMTIME creationTime() const { return m_CreationTime; } + + /** + * @return screenshot in the savegame + **/ + const QImage &screenshot() const { return m_Screenshot; } + +private: + + void setCreationTime(const QString &fileName); + +protected: + + QString m_FileName; + QString m_PCName; + unsigned short m_PCLevel; + QString m_PCLocation; + unsigned long m_SaveNumber; + SYSTEMTIME m_CreationTime; + QImage m_Screenshot; + +}; + + +#endif // SAVEGAME_H diff --git a/src/savegamegamebryo.cpp b/src/savegamegamebryo.cpp index f3794347..bf113254 100644 --- a/src/savegamegamebryo.cpp +++ b/src/savegamegamebryo.cpp @@ -117,16 +117,7 @@ SaveGameGamebryo::~SaveGameGamebryo() } -QStringList SaveGameGamebryo::attachedFiles() const -{ - QStringList result; - QString seFileFile = fileName().mid(0).replace(".ess", ".skse"); - QFileInfo seFile(seFileFile); - if (seFile.exists()) { - result.append(seFile.absoluteFilePath()); - } - return result; -} + void SaveGameGamebryo::readSkyrimFile(QFile &saveFile) diff --git a/src/savegamegamebyro.h b/src/savegamegamebyro.h index 25822b0c..70400636 100644 --- a/src/savegamegamebyro.h +++ b/src/savegamegamebyro.h @@ -17,91 +17,86 @@ You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see . */ -#ifndef SAVEGAMEGAMEBRYO_H -#define SAVEGAMEGAMEBRYO_H - - -#include "savegame.h" -#include -#include -#include -#include -#include -#include - -#define WIN32_LEAN_AND_MEAN -#include - - -/** - * @brief represents a single save game - **/ -class SaveGameGamebryo : public SaveGame { - -Q_OBJECT - -public: - - /** - * @brief construct an empty object - **/ - SaveGameGamebryo(QObject *parent = 0); - - /** - * @brief construct a save game and immediately read out information from the file - * - * @param filename absolute path of the save game file - **/ - SaveGameGamebryo(QObject *parent, const QString &filename); - - - SaveGameGamebryo(const SaveGameGamebryo &reference); - - SaveGameGamebryo &operator=(const SaveGameGamebryo &reference); - - ~SaveGameGamebryo(); - - /** - * @return a list of additional files that belong to this savegame - */ - virtual QStringList attachedFiles() const; - - /** - * @brief read out information from a savegame - * - * @param fileName absolute path of the save game file - **/ - virtual void readFile(const QString &fileName); - - /** - * @return number of plugins that were enabled when the save game was created - **/ - int numPlugins() const { return m_Plugins.size(); } - - /** - * retrieve the name of one of the plugins that were enabled when the save game - * was created. valid indices are in the range between [0, numPlugins()[ - * @param index plugin index - * @return name of the plugin - **/ - const QString &plugin(int index) const { return m_Plugins.at(index); } - - -private: - - void readESSFile(QFile &saveFile); - void readFOSFile(QFile &saveFile, bool newVegas); - void readSkyrimFile(QFile &saveFile); - - void setCreationTime(const QString &fileName); - -private: - - std::vector m_Plugins; - -}; - -Q_DECLARE_METATYPE(SaveGameGamebryo) -Q_DECLARE_METATYPE(SaveGameGamebryo*) - -#endif // SAVEGAMEGAMEBRYO_H +#ifndef SAVEGAMEGAMEBRYO_H +#define SAVEGAMEGAMEBRYO_H + + +#include "savegame.h" +#include +#include +#include +#include +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include + + +/** + * @brief represents a single save game + **/ +class SaveGameGamebryo : public SaveGame { + +Q_OBJECT + +public: + + /** + * @brief construct an empty object + **/ + SaveGameGamebryo(QObject *parent = 0); + + /** + * @brief construct a save game and immediately read out information from the file + * + * @param filename absolute path of the save game file + **/ + SaveGameGamebryo(QObject *parent, const QString &filename); + + + SaveGameGamebryo(const SaveGameGamebryo &reference); + + SaveGameGamebryo &operator=(const SaveGameGamebryo &reference); + + ~SaveGameGamebryo(); + + /** + * @brief read out information from a savegame + * + * @param fileName absolute path of the save game file + **/ + virtual void readFile(const QString &fileName); + + /** + * @return number of plugins that were enabled when the save game was created + **/ + int numPlugins() const { return m_Plugins.size(); } + + /** + * retrieve the name of one of the plugins that were enabled when the save game + * was created. valid indices are in the range between [0, numPlugins()[ + * @param index plugin index + * @return name of the plugin + **/ + const QString &plugin(int index) const { return m_Plugins.at(index); } + + +private: + + void readESSFile(QFile &saveFile); + void readFOSFile(QFile &saveFile, bool newVegas); + void readSkyrimFile(QFile &saveFile); + + void setCreationTime(const QString &fileName); + +private: + + std::vector m_Plugins; + +}; + +Q_DECLARE_METATYPE(SaveGameGamebryo) +Q_DECLARE_METATYPE(SaveGameGamebryo*) + +#endif // SAVEGAMEGAMEBRYO_H diff --git a/src/transfersavesdialog.cpp b/src/transfersavesdialog.cpp index e69e4ab2..8e2b9b59 100644 --- a/src/transfersavesdialog.cpp +++ b/src/transfersavesdialog.cpp @@ -151,13 +151,6 @@ bool TransferSavesDialog::testOverwrite(OverwriteMode &overwriteMode, const QStr return res == QMessageBox::Yes; } -QStringList TransferSavesDialog::getFilesToProcess(const SaveGame *save) -{ - QStringList result = save->attachedFiles(); - result.append(save->fileName()); - return result; -} - void TransferSavesDialog::on_moveToLocalBtn_clicked() { QString selectedCharacter = ui->globalCharacterList->currentItem()->text(); @@ -170,7 +163,7 @@ void TransferSavesDialog::on_moveToLocalBtn_clicked() for (std::vector::const_iterator iter = m_GlobalSaves.begin(); iter != m_GlobalSaves.end(); ++iter) { if ((*iter)->pcName() == selectedCharacter) { - QStringList files = getFilesToProcess(*iter); + QStringList files = (*iter)->saveFiles(); foreach (const QString &file, files) { QFileInfo fileInfo(file); QString destinationFile = destination.mid(0).append("/").append(fileInfo.fileName()); @@ -207,7 +200,7 @@ void TransferSavesDialog::on_copyToLocalBtn_clicked() for (std::vector::const_iterator iter = m_GlobalSaves.begin(); iter != m_GlobalSaves.end(); ++iter) { if ((*iter)->pcName() == selectedCharacter) { - QStringList files = getFilesToProcess(*iter); + QStringList files = (*iter)->saveFiles(); foreach (const QString &file, files) { QFileInfo fileInfo(file); QString destinationFile = destination.mid(0).append("/").append(fileInfo.fileName()); @@ -244,7 +237,7 @@ void TransferSavesDialog::on_moveToGlobalBtn_clicked() for (std::vector::const_iterator iter = m_LocalSaves.begin(); iter != m_LocalSaves.end(); ++iter) { if ((*iter)->pcName() == selectedCharacter) { - QStringList files = getFilesToProcess(*iter); + QStringList files = (*iter)->saveFiles(); foreach (const QString &file, files) { QFileInfo fileInfo(file); QString destinationFile = destination.mid(0).append("/").append(fileInfo.fileName()); @@ -283,7 +276,7 @@ void TransferSavesDialog::on_copyToGlobalBtn_clicked() for (std::vector::const_iterator iter = m_LocalSaves.begin(); iter != m_LocalSaves.end(); ++iter) { if ((*iter)->pcName() == selectedCharacter) { - QStringList files = getFilesToProcess(*iter); + QStringList files = (*iter)->saveFiles(); foreach (const QString &file, files) { QFileInfo fileInfo(file); QString destinationFile = destination.mid(0).append("/").append(fileInfo.fileName()); diff --git a/src/transfersavesdialog.h b/src/transfersavesdialog.h index 923259f6..4306b960 100644 --- a/src/transfersavesdialog.h +++ b/src/transfersavesdialog.h @@ -67,7 +67,6 @@ private: void refreshGlobalSaves(); void refreshLocalSaves(); bool testOverwrite(OverwriteMode &overwriteMode, const QString &destinationFile); - QStringList getFilesToProcess(const SaveGame *save); private: -- cgit v1.3.1 From 1b4c07eb20a8951ac72accf8ead302d65c8a2de5 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Fri, 11 Jul 2014 01:46:42 +0100 Subject: - savegameList: Improved save game handling from MainWindow -- Save game deletion now does Recycle Bin delete (wishlist #675) -- Save game deletion now also deletes .skse file (bug #687) -- Can select and delete multiple save games (ExtendedSelection) (wishlist #675) -- Uses new SaveGame->saveFiles() method to get filenames (eg .ess & .skse) -- Context menu - "Fix Mods.." option only appears if 1 save is selected -- Context menu - delete menu option labelled "Delete save" or "Delete saves", according to 1 or >1 saves selected. -- Context menu - delete menu confirmation shows list of all selected saves --- src/mainwindow.cpp | 58 ++++++++++++++++++++++++++++++++++++++---------------- src/mainwindow.h | 2 +- src/mainwindow.ui | 6 ++++++ 3 files changed, 48 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9cbe9c40..344173d4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3884,26 +3884,42 @@ void MainWindow::on_categoriesList_itemSelectionChanged() void MainWindow::deleteSavegame_clicked() { - QListWidgetItem *selectedItem = ui->savegameList->item(m_SelectedSaveGame); - if (selectedItem == NULL) { + QItemSelectionModel *selection = ui->savegameList->selectionModel(); + + if (!selection->hasSelection()) return; - } - QString fileName = selectedItem->data(Qt::UserRole).toString(); + int selectedCount = selection->selectedRows().count(); + QString savesMsgLabel; + QRegExp saveSuffix(".ess$"); + QStringList deleteFiles; + + foreach (QModelIndex idx, selection->selectedRows()) { + QString name = idx.data().toString(); + QString filename = idx.data(Qt::UserRole).toString(); + + SaveGame *save = new SaveGame(this, filename); + savesMsgLabel += "
  • " + name.replace(saveSuffix, "") + "
  • "; + deleteFiles << save->saveFiles(); + } - if (QMessageBox::question(this, tr("Confirm"), tr("Really delete \"%1\"?").arg(selectedItem->text()), + if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to remove the following save%1?
      %2

    Removed saves will be sent to the Recycle Bin.") + .arg((selectedCount > 1) ? "s" : "") + .arg(savesMsgLabel), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - shellDelete(QStringList() << fileName); + shellDelete(deleteFiles, true); // recycle bin delete. } } void MainWindow::fixMods_clicked() { - QListWidgetItem *selectedItem = ui->savegameList->item(m_SelectedSaveGame); - if (selectedItem == NULL) { - return; - } + QItemSelectionModel *selection = ui->savegameList->selectionModel(); + + if (!selection->hasSelection() || selection->selectedRows().count() > 1) + return; // Count should never be > 1 because of condition on context menu; check again just for safety. + + QListWidgetItem *selectedItem = ui->savegameList->item(selection->selectedRows().first().row()); // if required, parse the save game if (selectedItem->data(Qt::UserRole).isNull()) { @@ -3994,16 +4010,24 @@ void MainWindow::fixMods_clicked() void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) { - QListWidgetItem *selectedItem = ui->savegameList->itemAt(pos); - if (selectedItem == NULL) { - return; - } + QItemSelection currentSelection = ui->savegameList->selectionModel()->selection(); + + bool enableFixMods = false; + int selectedCount = currentSelection.count(); - m_SelectedSaveGame = ui->savegameList->row(selectedItem); + if ( selectedCount == 0) { + return; + } else if (currentSelection.count() == 1) + enableFixMods = true; QMenu menu; - menu.addAction(tr("Fix Mods..."), this, SLOT(fixMods_clicked())); - menu.addAction(tr("Delete"), this, SLOT(deleteSavegame_clicked())); + + if (enableFixMods) + menu.addAction(tr("Fix Mods..."), this, SLOT(fixMods_clicked())); + + QString deleteMenuLabel = tr("Delete save%1").arg((selectedCount > 1) ? "s" : ""); + + menu.addAction(deleteMenuLabel, this, SLOT(deleteSavegame_clicked())); menu.exec(ui->savegameList->mapToGlobal(pos)); } diff --git a/src/mainwindow.h b/src/mainwindow.h index cc144287..c1cfdb3c 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -335,7 +335,7 @@ private: QTreeWidgetItem *m_ContextItem; QAction *m_ContextAction; - int m_SelectedSaveGame; + //int m_SelectedSaveGame; Settings m_Settings; diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 1a45e21b..4201babf 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1100,6 +1100,12 @@ p, li { white-space: pre-wrap; } <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html> + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + -- cgit v1.3.1 From 7944bacfd9b7d74d1d45c8bea405a9daf0564002 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Sat, 12 Jul 2014 11:15:34 +0100 Subject: savegameList: A few cleanups and minor code improvements - Slight improvements over previous commits, using more appropriate methods and removing some unnecessary code. No functional changes. --- src/mainwindow.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 344173d4..fc0f8aa1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3889,22 +3889,23 @@ void MainWindow::deleteSavegame_clicked() if (!selection->hasSelection()) return; - int selectedCount = selection->selectedRows().count(); QString savesMsgLabel; QRegExp saveSuffix(".ess$"); QStringList deleteFiles; - foreach (QModelIndex idx, selection->selectedRows()) { + foreach (QModelIndex idx, selection->selectedIndexes()) { QString name = idx.data().toString(); - QString filename = idx.data(Qt::UserRole).toString(); + SaveGame *save = new SaveGame(this, idx.data(Qt::UserRole).toString()); - SaveGame *save = new SaveGame(this, filename); savesMsgLabel += "
  • " + name.replace(saveSuffix, "") + "
  • "; + deleteFiles << save->saveFiles(); } + bool multipleRows = (selection->selectedIndexes().count() > 1); + if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to remove the following save%1?
      %2

    Removed saves will be sent to the Recycle Bin.") - .arg((selectedCount > 1) ? "s" : "") + .arg((multipleRows) ? "s" : "") .arg(savesMsgLabel), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { shellDelete(deleteFiles, true); // recycle bin delete. @@ -3914,12 +3915,10 @@ void MainWindow::deleteSavegame_clicked() void MainWindow::fixMods_clicked() { - QItemSelectionModel *selection = ui->savegameList->selectionModel(); + QListWidgetItem *selectedItem = ui->savegameList->currentItem(); - if (!selection->hasSelection() || selection->selectedRows().count() > 1) - return; // Count should never be > 1 because of condition on context menu; check again just for safety. - - QListWidgetItem *selectedItem = ui->savegameList->item(selection->selectedRows().first().row()); + if (selectedItem == NULL) + return; // if required, parse the save game if (selectedItem->data(Qt::UserRole).isNull()) { @@ -4017,7 +4016,7 @@ void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) if ( selectedCount == 0) { return; - } else if (currentSelection.count() == 1) + } else if (selectedCount == 1) enableFixMods = true; QMenu menu; -- cgit v1.3.1 From 9b67e338e10e438112ad6ed03ec39dd1438758e3 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Sun, 13 Jul 2014 15:24:46 +0100 Subject: savegameList: - Context menu bugfix, previous method of getting rows didn't work when items were selected in certain ways, e.g. Control-A - Context menu now uses selectedIndexes(), which always works with all selections. - Renamed enableFixMods to multipleSelected so same value can be used to decide whether to show single or plural version of "Delete save(s)" --- src/mainwindow.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fc0f8aa1..1baf60d4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3884,16 +3884,13 @@ void MainWindow::on_categoriesList_itemSelectionChanged() void MainWindow::deleteSavegame_clicked() { - QItemSelectionModel *selection = ui->savegameList->selectionModel(); - - if (!selection->hasSelection()) - return; + QModelIndexList selectedIndexes = ui->savegameList->selectionModel()->selectedIndexes(); QString savesMsgLabel; QRegExp saveSuffix(".ess$"); QStringList deleteFiles; - foreach (QModelIndex idx, selection->selectedIndexes()) { + foreach (QModelIndex idx, selectedIndexes) { QString name = idx.data().toString(); SaveGame *save = new SaveGame(this, idx.data(Qt::UserRole).toString()); @@ -3902,7 +3899,7 @@ void MainWindow::deleteSavegame_clicked() deleteFiles << save->saveFiles(); } - bool multipleRows = (selection->selectedIndexes().count() > 1); + bool multipleRows = (selectedIndexes.count() > 1); if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to remove the following save%1?
      %2

    Removed saves will be sent to the Recycle Bin.") .arg((multipleRows) ? "s" : "") @@ -4009,22 +4006,23 @@ void MainWindow::fixMods_clicked() void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) { - QItemSelection currentSelection = ui->savegameList->selectionModel()->selection(); + QItemSelectionModel *selection = ui->savegameList->selectionModel(); + QModelIndexList selectedIndexes = selection->selectedIndexes(); - bool enableFixMods = false; - int selectedCount = currentSelection.count(); + bool multipleSelected = false; + int selectedCount = selectedIndexes.count(); - if ( selectedCount == 0) { + if ( !selection->hasSelection()) { return; - } else if (selectedCount == 1) - enableFixMods = true; + } else if (selectedCount > 1) + multipleSelected = true; QMenu menu; - if (enableFixMods) + if (!multipleSelected) menu.addAction(tr("Fix Mods..."), this, SLOT(fixMods_clicked())); - QString deleteMenuLabel = tr("Delete save%1").arg((selectedCount > 1) ? "s" : ""); + QString deleteMenuLabel = tr("Delete save%1").arg((multipleSelected) ? "s" : ""); menu.addAction(deleteMenuLabel, this, SLOT(deleteSavegame_clicked())); -- cgit v1.3.1 From f59f52501c1f4bf160075dc4439f5af883f730e1 Mon Sep 17 00:00:00 2001 From: TheBloke Date: Sun, 13 Jul 2014 15:45:19 +0100 Subject: savegameList: more minor changes - Context Menu - can do same job with fewer variables and assignments - deleteSaveGame_clicked - const reference, not new value, in foreach loop --- src/mainwindow.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1baf60d4..aed95616 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3890,7 +3890,7 @@ void MainWindow::deleteSavegame_clicked() QRegExp saveSuffix(".ess$"); QStringList deleteFiles; - foreach (QModelIndex idx, selectedIndexes) { + foreach (const QModelIndex &idx, selectedIndexes) { QString name = idx.data().toString(); SaveGame *save = new SaveGame(this, idx.data(Qt::UserRole).toString()); @@ -4007,15 +4007,11 @@ void MainWindow::fixMods_clicked() void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) { QItemSelectionModel *selection = ui->savegameList->selectionModel(); - QModelIndexList selectedIndexes = selection->selectedIndexes(); - bool multipleSelected = false; - int selectedCount = selectedIndexes.count(); - - if ( !selection->hasSelection()) { + if (!selection->hasSelection()) return; - } else if (selectedCount > 1) - multipleSelected = true; + + bool multipleSelected = (selection->selectedIndexes().count() > 1); QMenu menu; -- cgit v1.3.1 From bfb3385e4932530928cff5a94ad56d8f30e5babe Mon Sep 17 00:00:00 2001 From: TheBloke Date: Sun, 13 Jul 2014 16:11:30 +0100 Subject: deleteSavegame: - Confirmation question shows number of saves to be deleted, when more than 1 --- src/mainwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index aed95616..d6cef2dc 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3901,7 +3901,8 @@ void MainWindow::deleteSavegame_clicked() bool multipleRows = (selectedIndexes.count() > 1); - if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to remove the following save%1?
      %2

    Removed saves will be sent to the Recycle Bin.") + if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to remove the following %1save%2?
      %3

    Removed saves will be sent to the Recycle Bin.") + .arg((multipleRows) ? QString::number(selectedIndexes.count()) + " " : "") .arg((multipleRows) ? "s" : "") .arg(savesMsgLabel), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { -- cgit v1.3.1