From 47293827bbd92ce227e5188c10b66deb9f85d5bf Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 28 Sep 2013 21:13:57 +0200 Subject: - download progress is now visible in task bar - esp-tooltip now lists all masters, highlighting the missing ones - python plugin will now report a problem if the path contains a semicolon - leak detection now (somewaht) works around the fact that we don't always get a stack trace - bugfix: mod meta-file is now reliably created if it was missing - bugfix: parser for nxm-links didn't handle numbers in the mod name - bugfix: small memory leak --- src/downloadmanager.cpp | 4 ++++ src/downloadmanager.h | 2 ++ src/mainwindow.cpp | 2 -- src/modinfo.cpp | 39 +++++++++++++++++---------------------- src/pluginlist.cpp | 7 ++++++- src/shared/directoryentry.cpp | 7 +++++-- src/shared/leaktrace.cpp | 37 ++++++++++++++++++++++++++++--------- src/shared/leaktrace.h | 4 ++-- src/version.rc | 4 ++-- 9 files changed, 66 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index c8f118f6..bbb34ccc 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -22,6 +22,7 @@ along with Mod Organizer. If not, see . #include "nxmurl.h" #include #include +#include #include "utility.h" #include "json.h" #include "selectiondialog.h" @@ -63,6 +64,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Ne info->m_CurrentUrl = 0; info->m_Tries = AUTOMATIC_RETRIES; info->m_State = STATE_STARTED; + info->m_TaskProgressId = TaskProgressManager::instance().getId(); return info; } @@ -105,6 +107,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con info->m_CurrentUrl = 0; info->m_Urls = metaFile.value("url", "").toString().split(";"); info->m_Tries = 0; + info->m_TaskProgressId = TaskProgressManager::instance().getId(); info->m_NexusInfo.m_Name = metaFile.value("name", 0).toString(); info->m_NexusInfo.m_ModName = metaFile.value("modName", "").toString(); info->m_NexusInfo.m_Version = metaFile.value("version", 0).toString(); @@ -805,6 +808,7 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) } int oldProgress = info->m_Progress; info->m_Progress = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal); + TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal); if (oldProgress != info->m_Progress) { emit update(index); } diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 92ba3143..0d49aa35 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -98,6 +98,8 @@ private: int m_Tries; bool m_ReQueried; + quint32 m_TaskProgressId; + NexusInfo m_NexusInfo; static DownloadInfo *createNew(const NexusInfo &nexusInfo, int modID, int fileID, const QStringList &URLs); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 601ec5c5..b722b388 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -149,7 +149,6 @@ 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())); m_RefreshProgress = new QProgressBar(statusBar()); @@ -3194,7 +3193,6 @@ bool MainWindow::addCategories(QMenu *menu, int targetID) return childEnabled; } - void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow) { ModInfo::Ptr modInfo = ModInfo::getByIndex(modRow); diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 166c815b..7632a86e 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -350,8 +350,6 @@ ModInfoRegular::ModInfoRegular(const QDir &path, DirectoryEntry **directoryStruc ModInfoRegular::~ModInfoRegular() { try { - //TODO this may cause the meta-file and the directory to be - // re-created after a remove saveMeta(); } catch (const std::exception &e) { qCritical("failed to save meta information for \"%s\": %s", @@ -371,28 +369,25 @@ bool ModInfoRegular::isEmpty() const void ModInfoRegular::saveMeta() { - if (m_MetaInfoChanged) { - if (QFile::exists(absolutePath().append("/meta.ini"))) { - QSettings metaFile(absolutePath().append("/meta.ini"), QSettings::IniFormat); - if (metaFile.status() == QSettings::NoError) { - std::set temp = m_Categories; - temp.erase(m_PrimaryCategory); - metaFile.setValue("category", QString("%1").arg(m_PrimaryCategory) + "," + SetJoin(temp, ",")); - metaFile.setValue("newestVersion", m_NewestVersion.canonicalString()); - metaFile.setValue("version", m_Version.canonicalString()); - metaFile.setValue("modid", m_NexusID); - metaFile.setValue("notes", m_Notes); - metaFile.setValue("nexusDescription", m_NexusDescription); - metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate)); - if (m_EndorsedState != ENDORSED_UNKNOWN) { - metaFile.setValue("endorsed", m_EndorsedState); - } - - } else { - reportError(tr("failed to write %1/meta.ini: %2").arg(absolutePath()).arg(metaFile.status())); + // only write meta data if the mod directory exists + if (m_MetaInfoChanged && QFile::exists(absolutePath())) { + QSettings metaFile(absolutePath().append("/meta.ini"), QSettings::IniFormat); + if (metaFile.status() == QSettings::NoError) { + std::set temp = m_Categories; + temp.erase(m_PrimaryCategory); + metaFile.setValue("category", QString("%1").arg(m_PrimaryCategory) + "," + SetJoin(temp, ",")); + metaFile.setValue("newestVersion", m_NewestVersion.canonicalString()); + metaFile.setValue("version", m_Version.canonicalString()); + metaFile.setValue("modid", m_NexusID); + metaFile.setValue("notes", m_Notes); + metaFile.setValue("nexusDescription", m_NexusDescription); + metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate)); + if (m_EndorsedState != ENDORSED_UNKNOWN) { + metaFile.setValue("endorsed", m_EndorsedState); } + metaFile.sync(); // sync needs to be called to ensure the file is created } else { - qWarning("mod %s has no meta.ini at %s/meta.ini", m_Name.toUtf8().constData(), absolutePath().toUtf8().constData()); + reportError(tr("failed to write %1/meta.ini: %2").arg(absolutePath()).arg(metaFile.status())); } m_MetaInfoChanged = false; } diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 0ed0d7f9..39cca6af 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -675,8 +675,13 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const } else { QString text = tr("Origin: %1").arg(m_ESPs[index].m_OriginName); if (m_ESPs[index].m_MasterUnset.size() > 0) { - text += "\n" + tr("Missing Masters") + ": " + SetJoin(m_ESPs[index].m_MasterUnset, ", "); + text += "
" + tr("Missing Masters") + ": " + SetJoin(m_ESPs[index].m_MasterUnset, ", ") + ""; } + std::set enabledMasters; + std::set_difference(m_ESPs[index].m_Masters.begin(), m_ESPs[index].m_Masters.end(), + m_ESPs[index].m_MasterUnset.begin(), m_ESPs[index].m_MasterUnset.end(), + std::inserter(enabledMasters, enabledMasters.end())); + text += "
" + tr("Enabled Masters") + ": " + SetJoin(enabledMasters, ", "); return text; } } else { diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index bd33fef6..8380181f 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -568,8 +568,9 @@ void DirectoryEntry::removeDirRecursive() for (auto iter = m_SubDirectories.begin(); iter != m_SubDirectories.end(); ++iter) { (*iter)->removeDirRecursive(); + delete *iter; } - m_SubDirectories.clear(); + m_SubDirectories.clear(); } void DirectoryEntry::removeDir(const std::wstring &path) @@ -578,8 +579,10 @@ void DirectoryEntry::removeDir(const std::wstring &path) if (pos == std::string::npos) { for (auto iter = m_SubDirectories.begin(); iter != m_SubDirectories.end(); ++iter) { if (_wcsicmp((*iter)->getName().c_str(), path.c_str()) == 0) { - (*iter)->removeDirRecursive(); + DirectoryEntry *entry = *iter; + entry->removeDirRecursive(); m_SubDirectories.erase(iter); + delete entry; break; } } diff --git a/src/shared/leaktrace.cpp b/src/shared/leaktrace.cpp index 0c618b68..83ed4fd0 100644 --- a/src/shared/leaktrace.cpp +++ b/src/shared/leaktrace.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -32,8 +33,18 @@ class StackData { friend bool operator==(const StackData &LHS, const StackData &RHS); friend bool operator<(const StackData &LHS, const StackData &RHS); public: - StackData() { + + StackData() + : m_FunctionName("Dummy"), m_CodeLine(0) + {} + StackData(const char *functionName, int line) { m_Count = ::CaptureStackBackTrace(FRAMES_TO_SKIP, FRAMES_TO_CAPTURE, m_Stack, &m_Hash); + m_FunctionName = functionName; + m_CodeLine = line; + if (m_Count == 0) { + // TODO in this case the hash doesn't seem to be set. This is of course not a good solution + m_Hash = reinterpret_cast(m_FunctionName) + m_CodeLine; + } } std::string toString() const { initDbgIfNecessary(); @@ -45,6 +56,8 @@ public: std::ostringstream stackStream; + stackStream << m_FunctionName << " [" << m_CodeLine << "]\n"; + for(unsigned int i = 0; i < m_Count; ++i) { DWORD64 displacement = 0; if (!::SymFromAddr(::GetCurrentProcess(), (DWORD64)m_Stack[i], &displacement, symbol)) { @@ -59,6 +72,8 @@ private: LPVOID m_Stack[FRAMES_TO_CAPTURE]; USHORT m_Count; ULONG m_Hash; + const char *m_FunctionName; + int m_CodeLine; }; bool operator==(const StackData &LHS, const StackData &RHS) { @@ -70,10 +85,9 @@ bool operator<(const StackData &LHS, const StackData &RHS) { } - static struct __TraceData { - void regTrace(void *pointer) { - m_Traces[reinterpret_cast(pointer)] = StackData(); + void regTrace(void *pointer, const char *functionName, int line) { + m_Traces[reinterpret_cast(pointer)] = StackData(functionName, line); } void deregTrace(void *pointer) { auto iter = m_Traces.find(reinterpret_cast(pointer)); @@ -83,14 +97,19 @@ static struct __TraceData { } ~__TraceData() { - std::map result; + std::map > result; for (auto iter = m_Traces.begin(); iter != m_Traces.end(); ++iter) { - result[iter->second] += 1; + result[iter->second].push_back(iter->first); } for (auto iter = result.begin(); iter != result.end(); ++iter) { printf("-----------------------------------\n" "%d objects not freed, allocated at:\n%s", - iter->second, iter->first.toString().c_str()); + 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("\n"); } } @@ -98,9 +117,9 @@ static struct __TraceData { } __trace; -void LeakTrace::TraceAlloc(void *ptr) +void LeakTrace::TraceAlloc(void *ptr, const char *functionName, int line) { - __trace.regTrace(ptr); + __trace.regTrace(ptr, functionName, line); } void LeakTrace::TraceDealloc(void *ptr) diff --git a/src/shared/leaktrace.h b/src/shared/leaktrace.h index 78764260..4985925e 100644 --- a/src/shared/leaktrace.h +++ b/src/shared/leaktrace.h @@ -4,14 +4,14 @@ namespace LeakTrace { -void TraceAlloc(void *ptr); +void TraceAlloc(void *ptr, const char *functionName, int line); void TraceDealloc(void *ptr); }; #ifdef TRACE_LEAKS -#define LEAK_TRACE LeakTrace::TraceAlloc(this) +#define LEAK_TRACE LeakTrace::TraceAlloc(this, __FUNCTION__, __LINE__) #define LEAK_UNTRACE LeakTrace::TraceDealloc(this) #else // TRACE_LEAKS diff --git a/src/version.rc b/src/version.rc index 16e006cf..16669011 100644 --- a/src/version.rc +++ b/src/version.rc @@ -1,7 +1,7 @@ #include "Winver.h" -#define VER_FILEVERSION 1,0,2,0 -#define VER_FILEVERSION_STR "1,0,2,0\0" +#define VER_FILEVERSION 1,0,4,0 +#define VER_FILEVERSION_STR "1,0,4,0\0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION -- cgit v1.3.1