diff --git a/src/plugins/coreplugin/helpitem.cpp b/src/plugins/coreplugin/helpitem.cpp index 2a972cb98eb..50f84bbf7ab 100644 --- a/src/plugins/coreplugin/helpitem.cpp +++ b/src/plugins/coreplugin/helpitem.cpp @@ -29,6 +29,8 @@ #include #include +#include + using namespace Core; HelpItem::HelpItem() = default; @@ -165,31 +167,66 @@ QString HelpItem::extractContent(bool extended) const return contents; } -static std::pair extractVersion(const QUrl &url) +// The following is only correct under the specific current conditions, and it will +// always be quite some guessing as long as the version information does not +// include separators for major vs minor vs patch version. +static QVersionNumber qtVersionHeuristic(const QString &digits) +{ + if (digits.count() > 6 || digits.count() < 3) + return {}; // suspicious version number + + for (const QChar &digit : digits) + if (!digit.isDigit()) + return {}; // we should have only digits + + // When we have 3 digits, we split it like: ABC -> A.B.C + // When we have 4 digits, we split it like: ABCD -> A.BC.D + // When we have 5 digits, we split it like: ABCDE -> A.BC.DE + // When we have 6 digits, we split it like: ABCDEF -> AB.CD.EF + switch (digits.count()) { + case 3: + return QVersionNumber(digits.mid(0, 1).toInt(), + digits.mid(1, 1).toInt(), + digits.mid(2, 1).toInt()); + case 4: + return QVersionNumber(digits.mid(0, 1).toInt(), + digits.mid(1, 2).toInt(), + digits.mid(3, 1).toInt()); + case 5: + return QVersionNumber(digits.mid(0, 1).toInt(), + digits.mid(1, 2).toInt(), + digits.mid(3, 2).toInt()); + case 6: + return QVersionNumber(digits.mid(0, 2).toInt(), + digits.mid(2, 2).toInt(), + digits.mid(4, 2).toInt()); + default: + break; + } + return {}; +} + +static std::pair extractVersion(const QUrl &url) { const QString host = url.host(); const QStringList hostParts = host.split('.'); if (hostParts.size() == 4 && (host.startsWith("com.trolltech.") || host.startsWith("org.qt-project."))) { - bool ok = false; - // the following is only correct under the specific current conditions, and it will - // always be quite some guessing as long as the version information does not - // include separators for major vs minor vs patch version - const int version = hostParts.at(3).toInt(&ok); - if (ok) { + const QVersionNumber version = qtVersionHeuristic(hostParts.at(3)); + if (!version.isNull()) { QUrl urlWithoutVersion(url); urlWithoutVersion.setHost(hostParts.mid(0, 3).join('.')); return {urlWithoutVersion, version}; } } - return {url, 0}; + return {url, {}}; } // sort primary by "url without version" and seconday by "version" static bool helpUrlLessThan(const QUrl &a, const QUrl &b) { - const std::pair va = extractVersion(a); - const std::pair vb = extractVersion(b); + const std::pair va = extractVersion(a); + const std::pair vb = extractVersion(b); const QString sa = va.first.toString(); const QString sb = vb.first.toString(); if (sa == sb) @@ -260,10 +297,10 @@ static const HelpItem::Links getBestLink(const HelpItem::Links &links) // This is to ensure that if we succeeded with an ID lookup, and we have e.g. Qt5 and Qt4 // documentation, that we only return the Qt5 link even though the Qt5 and Qt4 URLs look // different. - int highestVersion = -1; + QVersionNumber highestVersion; HelpItem::Link bestLink; for (const HelpItem::Link &link : links) { - const int version = extractVersion(link.second).second; + const QVersionNumber version = extractVersion(link.second).second; if (version > highestVersion) { highestVersion = version; bestLink = link;