Compare commits

..
Author SHA1 Message Date
Tannin e43f126b03 - bugfix: crash on overwriting a mod (introduced after the previous release)
- bugfix: ncc installer now brings the installer window to front (again? more reliably? not sure if it really worked before)
2013-12-19 20:30:39 +01:00
Tannin 35c9fe3e98 - bugfix: archive.dll could cause a crash, attempting to close an archive that failed to open
- bugfix: upon changing categories the mappings of deleted categories wasn't cleaned up which could cause an error message
- bugfix: the number of esps/esms that can be loaded is actually 255 not 256 since the save game counts too
- bugfix: "visit on nexus" from the modinfo dialog also lead to the wrong url
2013-12-19 19:40:59 +01:00
Tannin 82f7b09b40 Merge 2013-12-14 17:19:27 +01:00
Tannin f33d24870f - added more information to readme
- 7zip source path is now configurable
2013-12-14 17:19:15 +01:00
Tannin 14ac234daf - plugin list now highlights plugins with attached ini files
- bugfix: opening nexus through the globe icon used the nmm.nexusmods.com url
2013-12-14 13:23:13 +01:00
Tannin 22b8eb7c5a - downgrading a mod (using replace) will now change the version
- bain installer will now accept archives with omod conversion data.
2013-12-11 20:43:30 +01:00
Tannin 9ee90a35dc - MO now applies a minimum to the nmm-compatibility field.
- bugfix: "visit on nexus" directed the browser to the servers meant for nmm
- bugfix: url for "check all for updates" and "enorse/unendorse" were not constructed correctly
2013-12-08 14:16:25 +01:00
26 changed files with 246 additions and 64 deletions
+158 -15
View File
@@ -1,46 +1,115 @@
HOW TO BUILD
============
Intro:
------
Building Mod Organizer can be a rather daunting task especially if you're not very comfortable with C++ development under windows.
Please note that if you only want to work on and build a plugin you can save yourself a lot of trouble
Overview:
---------
As of December 2013 MO consists of the following subprojects:
- organizer: The main userinterface. heavy usage of various libraries
- hookdll: core library of the virtual file system
- uibase: interop between plugins and the main application as well as some reusable functionality
- shared: functionality shared between organizer and hookdll. I'm attempting to get rid of this library over time
- nxmhandler: tool to pass handling of nxm links to MO or other applications
- helper: tool for doing operations requiring elevated priviledges if MO doesn't have them
- proxydll: dll used in the "proxy dll" load mechanism
- esptk: small library containing functionality to work with esps/esms
- bsatk: small library containing functionality to work with bsas. Requires zlib to extract files. Requires boost_thread to provide multi-threaded extraction
- archive: small wrapper library around 7zip for dealing with mod archives. Requires 7zip
- NCC: extension to NMM to provide a binary with command line interface for fomod installation. This is c# code and does not build with the rest of the project. Requires the rest of NMM
- bossdummy: dummy dll that looks like the boss.dll. This is used instead of the real boss dlls in NCC to save some disk space
- pythonrunner: library for embedding python code. Requires boost_python, python 2.7 and pyqt4
And various plugins:
- checkFNIS: Activates each time an application is started from MO and runs fnis if necessary
- diagnoseBasic: Various diagnostic checks on the game
- inieditor: minimalistic file editor for ini files
- installerBain: handles non-scripted bain installers
- installerBCF: no functionality. Supposed to eventually allow installations using bcfs (bain conversion file). python code
- installerBundle: handles installation of archives wrapped in archives
- installerFomod: handles installation of xml fomods
- installerManual: handles installations of archives that aren't supported by any other plugin (or if the user chooses to do the installation manually)
- installerNCC: handles installation of any fomod (requires NCC)
- installerQuick: handles very simple one-click installations
- NMMImport: importer from existing nmm installation
- proxyPython: integrates pythonrunner as a plugin into MO
- pyniEdit: more user-friendly ini editor. python code
Requirements:
-------------
Visual C++ compiler 2010 (VC 10.0) or up
- Included in visual c++ express 2010 or windows sdk 7.0
- Included in visual c++ express 2010 or windows sdk 7.x
- Do install windows sdk too if only for the cdb debugger which is included in that package
Note: If you're having trouble installing the windows sdk, you may be affected by this bug: http://support.microsoft.com/kb/2717426
QtSDK 4.8.x (http://qt-project.org/downloads)
- Qt5 is not yet supported but WIP
Qt Libraries 4.8.x (http://qt-project.org/downloads)
- i.e. "Qt libraries 4.8.5 for Windows (VS 2010, 235 MB)"
- tested: 4.8.5
- Qt5 is not yet supported but WIP. You will see a few conditional qt5 pathes
- Install according to instruction
boost libraries (http://www.boost.org/)
- Compile according to their instructions (using vc++): http://www.boost.org/doc/libs/1_54_0/more/getting_started/windows.html
- A few of the boost libraries need to be built (the rest is header-only). The only compiled lib MO needs (at the time of writing) is
boost_thread. You can disable the others to safe yourself compile time (even on a modern system compiling boost can easily take an hour)
- tested: 1.49
- Build according to their instructions (using vc++): http://www.boost.org/doc/libs/1_54_0/more/getting_started/windows.html
- A few of the boost libraries need to be built (the rest is header-only). The only compiled libs MO needs (at the time of writing) are
boost_thread (for everything that links agains bsatk) and boost_python (for pythonrunner). You can disable the others to save yourself compile time (even on a modern system compiling boost can easily take an hour)
zlib (http://www.zlib.net/)
- Compile static library according to their instructions
- Depending on the version of zlib and how you built you should have a file called zlibstatic.lib or zlibstat.lib in "build" or "x86\ZLibStatRelease".
- Please copy that lib file to "build\zlibstatic.lib" (if it doesn't exist) so MO finds it.
7z.dll (http://www.7-zip.org/download.html)
- Part of the 7-zip program
- Has to be the 32-bit dll! (approx. 893kb)
- If you don't want to install 7-zip (32-bit) you can open the 7z installer (i.e. 7z920.exe) in an archiving tool and unpack only the 7z.dll
7z sourcecode (http://www.7-zip.org/download.html)
- only for "archive" subproject
- no need to compile, will be linked into project
Python 2.7 (32-bit)
- only for pythonrunner
PyQt4 for Python 2.7
- tested: 4.10
- only for pythonrunner
Recommended:
------------
Qt Creator
- http://qt-project.org/downloads#qt-creator
- I.e. "Qt Creator 2.8.1 for Windows (53 MB)"
- With Qt Creator usually the rule is "the newer the better"
- Start Qt Creator and check if things are set up correctly:
1) Go to Tools > Options > Build & Run > Qt Versions
2.1) If the QtSDK 4.8.x you installed earlier is not auto-detected, click "Add" to add it manually
2.2) Navigate to your <your qt4 installation>\bin\qmake.exe
2.3) Restart qt creator
3) Go to Tools > Options > Build & Run > Kits
3.1) If no Kit is auto-detected (or the auto-detected ones have picked up the wrong qt or vc++ installation) click "Add"
3.2) Enter a Name (i.e. "Qt 4.8.5 MSVC2010 32bit")
3.3) In Compiler select the visual studio compiler installed earlier (may show up as "Microsoft Windows SDK for Windows x). Make sure you select the x86 variant
3.4) CDB should be auto-detected
3.5) Select the qt version set up earlier
4) Apply and close the options
Set up (using Qt Creator):
--------------------------
1. Using Qt Creator open source/ModOrganizer.pro from your working copy
2. Open the "Projects" tab, open the "Details" for "Build Environment"
3. Click "Add" to add a variable called "BOOSTPATH" with the path of your boost installation as the value (i.e. C:\code\boost_1_52_0)
4. Click "Add" to add a variable called "ZLIBPATH" with the path of your zlib installation as the value (i.e. C:\code\zlib-1.2.7)
5. Switch the build configuration at the very top of the same page from "debug" to "release" (or vice versa) and repeat steps 3 and 4
6. Compile the configuration(s) you want to use (debug and/or release) (Build All). This should compile correctly.
3a. Click "Add" to add a variable called "BOOSTPATH" with the path of your boost installation as the value (i.e. C:\code\boost_1_49_0)
3b. Click "Add" to add a variable called "ZLIBPATH" with the path of your zlib installation as the value (i.e. C:\code\zlib-1.2.7)
3c. Click "Add" to add a variable called "7ZIPPATH" with the path of your zlib installation as the value (i.e. C:\code\7zip)
3d. Click "Add" to add a variable called "PYTHONPATH" with the path of your zlib installation as the value (i.e. C:\code\python)
4. Switch the build configuration at the very top of the same page from "debug" to "release" (or vice versa) and repeat step 3
5. Compile the configuration(s) you want to use (debug and/or release) (Build All). This should compile correctly.
6. <reserved for future use. Maybe grab a coffee?>
7. return to the "projects" tab and switch to "Run Settings"
8. Determine the folder of the qt binaries in the package you downloaded. This could be "QtSDK\Desktop\Qt\4.8.5\msvc2010\bin" or "Qt4.8.5\bin"
For Release build:
@@ -68,4 +137,78 @@ Set up (without Qt Creator):
I'm not using this workflow so I can't give more detailed instructions.
Please note that the primary project format of MO remains qmake, if you work with visual studio and make changes to the project (like adding
source files) you have to manually transfer those changes to the .pro file.
source files) you have to manually transfer those changes to the .pro file.
-----------------
Troubleshooting (thanks to Ross):
-----------------
1) When I try to build, I am seeing the error "error: LNK1104: cannot open file 'zlibstatic.lib'"
a) Make sure you have the following files
{ZLIBPATH}\build\zconf.h
{ZLIBPATH}\build\zlib.h
{ZLIBPATH}\build\zlibstatic.lib
b) make sure "zlibstat.lib" was renamed to "zlibstatic.lib"
c) currently, there are references to zlibstatic in the following 2 project files:
./bsatk/bsatk.pro
./hookdll/hookdll.pro
2) After building, I try to open {MOPROJECTPATH}\outputd\ModOragnizer.exe and get this error
"The program can't start because QtDeclaratived4.dll is missing from your computer. Try reinstalling the program to fix this problem."
-> When setting up Qt4.8.x, make sure you copied the "d" (debug) versions of the dll files to {MOPROJECTPATH}\outputd\dlls
If you copied the release version or did not copy the dlls at all, you may see this error.
The *.dll files can be found in {QT48xPATH}\bin
Similiar:
http://stackoverflow.com/questions/11196416/cant-start-qt-exe-file-on-windows-7
3) I am getting one or more of the the following compiler warnings...
"{MOPROJECTPATH}\source\bsatk\bsaexception.cpp:32: warning: C4996: 'vsnprintf': This function or variable may be unsafe.
Consider using vsnprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details."
-> Ignore/suppress warning like this and make be ultra-careful using printf-style functions. vsnprintf_s is a visual-c++ only function so using those would make porting (i.e. to mingw) harder
"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\stdio.h:354: see declaration of 'vsnprintf'"
-> see previous
"debug\bsaarchive.obj:-1: warning: LNK4042: object specified more than once; extras ignored"
-> This appears to be an issue when using VC++ 2010 as the compiler. There are some posts on StackOverflow
which suggest fixes when using VC++ as the IDE, but not sure how to apply them to Qt Creator.
http://stackoverflow.com/questions/3729515
http://stackoverflow.com/questions/3695174
-> Also, not sure if this affects VC++ 2012 / VC++ 2013 / GCC via cygwin/mingw.
Not even sure if the project would successfully compile on these.
"{MOPROJECTPATH}\source\organizer\mainwindow.cpp:3995: warning: C4428: universal-character-name encountered in source"
-> very pointless warning.
http://stackoverflow.com/questions/11589571
http://stackoverflow.com/questions/7078013
the best solution I saw was to just disable the warning altogether...
#pragma warning( disable : 4428 )
"warning: LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library"
-> You can always add a #pragma to ignore them :P
http://msdn.microsoft.com/en-us/library/2c8f766e%28v=vs.80%29.aspx
4) I got the following error while building...
"error: LNK1201: error writing to program database
'{MOPROJECTPATH}\{whatever-your-build-directory-name-is}\organizer\debug\ModOrganizer.pdb';
check for insufficient disk space, invalid path, or insufficient privilege"
-> I had this happen after trying to look at something in memory via Process Explorer.
To resolve, I killed and restarted PE. Alternatively, you could probably use the
Unlocker utility. After unlocking, I manually deleted everything in the directory.
Unlocker: http://www.filehippo.com/download_unlocker/ or http://www.emptyloop.com/unlocker/
Warning: With Unlocker v1.9.2, you must select "Advanced" then uncheck everything to
avoid having some Delta toolbar garbage installed...
+1
View File
@@ -103,6 +103,7 @@ CategoryFactory &CategoryFactory::instance()
void CategoryFactory::reset()
{
m_Categories.clear();
m_IDMap.clear();
addCategory(0, "None", MakeVector<int>(2, 28, 87), 0);
}
+7 -3
View File
@@ -426,7 +426,7 @@ QString InstallationManager::generateBackupName(const QString &directoryName) co
}
bool InstallationManager::testOverwrite(GuessedValue<QString> &modName) const
bool InstallationManager::testOverwrite(GuessedValue<QString> &modName, bool *merge) const
{
QString targetDirectory = QDir::fromNativeSeparators(m_ModsDirectory + "\\" + modName);
@@ -440,6 +440,9 @@ bool InstallationManager::testOverwrite(GuessedValue<QString> &modName) const
return false;
}
}
if (merge != nullptr) {
*merge = (overwriteDialog.action() == QueryOverwriteDialog::ACT_MERGE);
}
if (overwriteDialog.action() == QueryOverwriteDialog::ACT_RENAME) {
bool ok = false;
QString name = QInputDialog::getText(m_ParentWidget, tr("Mod Name"), tr("Name"),
@@ -513,8 +516,9 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
return false;
}
bool merge = false;
// determine target directory
if (!testOverwrite(modName)) {
if (!testOverwrite(modName, &merge)) {
return false;
}
@@ -549,7 +553,7 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
}
if (!settingsFile.contains("version") ||
(!version.isEmpty() &&
(VersionInfo(version) >= VersionInfo(settingsFile.value("version").toString())))) {
(!merge || (VersionInfo(version) >= VersionInfo(settingsFile.value("version").toString()))))) {
settingsFile.setValue("version", version);
}
if (!newestVersion.isEmpty() || !settingsFile.contains("newestVersion")) {
+3 -2
View File
@@ -138,9 +138,10 @@ public:
/**
* @brief test if the specified mod name is free. If not, query the user how to proceed
* @param modName current possible names for the mod
* @param merge if this value is not null, the value will be set to whether the use chose to merge or replace
* @return true if we can proceed with the installation, false if the user canceled or in case of an unrecoverable error
*/
virtual bool testOverwrite(MOBase::GuessedValue<QString> &modName) const;
virtual bool testOverwrite(MOBase::GuessedValue<QString> &modName, bool *merge = NULL) const;
private:
@@ -165,7 +166,7 @@ private:
bool isSimpleArchiveTopLayer(const MOBase::DirectoryTree::Node *node, bool bainStyle);
MOBase::DirectoryTree::Node *getSimpleArchiveBase(MOBase::DirectoryTree *dataTree);
bool testOverwrite(const QString &modsDirectory, MOBase::GuessedValue<QString> &modName);
//bool testOverwrite(const QString &modsDirectory, MOBase::GuessedValue<QString> &modName, bool *merge = NULL);
bool doInstall(MOBase::GuessedValue<QString> &modName,
int modID, const QString &version, const QString &newestVersion, int categoryID);
+4 -4
View File
@@ -2203,7 +2203,7 @@ std::vector<unsigned int> MainWindow::activeProblems() const
if (m_UnloadedPlugins.size() != 0) {
problems.push_back(PROBLEM_PLUGINSNOTLOADED);
}
if (m_PluginList.enabledCount() > 256) {
if (m_PluginList.enabledCount() > 255) {
problems.push_back(PROBLEM_TOOMANYPLUGINS);
}
return problems;
@@ -2236,7 +2236,7 @@ QString MainWindow::fullDescription(unsigned int key) const
return result;
} break;
case PROBLEM_TOOMANYPLUGINS: {
return tr("The game doesn't allow more than 256 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or "
return tr("The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or "
"merge some plugins into one. You can find a guide here: <a href=\"http://wiki.step-project.com/Guide:Merging_Plugins\">http://wiki.step-project.com/Guide:Merging_Plugins</a>");
} break;
default: {
@@ -3215,7 +3215,7 @@ void MainWindow::visitOnNexus_clicked()
{
int modID = m_ModList.data(m_ModList.index(m_ContextRow, 0), Qt::UserRole).toInt();
if (modID > 0) {
nexusLinkActivated(QString("%1/mods/%2").arg(ToQString(GameInfo::instance().getNexusPage())).arg(modID));
nexusLinkActivated(QString("%1/mods/%2").arg(ToQString(GameInfo::instance().getNexusPage(false))).arg(modID));
} else {
MessageDialog::showMessage(tr("Nexus ID for this Mod is unknown"), this);
}
@@ -4031,7 +4031,7 @@ void MainWindow::on_actionNexus_triggered()
::ShellExecuteW(NULL, L"open", nxmPath.c_str(),
(std::wstring(L"reg ") + GameInfo::instance().getGameShortName() + L" \"" + executable + L"\"").c_str(), NULL, SW_SHOWNORMAL);
::ShellExecuteW(NULL, L"open", GameInfo::instance().getNexusPage().c_str(), NULL, NULL, SW_SHOWNORMAL);
::ShellExecuteW(NULL, L"open", GameInfo::instance().getNexusPage(false).c_str(), NULL, NULL, SW_SHOWNORMAL);
ui->tabWidget->setCurrentIndex(4);
}
+1 -1
View File
@@ -631,7 +631,7 @@ void ModInfoDialog::on_visitNexusLabel_linkActivated(const QString &link)
void ModInfoDialog::linkClicked(const QUrl &url)
{
if (url.toString().startsWith(ToQString(GameInfo::instance().getNexusPage()))) {
if (url.toString().startsWith(ToQString(GameInfo::instance().getNexusPage(false)))) {
this->close();
emit nexusLinkActivated(url.toString());
} else {
+2 -1
View File
@@ -171,7 +171,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
CategoryFactory &categoryFactory = CategoryFactory::instance();
if (categoryFactory.categoryExists(category)) {
try {
return categoryFactory.getCategoryName(categoryFactory.getCategoryIndex(category));
int categoryIdx = categoryFactory.getCategoryIndex(category);
return categoryFactory.getCategoryName(categoryIdx);
} catch (const std::exception &e) {
qCritical("failed to retrieve category name: %s", e.what());
return QString();
+4 -1
View File
@@ -381,6 +381,7 @@ void NexusInterface::nextRequest()
QString url;
if (!info.m_Reroute) {
bool hasParams = false;
switch (info.m_Type) {
case NXMRequestInfo::TYPE_DESCRIPTION: {
url = QString("%1/Mods/%2/").arg(info.m_URL).arg(info.m_ModID);
@@ -396,14 +397,16 @@ void NexusInterface::nextRequest()
} break;
case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: {
url = QString("%1/Mods/toggleendorsement/%2?lvote=%3").arg(info.m_URL).arg(info.m_ModID).arg(!info.m_Endorse);
hasParams = true;
} break;
case NXMRequestInfo::TYPE_GETUPDATES: {
QString modIDList = VectorJoin<int>(info.m_ModIDList, ",");
modIDList = "[" + modIDList + "]";
url = QString("%1/Mods/GetUpdates?ModList=%2").arg(info.m_URL).arg(modIDList);
hasParams = true;
} break;
}
url.append(QString("?game_id=%1").arg(GameInfo::instance().getNexusGameID()));
url.append(QString("%1game_id=%2").arg(hasParams ? '&' : '?').arg(GameInfo::instance().getNexusGameID()));
} else {
url = info.m_URL;
}
+17 -6
View File
@@ -146,7 +146,11 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD
bool archive = false;
try {
FilesOrigin &origin = baseDirectory.getOriginByID(current->getOrigin(archive));
m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath())));
QString iniPath = QFileInfo(filename).baseName() + ".ini";
bool hasIni = baseDirectory.findFile(ToWString(iniPath)).get() != NULL;
m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath()), hasIni));
} catch (const std::exception &e) {
reportError(tr("failed to update esp info for file %1 (source id: %2), error: %3").arg(filename).arg(current->getOrigin(archive)).arg(e.what()));
}
@@ -724,7 +728,9 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
return QIcon(":/MO/gui/warning");
} else if (m_LockedOrder.find(m_ESPs[index].m_Name.toLower()) != m_LockedOrder.end()) {
return QIcon(":/MO/gui/locked");
} else if (m_ESPs[index].m_IsDummy && m_ESPs[index].m_Enabled) {
} else if (m_ESPs[index].m_HasIni) {
return QIcon(":/MO/gui/attachment");
} else if (m_ESPs[index].m_IsDummy && m_ESPs[index].m_Enabled && !m_ESPs[index].m_HasIni) {
return QIcon(":/MO/gui/edit_clear");
} else {
return QVariant();
@@ -759,7 +765,10 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
m_ESPs[index].m_MasterUnset.begin(), m_ESPs[index].m_MasterUnset.end(),
std::inserter(enabledMasters, enabledMasters.end()));
text += "<br>" + tr("Enabled Masters") + ": " + SetJoin(enabledMasters, ", ");
if (m_ESPs[index].m_IsDummy) {
if (m_ESPs[index].m_HasIni) {
text += "<br>There is an ini file connected to this esp. Its settings will be added to your game settings, overwriting "
"in case of conflicts.";
} else if (m_ESPs[index].m_IsDummy) {
text += "<br>This file is a dummy! It exists only so the bsa with the same name gets loaded. With MO you don't need this: "
"If you enable the archive with the same name in the \"Archive\" tab you can disable this plugin.";
}
@@ -1021,9 +1030,11 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event)
}
PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, FILETIME time, const QString &originName, const QString &fullPath)
: m_Name(name), m_Enabled(enabled), m_ForceEnabled(enabled), m_Removed(false), m_Priority(0),
m_LoadOrder(-1), m_Time(time), m_OriginName(originName)
PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, FILETIME time,
const QString &originName, const QString &fullPath,
bool hasIni)
: m_Name(name), m_Enabled(enabled), m_ForceEnabled(enabled), m_Removed(false),
m_Priority(0), m_LoadOrder(-1), m_Time(time), m_OriginName(originName), m_HasIni(hasIni)
{
try {
ESP::File file(ToWString(fullPath));
+2 -2
View File
@@ -131,7 +131,6 @@ public:
*/
int enabledCount() const;
QString getName(int index) const { return m_ESPs.at(index).m_Name; }
int getPriority(int index) const { return m_ESPs.at(index).m_Priority; }
bool isESPLocked(int index) const;
@@ -193,7 +192,7 @@ private:
struct ESPInfo {
ESPInfo(const QString &name, bool enabled, FILETIME time, const QString &originName, const QString &fullPath);
ESPInfo(const QString &name, bool enabled, FILETIME time, const QString &originName, const QString &fullPath, bool hasIni);
QString m_Name;
QString m_FullPath;
bool m_Enabled;
@@ -205,6 +204,7 @@ private:
QString m_OriginName;
bool m_IsMaster;
bool m_IsDummy;
bool m_HasIni;
std::set<QString> m_Masters;
mutable std::set<QString> m_MasterUnset;
};
+1
View File
@@ -51,5 +51,6 @@
<file alias="emblem_notes">resources/accessories-text-editor.png</file>
<file alias="version_date">resources/x-office-calendar.png</file>
<file alias="warning_16">resources/dialog-warning_16.png</file>
<file alias="attachment">resources/mail-attachment.png</file>
</qresource>
</RCC>
Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

+9 -4
View File
@@ -214,7 +214,12 @@ QString Settings::getModDirectory() const
QString Settings::getNMMVersion() const
{
return m_Settings.value("Settings/nmm_version", "0.34.0").toString();
static const QString MIN_NMM_VERSION = "0.46.0";
QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString();
if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) {
result = MIN_NMM_VERSION;
}
return result;
}
bool Settings::getNexusLogin(QString &username, QString &password) const
@@ -583,9 +588,9 @@ void Settings::query(QWidget *parent)
downloadDirEdit->setText(getDownloadDirectory());
modDirEdit->setText(getModDirectory());
cacheDirEdit->setText(getCacheDirectory());
offlineBox->setChecked(m_Settings.value("Settings/offline_mode", false).toBool());
proxyBox->setChecked(m_Settings.value("Settings/use_proxy", false).toBool());
nmmVersionEdit->setText(m_Settings.value("Settings/nmm_version", "0.33.1").toString());
offlineBox->setChecked(offlineMode());
proxyBox->setChecked(useProxy());
nmmVersionEdit->setText(getNMMVersion());
logLevelBox->setCurrentIndex(logLevel());
// display plugin settings
+2 -2
View File
@@ -759,7 +759,7 @@ DirectoryEntry *DirectoryEntry::findSubDirectoryRecursive(const std::wstring &pa
}
const FileEntry::Ptr DirectoryEntry::findFile(const std::wstring &name)
const FileEntry::Ptr DirectoryEntry::findFile(const std::wstring &name) const
{
auto iter = m_Files.find(name);
if (iter != m_Files.end()) {
@@ -840,7 +840,7 @@ FileEntry::Ptr FileRegister::createFile(const std::wstring &name, DirectoryEntry
}
FileEntry::Ptr FileRegister::getFile(FileEntry::Index index)
FileEntry::Ptr FileRegister::getFile(FileEntry::Index index) const
{
auto iter = m_Files.find(index);
if (iter != m_Files.end()) {
+4 -5
View File
@@ -168,7 +168,7 @@ public:
bool indexValid(FileEntry::Index index) const;
FileEntry::Ptr createFile(const std::wstring &name, DirectoryEntry *parent);
FileEntry::Ptr getFile(FileEntry::Index index);
FileEntry::Ptr getFile(FileEntry::Index index) const;
void removeFile(FileEntry::Index index);
void removeOrigin(FileEntry::Index index, int originID);
@@ -233,11 +233,10 @@ public:
* @param name name of the file
* @return fileentry object for the file or NULL if no file matches
*/
const FileEntry::Ptr findFile(const std::wstring &name);
const FileEntry::Ptr findFile(const std::wstring &name) const;
/** search through this directory and all subdirectories for a file by the specified name.
if directory is not NULL, the referenced variable will be set to true if the path refers to a directory.
the returned pointer is NULL in that case */
/** search through this directory and all subdirectories for a file by the specified name (relative path).
if directory is not NULL, the referenced variable will be set to the path containing the file */
const FileEntry::Ptr searchFile(const std::wstring &path, const DirectoryEntry **directory) const;
void insertFile(const std::wstring &filePath, FilesOrigin &origin, FILETIME fileTime);
+6 -2
View File
@@ -153,9 +153,13 @@ std::wstring Fallout3Info::getSEName()
}
std::wstring Fallout3Info::getNexusPage()
std::wstring Fallout3Info::getNexusPage(bool nmmScheme)
{
return L"http://nmm.nexusmods.com/fallout3";
if (nmmScheme) {
return L"http://nmm.nexusmods.com/fallout3";
} else {
return L"http://www.nexusmods.com/fallout3";
}
}
+1 -1
View File
@@ -71,7 +71,7 @@ public:
virtual std::wstring getSEName();
virtual std::wstring getNexusPage();
virtual std::wstring getNexusPage(bool nmmScheme = true);
static std::wstring getNexusInfoUrlStatic();
virtual std::wstring getNexusInfoUrl() { return Fallout3Info::getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
+6 -2
View File
@@ -207,9 +207,13 @@ std::wstring FalloutNVInfo::getSEName()
}
std::wstring FalloutNVInfo::getNexusPage()
std::wstring FalloutNVInfo::getNexusPage(bool nmmScheme)
{
return L"http://nmm.nexusmods.com/newvegas";
if (nmmScheme) {
return L"http://nmm.nexusmods.com/newvegas";
} else {
return L"http://www.nexusmods.com/newvegas";
}
}
+1 -1
View File
@@ -72,7 +72,7 @@ public:
virtual std::wstring getSEName();
virtual std::wstring getNexusPage();
virtual std::wstring getNexusPage(bool nmmScheme = true);
static std::wstring getNexusInfoUrlStatic();
virtual std::wstring getNexusInfoUrl() { return FalloutNVInfo::getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
+1 -1
View File
@@ -142,7 +142,7 @@ public:
virtual std::wstring getSEName() = 0;
virtual std::wstring getNexusPage() = 0;
virtual std::wstring getNexusPage(bool nmmScheme = true) = 0;
virtual std::wstring getNexusInfoUrl() = 0;
virtual int getNexusModID() = 0;
virtual int getNexusGameID() = 0;

Some files were not shown because too many files have changed in this diff Show More