From f6ef5477e718b14af99bd22436f66dee0b9d22cd Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 17 Jul 2014 22:02:15 +0200 Subject: normalized eol style (all files should now have windows line endings) --- src/bbcode.cpp | 468 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 234 insertions(+), 234 deletions(-) (limited to 'src/bbcode.cpp') diff --git a/src/bbcode.cpp b/src/bbcode.cpp index f87b5d85..18f2beb1 100644 --- a/src/bbcode.cpp +++ b/src/bbcode.cpp @@ -1,234 +1,234 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see . -*/ - -#include "bbcode.h" - -#include -#include -#include -#include - - -namespace BBCode { - - -class BBCodeMap { - - typedef std::map > TagMap; - -public: - - static BBCodeMap &instance() { - static BBCodeMap s_Instance; - return s_Instance; - } - - QString convertTag(const QString &input, int &length) - { - // extract the tag name - m_TagNameExp.indexIn(input, 1, QRegExp::CaretAtOffset); - QString tagName = m_TagNameExp.cap(0).toLower(); - TagMap::iterator tagIter = m_TagMap.find(tagName); - if (tagIter != m_TagMap.end()) { - // recognized tag - if (tagName.endsWith('=')) { - tagName.chop(1); - } - QString closeTag = tagName == "*" ? "
" - : QString("[/%1]").arg(tagName); - - int closeTagPos = input.indexOf(closeTag, 0, Qt::CaseInsensitive); - //qDebug("close tag %s at %d", closeTag.toUtf8().constData(), closeTagPos); - - if (closeTagPos > -1) { - length = closeTagPos + closeTag.length(); - QString temp = input.mid(0, length); - if (tagIter->second.first.indexIn(temp) == 0) { - if (tagIter->second.second.isEmpty()) { - 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; - } - return temp.replace(tagIter->second.first, QString("%2").arg(color, content)); - } else { - qWarning("don't know how to deal with tag %s", qPrintable(tagName)); - } - } else { - return temp.replace(tagIter->second.first, tagIter->second.second); - } - } else { - // expression doesn't match. either the input string is invalid - // or the expression is - qWarning("%s doesn't match the expression for %s", - temp.toUtf8().constData(), tagName.toUtf8().constData()); - length = 0; - return QString(); - } - } - } - - // not a recognized tag or tag invalid - length = 0; - return QString(); - } - -private: - BBCodeMap() - : m_TagNameExp("^[a-zA-Z*]*=?") - { - m_TagMap["b"] = std::make_pair(QRegExp("\\[b\\](.*)\\[/b\\]"), - "\\1"); - m_TagMap["i"] = std::make_pair(QRegExp("\\[i\\](.*)\\[/i\\]"), - "\\1"); - m_TagMap["u"] = std::make_pair(QRegExp("\\[u\\](.*)\\[/u\\]"), - "\\1"); - m_TagMap["s"] = std::make_pair(QRegExp("\\[s\\](.*)\\[/s\\]"), - "\\1"); - m_TagMap["sub"] = std::make_pair(QRegExp("\\[sub\\](.*)\\[/sub\\]"), - "\\1"); - m_TagMap["sup"] = std::make_pair(QRegExp("\\[sup\\](.*)\\[/sup\\]"), - "\\1"); - m_TagMap["size="] = std::make_pair(QRegExp("\\[size=([^\\]]*)\\](.*)\\[/size\\]"), - "\\2"); - m_TagMap["color="] = std::make_pair(QRegExp("\\[color=([^\\]]*)\\](.*)\\[/color\\]"), - ""); - m_TagMap["font="] = std::make_pair(QRegExp("\\[font=([^\\]]*)\\](.*)\\[/font\\]"), - "\\2"); - m_TagMap["center"] = std::make_pair(QRegExp("\\[center\\](.*)\\[/center\\]"), - "
\\1
"); - m_TagMap["quote"] = std::make_pair(QRegExp("\\[quote\\](.*)\\[/quote\\]"), - "
\"\\1\"
"); - m_TagMap["quote="] = std::make_pair(QRegExp("\\[quote=([^\\]]*)\\](.*)\\[/quote\\]"), - "
\"\\2\"
--\\1

"); - m_TagMap["code"] = std::make_pair(QRegExp("\\[code\\](.*)\\[/code\\]"), - "
\\1
"); - m_TagMap["heading"]= std::make_pair(QRegExp("\\[heading\\](.*)\\[/heading\\]"), - "

\\1

"); - - // lists - m_TagMap["list"] = std::make_pair(QRegExp("\\[list\\](.*)\\[/list\\]"), - "
    \\1
"); - m_TagMap["list="] = std::make_pair(QRegExp("\\[list.*\\](.*)\\[/list\\]"), - "
    \\1
"); - m_TagMap["ul"] = std::make_pair(QRegExp("\\[ul\\](.*)\\[/ul\\]"), - "
    \\1
"); - m_TagMap["ol"] = std::make_pair(QRegExp("\\[ol\\](.*)\\[/ol\\]"), - "
    \\1
"); - m_TagMap["li"] = std::make_pair(QRegExp("\\[li\\](.*)\\[/li\\]"), - "
  • \\1
  • "); - m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)
    "), - "
  • \\1
  • "); - - // tables - m_TagMap["table"] = std::make_pair(QRegExp("\\[table\\](.*)\\[/table\\]"), - "\\1
    "); - m_TagMap["tr"] = std::make_pair(QRegExp("\\[tr\\](.*)\\[/tr\\]"), - "\\1"); - m_TagMap["th"] = std::make_pair(QRegExp("\\[th\\](.*)\\[/th\\]"), - "\\1"); - m_TagMap["td"] = std::make_pair(QRegExp("\\[td\\](.*)\\[/td\\]"), - "\\1"); - - // web content - m_TagMap["url"] = std::make_pair(QRegExp("\\[url\\](.*)\\[/url\\]"), - "\\1"); - m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"), - "\\2"); - m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), " "); - m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), " "); - m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"), - "\\2"); - m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"), - "http://www.youtube.com/v/\\1"); - - m_ColorMap.insert(std::make_pair("red", "FF0000")); - m_ColorMap.insert(std::make_pair("green", "00FF00")); - m_ColorMap.insert(std::make_pair("blue", "0000FF")); - m_ColorMap.insert(std::make_pair("black", "000000")); - m_ColorMap.insert(std::make_pair("gray", "7F7F7F")); - m_ColorMap.insert(std::make_pair("white", "FFFFFF")); - m_ColorMap.insert(std::make_pair("yellow", "FFFF00")); - m_ColorMap.insert(std::make_pair("cyan", "00FFFF")); - m_ColorMap.insert(std::make_pair("magenta", "FF00FF")); - m_ColorMap.insert(std::make_pair("brown", "A52A2A")); - m_ColorMap.insert(std::make_pair("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); - } - } - -private: - - QRegExp m_TagNameExp; - TagMap m_TagMap; - std::map m_ColorMap; -}; - - -QString convertToHTML(const QString &inputParam) -{ - // this code goes over the input string once and replaces all bbtags - // it encounters. This function is called recursively for every replaced - // string to convert nested tags. - // - // This could be implemented simpler by applying a set of regular expressions - // for each recognized bb-tag one after the other but that would probably be - // very inefficient (O(n^2)). - - QString input = inputParam.mid(0).replace("\r\n", "
    "); - input.replace("\\\"", "\"").replace("\\'", "'"); - - QString result; - int lastBlock = 0; - int pos = 0; - - // iterate over the input buffer - while ((pos = input.indexOf('[', lastBlock)) != -1) { - // 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; - } else { - // nothing replaced - result.append('['); - ++pos; - } - lastBlock = pos; - } - - // append the remainder (everything after the last tag) - result.append(input.midRef(lastBlock)); - return result; -} - -} // namespace BBCode - +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#include "bbcode.h" + +#include +#include +#include +#include + + +namespace BBCode { + + +class BBCodeMap { + + typedef std::map > TagMap; + +public: + + static BBCodeMap &instance() { + static BBCodeMap s_Instance; + return s_Instance; + } + + QString convertTag(const QString &input, int &length) + { + // extract the tag name + m_TagNameExp.indexIn(input, 1, QRegExp::CaretAtOffset); + QString tagName = m_TagNameExp.cap(0).toLower(); + TagMap::iterator tagIter = m_TagMap.find(tagName); + if (tagIter != m_TagMap.end()) { + // recognized tag + if (tagName.endsWith('=')) { + tagName.chop(1); + } + QString closeTag = tagName == "*" ? "
    " + : QString("[/%1]").arg(tagName); + + int closeTagPos = input.indexOf(closeTag, 0, Qt::CaseInsensitive); + //qDebug("close tag %s at %d", closeTag.toUtf8().constData(), closeTagPos); + + if (closeTagPos > -1) { + length = closeTagPos + closeTag.length(); + QString temp = input.mid(0, length); + if (tagIter->second.first.indexIn(temp) == 0) { + if (tagIter->second.second.isEmpty()) { + 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; + } + return temp.replace(tagIter->second.first, QString("%2").arg(color, content)); + } else { + qWarning("don't know how to deal with tag %s", qPrintable(tagName)); + } + } else { + return temp.replace(tagIter->second.first, tagIter->second.second); + } + } else { + // expression doesn't match. either the input string is invalid + // or the expression is + qWarning("%s doesn't match the expression for %s", + temp.toUtf8().constData(), tagName.toUtf8().constData()); + length = 0; + return QString(); + } + } + } + + // not a recognized tag or tag invalid + length = 0; + return QString(); + } + +private: + BBCodeMap() + : m_TagNameExp("^[a-zA-Z*]*=?") + { + m_TagMap["b"] = std::make_pair(QRegExp("\\[b\\](.*)\\[/b\\]"), + "\\1"); + m_TagMap["i"] = std::make_pair(QRegExp("\\[i\\](.*)\\[/i\\]"), + "\\1"); + m_TagMap["u"] = std::make_pair(QRegExp("\\[u\\](.*)\\[/u\\]"), + "\\1"); + m_TagMap["s"] = std::make_pair(QRegExp("\\[s\\](.*)\\[/s\\]"), + "\\1"); + m_TagMap["sub"] = std::make_pair(QRegExp("\\[sub\\](.*)\\[/sub\\]"), + "\\1"); + m_TagMap["sup"] = std::make_pair(QRegExp("\\[sup\\](.*)\\[/sup\\]"), + "\\1"); + m_TagMap["size="] = std::make_pair(QRegExp("\\[size=([^\\]]*)\\](.*)\\[/size\\]"), + "\\2"); + m_TagMap["color="] = std::make_pair(QRegExp("\\[color=([^\\]]*)\\](.*)\\[/color\\]"), + ""); + m_TagMap["font="] = std::make_pair(QRegExp("\\[font=([^\\]]*)\\](.*)\\[/font\\]"), + "\\2"); + m_TagMap["center"] = std::make_pair(QRegExp("\\[center\\](.*)\\[/center\\]"), + "
    \\1
    "); + m_TagMap["quote"] = std::make_pair(QRegExp("\\[quote\\](.*)\\[/quote\\]"), + "
    \"\\1\"
    "); + m_TagMap["quote="] = std::make_pair(QRegExp("\\[quote=([^\\]]*)\\](.*)\\[/quote\\]"), + "
    \"\\2\"
    --\\1

    "); + m_TagMap["code"] = std::make_pair(QRegExp("\\[code\\](.*)\\[/code\\]"), + "
    \\1
    "); + m_TagMap["heading"]= std::make_pair(QRegExp("\\[heading\\](.*)\\[/heading\\]"), + "

    \\1

    "); + + // lists + m_TagMap["list"] = std::make_pair(QRegExp("\\[list\\](.*)\\[/list\\]"), + "
      \\1
    "); + m_TagMap["list="] = std::make_pair(QRegExp("\\[list.*\\](.*)\\[/list\\]"), + "
      \\1
    "); + m_TagMap["ul"] = std::make_pair(QRegExp("\\[ul\\](.*)\\[/ul\\]"), + "
      \\1
    "); + m_TagMap["ol"] = std::make_pair(QRegExp("\\[ol\\](.*)\\[/ol\\]"), + "
      \\1
    "); + m_TagMap["li"] = std::make_pair(QRegExp("\\[li\\](.*)\\[/li\\]"), + "
  • \\1
  • "); + m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)
    "), + "
  • \\1
  • "); + + // tables + m_TagMap["table"] = std::make_pair(QRegExp("\\[table\\](.*)\\[/table\\]"), + "\\1
    "); + m_TagMap["tr"] = std::make_pair(QRegExp("\\[tr\\](.*)\\[/tr\\]"), + "\\1"); + m_TagMap["th"] = std::make_pair(QRegExp("\\[th\\](.*)\\[/th\\]"), + "\\1"); + m_TagMap["td"] = std::make_pair(QRegExp("\\[td\\](.*)\\[/td\\]"), + "\\1"); + + // web content + m_TagMap["url"] = std::make_pair(QRegExp("\\[url\\](.*)\\[/url\\]"), + "\\1"); + m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"), + "\\2"); + m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), " "); + m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), " "); + m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"), + "\\2"); + m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"), + "http://www.youtube.com/v/\\1"); + + m_ColorMap.insert(std::make_pair("red", "FF0000")); + m_ColorMap.insert(std::make_pair("green", "00FF00")); + m_ColorMap.insert(std::make_pair("blue", "0000FF")); + m_ColorMap.insert(std::make_pair("black", "000000")); + m_ColorMap.insert(std::make_pair("gray", "7F7F7F")); + m_ColorMap.insert(std::make_pair("white", "FFFFFF")); + m_ColorMap.insert(std::make_pair("yellow", "FFFF00")); + m_ColorMap.insert(std::make_pair("cyan", "00FFFF")); + m_ColorMap.insert(std::make_pair("magenta", "FF00FF")); + m_ColorMap.insert(std::make_pair("brown", "A52A2A")); + m_ColorMap.insert(std::make_pair("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); + } + } + +private: + + QRegExp m_TagNameExp; + TagMap m_TagMap; + std::map m_ColorMap; +}; + + +QString convertToHTML(const QString &inputParam) +{ + // this code goes over the input string once and replaces all bbtags + // it encounters. This function is called recursively for every replaced + // string to convert nested tags. + // + // This could be implemented simpler by applying a set of regular expressions + // for each recognized bb-tag one after the other but that would probably be + // very inefficient (O(n^2)). + + QString input = inputParam.mid(0).replace("\r\n", "
    "); + input.replace("\\\"", "\"").replace("\\'", "'"); + + QString result; + int lastBlock = 0; + int pos = 0; + + // iterate over the input buffer + while ((pos = input.indexOf('[', lastBlock)) != -1) { + // 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; + } else { + // nothing replaced + result.append('['); + ++pos; + } + lastBlock = pos; + } + + // append the remainder (everything after the last tag) + result.append(input.midRef(lastBlock)); + return result; +} + +} // namespace BBCode + -- cgit v1.3.1 From 482f13a50b921e61d34d09f72a7fb4216efe742b Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 8 Sep 2014 20:37:23 +0200 Subject: - re-enabled building of loot_cli and started developing against the new api - extended set of default categories - more tolerand bbcode parser - added a few colors for the bbcode parser - more fixes to qt5 compatibility - started work on ability to unloading (and thus re-loading) of plugins - names of plugins are no longer localizable (because those names are also used to store settings) - added settings to disable individual diagnosis settings - path of dependencies is now configured in a .pri file instead of environment variablees - bugfix: if the modid-input is canceled, the id was saved as -1 and wasn't re-requested from the user - bugfix: moving files with the SHFileOperation-Api didn't update the vfs correctly (still not perfect but better) - bugfix: attempt to remove the deleter-file seems to have caused error messages for some users - bugfix: fixed a couple of cases that might have caused the tutorial to hang --- .hgignore | 3 + src/ModOrganizer.pro | 6 +- src/bbcode.cpp | 93 +++++++++++++++++++++---------- src/categories.cpp | 26 +++++++-- src/downloadmanager.cpp | 2 +- src/editexecutablesdialog.cpp | 2 +- src/main.cpp | 12 +++- src/mainwindow.cpp | 77 ++++++++++++++++++------- src/mainwindow.h | 8 +++ src/modinfo.cpp | 4 +- src/modlist.cpp | 11 ++++ src/modlist.h | 6 ++ src/nexusinterface.cpp | 23 ++++---- src/nexusinterface.h | 8 ++- src/organizer.pro | 50 +++++++++-------- src/pluginlist.cpp | 5 +- src/pluginlist.h | 12 ++-- src/settings.cpp | 1 - src/shared/directoryentry.cpp | 4 -- src/shared/directoryentry.h | 2 + src/shared/shared.pro | 53 ++++++++++-------- src/tutorials/TutorialOverlay.qml | 6 +- src/tutorials/tutorial_firststeps_main.js | 35 ++++++++---- 23 files changed, 305 insertions(+), 144 deletions(-) (limited to 'src/bbcode.cpp') diff --git a/.hgignore b/.hgignore index d1092a1d..acba45c6 100644 --- a/.hgignore +++ b/.hgignore @@ -32,5 +32,8 @@ html *.filters *.lib source/organizer/resources/contents/icons +source/plugins/build-* +*/GeneratedFiles/* syntax: regexp Makefile\.(Debug|Release) +source/.*/debug/.* diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro index 9907d086..9b2d998b 100644 --- a/src/ModOrganizer.pro +++ b/src/ModOrganizer.pro @@ -1,6 +1,5 @@ TEMPLATE = subdirs - SUBDIRS = bsatk \ shared \ uibase \ @@ -13,9 +12,10 @@ SUBDIRS = bsatk \ nxmhandler \ BossDummy \ pythonRunner \ + loot_cli \ esptk -plugins.depends = pythonRunner +plugins.depends = pythonRunner uibase hookdll.depends = shared organizer.depends = shared uibase plugins @@ -30,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 == "*" ? "
    " - : 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("(\\[\\*\\]|)", 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("(\\[/\\*\\])?(
    )?$")); + } return temp.replace(tagIter->second.first, tagIter->second.second); } } else { @@ -123,6 +142,8 @@ private: "
    \\1
    "); m_TagMap["heading"]= std::make_pair(QRegExp("\\[heading\\](.*)\\[/heading\\]"), "

    \\1

    "); + m_TagMap["line"] = std::make_pair(QRegExp("\\[line\\]"), + "
    "); // lists m_TagMap["list"] = std::make_pair(QRegExp("\\[list\\](.*)\\[/list\\]"), @@ -135,8 +156,6 @@ private: "
      \\1
    "); m_TagMap["li"] = std::make_pair(QRegExp("\\[li\\](.*)\\[/li\\]"), "
  • \\1
  • "); - m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)
    "), - "
  • \\1
  • "); // tables m_TagMap["table"] = std::make_pair(QRegExp("\\[table\\](.*)\\[/table\\]"), @@ -153,13 +172,26 @@ private: "\\1"); m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"), "\\2"); - 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\\]"), + "\\1"); + m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), + "\\2"); m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"), "\\2"); m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"), "http://www.youtube.com/v/\\1"); + + // 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("\\[\\*\\](.*)"), + "
  • \\1
  • "); + m_ColorMap.insert(std::make_pair("red", "FF0000")); m_ColorMap.insert(std::make_pair("green", "00FF00")); m_ColorMap.insert(std::make_pair("blue", "0000FF")); @@ -170,13 +202,13 @@ private: m_ColorMap.insert(std::make_pair("cyan", "00FFFF")); m_ColorMap.insert(std::make_pair("magenta", "FF00FF")); m_ColorMap.insert(std::make_pair("brown", "A52A2A")); - m_ColorMap.insert(std::make_pair("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("orange", "FFA500")); + m_ColorMap.insert(std::make_pair("gold", "FFD700")); + m_ColorMap.insert(std::make_pair("deepskyblue", "00BFFF")); + m_ColorMap.insert(std::make_pair("salmon", "FA8072")); + m_ColorMap.insert(std::make_pair("dodgerblue", "1E90FF")); + m_ColorMap.insert(std::make_pair("greenyellow", "ADFF2F")); + m_ColorMap.insert(std::make_pair("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 4c851338..28b1f4a2 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(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(4, 28, 43, 45, 87), 0); } @@ -189,24 +193,38 @@ void CategoryFactory::loadDefaultCategories() // mods appear in the combo box addCategory(1, "Animations", MakeVector(1, 51), 0); addCategory(2, "Armour", MakeVector(1, 54), 0); - addCategory(3, "Audio", MakeVector(1, 61), 0); + addCategory(3, "Sound & Music", MakeVector(1, 61), 0); addCategory(5, "Clothing", MakeVector(1, 60), 0); addCategory(6, "Collectables", MakeVector(1, 92), 0); - addCategory(7, "Creatures", MakeVector(2, 83, 65), 0); + addCategory(28, "Companions", MakeVector(2, 66, 96), 0); + addCategory(7, "Creatures & Mounts", MakeVector(2, 83, 65), 0); addCategory(8, "Factions", MakeVector(1, 25), 0); addCategory(9, "Gameplay", MakeVector(1, 24), 0); addCategory(10, "Hair", MakeVector(1, 26), 0); addCategory(11, "Items", MakeVector(2, 27, 85), 0); - addCategory(19, "Weapons", MakeVector(2, 36, 55), 11); + addCategory(32, "Mercantile", MakeVector(1, 69), 0); + addCategory(19, "Weapons", MakeVector(1, 55), 11); + addCategory(36, "Weapon & Armour Sets", MakeVector(1, 39), 11); addCategory(12, "Locations", MakeVector(7, 22, 30, 70, 88, 89, 90, 91), 0); + addCategory(31, "Landscape Changes", MakeVector(1, 58), 0); addCategory(4, "Cities", MakeVector(1, 53), 12); + addCategory(29, "Environment", MakeVector(1, 74), 0); + addCategory(30, "Immersion", MakeVector(1, 78), 0); + addCategory(25, "Castles & Mansions", MakeVector(1, 68), 23); addCategory(20, "Magic", MakeVector(3, 75, 93, 94), 0); addCategory(21, "Models & Textures", MakeVector(1, 29), 0); + addCategory(33, "Modders resources", MakeVector(1, 82), 0); addCategory(13, "NPCs", MakeVector(1, 33), 0); addCategory(14, "Patches", MakeVector(2, 79, 84), 0); + addCategory(24, "Bugfixes", MakeVector(1, 95), 0); + addCategory(35, "Utilities", MakeVector(1, 39), 0); + addCategory(26, "Cheats", MakeVector(1, 40), 0); + addCategory(23, "Player Homes", MakeVector(1, 67), 0); addCategory(15, "Quests", MakeVector(1, 35), 0); addCategory(16, "Races & Classes", MakeVector(1, 34), 0); + addCategory(27, "Combat", MakeVector(1, 77), 0); addCategory(22, "Skills", MakeVector(1, 73), 0); + addCategory(34, "Stealth", MakeVector(1, 76), 0); addCategory(17, "UI", MakeVector(1, 42), 0); addCategory(18, "Visuals", MakeVector(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/main.cpp b/src/main.cpp index a21f41e4..3198208a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -311,9 +311,19 @@ int main(int argc, char *argv[]) } QString dataPath = instanceID.isEmpty() ? application.applicationDirPath() - : QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation)) + "/" + instanceID; + : QDir::fromNativeSeparators( +#if QT_VERSION >= 0x050000 + QStandardPaths::writableLocation(QStandardPaths::DataLocation) +#else + QDesktopServices::storageLocation(QDesktopServices::DataLocation) +#endif + ) + "/" + instanceID; application.setProperty("dataPath", dataPath); +#if QT_VERSION >= 0x050000 + qDebug("ssl support: %d", QSslSocket::supportsSsl()); +#endif + qDebug("data path: %s", qPrintable(dataPath)); if (!QDir(dataPath).exists()) { if (!QDir().mkpath(dataPath)) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0d9fad5d..984d8cfd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -97,9 +97,6 @@ along with Mod Organizer. If not, see . #include #include #include -#include -#include -#include #include #include #include @@ -114,8 +111,13 @@ along with Mod Organizer. If not, see . #include #include #include +#ifndef Q_MOC_RUN #include #include +#include +#include +#include +#endif #include #ifdef TEST_MODELS @@ -313,8 +315,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))); @@ -367,6 +367,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(); @@ -888,6 +890,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; @@ -895,6 +899,7 @@ void MainWindow::closeEvent(QCloseEvent* event) ModInfo::clear(); LogBuffer::cleanQuit(); m_ModList.setProfile(NULL); + NexusInterface::instance()->cleanup(); } @@ -1175,7 +1180,9 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) IPluginDiagnose *diagnose = qobject_cast(plugin); if (diagnose != NULL) { m_DiagnosisPlugins.push_back(diagnose); - diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); }); + m_DiagnosisConnections.push_back( + diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); }) + ); } } { // mod page plugin @@ -1204,6 +1211,7 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName) IPluginPreview *preview = qobject_cast(plugin); if (verifyPlugin(preview)) { m_PreviewGenerator.registerPlugin(preview); + return true; } } { // proxy plugins @@ -1242,13 +1250,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, ""); } @@ -1287,14 +1323,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)); @@ -2214,6 +2251,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"); @@ -4315,13 +4354,10 @@ void MainWindow::downloadRequested(QNetworkReply *reply, int modID, const QStrin void MainWindow::installTranslator(const QString &name) { -/* if (m_CurrentLanguage == "en_US") { - return; - }*/ QTranslator *translator = new QTranslator(this); QString fileName = name + "_" + m_CurrentLanguage; if (!translator->load(fileName, qApp->applicationDirPath() + "/translations")) { - if (m_CurrentLanguage != "en-US") { + if ((m_CurrentLanguage != "en-US") && (m_CurrentLanguage != "en_US")) { qWarning("localization file %s not found", qPrintable(fileName)); } // we don't actually expect localization files for english } @@ -4485,7 +4521,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); } @@ -5088,9 +5124,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(); @@ -5594,7 +5627,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 22152f1c..8bd663ac 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -29,6 +29,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include "executableslist.h" #include "modlist.h" #include "pluginlist.h" @@ -53,7 +54,9 @@ along with Mod Organizer. If not, see . #include "browserdialog.h" #include #include +#ifndef Q_MOC_RUN #include +#endif namespace Ui { class MainWindow; @@ -139,6 +142,8 @@ public: void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo); + QString getOriginDisplayName(int originID); + void unloadPlugins(); public slots: void refreshLists(); @@ -191,6 +196,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(); @@ -373,8 +379,10 @@ private: MOBase::IGameInfo *m_GameInfo; std::vector m_DiagnosisPlugins; + std::vector m_DiagnosisConnections; std::vector m_ModPages; std::vector m_UnloadedPlugins; + std::vector m_PluginLoaders; QFile m_PluginsCheck; diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 9558e03b..4ab6d142 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -569,9 +569,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 681d880c..eedf1ec6 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -64,6 +64,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; @@ -653,6 +659,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 6116a913..632689c6 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -32,7 +32,9 @@ along with Mod Organizer. If not, see . #include #include #include +#ifndef Q_MOC_RUN #include +#endif #include #include #include @@ -73,6 +75,8 @@ public: **/ ModList(QObject *parent = NULL); + ~ModList(); + /** * @brief set the profile used for status information * @@ -103,6 +107,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(); /** @@ -137,6 +139,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 * @@ -301,7 +308,6 @@ private: void nextRequest(); void requestFinished(std::list::iterator iter); bool requiresLogin(const NXMRequestInfo &info); - static void cleanup(); private: diff --git a/src/organizer.pro b/src/organizer.pro index bffd1e16..b24586e6 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -9,11 +9,15 @@ TARGET = ModOrganizer TEMPLATE = app greaterThan(QT_MAJOR_VERSION, 4) { - QT += core gui widgets network xml sql xmlpatterns qml quick script webkit + QT += core gui widgets network xml sql xmlpatterns qml declarative script webkit webkitwidgets } else { 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 \ @@ -248,9 +252,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 @@ -258,7 +262,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 @@ -266,20 +271,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 \ @@ -313,9 +317,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 @@ -324,40 +328,40 @@ 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) { greaterThan(QT_MAJOR_VERSION, 4) { - QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest.debug.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) + QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest.debug.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) QMAKE_POST_LINK += copy /y $$quote($$DSTDIR\\dlls\\dlls.manifest.debug.qt5) $$quote($$DSTDIR\\dlls\\dlls.manifest) $$escape_expand(\\n) QMAKE_POST_LINK += del $$quote($$DSTDIR)\\dlls\\dlls.manifest.debug.qt5 $$escape_expand(\\n) } else { - QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest.debug) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) + QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest.debug) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) QMAKE_POST_LINK += copy /y $$quote($$DSTDIR)\\dlls\\dlls.manifest.debug $$quote($$DSTDIR)\\dlls\\dlls.manifest $$escape_expand(\\n) QMAKE_POST_LINK += del $$quote($$DSTDIR)\\dlls\\dlls.manifest.debug $$escape_expand(\\n) } } else { greaterThan(QT_MAJOR_VERSION, 4) { - QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) + QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) QMAKE_POST_LINK += copy /y $$quote($$DSTDIR\\dlls\\dlls.manifest.qt5) $$quote($$DSTDIR\\dlls\\dlls.manifest) $$escape_expand(\\n) QMAKE_POST_LINK += del $$quote($$DSTDIR)\\dlls\\dlls.manifest.qt5 $$escape_expand(\\n) } else { - QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) + QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n) } } diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index f37f9e3a..43246b55 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -33,6 +33,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include #include @@ -95,6 +96,8 @@ PluginList::PluginList(QObject *parent) PluginList::~PluginList() { + m_Refreshed.disconnect_all_slots(); + m_PluginMoved.disconnect_all_slots(); } @@ -484,7 +487,7 @@ void PluginList::saveTo(const QString &pluginFileName if (deleterFile.commitIfDifferent(m_LastSaveHash[deleterFileName])) { qDebug("%s saved", qPrintable(QDir::toNativeSeparators(deleterFileName))); } - } else { + } else if (QFile::exists(deleterFileName)) { shellDelete(QStringList() << deleterFileName); } 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 . #include #include #include +#ifndef Q_MOC_RUN #include #include +#endif #include #include #include "pdll.h" #include - template 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 6bf13ee0..65ea3a27 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 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 7836d719..096f373e 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -29,8 +29,10 @@ along with Mod Organizer. If not, see . #define WIN32_MEAN_AND_LEAN #include #include +#ifndef Q_MOC_RUN #include #include +#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() { -- 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/bbcode.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 01265e9b0300cb4fe2dbed53050570ddee653da4 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 11 Nov 2014 21:46:16 +0100 Subject: - re-enabled use of img-tags in bbcode converter - addded a workaround for cases where, after a MO update, the stored modlist layout has no size for new columns - using a webview again for the nexus view of the modinfo dialog --- src/bbcode.cpp | 4 ++-- src/mainwindow.cpp | 11 +++++++++-- src/modinfodialog.cpp | 3 ++- src/modinfodialog.ui | 35 ++++++++++++++--------------------- src/modlistsortproxy.cpp | 30 ------------------------------ src/modlistsortproxy.h | 1 - 6 files changed, 27 insertions(+), 57 deletions(-) (limited to 'src/bbcode.cpp') diff --git a/src/bbcode.cpp b/src/bbcode.cpp index 2e22859d..0f9170d4 100644 --- a/src/bbcode.cpp +++ b/src/bbcode.cpp @@ -177,9 +177,9 @@ private: m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"), "\\2"); m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), - "\\1"); + ""); m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), - "\\2"); + "\"\\1\""); m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"), "\\2"); m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"), diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ede14448..eb1e1b09 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -226,8 +226,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray()); // hack: force the resize-signal to be triggered because restoreState doesn't seem to do that - ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) + 1); - ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) - 1); + ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize + 1); + ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize - 1); } else { // hide these columns by default ui->modList->header()->setSectionHidden(ModList::COL_CONTENT, true); @@ -399,6 +399,13 @@ void MainWindow::resizeLists(bool modListCustom, bool pluginListCustom) #endif } + // ensure the columns aren't so small you can't see them any more + for (int i = 0; i < ui->modList->header()->count(); ++i) { + if (ui->modList->header()->sectionSize(i) < 10) { + ui->modList->header()->resizeSection(i, 10); + } + } + if (!pluginListCustom) { // resize plugin list to fit content #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 1cea9e1e..9133b166 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -84,7 +84,8 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo connect(&m_ThumbnailMapper, SIGNAL(mapped(const QString&)), this, SIGNAL(thumbnailClickedSignal(const QString&))); connect(this, SIGNAL(thumbnailClickedSignal(const QString&)), this, SLOT(thumbnailClicked(const QString&))); connect(m_ModInfo.data(), SIGNAL(modDetailsUpdated(bool)), this, SLOT(modDetailsUpdated(bool))); - connect(ui->descriptionView, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkClicked(QUrl))); + connect(ui->descriptionView, SIGNAL(linkClicked(QUrl)), this, SLOT(linkClicked(QUrl))); + ui->descriptionView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); if (directory->originExists(ToWString(modInfo->name()))) { m_Origin = &directory->getOriginByName(ToWString(modInfo->name())); diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui index d3862b58..a03edef7 100644 --- a/src/modinfodialog.ui +++ b/src/modinfodialog.ui @@ -232,8 +232,8 @@ 0 0 - 676 - 126 + 98 + 28 @@ -678,25 +678,11 @@ p, li { white-space: pre-wrap; } - - - - 0 - 200 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> - - - Qt::TextBrowserInteraction - - - false + + + + about:blank + @@ -819,6 +805,13 @@ p, li { white-space: pre-wrap; } + + + QWebView + QWidget +
    QtWebKitWidgets/QWebView
    +
    +
    diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 8907e712..e132b71e 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -79,36 +79,6 @@ Qt::ItemFlags ModListSortProxy::flags(const QModelIndex &modelIndex) const return flags; } -void ModListSortProxy::displayColumnSelection(const QPoint &pos) -{ - QMenu menu; - - for (int i = 0; i <= ModList::COL_LASTCOLUMN; ++i) { - QCheckBox *checkBox = new QCheckBox(&menu); - checkBox->setText(ModList::getColumnName(i)); - checkBox->setChecked(m_EnabledColumns.test(i) ? Qt::Checked : Qt::Unchecked); - QWidgetAction *checkableAction = new QWidgetAction(&menu); - checkableAction->setDefaultWidget(checkBox); - menu.addAction(checkableAction); - } - menu.exec(pos); - int i = 0; - - emit layoutAboutToBeChanged(); - m_EnabledColumns.reset(); - foreach (const QAction *action, menu.actions()) { - const QWidgetAction *widgetAction = qobject_cast(action); - if (widgetAction != NULL) { - const QCheckBox *checkBox = qobject_cast(widgetAction->defaultWidget()); - if (checkBox != NULL) { - m_EnabledColumns.set(i, checkBox->checkState() == Qt::Checked); - } - } - ++i; - } - emit layoutChanged(); -} - void ModListSortProxy::enableAllVisible() { if (m_Profile == NULL) return; diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index 71da79eb..05392c0b 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -95,7 +95,6 @@ public: public slots: - void displayColumnSelection(const QPoint &pos); void updateFilter(const QString &filter); signals: -- cgit v1.3.1