mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e43f126b03 | ||
|
|
35c9fe3e98 | ||
|
|
82f7b09b40 | ||
|
|
f33d24870f | ||
|
|
14ac234daf | ||
|
|
22b8eb7c5a | ||
|
|
9ee90a35dc |
+158
-15
@@ -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...
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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")) {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user