summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/categories.cpp7
-rw-r--r--src/categories.h4
-rw-r--r--src/downloadmanager.cpp1
-rw-r--r--src/installationmanager.cpp6
-rw-r--r--src/main.cpp95
-rw-r--r--src/mainwindow.cpp87
-rw-r--r--src/mainwindow.h4
-rw-r--r--src/modinfo.cpp30
-rw-r--r--src/modinfo.h49
-rw-r--r--src/modinfodialog.cpp11
-rw-r--r--src/modlist.cpp34
-rw-r--r--src/modlistsortproxy.cpp2
-rw-r--r--src/modlistview.cpp4
-rw-r--r--src/nexusinterface.cpp10
-rw-r--r--src/nexusinterface.h1
-rw-r--r--src/nxmaccessmanager.cpp8
-rw-r--r--src/nxmaccessmanager.h2
-rw-r--r--src/organizer.pro7
-rw-r--r--src/pluginlist.cpp4
-rw-r--r--src/pluginlist.h2
-rw-r--r--src/profile.cpp3
-rw-r--r--src/selfupdater.cpp2
-rw-r--r--src/shared/gameinfo.cpp7
-rw-r--r--src/shared/gameinfo.h4
-rw-r--r--src/shared/leaktrace.cpp1
-rw-r--r--src/shared/shared.pro10
-rw-r--r--src/spawn.cpp4
-rw-r--r--src/spawn.h4
-rw-r--r--src/splash.pngbin103422 -> 260807 bytes
29 files changed, 295 insertions, 108 deletions
diff --git a/src/categories.cpp b/src/categories.cpp
index 62ba3ca5..c084c238 100644
--- a/src/categories.cpp
+++ b/src/categories.cpp
@@ -43,6 +43,7 @@ QString CategoryFactory::categoriesFilePath()
CategoryFactory::CategoryFactory()
{
+ atexit(&cleanup);
reset();
QFile categoryFile(categoriesFilePath());
@@ -124,6 +125,12 @@ void CategoryFactory::setParents()
}
}
+void CategoryFactory::cleanup()
+{
+ delete s_Instance;
+ s_Instance = NULL;
+}
+
void CategoryFactory::saveCategories()
{
diff --git a/src/categories.h b/src/categories.h
index 75698149..31fccd6d 100644
--- a/src/categories.h
+++ b/src/categories.h
@@ -180,6 +180,8 @@ private:
void setParents();
+ static void cleanup();
+
private:
static CategoryFactory *s_Instance;
@@ -188,6 +190,8 @@ private:
std::map<int, unsigned int> m_IDMap;
std::map<int, unsigned int> m_NexusMap;
+private:
+
};
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index bbb34ccc..b965d598 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -162,6 +162,7 @@ DownloadManager::~DownloadManager()
for (QVector<DownloadInfo*>::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter) {
delete *iter;
}
+ m_ActiveDownloads.clear();
}
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index 378eb38a..87efecf1 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -46,6 +46,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QDateTime>
#include <QDirIterator>
#include <boost/assign.hpp>
+#include <boost/scoped_ptr.hpp>
using namespace MOBase;
@@ -678,8 +679,7 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
this->m_CurrentArchive->close();
});
- DirectoryTree *filesTree = archiveOpen ? createFilesTree() : NULL;
-
+ QScopedPointer<DirectoryTree> filesTree(archiveOpen ? createFilesTree() : NULL);
IPluginInstaller::EInstallResult installResult = IPluginInstaller::RESULT_NOTATTEMPTED;
std::sort(m_Installers.begin(), m_Installers.end(), [] (IPluginInstaller *LHS, IPluginInstaller *RHS) {
@@ -704,7 +704,7 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
(filesTree != NULL) && (installer->isArchiveSupported(*filesTree))) {
installResult = installerSimple->install(modName, *filesTree, version, modID);
if (installResult == IPluginInstaller::RESULT_SUCCESS) {
- mapToArchive(filesTree);
+ mapToArchive(filesTree.data());
// the simple installer only prepares the installation, the rest works the same for all installers
if (!doInstall(modName, modID, version, newestVersion, categoryID)) {
installResult = IPluginInstaller::RESULT_FAILED;
diff --git a/src/main.cpp b/src/main.cpp
index 5a694121..c4431ac4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,6 +18,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef LEAK_CHECK_WITH_VLD
+#include <wchar.h>
+#include <vld.h>
+#endif // LEAK_CHECK_WITH_VLD
+
#include <QApplication>
#include <QPushButton>
#include <QListWidget>
@@ -430,61 +435,65 @@ int main(int argc, char *argv[])
application.setStyleFile(settings.value("Settings/style", "").toString());
- // set up main window and its data structures
- MainWindow mainWindow(argv[0], settings);
- QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString)));
- QObject::connect(&instance, SIGNAL(messageSent(QString)), &mainWindow, SLOT(externalMessage(QString)));
+ int res = 1;
+ { // scope to control lifetime of mainwindow
+ // set up main window and its data structures
+ MainWindow mainWindow(argv[0], settings);
+ QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString)));
+ QObject::connect(&instance, SIGNAL(messageSent(QString)), &mainWindow, SLOT(externalMessage(QString)));
- mainWindow.setExecutablesList(executablesList);
- mainWindow.readSettings();
+ mainWindow.setExecutablesList(executablesList);
+ mainWindow.readSettings();
- QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray());
+ QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray());
- { // see if there is a profile on the command line
- int profileIndex = arguments.indexOf("-p", 1);
- if ((profileIndex != -1) && (profileIndex < arguments.size() - 1)) {
- qDebug("profile overwritten on command line");
- selectedProfileName = arguments.at(profileIndex + 1);
+ { // see if there is a profile on the command line
+ int profileIndex = arguments.indexOf("-p", 1);
+ if ((profileIndex != -1) && (profileIndex < arguments.size() - 1)) {
+ qDebug("profile overwritten on command line");
+ selectedProfileName = arguments.at(profileIndex + 1);
+ }
+ arguments.removeAt(profileIndex);
+ arguments.removeAt(profileIndex);
}
- arguments.removeAt(profileIndex);
- arguments.removeAt(profileIndex);
- }
- qDebug("configured profile: %s", qPrintable(selectedProfileName));
+ qDebug("configured profile: %s", qPrintable(selectedProfileName));
- // if we have a command line parameter, it is either a nxm link or
- // a binary to start
- if ((arguments.size() > 1) && (!isNxmLink(arguments.at(1)))) {
- QString exeName = arguments.at(1);
- qDebug("starting %s from command line", qPrintable(exeName));
- arguments.removeFirst(); // remove application name (ModOrganizer.exe)
- arguments.removeFirst(); // remove binary name
- // pass the remaining parameters to the binary
- mainWindow.spawnProgram(exeName, arguments.join(" "), selectedProfileName, QDir());
- return 0;
- }
+ // if we have a command line parameter, it is either a nxm link or
+ // a binary to start
+ if ((arguments.size() > 1) && (!isNxmLink(arguments.at(1)))) {
+ QString exeName = arguments.at(1);
+ qDebug("starting %s from command line", qPrintable(exeName));
+ arguments.removeFirst(); // remove application name (ModOrganizer.exe)
+ arguments.removeFirst(); // remove binary name
+ // pass the remaining parameters to the binary
+ mainWindow.spawnProgram(exeName, arguments.join(" "), selectedProfileName, QDir());
+ return 0;
+ }
- mainWindow.createFirstProfile();
+ mainWindow.createFirstProfile();
- if (selectedProfileName.length() != 0) {
- if (!mainWindow.setCurrentProfile(selectedProfileName)) {
+ if (selectedProfileName.length() != 0) {
+ if (!mainWindow.setCurrentProfile(selectedProfileName)) {
+ mainWindow.setCurrentProfile(1);
+ qWarning("failed to set profile: %s",
+ selectedProfileName.toUtf8().constData());
+ }
+ } else {
mainWindow.setCurrentProfile(1);
- qWarning("failed to set profile: %s",
- selectedProfileName.toUtf8().constData());
}
- } else {
- mainWindow.setCurrentProfile(1);
- }
- qDebug("displaying main window");
- mainWindow.show();
+ qDebug("displaying main window");
+ mainWindow.show();
- if ((arguments.size() > 1) &&
- (isNxmLink(arguments.at(1)))) {
- qDebug("starting download from command line: %s", qPrintable(arguments.at(1)));
- mainWindow.externalMessage(arguments.at(1));
+ if ((arguments.size() > 1) &&
+ (isNxmLink(arguments.at(1)))) {
+ qDebug("starting download from command line: %s", qPrintable(arguments.at(1)));
+ mainWindow.externalMessage(arguments.at(1));
+ }
+ splash.finish(&mainWindow);
+ res = application.exec();
}
- splash.finish(&mainWindow);
- return application.exec();
+ return res;
} catch (const std::exception &e) {
reportError(e.what());
return 1;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 24772db1..1ea35d74 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -139,8 +139,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
: QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"),
m_ExeName(exeName), m_OldProfileIndex(-1),
m_DirectoryStructure(new DirectoryEntry(L"data", NULL, 0)),
- m_ModList(NexusInterface::instance()), m_ModListGroupingProxy(NULL), m_ModListSortProxy(NULL),
- m_OldExecutableIndex(-1), m_GamePath(ToQString(GameInfo::instance().getGameDirectory())),
+ m_ModList(this), m_ModListGroupingProxy(NULL), m_ModListSortProxy(NULL),
+ m_PluginList(this), m_OldExecutableIndex(-1), m_GamePath(ToQString(GameInfo::instance().getGameDirectory())),
m_DownloadManager(NexusInterface::instance(), this),
m_InstallationManager(this), m_Translator(NULL), m_TranslatorQt(NULL),
m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
@@ -149,7 +149,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
m_GameInfo(new GameInfoImpl())
{
ui->setupUi(this);
- this->setWindowTitle(ToQString(GameInfo::instance().getGameName()).append(" Mod Organizer v").append(m_Updater.getVersion().canonicalString()));
+ this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_Updater.getVersion().displayString());
m_RefreshProgress = new QProgressBar(statusBar());
m_RefreshProgress->setTextVisible(true);
@@ -255,7 +255,7 @@ 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(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)));
@@ -412,7 +412,7 @@ void MainWindow::actionToToolButton(QAction *&sourceAction)
button->setToolButtonStyle(ui->toolBar->toolButtonStyle());
button->setToolTip(sourceAction->toolTip());
button->setShortcut(sourceAction->shortcut());
- QMenu *buttonMenu = new QMenu(sourceAction->text());
+ QMenu *buttonMenu = new QMenu(sourceAction->text(), button);
button->setMenu(buttonMenu);
QAction *newAction = ui->toolBar->insertWidget(sourceAction, button);
newAction->setObjectName(sourceAction->objectName());
@@ -1499,6 +1499,8 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director
updateTo(directoryChild, temp.str(), **current, conflictsOnly);
if (directoryChild->childCount() != 0) {
subTree->addChild(directoryChild);
+ } else {
+ delete directoryChild;
}
}
}
@@ -3069,7 +3071,6 @@ void MainWindow::openExplorer_clicked()
::ShellExecuteW(NULL, L"explore", ToWString(modInfo->absolutePath()).c_str(), NULL, NULL, SW_SHOWNORMAL);
}
-
void MainWindow::information_clicked()
{
try {
@@ -3079,7 +3080,6 @@ void MainWindow::information_clicked()
}
}
-
void MainWindow::syncOverwrite()
{
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
@@ -3091,7 +3091,6 @@ void MainWindow::syncOverwrite()
}
}
-
void MainWindow::createModFromOverwrite()
{
GuessedValue<QString> name;
@@ -3125,14 +3124,12 @@ void MainWindow::createModFromOverwrite()
refreshModList();
}
-
void MainWindow::cancelModListEditor()
{
ui->modList->setEnabled(false);
ui->modList->setEnabled(true);
}
-
void MainWindow::on_modList_doubleClicked(const QModelIndex &index)
{
if (!index.isValid()) {
@@ -3155,7 +3152,6 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index)
}
}
-
bool MainWindow::addCategories(QMenu *menu, int targetID)
{
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
@@ -3210,7 +3206,6 @@ void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow)
}
}
-
void MainWindow::saveCategories()
{
QMenu *menu = qobject_cast<QMenu*>(sender());
@@ -3254,8 +3249,6 @@ void MainWindow::saveCategories()
refreshFilters();
}
-
-
void MainWindow::savePrimaryCategory()
{
QMenu *menu = qobject_cast<QMenu*>(sender());
@@ -3280,7 +3273,6 @@ void MainWindow::savePrimaryCategory()
}
}
-
void MainWindow::checkModsForUpdates()
{
statusBar()->show();
@@ -3298,6 +3290,45 @@ void MainWindow::checkModsForUpdates()
}
}
+void MainWindow::changeVersioningScheme() {
+ if (QMessageBox::question(this, tr("Continue?"),
+ tr("This will try to change the versioning scheme so that the newest version is interpreted as an update to "
+ "the installed version."),
+ QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Yes) {
+
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+
+ bool success = false;
+
+ static VersionInfo::VersionScheme schemes[] = { VersionInfo::SCHEME_REGULAR, VersionInfo::SCHEME_DECIMALMARK, VersionInfo::SCHEME_NUMBERSANDLETTERS };
+
+ for (int i = 0; i < sizeof(schemes) / sizeof(VersionInfo::VersionScheme) && !success; ++i) {
+ VersionInfo verOld(info->getVersion().canonicalString(), schemes[i]);
+ VersionInfo verNew(info->getNewestVersion().canonicalString(), schemes[i]);
+ if (verOld < verNew) {
+ info->setVersion(verOld);
+ info->setNewestVersion(verNew);
+ success = true;
+ }
+ }
+ if (!success) {
+ QMessageBox::information(this, tr("Sorry"),
+ tr("I don't know a versioning scheme where %1 is newer than %2.").arg(info->getNewestVersion().canonicalString()).arg(info->getVersion().canonicalString()),
+ QMessageBox::Ok);
+ }
+ }
+}
+
+void MainWindow::ignoreUpdate() {
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+ info->ignoreUpdate(true);
+}
+
+void MainWindow::unignoreUpdate()
+{
+ ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
+ info->ignoreUpdate(false);
+}
void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info)
{
@@ -3319,7 +3350,6 @@ void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInf
}
}
-
void MainWindow::addPrimaryCategoryCandidates()
{
QMenu *menu = qobject_cast<QMenu*>(sender());
@@ -3333,7 +3363,6 @@ void MainWindow::addPrimaryCategoryCandidates()
addPrimaryCategoryCandidates(menu, modInfo);
}
-
void MainWindow::enableVisibleMods()
{
if (QMessageBox::question(NULL, tr("Confirm"), tr("Really enable all visible mods?"),
@@ -3342,7 +3371,6 @@ void MainWindow::enableVisibleMods()
}
}
-
void MainWindow::disableVisibleMods()
{
if (QMessageBox::question(NULL, tr("Confirm"), tr("Really disable all visible mods?"),
@@ -3351,7 +3379,6 @@ void MainWindow::disableVisibleMods()
}
}
-
void MainWindow::exportModListCSV()
{
SelectionDialog selection(tr("Choose what to export"));
@@ -3406,7 +3433,6 @@ void MainWindow::exportModListCSV()
}
}
-
void addMenuAsPushButton(QMenu *menu, QMenu *subMenu)
{
QPushButton *pushBtn = new QPushButton(subMenu->title());
@@ -3416,13 +3442,13 @@ void addMenuAsPushButton(QMenu *menu, QMenu *subMenu)
menu->addAction(action);
}
-
void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
{
try {
QTreeView *modList = findChild<QTreeView*>("modList");
- m_ContextRow = mapToModel(&m_ModList, modList->indexAt(pos)).row();
+ QModelIndex index = mapToModel(&m_ModList, modList->indexAt(pos));
+ m_ContextRow = index.row();
QMenu menu;
@@ -3461,6 +3487,17 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
connect(primaryCategoryMenu, SIGNAL(aboutToHide()), this, SLOT(savePrimaryCategory()));
addMenuAsPushButton(&menu, primaryCategoryMenu);
+ menu.addSeparator();
+ if (info->downgradeAvailable()) {
+ menu.addAction(tr("Change versioning scheme"), this, SLOT(changeVersioningScheme()));
+ }
+ if (info->updateIgnored()) {
+ menu.addAction(tr("Un-ignore update"), this, SLOT(unignoreUpdate()));
+ } else {
+ menu.addAction(tr("Ignore update"), this, SLOT(ignoreUpdate()));
+ }
+ menu.addSeparator();
+
menu.addAction(tr("Rename Mod..."), this, SLOT(renameMod_clicked()));
menu.addAction(tr("Remove Mod..."), this, SLOT(removeMod_clicked()));
menu.addAction(tr("Reinstall Mod"), this, SLOT(reinstallMod_clicked()));
@@ -4207,9 +4244,9 @@ void MainWindow::on_actionEndorseMO_triggered()
void MainWindow::updateDownloadListDelegate()
{
if (ui->compactBox->isChecked()) {
- ui->downloadView->setItemDelegate(new DownloadListWidgetCompactDelegate(&m_DownloadManager, ui->downloadView));
+ ui->downloadView->setItemDelegate(new DownloadListWidgetCompactDelegate(&m_DownloadManager, ui->downloadView, ui->downloadView));
} else {
- ui->downloadView->setItemDelegate(new DownloadListWidgetDelegate(&m_DownloadManager, ui->downloadView));
+ ui->downloadView->setItemDelegate(new DownloadListWidgetDelegate(&m_DownloadManager, ui->downloadView, ui->downloadView));
}
DownloadListSortProxy *sortProxy = new DownloadListSortProxy(&m_DownloadManager, ui->downloadView);
@@ -4267,7 +4304,7 @@ void MainWindow::nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant us
} else {
std::vector<ModInfo::Ptr> info = ModInfo::getByModID(result["id"].toInt());
for (auto iter = info.begin(); iter != info.end(); ++iter) {
- (*iter)->setNewestVersion(VersionInfo(result["version"].toString()));
+ (*iter)->setNewestVersion(result["version"].toString());
(*iter)->setNexusDescription(result["description"].toString());
if (NexusInterface::instance()->getAccessManager()->loggedIn() &&
result.contains("voted_by_user")) {
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 80dca172..dfec5f49 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -466,6 +466,10 @@ private slots:
void removeFromToolbar();
void overwriteClosed(int);
+ void changeVersioningScheme();
+ void ignoreUpdate();
+ void unignoreUpdate();
+
private slots: // ui slots
// actions
void on_actionAdd_Profile_triggered();
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index 7632a86e..1479f7b4 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -303,10 +303,11 @@ ModInfoRegular::ModInfoRegular(const QDir &path, DirectoryEntry **directoryStruc
QString metaFileName = path.absoluteFilePath("meta.ini");
QSettings metaFile(metaFileName, QSettings::IniFormat);
- m_Notes = metaFile.value("notes", "").toString();
- m_NexusID = metaFile.value("modid", -1).toInt();
+ m_Notes = metaFile.value("notes", "").toString();
+ m_NexusID = metaFile.value("modid", -1).toInt();
m_Version.parse(metaFile.value("version", "").toString());
- m_NewestVersion = metaFile.value("newestVersion", "").toString();
+ m_NewestVersion = metaFile.value("newestVersion", "").toString();
+ m_IgnoredVersion = metaFile.value("ignoredVersion", "").toString();
m_InstallationFile = metaFile.value("installationFile", "").toString();
m_NexusDescription = metaFile.value("nexusDescription", "").toString();
m_LastNexusQuery = QDateTime::fromString(metaFile.value("lastNexusQuery", "").toString(), Qt::ISODate);
@@ -377,6 +378,7 @@ void ModInfoRegular::saveMeta()
temp.erase(m_PrimaryCategory);
metaFile.setValue("category", QString("%1").arg(m_PrimaryCategory) + "," + SetJoin(temp, ","));
metaFile.setValue("newestVersion", m_NewestVersion.canonicalString());
+ metaFile.setValue("ignoredVersion", m_IgnoredVersion.canonicalString());
metaFile.setValue("version", m_Version.canonicalString());
metaFile.setValue("modid", m_NexusID);
metaFile.setValue("notes", m_Notes);
@@ -396,10 +398,22 @@ void ModInfoRegular::saveMeta()
bool ModInfoRegular::updateAvailable() const
{
+ if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) {
+ return false;
+ }
return m_NewestVersion.isValid() && (m_Version < m_NewestVersion);
}
+bool ModInfoRegular::downgradeAvailable() const
+{
+ if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) {
+ return false;
+ }
+ return m_NewestVersion.isValid() && (m_NewestVersion < m_Version);
+}
+
+
void ModInfoRegular::nxmDescriptionAvailable(int, QVariant, QVariant resultData)
{
QVariantMap result = resultData.toMap();
@@ -576,6 +590,16 @@ QString ModInfoRegular::absolutePath() const
return m_Path;
}
+void ModInfoRegular::ignoreUpdate(bool ignore)
+{
+ if (ignore) {
+ m_IgnoredVersion = m_NewestVersion;
+ } else {
+ m_IgnoredVersion.clear();
+ }
+ m_MetaInfoChanged = true;
+}
+
std::vector<ModInfo::EFlag> ModInfoRegular::getFlags() const
{
diff --git a/src/modinfo.h b/src/modinfo.h
index 7e217de7..3b83d207 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -193,6 +193,22 @@ public:
virtual bool updateAvailable() const = 0;
/**
+ * @return true if the update currently available is ignored
+ */
+ virtual bool updateIgnored() const = 0;
+
+ /**
+ * @brief test if the "newest" version of the mod is older than the installed version
+ *
+ * test if there is a newer version of the mod. This does NOT cause
+ * information to be retrieved from the nexus, it will only test version information already
+ * available locally. Use checkAllForUpdate() to update this version information
+ *
+ * @return true if the newest version is older than the installed one
+ **/
+ virtual bool downgradeAvailable() const = 0;
+
+ /**
* @brief request an update of nexus description for this mod.
*
* This requests mod information from the nexus. This is an asynchronous request,
@@ -310,6 +326,11 @@ public:
virtual MOBase::VersionInfo getNewestVersion() const = 0;
/**
+ * @brief ignore the newest version for updates
+ */
+ virtual void ignoreUpdate(bool ignore) = 0;
+
+ /**
* @brief getter for the nexus mod id
*
* @return the nexus mod id. may be 0 if the mod id isn't known or doesn't exist
@@ -495,6 +516,22 @@ public:
bool updateAvailable() const;
/**
+ * @return true if the current update is being ignored
+ */
+ virtual bool updateIgnored() const { return m_IgnoredVersion == m_NewestVersion; }
+
+ /**
+ * @brief test if there is a newer version of the mod
+ *
+ * test if there is a newer version of the mod. This does NOT cause
+ * information to be retrieved from the nexus, it will only test version information already
+ * available locally. Use checkAllForUpdate() to update this version information
+ *
+ * @return true if there is a newer version
+ **/
+ bool downgradeAvailable() const;
+
+ /**
* @brief request an update of nexus description for this mod.
*
* This requests mod information from the nexus. This is an asynchronous request,
@@ -621,6 +658,11 @@ public:
MOBase::VersionInfo getNewestVersion() const { return m_NewestVersion; }
/**
+ * @brief ignore the newest version for updates
+ */
+ void ignoreUpdate(bool ignore);
+
+ /**
* @brief getter for the installation file
*
* @return file used to install this mod from
@@ -746,6 +788,7 @@ private:
bool m_MetaInfoChanged;
MOBase::VersionInfo m_NewestVersion;
+ MOBase::VersionInfo m_IgnoredVersion;
EEndorsedState m_EndorsedState;
@@ -767,10 +810,13 @@ class ModInfoBackup : public ModInfoRegular
public:
virtual bool updateAvailable() const { return false; }
+ virtual bool updateIgnored() const { return false; }
+ virtual bool downgradeAvailable() const { return false; }
virtual bool updateNXMInfo() { return false; }
virtual void setNexusID(int) {}
virtual void endorse(bool) {}
virtual int getFixedPriority() const { return -1; }
+ virtual void ignoreUpdate(bool) {}
virtual bool canBeUpdated() const { return false; }
virtual bool canBeEnabled() const { return false; }
virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
@@ -798,12 +844,15 @@ class ModInfoOverwrite : public ModInfo
public:
virtual bool updateAvailable() const { return false; }
+ virtual bool updateIgnored() const { return false; }
+ virtual bool downgradeAvailable() const { return false; }
virtual bool updateNXMInfo() { return false; }
virtual void setCategory(int, bool) {}
virtual bool setName(const QString&) { return false; }
virtual void setNotes(const QString&) {}
virtual void setNexusID(int) {}
virtual void setNewestVersion(const MOBase::VersionInfo&) {}
+ virtual void ignoreUpdate(bool) {}
virtual void setNexusDescription(const QString&) {}
virtual void setIsEndorsed(bool) {}
virtual void setNeverEndorse() {}
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index 75e7e499..b4ae57ea 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -76,7 +76,6 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
m_UTF8Codec = QTextCodec::codecForName("utf-8");
QListWidget *textFileList = findChild<QListWidget*>("textFileList");
- QListWidget *iniFileList = findChild<QListWidget*>("iniFileList");
QListWidget *iniTweaksList = findChild<QListWidget*>("iniTweaksList");
QListWidget *activeESPList = findChild<QListWidget*>("activeESPList");
QListWidget *inactiveESPList = findChild<QListWidget*>("inactiveESPList");
@@ -707,7 +706,7 @@ QString ModInfoDialog::getFileCategory(int categoryID)
void ModInfoDialog::updateVersionColor()
{
// QPalette versionColor;
- if (m_ModInfo->getVersion() < m_ModInfo->getNewestVersion()) {
+ if (m_ModInfo->getVersion() != m_ModInfo->getNewestVersion()) {
ui->versionEdit->setStyleSheet("color: red");
// versionColor.setColor(QPalette::Text, Qt::red);
ui->versionEdit->setToolTip(tr("Current Version: %1").arg(m_ModInfo->getNewestVersion().canonicalString()));
@@ -758,13 +757,7 @@ void ModInfoDialog::modDetailsUpdated(bool success)
ui->descriptionView->setHtml(tr("(description incomplete, please visit nexus)"));
}
- QString version = m_ModInfo->getNewestVersion().canonicalString();
-
- if (!version.isEmpty()) {
- m_ModInfo->setNewestVersion(version);
-
- updateVersionColor();
- }
+ updateVersionColor();
}
}
diff --git a/src/modlist.cpp b/src/modlist.cpp
index b5a7182e..7367b2ae 100644
--- a/src/modlist.cpp
+++ b/src/modlist.cpp
@@ -143,13 +143,16 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
} else if (column == COL_NAME) {
return modInfo->name();
} else if (column == COL_VERSION) {
- QString version = modInfo->getVersion().canonicalString();
- if (version.isEmpty() && modInfo->canBeUpdated()) {
- version = "?";
- } else if (version[0] == 'd') {
- version.remove(0, 1);
+ VersionInfo verInfo = modInfo->getVersion();
+ if (role == Qt::EditRole) {
+ return verInfo.canonicalString();
+ } else {
+ QString version = verInfo.displayString();
+ if (version.isEmpty() && modInfo->canBeUpdated()) {
+ version = "?";
+ }
+ return version;
}
- return version;
} else if (column == COL_PRIORITY) {
int priority = modInfo->getFixedPriority();
if (priority != INT_MIN) {
@@ -241,17 +244,18 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
result.setItalic(true);
}
} else if (column == COL_VERSION) {
- if (modInfo->updateAvailable()) {
+ if (modInfo->updateAvailable() || modInfo->downgradeAvailable()) {
result.setWeight(QFont::Bold);
}
}
return result;
} else if (role == Qt::DecorationRole) {
if (column == COL_VERSION) {
- if (modInfo->updateAvailable() &&
- modInfo->getNewestVersion().isValid()) {
+ if (modInfo->updateAvailable()) {
return QIcon(":/MO/gui/update_available");
- } else if (modInfo->getVersion().isVersionDate()) {
+ } else if (modInfo->downgradeAvailable()) {
+ return QIcon(":/MO/gui/warning");
+ } else if (modInfo->getVersion().scheme() == VersionInfo::SCHEME_DATE) {
return QIcon(":/MO/gui/version_date");
}
}
@@ -264,7 +268,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
} else if (column == COL_VERSION) {
if (!modInfo->getNewestVersion().isValid()) {
return QVariant();
- } else if (modInfo->updateAvailable()) {
+ } else if (modInfo->updateAvailable() || modInfo->downgradeAvailable()) {
return QBrush(Qt::red);
} else {
return QBrush(Qt::darkGreen);
@@ -291,7 +295,13 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
return QString();
}
} else if (column == COL_VERSION) {
- return tr("installed version: %1, newest version: %2").arg(modInfo->getVersion().canonicalString()).arg(modInfo->getNewestVersion().canonicalString());
+ QString text = tr("installed version: %1, newest version: %2").arg(modInfo->getVersion().displayString()).arg(modInfo->getNewestVersion().displayString());
+ if (modInfo->downgradeAvailable()) {
+ text += "<br>" + tr("The newest version on Nexus seems to be older than the one you have installed. This could either mean the version you have has been withdrawn "
+ "(i.e. due to a bug) or the author uses a non-standard versioning scheme and that newest version is actually newer. "
+ "Either way you may want to \"upgrade\".");
+ }
+ return text;
} else if (column == COL_CATEGORY) {
const std::set<int> &categories = modInfo->getCategories();
std::wostringstream categoryString;
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp
index 53c03c6a..c7c3ab28 100644
--- a/src/modlistsortproxy.cpp
+++ b/src/modlistsortproxy.cpp
@@ -211,7 +211,7 @@ bool ModListSortProxy::filterMatches(ModInfo::Ptr info, bool enabled) const
if (enabled) return false;
} break;
case CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE: {
- if (!info->updateAvailable()) return false;
+ if (!info->updateAvailable() && !info->downgradeAvailable()) return false;
} break;
case CategoryFactory::CATEGORY_SPECIAL_NOCATEGORY: {
if (info->getCategories().size() > 0) return false;
diff --git a/src/modlistview.cpp b/src/modlistview.cpp
index 44228d5b..1a4f6266 100644
--- a/src/modlistview.cpp
+++ b/src/modlistview.cpp
@@ -4,7 +4,7 @@
#include <QProxyStyle>
-class ModListViewStyle: public QProxyStyle{
+class ModListViewStyle: public QProxyStyle {
public:
ModListViewStyle(QStyle *style, int indentation);
@@ -37,7 +37,7 @@ void ModListViewStyle::drawPrimitive(PrimitiveElement element, const QStyleOptio
ModListView::ModListView(QWidget *parent)
: QTreeView(parent)
{
- setStyle(new ModListViewStyle(style(), indentation()));
+// setStyle(new ModListViewStyle(style(), indentation()));
}
void ModListView::dragEnterEvent(QDragEnterEvent *event)
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp
index cd78ca4c..bee0bb44 100644
--- a/src/nexusinterface.cpp
+++ b/src/nexusinterface.cpp
@@ -68,6 +68,7 @@ void NexusBridge::nxmDescriptionAvailable(int modID, QVariant userData, QVariant
std::set<int>::iterator iter = m_RequestIDs.find(requestID);
if (iter != m_RequestIDs.end()) {
m_RequestIDs.erase(iter);
+
emit descriptionAvailable(modID, userData, resultData);
}
}
@@ -142,6 +143,7 @@ QAtomicInt NexusInterface::NXMRequestInfo::s_NextID(0);
NexusInterface::NexusInterface()
: m_NMMVersion()
{
+ atexit(&cleanup);
m_AccessManager = new NXMAccessManager(this);
m_DiskCache = new QNetworkDiskCache(this);
@@ -149,6 +151,13 @@ NexusInterface::NexusInterface()
}
+void NexusInterface::cleanup()
+{
+ delete NexusInterface::s_Instance;
+ NexusInterface::s_Instance = NULL;
+}
+
+
NXMAccessManager *NexusInterface::getAccessManager()
{
return m_AccessManager;
@@ -405,6 +414,7 @@ void NexusInterface::downloadRequestedNXM(const QString &url)
emit requestNXMDownload(url);
}
+#include <QDebug>
void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter)
{
diff --git a/src/nexusinterface.h b/src/nexusinterface.h
index 0c304a71..0b53f9d0 100644
--- a/src/nexusinterface.h
+++ b/src/nexusinterface.h
@@ -294,6 +294,7 @@ private:
NexusInterface();
void nextRequest();
void requestFinished(std::list<NXMRequestInfo>::iterator iter);
+ static void cleanup();
private:
diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp
index d83ffa61..a05b8a6c 100644
--- a/src/nxmaccessmanager.cpp
+++ b/src/nxmaccessmanager.cpp
@@ -44,6 +44,14 @@ NXMAccessManager::NXMAccessManager(QObject *parent)
{
}
+NXMAccessManager::~NXMAccessManager()
+{
+ if (m_LoginReply != NULL) {
+ m_LoginReply->deleteLater();
+ m_LoginReply = NULL;
+ }
+}
+
QNetworkReply *NXMAccessManager::createRequest(
QNetworkAccessManager::Operation operation, const QNetworkRequest &request,
diff --git a/src/nxmaccessmanager.h b/src/nxmaccessmanager.h
index b0c43978..1d8d36ab 100644
--- a/src/nxmaccessmanager.h
+++ b/src/nxmaccessmanager.h
@@ -37,6 +37,8 @@ public:
explicit NXMAccessManager(QObject *parent);
+ ~NXMAccessManager();
+
bool loggedIn() const;
void login(const QString &username, const QString &password);
diff --git a/src/organizer.pro b/src/organizer.pro
index e89b6e99..a9353361 100644
--- a/src/organizer.pro
+++ b/src/organizer.pro
@@ -183,7 +183,6 @@ INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk "$(BOOSTPATH)"
LIBS += -L"$(BOOSTPATH)/stage/lib"
-
CONFIG(debug, debug|release) {
OUTDIR = $$OUT_PWD/debug
DSTDIR = $$PWD/../../outputd
@@ -294,6 +293,12 @@ OTHER_FILES += \
INCLUDEPATH += "$(ZLIBPATH)" "$(ZLIBPATH)/build" "$(BOOSTPATH)"
LIBS += -L"$(ZLIBPATH)/build" -lzlibstatic
+
+# leak detection with vld
+#INCLUDEPATH += "E:/Visual Leak Detector/include"
+#LIBS += -L"E:/Visual Leak Detector/lib/Win32"
+#DEFINES += LEAK_CHECK_WITH_VLD
+
#SOURCES += modeltest.cpp
#HEADERS += modeltest.h
#DEFINES += TEST_MODELS
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index 39cca6af..e730d3f4 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -90,6 +90,10 @@ PluginList::PluginList(QObject *parent)
}
+PluginList::~PluginList()
+{
+}
+
QString PluginList::getColumnName(int column)
{
diff --git a/src/pluginlist.h b/src/pluginlist.h
index 3442a9f7..60c9be95 100644
--- a/src/pluginlist.h
+++ b/src/pluginlist.h
@@ -53,6 +53,8 @@ public:
**/
PluginList(QObject *parent = NULL);
+ ~PluginList();
+
/**
* @brief does a complete refresh of the list
*
diff --git a/src/profile.cpp b/src/profile.cpp
index 07f7010e..3da12d7d 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -185,7 +185,7 @@ void Profile::writeModlistNow(bool onlyOnTimer) const
QString fileName = getModlistFileName();
if (QFile::exists(fileName)) {
- shellDelete(QStringList(fileName));
+ shellDelete(QStringList(fileName), false, QApplication::activeModalWidget());
}
if (!file.copy(fileName)) {
@@ -238,6 +238,7 @@ void Profile::createTweakedIniFile()
if (error) {
reportError(tr("failed to create tweaked ini: %1").arg(getCurrentErrorStringA().c_str()));
}
+ qDebug("%s saved", qPrintable(QDir::toNativeSeparators(tweakedIni)));
}
diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp
index 421fbeab..bdace814 100644
--- a/src/selfupdater.cpp
+++ b/src/selfupdater.cpp
@@ -126,7 +126,6 @@ void SelfUpdater::startUpdate()
void SelfUpdater::download(const QString &downloadLink, const QString &fileName)
{
- qDebug("download: %s", downloadLink.toUtf8().constData());
QNetworkAccessManager *accessManager = m_Interface->getAccessManager();
QUrl dlUrl(downloadLink);
QNetworkRequest request(dlUrl);
@@ -324,7 +323,6 @@ void SelfUpdater::nxmDescriptionAvailable(int, QVariant, QVariant resultData, in
if (m_NewestVersion.isEmpty()) {
QTimer::singleShot(5000, this, SLOT(testForUpdate()));
}
-
VersionInfo currentVersion(m_MOVersion);
VersionInfo newestVersion(m_NewestVersion);
diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp
index 6b53450d..f74e52b4 100644
--- a/src/shared/gameinfo.cpp
+++ b/src/shared/gameinfo.cpp
@@ -40,6 +40,13 @@ GameInfo* GameInfo::s_Instance = NULL;
GameInfo::GameInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory)
: m_GameDirectory(gameDirectory), m_OrganizerDirectory(omoDirectory)
{
+ atexit(&cleanup);
+}
+
+
+void GameInfo::cleanup() {
+ delete GameInfo::s_Instance;
+ GameInfo::s_Instance = NULL;
}
diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h
index 3e022ef4..14f52f05 100644
--- a/src/shared/gameinfo.h
+++ b/src/shared/gameinfo.h
@@ -176,9 +176,11 @@ private:
static bool identifyGame(const std::wstring &omoDirectory, const std::wstring &searchPath);
std::wstring getSpecialPath(LPCWSTR name) const;
+ static void cleanup();
+
private:
- static GameInfo* s_Instance;
+ static GameInfo *s_Instance;
std::wstring m_MyGamesDirectory;
diff --git a/src/shared/leaktrace.cpp b/src/shared/leaktrace.cpp
index 83ed4fd0..c3721557 100644
--- a/src/shared/leaktrace.cpp
+++ b/src/shared/leaktrace.cpp
@@ -114,6 +114,7 @@ static struct __TraceData {
}
std::map<unsigned long, StackData> m_Traces;
+
} __trace;
diff --git a/src/shared/shared.pro b/src/shared/shared.pro
index ab0bd8a0..992fd7f2 100644
--- a/src/shared/shared.pro
+++ b/src/shared/shared.pro
@@ -13,9 +13,17 @@ 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 += -L$$OUT_PWD/../bsatk/debug
LIBS += -lDbgHelp
+ QMAKE_CXXFLAGS_DEBUG -= -Zi
+ QMAKE_CXXFLAGS += -Z7
} else {
LIBS += -L$$OUT_PWD/../bsatk/release
}
diff --git a/src/spawn.cpp b/src/spawn.cpp
index ab43b687..5639a78c 100644
--- a/src/spawn.cpp
+++ b/src/spawn.cpp
@@ -156,7 +156,7 @@ HANDLE startBinary(const QFileInfo &binary, const QString &arguments, const QStr
return processHandle;
}
-
+/*
ExitProxy *ExitProxy::s_Instance = NULL;
ExitProxy *ExitProxy::instance()
@@ -170,4 +170,4 @@ ExitProxy *ExitProxy::instance()
void ExitProxy::emitExit()
{
emit exit();
-}
+}*/
diff --git a/src/spawn.h b/src/spawn.h
index e0d1f958..48320fea 100644
--- a/src/spawn.h
+++ b/src/spawn.h
@@ -31,7 +31,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
* @brief a dirty little trick so we can issue a clean restart from startBinary
* @note unused
*/
-class ExitProxy : public QObject {
+/*class ExitProxy : public QObject {
Q_OBJECT
public:
static ExitProxy *instance();
@@ -42,7 +42,7 @@ private:
ExitProxy() {}
private:
static ExitProxy *s_Instance;
-};
+};*/
/**
diff --git a/src/splash.png b/src/splash.png
index 45ace8f8..0137bf72 100644
--- a/src/splash.png
+++ b/src/splash.png
Binary files differ