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 --- src/bbcode.cpp | 93 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 28 deletions(-) (limited to 'src/bbcode.cpp') 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; } -- 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