From 0050cb07409d775efe14e728c1cef4a2c33aa1db Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 21 Jul 2014 19:14:24 +0200 Subject: - download-list will no longer show a file as having incomplete data if there is no file version - added a new mod column with icons displaying the content of the mod - MO now differentiates between mods using an internal name that disambiguates between foreign and regular mods --- src/aboutdialog.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/aboutdialog.cpp') diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index a8f9b4db..b5bfeb04 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -39,13 +39,12 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent) addLicense("Qt 4.8.5", LICENSE_LGPL3); addLicense("Qt Json", LICENSE_GPL3); addLicense("Boost Library", LICENSE_BOOST); - addLicense("Tango Icon Theme", LICENSE_NONE); - addLicense("RRZE Icon Set", LICENSE_CCBY3); addLicense("7-zip", LICENSE_LGPL3); addLicense("ZLib", LICENSE_ZLIB); addLicense("NIF File Format Library", LICENSE_BSD3); - addLicense("BOSS (modified)", LICENSE_GPL3); - addLicense("Alphanum Algorithm", LICENSE_ZLIB); + addLicense("Tango Icon Theme", LICENSE_NONE); + addLicense("RRZE Icon Set", LICENSE_CCBY3); + addLicense("Icons by Lorc, Delapouite and sbed available on http://game-icons.net", LICENSE_CCBY3); ui->nameLabel->setText(QString("%1 %2").arg(ui->nameLabel->text()).arg(version)); #ifdef HGID -- cgit v1.3.1 From df0bd3331a4b2174f99117c5a6f21ff6bddca1ba Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 5 Nov 2014 23:48:06 +0100 Subject: - archive library can now query for password during extraction (seems to be necessary for rars) - process blacklist is now taken from a file if there is one, not hardcoded - removed workaround for the papyrus compiler - updated loot client to work with the actual api - loot client now links with loot32.dll at runtime - loot client now produces its output in a (json-)file which includes all plugin messages and dirty flags - fomod installer now tries to parse the xml with several encodings - fomod installer will now display a diagnostics warning if the jpg imageformat isn't supported - base preview plugin now tries to be a bit smarter about resizing images to fit the screen - bugfix: fomod installer no longer tries to open an image even after detecting its invalid - bugfix: potential null-pointer dereferentiation in getprivateprofile... hooks - bugfix: potential null-pointer dereferentiation in download manager - bugfix: internal origin name showed up in one more place - bugfix: ToString function produced strings that were one (zero-termination-)character too long --- src/aboutdialog.cpp | 1 - src/dlls.manifest.debug.qt5 | 3 +++ src/downloadmanager.cpp | 2 +- src/main.cpp | 2 +- src/mainwindow.cpp | 48 ++++++++++++++++++++++++++++++++------------- src/mainwindow.h | 2 +- src/organizer.pro | 2 +- src/pluginlist.cpp | 12 +++++++++++- src/settings.cpp | 2 +- src/shared/util.cpp | 9 ++++++--- 10 files changed, 59 insertions(+), 24 deletions(-) (limited to 'src/aboutdialog.cpp') diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index b5bfeb04..90dcd073 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -41,7 +41,6 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent) addLicense("Boost Library", LICENSE_BOOST); addLicense("7-zip", LICENSE_LGPL3); addLicense("ZLib", LICENSE_ZLIB); - addLicense("NIF File Format Library", LICENSE_BSD3); addLicense("Tango Icon Theme", LICENSE_NONE); addLicense("RRZE Icon Set", LICENSE_CCBY3); addLicense("Icons by Lorc, Delapouite and sbed available on http://game-icons.net", LICENSE_CCBY3); diff --git a/src/dlls.manifest.debug.qt5 b/src/dlls.manifest.debug.qt5 index 6cc0a83d..1bbdf691 100644 --- a/src/dlls.manifest.debug.qt5 +++ b/src/dlls.manifest.debug.qt5 @@ -8,7 +8,10 @@ + + + diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index bc31adf4..82701a05 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -606,7 +606,7 @@ void DownloadManager::pauseDownload(int index) DownloadInfo *info = m_ActiveDownloads.at(index); if (info->m_State == STATE_DOWNLOADING) { - if (info->m_Reply->isRunning()) { + if ((info->m_Reply != NULL) && (info->m_Reply->isRunning())) { setState(info, STATE_PAUSING); } else { setState(info, STATE_PAUSED); diff --git a/src/main.cpp b/src/main.cpp index 642bfa1a..b4139f09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -332,7 +332,7 @@ int main(int argc, char *argv[]) } } - application.addLibraryPath(application.applicationDirPath() + "/dlls"); + application.setLibraryPaths(QStringList() << (application.applicationDirPath() + "/dlls")); SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 19be758e..d9db84ae 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -103,6 +103,10 @@ along with Mod Organizer. If not, see . #include #include #include +#include +#include +#include +#include #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) #include #else @@ -1268,14 +1272,14 @@ void MainWindow::unloadPlugins() ui->actionTool->menu()->clear(); } - foreach (QPluginLoader *loader, m_PluginLoaders) { - qDebug("unloading %s", qPrintable(loader->fileName())); + while (!m_PluginLoaders.empty()) { + QPluginLoader *loader = m_PluginLoaders.back(); + m_PluginLoaders.pop_back(); if (!loader->unload()) { qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString())); } delete loader; } - m_PluginLoaders.clear(); } void MainWindow::loadPlugins() @@ -1322,7 +1326,7 @@ void MainWindow::loadPlugins() if (QLibrary::isLibrary(pluginName)) { QPluginLoader *pluginLoader = new QPluginLoader(pluginName, this); if (pluginLoader->instance() == NULL) { - m_UnloadedPlugins.push_back(pluginName); + m_FailedPlugins.push_back(pluginName); qCritical("failed to load plugin %s: %s", qPrintable(pluginName), qPrintable(pluginLoader->errorString())); } else { @@ -1330,7 +1334,7 @@ void MainWindow::loadPlugins() qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); m_PluginLoaders.push_back(pluginLoader); } else { - m_UnloadedPlugins.push_back(pluginName); + m_FailedPlugins.push_back(pluginName); qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); } } @@ -2285,7 +2289,7 @@ void MainWindow::on_tabWidget_currentChanged(int index) std::vector MainWindow::activeProblems() const { std::vector problems; - if (m_UnloadedPlugins.size() != 0) { + if (m_FailedPlugins.size() != 0) { problems.push_back(PROBLEM_PLUGINSNOTLOADED); } if (m_PluginList.enabledCount() > 255) { @@ -2314,7 +2318,7 @@ QString MainWindow::fullDescription(unsigned int key) const switch (key) { case PROBLEM_PLUGINSNOTLOADED: { QString result = tr("The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:") + "
    "; - foreach (const QString &plugin, m_UnloadedPlugins) { + foreach (const QString &plugin, m_FailedPlugins) { result += "
  • " + plugin + "
  • "; } result += "
      "; @@ -5375,13 +5379,10 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU foreach (const std::string &line, lines) { if (line.length() > 0) { - size_t progidx = line.find("[progress]"); - size_t reportidx = line.find("[Report]"); - size_t erroridx = line.find("[error]"); + size_t progidx = line.find("[progress]"); + size_t erroridx = line.find("[error]"); if (progidx != std::string::npos) { dialog.setLabelText(line.substr(progidx + 11).c_str()); - } else if (reportidx != std::string::npos) { - reportURL = line.substr(reportidx + 9); } else if (erroridx != std::string::npos) { qWarning("%s", line.c_str()); errorMessages.append(boost::algorithm::trim_copy(line.substr(erroridx + 8)) + "\n"); @@ -5525,12 +5526,15 @@ void MainWindow::on_bossButton_clicked() dialog.setMaximum(0); dialog.show(); + QString outPath = QDir::temp().absoluteFilePath("lootreport.json"); + QStringList parameters; parameters << "--unattended" << "--stdout" << "--noreport" << "--game" << ToQString(GameInfo::instance().getGameShortName()) - << "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory())); + << "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory())) + << "--out" << outPath; if (m_DidUpdateMasterList) { parameters << "--skipUpdateMasterlist"; @@ -5540,7 +5544,7 @@ void MainWindow::on_bossButton_clicked() HANDLE stdOutWrite = INVALID_HANDLE_VALUE; HANDLE stdOutRead = INVALID_HANDLE_VALUE; createStdoutPipe(&stdOutRead, &stdOutWrite); - HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/LOOT.exe"), + HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"), parameters.join(" "), m_CurrentProfile->getName(), m_Settings.logLevel(), @@ -5615,6 +5619,22 @@ void MainWindow::on_bossButton_clicked() return; } else { success = true; + QFile outFile(outPath); + outFile.open(QIODevice::ReadOnly); + QJsonDocument doc = QJsonDocument::fromJson(outFile.readAll()); + QJsonArray array = doc.array(); + for (auto iter = array.begin(); iter != array.end(); ++iter) { + QJsonObject pluginObj = (*iter).toObject(); + QJsonArray pluginMessages = pluginObj["messages"].toArray(); + for (auto msgIter = pluginMessages.begin(); msgIter != pluginMessages.end(); ++msgIter) { + QJsonObject msg = (*msgIter).toObject(); + m_PluginList.addInformation(pluginObj["name"].toString(), + QString("%1: %2").arg(msg["type"].toString(), msg["message"].toString())); + } + if (pluginObj["dirty"].toString() == "yes") + m_PluginList.addInformation(pluginObj["name"].toString(), "dirty"); + } + } } else { reportError(tr("failed to start loot")); diff --git a/src/mainwindow.h b/src/mainwindow.h index 8bd663ac..ea79fc37 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -381,7 +381,7 @@ private: std::vector m_DiagnosisPlugins; std::vector m_DiagnosisConnections; std::vector m_ModPages; - std::vector m_UnloadedPlugins; + std::vector m_FailedPlugins; std::vector m_PluginLoaders; QFile m_PluginsCheck; diff --git a/src/organizer.pro b/src/organizer.pro index b24586e6..fd1e6aad 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -341,7 +341,7 @@ SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g DSTDIR ~= s,/,$$QMAKE_DIR_SEP,g QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n) -QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.pdb) $$quote($$DSTDIR) $$escape_expand(\\n) +QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n) QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\stylesheets) $$quote($$DSTDIR)\\stylesheets $$escape_expand(\\n) QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\tutorials) $$quote($$DSTDIR)\\tutorials $$escape_expand(\\n) QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\*.qm) $$quote($$DSTDIR)\\translations $$escape_expand(\\n) diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 973e3cfc..b2d02cd2 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see . #include "settings.h" #include "safewritefile.h" #include "scopeguard.h" +#include "modinfo.h" #include #include #include @@ -158,7 +159,14 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD 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)); + QString originName = ToQString(origin.getName()); + unsigned int modIndex = ModInfo::getIndex(originName); + if (modIndex != UINT_MAX) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex); + originName = modInfo->name(); + } + + m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), originName, 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())); } @@ -290,6 +298,8 @@ void PluginList::addInformation(const QString &name, const QString &message) if (iter != m_ESPsByName.end()) { m_AdditionalInfo[name.toLower()].m_Messages.append(message); + } else { + qWarning("failed to associate message for \"%s\"", qPrintable(name)); } } diff --git a/src/settings.cpp b/src/settings.cpp index 0ca811a3..274e5979 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -231,7 +231,7 @@ QString Settings::getModDirectory() const QString Settings::getNMMVersion() const { - static const QString MIN_NMM_VERSION = "0.47.0"; + static const QString MIN_NMM_VERSION = "0.52.3"; QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString(); if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) { result = MIN_NMM_VERSION; diff --git a/src/shared/util.cpp b/src/shared/util.cpp index 4bc5a8a4..d4a77929 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -71,7 +71,9 @@ std::string ToString(const std::wstring &source, bool utf8) if (sizeRequired == 0) { throw windows_error("failed to convert string to multibyte"); } - result.resize(sizeRequired, '\0'); + // the size returned by WideCharToMultiByte contains zero termination IF -1 is specified for the length. + // we don't want that \0 in the string because then the length field would be wrong. Because madness + result.resize(sizeRequired - 1, '\0'); ::WideCharToMultiByte(codepage, 0, &source[0], (int)source.size(), &result[0], sizeRequired, NULL, NULL); return result; } @@ -117,14 +119,15 @@ std::wstring ToLower(const std::wstring &text) VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) { - DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), NULL); + DWORD handle; + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); if (size == 0) { throw windows_error("failed to determine file version info size"); } void *buffer = new char[size]; try { - if (!::GetFileVersionInfoW(fileName.c_str(), 0UL, size, buffer)) { + if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer)) { throw windows_error("failed to determine file version info"); } -- cgit v1.3.1 From 9ab7bada1c81eb82d97df23da64a56a0eba0bf42 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 9 Nov 2014 14:01:48 +0100 Subject: - bsa parser will now cancel in case of a read error. Before, when attempting to parse a broken bsa it could take forever and continuously allocate memory - better error message when bsa parsing fails - slightly better support for font colors in bbcode converter - configurator now also uses pyqt5 - bugfix: bsa hashing function converted backslashes to slashes instead of the other way around. hash calculation is still often wrong on folder names... --- src/aboutdialog.cpp | 2 +- src/bbcode.cpp | 15 +++++++++------ src/directoryrefresher.cpp | 10 +++++++--- 3 files changed, 17 insertions(+), 10 deletions(-) (limited to 'src/aboutdialog.cpp') diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index 90dcd073..d7749187 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -36,7 +36,7 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent) m_LicenseFiles[LICENSE_CCBY3] = "by-sa3.txt"; m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt"; - addLicense("Qt 4.8.5", LICENSE_LGPL3); + addLicense("Qt 5.3", LICENSE_LGPL3); addLicense("Qt Json", LICENSE_GPL3); addLicense("Boost Library", LICENSE_BOOST); addLicense("7-zip", LICENSE_LGPL3); diff --git a/src/bbcode.cpp b/src/bbcode.cpp index 92eb427f..2e22859d 100644 --- a/src/bbcode.cpp +++ b/src/bbcode.cpp @@ -80,11 +80,15 @@ public: if (tagName == "color") { QString color = tagIter->second.first.cap(1); QString content = tagIter->second.first.cap(2); - auto colIter = m_ColorMap.find(color.toLower()); - if (colIter != m_ColorMap.end()) { - color = colIter->second; + if (color.at(0) == "#") { + return temp.replace(tagIter->second.first, QString("%2").arg(color, content)); + } else { + auto colIter = m_ColorMap.find(color.toLower()); + if (colIter != m_ColorMap.end()) { + color = colIter->second; + } + return temp.replace(tagIter->second.first, QString("%2").arg(color, content)); } - return temp.replace(tagIter->second.first, QString("%2").arg(color, content)); } else { qWarning("don't know how to deal with tag %s", qPrintable(tagName)); } @@ -131,7 +135,7 @@ private: m_TagMap["color="] = std::make_pair(QRegExp("\\[color=([^\\]]*)\\](.*)\\[/color\\]"), ""); m_TagMap["font="] = std::make_pair(QRegExp("\\[font=([^\\]]*)\\](.*)\\[/font\\]"), - "\\2"); + "\\2"); m_TagMap["center"] = std::make_pair(QRegExp("\\[center\\](.*)\\[/center\\]"), "
      \\1
      "); m_TagMap["quote"] = std::make_pair(QRegExp("\\[quote\\](.*)\\[/quote\\]"), @@ -231,7 +235,6 @@ QString convertToHTML(const QString &inputParam) QString input = inputParam.mid(0).replace("\r\n", "
      "); input.replace("\\\"", "\"").replace("\\'", "'"); - QString result; int lastBlock = 0; int pos = 0; diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 2186f9a5..24fda501 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -83,8 +83,12 @@ void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure foreach (const QString &archive, archives) { QFileInfo fileInfo(archive); if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) { - directoryStructure->addFromBSA(ToWString(modName), directoryW, - ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority); + try { + directoryStructure->addFromBSA(ToWString(modName), directoryW, + ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority); + } catch (const std::exception &e) { + throw MyException(tr("failed to parse bsa %1: %2").arg(archive, e.what())); + } } } } @@ -143,7 +147,7 @@ void DirectoryRefresher::refresh() try { addModToStructure(m_DirectoryStructure, iter->modName, i, iter->absolutePath, iter->stealFiles, iter->archives); } catch (const std::exception &e) { - emit error(tr("failed to read bsa: %1").arg(e.what())); + emit error(tr("failed to read mod (%1): %2").arg(iter->modName, e.what())); } emit progress((i * 100) / m_Mods.size() + 1); } -- cgit v1.3.1 From 6479f972dccaabb3afadb570583a4269e8a785e4 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 25 Feb 2015 18:38:01 +0100 Subject: tons of code cleanup and minor fixes to harden the code (mostly suggestions from static code analysis) --- src/ModOrganizer.pro | 1 - src/aboutdialog.cpp | 2 +- src/helper.cpp | 2 +- src/installationmanager.cpp | 10 +++++----- src/main.cpp | 4 ++-- src/mainwindow.cpp | 7 +++---- src/plugincontainer.cpp | 11 +++++++---- src/qt.conf | 3 +++ src/shared/directoryentry.cpp | 8 +++++--- src/shared/error_report.cpp | 3 +-- src/shared/fallout3info.h | 33 +-------------------------------- src/shared/leaktrace.cpp | 2 +- src/shared/stackdata.cpp | 1 - src/shared/util.cpp | 13 ++++++++++--- src/spawn.cpp | 6 +++--- 15 files changed, 43 insertions(+), 63 deletions(-) create mode 100644 src/qt.conf (limited to 'src/aboutdialog.cpp') diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro index a8f7f53e..c0e5d9f5 100644 --- a/src/ModOrganizer.pro +++ b/src/ModOrganizer.pro @@ -8,7 +8,6 @@ SUBDIRS = bsatk \ archive \ helper \ plugins \ - proxydll \ nxmhandler \ BossDummy \ pythonRunner \ diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index cd29600b..7b311263 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -37,7 +37,7 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent) m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt"; m_LicenseFiles[LICENSE_APACHE2] = "apache-license-2.0.txt"; - addLicense("Qt 5.3", LICENSE_LGPL3); + addLicense("Qt 5.4", LICENSE_LGPL3); addLicense("Qt Json", LICENSE_GPL3); addLicense("Boost Library", LICENSE_BOOST); addLicense("7-zip", LICENSE_LGPL3); diff --git a/src/helper.cpp b/src/helper.cpp index 4c22dbda..1f072bd9 100644 --- a/src/helper.cpp +++ b/src/helper.cpp @@ -49,7 +49,7 @@ static bool helperExec(LPCWSTR moDirectory, LPCWSTR commandLine) ::ShellExecuteExW(&execInfo); - if (::WaitForSingleObject(execInfo.hProcess, INFINITE) != WAIT_OBJECT_0) { + if ((execInfo.hProcess == 0) || (::WaitForSingleObject(execInfo.hProcess, INFINITE) != WAIT_OBJECT_0)) { reportError(QObject::tr("helper failed")); return false; } diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index 6101cf39..7d431f02 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -70,7 +70,8 @@ static T resolveFunction(QLibrary &lib, const char *name) InstallationManager::InstallationManager() - : m_InstallationProgress(nullptr) + : m_ParentWidget(nullptr) + , m_InstallationProgress(nullptr) , m_SupportedExtensions({ "zip", "rar", "7z", "fomod", "001" }) { QLibrary archiveLib("dlls\\archive.dll"); @@ -441,7 +442,6 @@ QString InstallationManager::generateBackupName(const QString &directoryName) co bool InstallationManager::testOverwrite(GuessedValue &modName, bool *merge) const { QString targetDirectory = QDir::fromNativeSeparators(m_ModsDirectory + "\\" + modName); - while (QDir(targetDirectory).exists()) { QueryOverwriteDialog overwriteDialog(m_ParentWidget); if (overwriteDialog.exec()) { @@ -644,7 +644,7 @@ bool InstallationManager::install(const QString &fileName, GuessedValue int categoryID = 0; QString repository = "Nexus"; - QString metaName = fileName.mid(0).append(".meta"); + QString metaName = fileName + ".meta"; if (QFile(metaName).exists()) { QSettings metaFile(metaName, QSettings::IniFormat); modID = metaFile.value("modID", 0).toInt(); @@ -697,8 +697,8 @@ bool InstallationManager::install(const QString &fileName, GuessedValue }); foreach (IPluginInstaller *installer, m_Installers) { - // don't use inactive installers - if (!installer->isActive()) { + // don't use inactive installers (installer can't be null here but vc static code analysis thinks it could) + if ((installer == nullptr) || !installer->isActive()) { continue; } diff --git a/src/main.cpp b/src/main.cpp index bc89375e..a61e3150 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,6 +69,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include #include @@ -146,7 +147,7 @@ bool bootstrap() bool isNxmLink(const QString &link) { - return link.left(6).toLower() == "nxm://"; + return link.startsWith("nxm://", Qt::CaseInsensitive); } static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs) @@ -166,7 +167,6 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except if (dbgDLL) { FuncMiniDumpWriteDump funcDump = (FuncMiniDumpWriteDump)::GetProcAddress(dbgDLL, "MiniDumpWriteDump"); if (funcDump) { - if (QMessageBox::question(nullptr, QObject::tr("Woops"), QObject::tr("ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file " "(%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. " diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9e8d0c82..af654e2f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -138,8 +138,6 @@ using namespace MOBase; using namespace MOShared; - - MainWindow::MainWindow(const QString &exeName , QSettings &initSettings , OrganizerCore &organizerCore @@ -2172,7 +2170,6 @@ void MainWindow::removeMod_clicked() QString mods; QStringList modNames; foreach (QModelIndex idx, selection->selectedRows()) { -// QString name = ModInfo::getByIndex(m_ModListGroupProxy->mapToSource(idx).row())->name(); QString name = idx.data().toString(); if (!ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt())->isRegular()) { continue; @@ -3363,7 +3360,9 @@ void MainWindow::installTranslator(const QString &name) QTranslator *translator = new QTranslator(this); QString fileName = name + "_" + m_CurrentLanguage; if (!translator->load(fileName, qApp->applicationDirPath() + "/translations")) { - if ((m_CurrentLanguage != "en-US") && (m_CurrentLanguage != "en_US")) { + if ((m_CurrentLanguage != "en-US") + && (m_CurrentLanguage != "en_US") + && (m_CurrentLanguage != "en-GB")) { qDebug("localization file %s not found", qPrintable(fileName)); } // we don't actually expect localization files for english } diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp index bbcd3b6a..1b06d1a6 100644 --- a/src/plugincontainer.cpp +++ b/src/plugincontainer.cpp @@ -138,7 +138,8 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) IPluginProxy *proxy = qobject_cast(plugin); if (verifyPlugin(proxy)) { bf::at_key(m_Plugins).push_back(proxy); - QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath())); + QStringList pluginNames = proxy->pluginList( + QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath())); foreach (const QString &pluginName, pluginNames) { try { QObject *proxiedPlugin = proxy->instantiate(pluginName); @@ -146,11 +147,13 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) if (registerPlugin(proxiedPlugin, pluginName)) { qDebug("loaded plugin \"%s\"", qPrintable(pluginName)); } else { - qWarning("plugin \"%s\" failed to load", qPrintable(pluginName)); + qWarning("plugin \"%s\" failed to load. If this plugin is for an older version of MO " + "you have to update it or delete it if no update exists.", + qPrintable(pluginName)); } } } catch (const std::exception &e) { - reportError(QObject::tr("failed to init plugin %1: %2").arg(pluginName).arg(e.what())); + reportError(QObject::tr("failed to initialize plugin %1: %2").arg(pluginName).arg(e.what())); } } return true; @@ -199,7 +202,7 @@ void PluginContainer::unloadPlugins() while (!m_PluginLoaders.empty()) { QPluginLoader *loader = m_PluginLoaders.back(); m_PluginLoaders.pop_back(); - if (!loader->unload()) { + if ((loader != nullptr) && !loader->unload()) { qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString())); } delete loader; diff --git a/src/qt.conf b/src/qt.conf new file mode 100644 index 00000000..f834a22a --- /dev/null +++ b/src/qt.conf @@ -0,0 +1,3 @@ +[Paths] +Prefix=. +Plugins=dlls diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 5cf75752..9a864245 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -235,7 +235,8 @@ void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &arc m_Origin = origin; m_FileTime = fileTime; m_Archive = archive; - } else if (m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority()) { + } else if ((m_Parent != nullptr) + && (m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority())) { if (std::find(m_Alternatives.begin(), m_Alternatives.end(), m_Origin) == m_Alternatives.end()) { m_Alternatives.push_back(m_Origin); } @@ -253,7 +254,8 @@ void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &arc // already an origin return; } - if (m_Parent->getOriginByID(*iter).getPriority() < m_Parent->getOriginByID(origin).getPriority()) { + if ((m_Parent != nullptr) + && (m_Parent->getOriginByID(*iter).getPriority() < m_Parent->getOriginByID(origin).getPriority())) { m_Alternatives.insert(iter, origin); found = true; break; @@ -508,7 +510,7 @@ void DirectoryEntry::addFiles(FilesOrigin &origin, wchar_t *buffer, int bufferOf { WIN32_FIND_DATAW findData; - _snwprintf(buffer + bufferOffset, MAXPATH_UNICODE - bufferOffset, L"\\*"); + _snwprintf_s(buffer + bufferOffset, MAXPATH_UNICODE - bufferOffset, _TRUNCATE, L"\\*"); HANDLE searchHandle = nullptr; diff --git a/src/shared/error_report.cpp b/src/shared/error_report.cpp index c9277c1b..6d091630 100644 --- a/src/shared/error_report.cpp +++ b/src/shared/error_report.cpp @@ -46,8 +46,7 @@ void reportError(LPCWSTR format, ...) va_list argList; va_start(argList, format); - - _vsnwprintf(buffer, 1024, format, argList); + _vsnwprintf_s(buffer, 1024, format, argList); va_end(argList); MessageBoxW(nullptr, buffer, L"Error", MB_OK | MB_ICONERROR); diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h index 1f3a381d..6e6a7b85 100644 --- a/src/shared/fallout3info.h +++ b/src/shared/fallout3info.h @@ -43,38 +43,7 @@ public: virtual std::wstring getGameName() const { return L"Fallout 3"; } virtual std::wstring getGameShortName() const { return L"Fallout3"; } -/* - virtual std::wstring getInvalidationBSA() - { - return L"Fallout - Invalidation.bsa"; - } - - virtual bool isInvalidationBSA(const std::wstring &bsaName) - { - static LPCWSTR invalidation[] = { L"Fallout - AI!.bsa", L"Fallout - Invalidation.bsa", nullptr }; - - for (int i = 0; invalidation[i] != nullptr; ++i) { - if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { - return true; - } - } - return false; - } - - virtual std::vector getVanillaBSAs() - { - return boost::assign::list_of (L"Fallout - Textures.bsa") - (L"Fallout - Meshes.bsa") - (L"Fallout - Voices.bsa") - (L"Fallout - Sound.bsa") - (L"Fallout - MenuVoices.bsa") - (L"Fallout - Misc.bsa"); - } - - virtual std::vector getPrimaryPlugins() - { - return boost::assign::list_of(L"fallout3.esm"); - }*/ + virtual std::vector getDLCPlugins(); virtual std::vector getSavegameAttachmentExtensions(); diff --git a/src/shared/leaktrace.cpp b/src/shared/leaktrace.cpp index 0d99b82e..73786c6b 100644 --- a/src/shared/leaktrace.cpp +++ b/src/shared/leaktrace.cpp @@ -34,7 +34,7 @@ static struct __TraceData { iter->second.size(), iter->first.toString().c_str()); printf("Addresses: "); for (int i = 0; i < (std::min)(5, iter->second.size()); ++i) { - printf("%p, ", iter->second[i]); + printf("%p, ", reinterpret_cast(iter->second[i])); } printf("\n"); } diff --git a/src/shared/stackdata.cpp b/src/shared/stackdata.cpp index 2f8bfc4e..43acd90a 100644 --- a/src/shared/stackdata.cpp +++ b/src/shared/stackdata.cpp @@ -135,7 +135,6 @@ void StackData::initTrace() { } } -#pragma warning( enable : 4748 ) bool MOShared::operator==(const StackData &LHS, const StackData &RHS) { if (LHS.m_Count != RHS.m_Count) { diff --git a/src/shared/util.cpp b/src/shared/util.cpp index ceed3a34..2ce88eca 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -55,7 +55,10 @@ std::string ToString(const std::wstring &source, bool utf8) { std::string result; if (source.length() > 0) { - UINT codepage = utf8 ? CP_UTF8 : GetACP(); + UINT codepage = CP_UTF8; + if (!utf8) { + codepage = AreFileApisANSI() ? GetACP() : GetOEMCP(); + } int sizeRequired = ::WideCharToMultiByte(codepage, 0, &source[0], -1, nullptr, 0, nullptr, nullptr); if (sizeRequired == 0) { throw windows_error("failed to convert string to multibyte"); @@ -73,7 +76,10 @@ std::wstring ToWString(const std::string &source, bool utf8) { std::wstring result; if (source.length() > 0) { - UINT codepage = utf8 ? CP_UTF8 : GetACP(); + UINT codepage = CP_UTF8; + if (!utf8) { + codepage = AreFileApisANSI() ? GetACP() : GetOEMCP(); + } int sizeRequired = ::MultiByteToWideChar(codepage, 0, source.c_str(), source.length(), nullptr, 0); if (sizeRequired == 0) { throw windows_error("failed to convert string to wide character"); @@ -113,7 +119,7 @@ std::wstring ToLower(const std::wstring &text) VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) { - DWORD handle; + DWORD handle = 0UL; DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); if (size == 0) { throw windows_error("failed to determine file version info size"); @@ -121,6 +127,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) void *buffer = new char[size]; try { + handle = 0UL; if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer)) { throw windows_error("failed to determine file version info"); } diff --git a/src/spawn.cpp b/src/spawn.cpp index c031b25e..b1127df3 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -61,7 +61,7 @@ static bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, b _snwprintf(commandLine, length, L"\"%ls\" %ls", binary, arguments); } else { commandLine = new wchar_t[length]; - _snwprintf(commandLine, length, L"\"%ls\"", binary); + _snwprintf_s(commandLine, length, _TRUNCATE, L"\"%ls\"", binary); } QString moPath = QCoreApplication::applicationDirPath(); @@ -75,8 +75,8 @@ static bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, b { boost::scoped_array newPath(new TCHAR[offset + moPath.length() + 2]); - _tcsncpy(newPath.get(), oldPath.get(), offset - 1); - newPath.get()[offset - 1] = L'\0'; + _tcsncpy(newPath.get(), oldPath.get(), offset); + newPath.get()[offset] = '\0'; _tcsncat(newPath.get(), TEXT(";"), 1); _tcsncat(newPath.get(), ToWString(QDir::toNativeSeparators(moPath)).c_str(), moPath.length()); -- cgit v1.3.1