diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ModOrganizer.pro | 3 | ||||
| -rw-r--r-- | src/bbcode.cpp | 93 | ||||
| -rw-r--r-- | src/categories.cpp | 26 | ||||
| -rw-r--r-- | src/downloadmanager.cpp | 2 | ||||
| -rw-r--r-- | src/editexecutablesdialog.cpp | 2 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 72 | ||||
| -rw-r--r-- | src/mainwindow.h | 8 | ||||
| -rw-r--r-- | src/modinfo.cpp | 4 | ||||
| -rw-r--r-- | src/modlist.cpp | 11 | ||||
| -rw-r--r-- | src/modlist.h | 6 | ||||
| -rw-r--r-- | src/nexusinterface.cpp | 23 | ||||
| -rw-r--r-- | src/nexusinterface.h | 8 | ||||
| -rw-r--r-- | src/organizer.pro | 40 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 10 | ||||
| -rw-r--r-- | src/pluginlist.h | 12 | ||||
| -rw-r--r-- | src/settings.cpp | 1 | ||||
| -rw-r--r-- | src/shared/directoryentry.cpp | 4 | ||||
| -rw-r--r-- | src/shared/directoryentry.h | 2 | ||||
| -rw-r--r-- | src/shared/shared.pro | 53 | ||||
| -rw-r--r-- | src/tutorials/TutorialOverlay.qml | 6 | ||||
| -rw-r--r-- | src/tutorials/tutorial_firststeps_main.js | 35 |
21 files changed, 287 insertions, 134 deletions
diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro index 596b8f21..43a0fbf0 100644 --- a/src/ModOrganizer.pro +++ b/src/ModOrganizer.pro @@ -1,6 +1,5 @@ TEMPLATE = subdirs
-
SUBDIRS = bsatk \
shared \
uibase \
@@ -31,7 +30,7 @@ DLLSPATH = $${DESTDIR}\\dlls otherlibs.path = $$DLLSPATH
otherlibs.files += $${STATICDATAPATH}\\7z.dll \
- $$(BOOSTPATH)\\stage\\lib\\boost_python-vc*-mt-1*.dll
+ $${BOOSTPATH}\\stage\\lib\\boost_python-vc*-mt-1*.dll
qtlibs.path = $$DLLSPATH
diff --git a/src/bbcode.cpp b/src/bbcode.cpp index 18f2beb1..92eb427f 100644 --- a/src/bbcode.cpp +++ b/src/bbcode.cpp @@ -39,7 +39,7 @@ public: return s_Instance;
}
- QString convertTag(const QString &input, int &length)
+ QString convertTag(QString input, int &length)
{
// extract the tag name
m_TagNameExp.indexIn(input, 1, QRegExp::CaretAtOffset);
@@ -50,14 +50,30 @@ public: if (tagName.endsWith('=')) {
tagName.chop(1);
}
- QString closeTag = tagName == "*" ? "<br/>"
- : QString("[/%1]").arg(tagName);
- int closeTagPos = input.indexOf(closeTag, 0, Qt::CaseInsensitive);
- //qDebug("close tag %s at %d", closeTag.toUtf8().constData(), closeTagPos);
+ int closeTagPos = 0;
+ int closeTagLength = 0;
+ if (tagName == "*") {
+ // ends at the next bullet point
+ closeTagPos = input.indexOf(QRegExp("(\\[\\*\\]|</ul>)", Qt::CaseInsensitive), 3);
+ // leave closeTagLength at 0 because we don't want to "eat" the next bullet point
+ } else if (tagName == "line") {
+ // ends immediately after the tag
+ closeTagPos = 6;
+ // leave closeTagLength at 0 because there is no close tag to skip over
+ } else {
+ QString closeTag = QString("[/%1]").arg(tagName);
+ closeTagPos = input.indexOf(closeTag, 0, Qt::CaseInsensitive);
+ if (closeTagPos == -1) {
+ // workaround to improve compatibility: add fake closing tag
+ input.append(closeTag);
+ closeTagPos = input.size() - closeTag.size();
+ }
+ closeTagLength = closeTag.size();
+ }
if (closeTagPos > -1) {
- length = closeTagPos + closeTag.length();
+ length = closeTagPos + closeTagLength;
QString temp = input.mid(0, length);
if (tagIter->second.first.indexIn(temp) == 0) {
if (tagIter->second.second.isEmpty()) {
@@ -73,6 +89,9 @@ public: qWarning("don't know how to deal with tag %s", qPrintable(tagName));
}
} else {
+ if (tagName == "*") {
+ temp.remove(QRegExp("(\\[/\\*\\])?(<br/>)?$"));
+ }
return temp.replace(tagIter->second.first, tagIter->second.second);
}
} else {
@@ -123,6 +142,8 @@ private: "<pre>\\1</pre>");
m_TagMap["heading"]= std::make_pair(QRegExp("\\[heading\\](.*)\\[/heading\\]"),
"<h2><strong>\\1</strong></h2>");
+ m_TagMap["line"] = std::make_pair(QRegExp("\\[line\\]"),
+ "<hr>");
// lists
m_TagMap["list"] = std::make_pair(QRegExp("\\[list\\](.*)\\[/list\\]"),
@@ -135,8 +156,6 @@ private: "<ol>\\1</ol>");
m_TagMap["li"] = std::make_pair(QRegExp("\\[li\\](.*)\\[/li\\]"),
"<li>\\1</li>");
- m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)<br/>"),
- "<li>\\1</li>");
// tables
m_TagMap["table"] = std::make_pair(QRegExp("\\[table\\](.*)\\[/table\\]"),
@@ -153,13 +172,26 @@ private: "<a href=\"\\1\">\\1</a>");
m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"),
"<a href=\"\\1\">\\2</a>");
- m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), " ");
- m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), " ");
+ m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"),
+ "<a href=\"\\1\">\\1</a>");
+ m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"),
+ "<a href=\"\\1\">\\2</a>");
m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"),
"<a href=\"mailto:\\1\">\\2</a>");
m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"),
"<a href=\"http://www.youtube.com/v/\\1\">http://www.youtube.com/v/\\1</a>");
+
+ // make all patterns non-greedy and case-insensitive
+ for (TagMap::iterator iter = m_TagMap.begin(); iter != m_TagMap.end(); ++iter) {
+ iter->second.first.setCaseSensitivity(Qt::CaseInsensitive);
+ iter->second.first.setMinimal(true);
+ }
+
+ // this tag is in fact greedy
+ m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)"),
+ "<li>\\1</li>");
+
m_ColorMap.insert(std::make_pair<QString, QString>("red", "FF0000"));
m_ColorMap.insert(std::make_pair<QString, QString>("green", "00FF00"));
m_ColorMap.insert(std::make_pair<QString, QString>("blue", "0000FF"));
@@ -170,13 +202,13 @@ private: m_ColorMap.insert(std::make_pair<QString, QString>("cyan", "00FFFF"));
m_ColorMap.insert(std::make_pair<QString, QString>("magenta", "FF00FF"));
m_ColorMap.insert(std::make_pair<QString, QString>("brown", "A52A2A"));
- m_ColorMap.insert(std::make_pair<QString, QString>("orange", "FFCC00"));
-
- // make all patterns non-greedy and case-insensitive
- for (TagMap::iterator iter = m_TagMap.begin(); iter != m_TagMap.end(); ++iter) {
- iter->second.first.setCaseSensitivity(Qt::CaseInsensitive);
- iter->second.first.setMinimal(true);
- }
+ m_ColorMap.insert(std::make_pair<QString, QString>("orange", "FFA500"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("gold", "FFD700"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("deepskyblue", "00BFFF"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("salmon", "FA8072"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("dodgerblue", "1E90FF"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("greenyellow", "ADFF2F"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("peru", "CD853F"));
}
private:
@@ -209,18 +241,23 @@ QString convertToHTML(const QString &inputParam) // append everything between the previous tag-block and the current one
result.append(input.midRef(lastBlock, pos - lastBlock));
- // convert the tag and content if necessary
- int length = -1;
- QString replacement = BBCodeMap::instance().convertTag(input.mid(pos), length);
- if (length != 0) {
- QString temp = convertToHTML(replacement);
- result.append(temp);
- // length contains the number of characters in the original tag
- pos += length;
+ if ((pos < (input.size() - 1)) && (input.at(pos + 1) == '/')) {
+ // skip invalid end tag
+ int tagEnd = input.indexOf(']', pos) + 1;
+ pos = tagEnd;
} else {
- // nothing replaced
- result.append('[');
- ++pos;
+ // convert the tag and content if necessary
+ int length = -1;
+ QString replacement = BBCodeMap::instance().convertTag(input.mid(pos), length);
+ if (length != 0) {
+ result.append(convertToHTML(replacement));
+ // length contains the number of characters in the original tag
+ pos += length;
+ } else {
+ // nothing replaced
+ result.append('[');
+ ++pos;
+ }
}
lastBlock = pos;
}
diff --git a/src/categories.cpp b/src/categories.cpp index 79c646b3..ec3e29f4 100644 --- a/src/categories.cpp +++ b/src/categories.cpp @@ -104,7 +104,11 @@ void CategoryFactory::reset() {
m_Categories.clear();
m_IDMap.clear();
- addCategory(0, "None", MakeVector<int>(2, 28, 87), 0);
+ // 28 =
+ // 43 = Savegames (makes no sense to install them through MO)
+ // 45 = Videos and trailers
+ // 87 = Miscelanous
+ addCategory(0, "None", MakeVector<int>(4, 28, 43, 45, 87), 0);
}
@@ -189,24 +193,38 @@ void CategoryFactory::loadDefaultCategories() // mods appear in the combo box
addCategory(1, "Animations", MakeVector<int>(1, 51), 0);
addCategory(2, "Armour", MakeVector<int>(1, 54), 0);
- addCategory(3, "Audio", MakeVector<int>(1, 61), 0);
+ addCategory(3, "Sound & Music", MakeVector<int>(1, 61), 0);
addCategory(5, "Clothing", MakeVector<int>(1, 60), 0);
addCategory(6, "Collectables", MakeVector<int>(1, 92), 0);
- addCategory(7, "Creatures", MakeVector<int>(2, 83, 65), 0);
+ addCategory(28, "Companions", MakeVector<int>(2, 66, 96), 0);
+ addCategory(7, "Creatures & Mounts", MakeVector<int>(2, 83, 65), 0);
addCategory(8, "Factions", MakeVector<int>(1, 25), 0);
addCategory(9, "Gameplay", MakeVector<int>(1, 24), 0);
addCategory(10, "Hair", MakeVector<int>(1, 26), 0);
addCategory(11, "Items", MakeVector<int>(2, 27, 85), 0);
- addCategory(19, "Weapons", MakeVector<int>(2, 36, 55), 11);
+ addCategory(32, "Mercantile", MakeVector<int>(1, 69), 0);
+ addCategory(19, "Weapons", MakeVector<int>(1, 55), 11);
+ addCategory(36, "Weapon & Armour Sets", MakeVector<int>(1, 39), 11);
addCategory(12, "Locations", MakeVector<int>(7, 22, 30, 70, 88, 89, 90, 91), 0);
+ addCategory(31, "Landscape Changes", MakeVector<int>(1, 58), 0);
addCategory(4, "Cities", MakeVector<int>(1, 53), 12);
+ addCategory(29, "Environment", MakeVector<int>(1, 74), 0);
+ addCategory(30, "Immersion", MakeVector<int>(1, 78), 0);
+ addCategory(25, "Castles & Mansions", MakeVector<int>(1, 68), 23);
addCategory(20, "Magic", MakeVector<int>(3, 75, 93, 94), 0);
addCategory(21, "Models & Textures", MakeVector<int>(1, 29), 0);
+ addCategory(33, "Modders resources", MakeVector<int>(1, 82), 0);
addCategory(13, "NPCs", MakeVector<int>(1, 33), 0);
addCategory(14, "Patches", MakeVector<int>(2, 79, 84), 0);
+ addCategory(24, "Bugfixes", MakeVector<int>(1, 95), 0);
+ addCategory(35, "Utilities", MakeVector<int>(1, 39), 0);
+ addCategory(26, "Cheats", MakeVector<int>(1, 40), 0);
+ addCategory(23, "Player Homes", MakeVector<int>(1, 67), 0);
addCategory(15, "Quests", MakeVector<int>(1, 35), 0);
addCategory(16, "Races & Classes", MakeVector<int>(1, 34), 0);
+ addCategory(27, "Combat", MakeVector<int>(1, 77), 0);
addCategory(22, "Skills", MakeVector<int>(1, 73), 0);
+ addCategory(34, "Stealth", MakeVector<int>(1, 76), 0);
addCategory(17, "UI", MakeVector<int>(1, 42), 0);
addCategory(18, "Visuals", MakeVector<int>(1, 62), 0);
}
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 856ca79c..bc31adf4 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -685,7 +685,7 @@ void DownloadManager::queryInfo(int index) return;
}
- if (info->m_FileInfo->modID == 0UL) {
+ if (info->m_FileInfo->modID <= 0) {
QString fileName = getFileName(index);
QString ignore;
NexusInterface::interpretNexusFileName(fileName, ignore, info->m_FileInfo->modID, true);
diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 02abf30e..0e3aa55b 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -132,7 +132,7 @@ void EditExecutablesDialog::on_browseButton_clicked() if (::FindExecutableW(binaryNameW.c_str(), NULL, buffer) > (HINSTANCE)32) {
DWORD binaryType = 0UL;
if (!::GetBinaryTypeW(binaryNameW.c_str(), &binaryType)) {
- qDebug("failed to determine binary type: %lu", ::GetLastError());
+ qDebug("failed to determine binary type of \"%ls\": %lu", binaryNameW.c_str(), ::GetLastError());
} else if (binaryType == SCS_32BIT_BINARY) {
binaryPath = ToQString(buffer);
}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d8e2a84c..954c6e85 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -97,9 +97,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QtPlugin>
#include <QIdentityProxyModel>
#include <QClipboard>
-#include <boost/bind.hpp>
-#include <boost/foreach.hpp>
-#include <boost/assign.hpp>
#include <Psapi.h>
#include <shlobj.h>
#include <ShellAPI.h>
@@ -114,8 +111,13 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QCoreApplication>
#include <QProgressDialog>
#include <scopeguard.h>
+#ifndef Q_MOC_RUN
#include <boost/thread.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/assign.hpp>
+#endif
#include <regex>
#ifdef TEST_MODELS
@@ -309,8 +311,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&m_Updater, SIGNAL(updateAvailable()), this, SLOT(updateAvailable()));
connect(&m_Updater, SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString)));
-// connect(ExitProxy::instance(), SIGNAL(exit()), this, SLOT(close()));
-
connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool)));
connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
connect(NexusInterface::instance(), SIGNAL(requestNXMDownload(QString)), this, SLOT(downloadRequestedNXM(QString)));
@@ -363,6 +363,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget MainWindow::~MainWindow()
{
+ m_AboutToRun.disconnect_all_slots();
+ m_ModInstalled.disconnect_all_slots();
m_RefresherThread.exit();
m_RefresherThread.wait();
m_IntegratedBrowser.close();
@@ -880,6 +882,8 @@ void MainWindow::closeEvent(QCloseEvent* event) storeSettings();
+// unloadPlugins();
+
// profile has to be cleaned up before the modinfo-buffer is cleared
delete m_CurrentProfile;
m_CurrentProfile = NULL;
@@ -887,6 +891,7 @@ void MainWindow::closeEvent(QCloseEvent* event) ModInfo::clear();
LogBuffer::cleanQuit();
m_ModList.setProfile(NULL);
+ NexusInterface::instance()->cleanup();
}
@@ -1166,7 +1171,9 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(plugin);
if (diagnose != NULL) {
m_DiagnosisPlugins.push_back(diagnose);
- diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); });
+ m_DiagnosisConnections.push_back(
+ diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); })
+ );
}
}
{ // mod page plugin
@@ -1195,6 +1202,7 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) IPluginPreview *preview = qobject_cast<IPluginPreview*>(plugin);
if (verifyPlugin(preview)) {
m_PreviewGenerator.registerPlugin(preview);
+ return true;
}
}
{ // proxy plugins
@@ -1233,13 +1241,41 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) return false;
}
-
-void MainWindow::loadPlugins()
+void MainWindow::unloadPlugins()
{
+ // disconnect all slots before unloading plugins so plugins don't have to take care of that
+ m_AboutToRun.disconnect_all_slots();
+ m_ModInstalled.disconnect_all_slots();
+ m_ModList.disconnectSlots();
+ m_PluginList.disconnectSlots();
+
m_DiagnosisPlugins.clear();
+ foreach (const boost::signals2::connection &connection, m_DiagnosisConnections) {
+ connection.disconnect();
+ }
+ m_DiagnosisConnections.clear();
+
m_Settings.clearPlugins();
+ if (ui->actionTool->menu() != NULL) {
+ ui->actionTool->menu()->clear();
+ }
+
+ foreach (QPluginLoader *loader, m_PluginLoaders) {
+ qDebug("unloading %s", qPrintable(loader->fileName()));
+ if (!loader->unload()) {
+ qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString()));
+ }
+ delete loader;
+ }
+ m_PluginLoaders.clear();
+}
+
+void MainWindow::loadPlugins()
+{
+ unloadPlugins();
+
foreach (QObject *plugin, QPluginLoader::staticInstances()) {
registerPlugin(plugin, "");
}
@@ -1278,14 +1314,15 @@ void MainWindow::loadPlugins() loadCheck.flush();
QString pluginName = iter.filePath();
if (QLibrary::isLibrary(pluginName)) {
- QPluginLoader pluginLoader(pluginName);
- if (pluginLoader.instance() == NULL) {
+ QPluginLoader *pluginLoader = new QPluginLoader(pluginName, this);
+ if (pluginLoader->instance() == NULL) {
m_UnloadedPlugins.push_back(pluginName);
qCritical("failed to load plugin %s: %s",
- qPrintable(pluginName), qPrintable(pluginLoader.errorString()));
+ qPrintable(pluginName), qPrintable(pluginLoader->errorString()));
} else {
- if (registerPlugin(pluginLoader.instance(), pluginName)) {
+ if (registerPlugin(pluginLoader->instance(), pluginName)) {
qDebug("loaded plugin \"%s\"", qPrintable(pluginName));
+ m_PluginLoaders.push_back(pluginLoader);
} else {
m_UnloadedPlugins.push_back(pluginName);
qWarning("plugin \"%s\" failed to load", qPrintable(pluginName));
@@ -2181,6 +2218,8 @@ void MainWindow::storeSettings() void MainWindow::on_btnRefreshData_clicked()
{
if (!m_DirectoryUpdate) {
+ // save the mod list so changes don't get lost
+ m_CurrentProfile->writeModlistNow(true);
refreshDirectoryStructure();
} else {
qDebug("directory update");
@@ -4420,7 +4459,7 @@ int MainWindow::getBinaryExecuteInfo(const QFileInfo &targetInfo, if (::FindExecutableW(targetPathW.c_str(), NULL, buffer) > (HINSTANCE)32) {
DWORD binaryType = 0UL;
if (!::GetBinaryTypeW(targetPathW.c_str(), &binaryType)) {
- qDebug("failed to determine binary type: %lu", ::GetLastError());
+ qDebug("failed to determine binary type of \"%ls\": %lu", targetPathW.c_str(), ::GetLastError());
} else if (binaryType == SCS_32BIT_BINARY) {
binaryPath = ToQString(buffer);
}
@@ -5023,9 +5062,6 @@ void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int) void MainWindow::on_actionProblems_triggered()
{
-// QString problemDescription;
-// checkForProblems(problemDescription);
-// QMessageBox::information(this, tr("Problems"), problemDescription);
ProblemsDialog problems(m_DiagnosisPlugins, this);
if (problems.hasProblems()) {
problems.exec();
@@ -5484,7 +5520,11 @@ void MainWindow::on_bossButton_clicked() QStringList temp = report.split("?");
QUrl url = QUrl::fromLocalFile(temp.at(0));
if (temp.size() > 1) {
+#if QT_VERSION >= 0x050000
+ url.setQuery(temp.at(1).toUtf8());
+#else
url.setEncodedQuery(temp.at(1).toUtf8());
+#endif
}
m_IntegratedBrowser.openUrl(url);
}
diff --git a/src/mainwindow.h b/src/mainwindow.h index e43feb89..65e0b264 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -29,6 +29,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QThread>
#include <QProgressBar>
#include <QTranslator>
+#include <QPluginLoader>
#include "executableslist.h"
#include "modlist.h"
#include "pluginlist.h"
@@ -53,7 +54,9 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "browserdialog.h"
#include <guessedvalue.h>
#include <directoryentry.h>
+#ifndef Q_MOC_RUN
#include <boost/signals2.hpp>
+#endif
namespace Ui {
class MainWindow;
@@ -138,6 +141,8 @@ public: void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo);
+ QString getOriginDisplayName(int originID);
+ void unloadPlugins();
public slots:
void refreshLists();
@@ -190,6 +195,7 @@ private: void registerPluginTool(MOBase::IPluginTool *tool);
void registerModPage(MOBase::IPluginModPage *modPage);
bool registerPlugin(QObject *pluginObj, const QString &fileName);
+ bool unregisterPlugin(QObject *pluginObj, const QString &fileName);
void updateToolBar();
void activateSelectedProfile();
@@ -371,8 +377,10 @@ private: MOBase::IGameInfo *m_GameInfo;
std::vector<MOBase::IPluginDiagnose*> m_DiagnosisPlugins;
+ std::vector<boost::signals2::connection> m_DiagnosisConnections;
std::vector<MOBase::IPluginModPage*> m_ModPages;
std::vector<QString> m_UnloadedPlugins;
+ std::vector<QPluginLoader*> m_PluginLoaders;
QFile m_PluginsCheck;
diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 127f7c4c..23fd9f3c 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -540,9 +540,7 @@ void ModInfoRegular::saveMeta() metaFile.setValue("newestVersion", m_NewestVersion.canonicalString());
metaFile.setValue("ignoredVersion", m_IgnoredVersion.canonicalString());
metaFile.setValue("version", m_Version.canonicalString());
- if (m_NexusID != -1) {
- metaFile.setValue("modid", m_NexusID);
- }
+ metaFile.setValue("modid", m_NexusID);
metaFile.setValue("notes", m_Notes);
metaFile.setValue("nexusDescription", m_NexusDescription);
metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate));
diff --git a/src/modlist.cpp b/src/modlist.cpp index fd8a2a4f..1742c7ad 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -63,6 +63,12 @@ ModList::ModList(QObject *parent) m_ContentIcons[ModInfo::CONTENT_TEXTURE] = std::make_tuple(QIcon(":/MO/gui/content/texture"), ":/MO/gui/content/texture", tr("Textures"));
}
+ModList::~ModList()
+{
+ m_ModStateChanged.disconnect_all_slots();
+ m_ModMoved.disconnect_all_slots();
+}
+
void ModList::setProfile(Profile *profile)
{
m_Profile = profile;
@@ -636,6 +642,11 @@ void ModList::modInfoChanged(ModInfo::Ptr info) }
}
+void ModList::disconnectSlots() {
+ m_ModMoved.disconnect_all_slots();
+ m_ModStateChanged.disconnect_all_slots();
+}
+
IModList::ModStates ModList::state(unsigned int modIndex) const
{
IModList::ModStates result;
diff --git a/src/modlist.h b/src/modlist.h index f5cd70f2..dec6d6d0 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -32,7 +32,9 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QListWidget>
#include <QNetworkReply>
#include <QNetworkAccessManager>
+#ifndef Q_MOC_RUN
#include <boost/signals2.hpp>
+#endif
#include <set>
#include <vector>
#include <QVector>
@@ -73,6 +75,8 @@ public: **/
ModList(QObject *parent = NULL);
+ ~ModList();
+
/**
* @brief set the profile used for status information
*
@@ -101,6 +105,8 @@ public: void modInfoAboutToChange(ModInfo::Ptr info);
void modInfoChanged(ModInfo::Ptr info);
+ void disconnectSlots();
+
public:
/// \copydoc MOBase::IModList::displayName
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index d844cd39..30221f4b 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -145,30 +145,25 @@ QAtomicInt NexusInterface::NXMRequestInfo::s_NextID(0); NexusInterface::NexusInterface()
: m_NMMVersion()
{
- atexit(&cleanup);
-
VS_FIXEDFILEINFO version = GetFileVersion(ToWString(QApplication::applicationFilePath()));
m_MOVersion = VersionInfo(version.dwFileVersionMS >> 16,
version.dwFileVersionMS & 0xFFFF,
version.dwFileVersionLS >> 16);
m_AccessManager = new NXMAccessManager(this, m_MOVersion.displayString());
-
m_DiskCache = new QNetworkDiskCache(this);
connect(m_AccessManager, SIGNAL(requestNXMDownload(QString)), this, SLOT(downloadRequestedNXM(QString)));
}
-
-void NexusInterface::cleanup()
-{
-}
-
-
NXMAccessManager *NexusInterface::getAccessManager()
{
return m_AccessManager;
}
+NexusInterface::~NexusInterface()
+{
+ cleanup();
+}
NexusInterface *NexusInterface::instance()
{
@@ -176,14 +171,12 @@ NexusInterface *NexusInterface::instance() return &s_Instance;
}
-
void NexusInterface::setCacheDirectory(const QString &directory)
{
m_DiskCache->setCacheDirectory(directory);
m_AccessManager->setCache(m_DiskCache);
}
-
void NexusInterface::setNMMVersion(const QString &nmmVersion)
{
m_NMMVersion = nmmVersion;
@@ -378,6 +371,14 @@ bool NexusInterface::requiresLogin(const NXMRequestInfo &info) || (info.m_Type == NXMRequestInfo::TYPE_DOWNLOADURL);
}
+void NexusInterface::cleanup()
+{
+// delete m_AccessManager;
+// delete m_DiskCache;
+ m_AccessManager = nullptr;
+ m_DiskCache = nullptr;
+}
+
void NexusInterface::nextRequest()
{
if ((m_ActiveRequest.size() >= MAX_ACTIVE_DOWNLOADS)
diff --git a/src/nexusinterface.h b/src/nexusinterface.h index cc54daa9..af2f8c75 100644 --- a/src/nexusinterface.h +++ b/src/nexusinterface.h @@ -130,6 +130,8 @@ class NexusInterface : public QObject public:
+ ~NexusInterface();
+
static NexusInterface *instance();
/**
@@ -138,6 +140,11 @@ public: NXMAccessManager *getAccessManager();
/**
+ * @brief cleanup this interface. this is destructive, afterwards it can't be used again
+ */
+ void cleanup();
+
+ /**
* @brief request description for a mod
*
* @param modID id of the mod caller is interested in
@@ -301,7 +308,6 @@ private: void nextRequest();
void requestFinished(std::list<NXMRequestInfo>::iterator iter);
bool requiresLogin(const NXMRequestInfo &info);
- static void cleanup();
private:
diff --git a/src/organizer.pro b/src/organizer.pro index 4e46d1c1..77408cc5 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -14,6 +14,10 @@ greaterThan(QT_MAJOR_VERSION, 4) { QT += core gui network xml declarative script sql xmlpatterns webkit
}
+!include(../LocalPaths.pri) {
+ message("paths to required libraries need to be set up in LocalPaths.pri")
+}
+
SOURCES += \
transfersavesdialog.cpp \
syncoverwritedialog.cpp \
@@ -246,9 +250,9 @@ LIBS += -lDbgHelp #DEFINES += TEST_MODELS
-INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk ../boss_modified/boss-api "$(BOOSTPATH)"
+INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk ../boss_modified/boss-api "$${BOOSTPATH}"
-LIBS += -L"$(BOOSTPATH)/stage/lib"
+LIBS += -L"$${BOOSTPATH}/stage/lib"
CONFIG(debug, debug|release) {
LIBS += -L$$OUT_PWD/../shared/debug
@@ -256,7 +260,8 @@ CONFIG(debug, debug|release) { LIBS += -L$$OUT_PWD/../uibase/debug
LIBS += -L$$OUT_PWD/../boss_modified/debug
LIBS += -lDbgHelp
- PRE_TARGETDEPS += $$OUT_PWD/../shared/debug/mo_shared.lib \
+ PRE_TARGETDEPS += \
+ $$OUT_PWD/../shared/debug/mo_shared.lib \
$$OUT_PWD/../bsatk/debug/bsatk.lib
} else {
LIBS += -L$$OUT_PWD/../shared/release
@@ -264,20 +269,19 @@ CONFIG(debug, debug|release) { LIBS += -L$$OUT_PWD/../uibase/release
LIBS += -L$$OUT_PWD/../boss_modified/release
QMAKE_CXXFLAGS += /Zi# /GL
-# QMAKE_CXXFLAGS -= -O2
QMAKE_LFLAGS += /DEBUG# /LTCG /OPT:REF /OPT:ICF
- PRE_TARGETDEPS += $$OUT_PWD/../shared/release/mo_shared.lib \
+ PRE_TARGETDEPS += \
+ $$OUT_PWD/../shared/release/mo_shared.lib \
$$OUT_PWD/../bsatk/release/bsatk.lib
}
#QMAKE_CXXFLAGS_WARN_ON -= -W3
#QMAKE_CXXFLAGS_WARN_ON += -W4
-QMAKE_CXXFLAGS += -wd4127 -wd4512 -wd4189
+QMAKE_CXXFLAGS += -wd4100 -wd4127 -wd4512 -wd4189
CONFIG += embed_manifest_exe
# QMAKE_CXXFLAGS += /analyze
-
# QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'highestAvailable\' uiAccess=\'false\'\"
TRANSLATIONS = organizer_de.ts \
@@ -311,9 +315,9 @@ TRANSLATIONS = organizer_de.ts \ LIBS += -lmo_shared -luibase -lshell32 -lole32 -luser32 -ladvapi32 -lgdi32 -lPsapi -lVersion -lbsatk -lshlwapi
-LIBS += -L"$(ZLIBPATH)/build" -lzlibstatic
+LIBS += -L"$${ZLIBPATH}/build" -lzlibstatic
-DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS NOMINMAX
+DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS NOMINMAX
DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
#DEFINES += QMLJSDEBUGGER
@@ -322,23 +326,23 @@ HGID = $$system(hg id -i) DEFINES += HGID=\\\"$${HGID}\\\"
CONFIG(debug, debug|release) {
- OUTDIR = $$OUT_PWD/debug
+ SRCDIR = $$OUT_PWD/debug
DSTDIR = $$PWD/../../outputd
} else {
- OUTDIR = $$OUT_PWD/release
+ SRCDIR = $$OUT_PWD/release
DSTDIR = $$PWD/../../output
}
-SRCDIR = $$PWD
+BASEDIR = $$PWD
+BASEDIR ~= s,/,$$QMAKE_DIR_SEP,g
SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g
-OUTDIR ~= s,/,$$QMAKE_DIR_SEP,g
DSTDIR ~= s,/,$$QMAKE_DIR_SEP,g
-QMAKE_POST_LINK += xcopy /y /I $$quote($$OUTDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /I $$quote($$OUTDIR\\ModOrganizer*.pdb) $$quote($$DSTDIR) $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\stylesheets) $$quote($$DSTDIR)\\stylesheets $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\tutorials) $$quote($$DSTDIR)\\tutorials $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\*.qm) $$quote($$DSTDIR)\\translations $$escape_expand(\\n)
+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 /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)
CONFIG(debug, debug|release) {
QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest.debug) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index a2d0d04a..3146969a 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -33,6 +33,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QMimeData>
#include <QCoreApplication>
#include <QDir>
+#include <QFile>
#include <QTextCodec>
#include <QFileInfo>
#include <QListWidgetItem>
@@ -95,6 +96,8 @@ PluginList::PluginList(QObject *parent) PluginList::~PluginList()
{
+ m_Refreshed.disconnect_all_slots();
+ m_PluginMoved.disconnect_all_slots();
}
@@ -482,8 +485,11 @@ void PluginList::saveTo(const QString &pluginFileName deleterFile.write("\r\n");
}
}
- deleterFile.close();
- qDebug("%s saved", QDir::toNativeSeparators(deleterFileName).toUtf8().constData());
+ if (deleterFile.commitIfDifferent(m_LastSaveHash[deleterFileName])) {
+ qDebug("%s saved", qPrintable(QDir::toNativeSeparators(deleterFileName)));
+ }
+ } else if (QFile::exists(deleterFileName)) {
+ shellDelete(QStringList() << deleterFileName);
}
m_SaveTimer.stop();
diff --git a/src/pluginlist.h b/src/pluginlist.h index 67d1b640..8c06fefd 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -26,15 +26,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QListWidget>
#include <QTimer>
#include <QTemporaryFile>
+#ifndef Q_MOC_RUN
#include <boost/signals2.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
+#endif
#include <vector>
#include <map>
#include "pdll.h"
#include <BOSS-API.h>
-
template <class C>
class ChangeBracket {
public:
@@ -212,6 +213,11 @@ public: void refreshLoadOrder();
+ void disconnectSlots() {
+ m_PluginMoved.disconnect_all_slots();
+ m_Refreshed.disconnect_all_slots();
+ }
+
public:
virtual PluginState state(const QString &name) const;
@@ -333,13 +339,11 @@ private: mutable QTimer m_SaveTimer;
SignalRefreshed m_Refreshed;
+ SignalPluginMoved m_PluginMoved;
QTemporaryFile m_TempFile;
- SignalPluginMoved m_PluginMoved;
};
-
-
#endif // PLUGINLIST_H
diff --git a/src/settings.cpp b/src/settings.cpp index ba3c820d..293a06ab 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -132,7 +132,6 @@ void Settings::registerPlugin(IPlugin *plugin) }
}
-
QString Settings::obfuscate(const QString &password) const
{
QByteArray temp = password.toUtf8();
diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index e0914870..5d785822 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -936,10 +936,6 @@ void FileRegister::removeOriginMulti(std::set<FileEntry::Index> indices, int ori }
}
- if (removedFiles.size() > 0) {
- log("%d files actually removed", removedFiles.size());
- }
-
// optimization: this is only called when disabling an origin and in this case we don't have
// to remove the file from the origin
diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 1e904311..0ab1ee36 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -29,8 +29,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #define WIN32_MEAN_AND_LEAN
#include <Windows.h>
#include <bsatk.h>
+#ifndef Q_MOC_RUN
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
+#endif
#include "util.h"
diff --git a/src/shared/shared.pro b/src/shared/shared.pro index 84a9c274..69f6f2e6 100644 --- a/src/shared/shared.pro +++ b/src/shared/shared.pro @@ -11,33 +11,11 @@ TARGET = mo_shared TEMPLATE = lib
CONFIG += staticlib
-INCLUDEPATH += ../bsatk "$(BOOSTPATH)"
-
-# only for custom leak detection
-DEFINES += TRACE_LEAKS
-LIBS += -lDbgHelp
-
-
-CONFIG(debug, debug|release) {
- LIBS += -L$$OUT_PWD/../bsatk/debug
- LIBS += -lDbgHelp
- QMAKE_CXXFLAGS_DEBUG -= -Zi
- QMAKE_CXXFLAGS += -Z7
- PRE_TARGETDEPS += $$OUT_PWD/../bsatk/debug/bsatk.lib
-} else {
- LIBS += -L$$OUT_PWD/../bsatk/release
- PRE_TARGETDEPS += $$OUT_PWD/../bsatk/release/bsatk.lib
+!include(../LocalPaths.pri) {
+ message("paths to required libraries need to be set up in LocalPaths.pri")
}
-LIBS += -lbsatk
-
-DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS
-
-DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
-
-# QMAKE_CXXFLAGS += /analyze
-
SOURCES += \
inject.cpp \
windows_error.cpp \
@@ -66,3 +44,30 @@ HEADERS += \ appconfig.h \
appconfig.inc \
leaktrace.h
+
+
+# only for custom leak detection
+DEFINES += TRACE_LEAKS
+LIBS += -lDbgHelp
+
+
+CONFIG(debug, debug|release) {
+ LIBS += -L$$OUT_PWD/../bsatk/debug
+ LIBS += -lDbgHelp
+ QMAKE_CXXFLAGS_DEBUG -= -Zi
+ QMAKE_CXXFLAGS += -Z7
+ PRE_TARGETDEPS += $$OUT_PWD/../bsatk/debug/bsatk.lib
+} else {
+ LIBS += -L$$OUT_PWD/../bsatk/release
+ PRE_TARGETDEPS += $$OUT_PWD/../bsatk/release/bsatk.lib
+}
+
+LIBS += -lbsatk
+
+DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS
+
+DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
+
+# QMAKE_CXXFLAGS += /analyze
+
+INCLUDEPATH += ../bsatk "$${BOOSTPATH}"
diff --git a/src/tutorials/TutorialOverlay.qml b/src/tutorials/TutorialOverlay.qml index 34959d7d..f2aad027 100644 --- a/src/tutorials/TutorialOverlay.qml +++ b/src/tutorials/TutorialOverlay.qml @@ -1,4 +1,3 @@ -// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
import "tutorials.js" as Logic
@@ -21,10 +20,11 @@ Rectangle { function enableBackground(enabled) {
disabledBackground.visible = enabled
}
-
+/*
signal nextStep
- onNextStep: {
+ onNextStep: {*/
+ function nextStep() {
if (step == 0) {
Logic.init()
}
diff --git a/src/tutorials/tutorial_firststeps_main.js b/src/tutorials/tutorial_firststeps_main.js index 4f9c1a74..5ee4e790 100644 --- a/src/tutorials/tutorial_firststeps_main.js +++ b/src/tutorials/tutorial_firststeps_main.js @@ -15,19 +15,24 @@ function getTutorialSteps() function() {
tutorial.text = qsTr("The highlighted button provides hints on solving problems MO recognized automatically.")
- if (!tutorialControl.waitForAction("actionProblems")) {
- highlightAction("actionProblems", false)
- waitForClick()
- } else {
+ if (tutorialControl.waitForAction("actionProblems")) {
tutorial.text += qsTr("\nThere IS a problem now but you may want to hold off on fixing it until after completing the tutorial.")
highlightAction("actionProblems", true)
+ } else {
+ highlightAction("actionProblems", false)
+ waitForClick()
}
},
function() {
+ console.log("next")
tutorial.text = qsTr("This button provides multiple sources of information and further tutorials.")
- highlightItem("actionHelp", true)
- tutorialControl.waitForButton("actionHelp")
+ if (tutorialControl.waitForButton("actionHelp")) {
+ highlightItem("actionHelp", true)
+ } else {
+ console.error("help button broken")
+ waitForClick()
+ }
},
function() {
@@ -47,12 +52,16 @@ function getTutorialSteps() function() {
tutorial.text = qsTr("Before we start installing mods, let's have a quick look at the settings.")
manager.activateTutorial("SettingsDialog", "tutorial_firststeps_settings.js")
- highlightAction("actionSettings", true)
- tutorialControl.waitForAction("actionSettings")
+ if (tutorialControl.waitForAction("actionSettings")) {
+ highlightAction("actionSettings", true)
+ } else {
+ console.error("settings action broken")
+ waitForClick()
+ }
},
function() {
- tutorial.text = qsTr("Now it's time to install a few mods!"
+ tutorial.text = qsTr("Now it's time to install a few mods!"
+ "Please go along with this because we need a few mods installed to demonstrate other features")
waitForClick()
},
@@ -61,8 +70,12 @@ function getTutorialSteps() tutorial.text = qsTr("There are a few ways to get mods into ModOrganizer. "
+ "If you associated MO with NXM links in the settings you can now use your regular browser to send downloads from Nexus to MO. "
+ "Click on \"Nexus\" to open nexus, find a mod and click the green download buttons on Nexus saying \"Download with Manager\".")
- highlightAction("actionNexus", true)
- tutorialControl.waitForAction("actionNexus")
+ if (tutorialControl.waitForAction("actionNexus")) {
+ highlightAction("actionNexus", true)
+ } else {
+ console.error("browser action broken")
+ waitForClick()
+ }
},
function() {
|
