Revision control
Copy as Markdown
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "helpclient.h"
#if QT_CONFIG(process)
# include "assistantclient.h"
#endif
#include <QtGui/qdesktopservices.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qstring.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qurl.h>
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
QString HelpClient::designerManualUrl() const
{
return documentUrl(u"qtdesigner"_s);
}
std::unique_ptr<HelpClient> HelpClient::create(HelpClientType type)
{
std::unique_ptr<HelpClient> result;
switch (type) {
case HelpClientType::Assistant:
#if QT_CONFIG(process)
result = std::make_unique<AssistantClient>();
break;
#endif
case HelpClientType::Web:
result = std::make_unique<WebHelpClient>();
break;
case HelpClientType::Python:
result = std::make_unique<PythonWebHelpClient>();
break;
}
return result;
}
static constexpr auto htmlSuffix = ".html"_L1;
static constexpr auto propertySeparator = "::"_L1;
bool WebHelpClient::showPage(const QString &path, QString *errorMessage)
{
const bool result = QDesktopServices::openUrl(QUrl(path));
if (!result) {
*errorMessage = QCoreApplication::translate("WebHelpClient",
"Unable to open url (%1).").arg(path);
}
return result;
}
// C++ "QWidget::geometry" -> "qwidget.html#geometry-prop
QString WebHelpClient::webPage(const QString &identifier)
{
const auto propPos = identifier.lastIndexOf(propertySeparator);
const QString widget = propPos != -1 ? identifier.sliced(0, propPos) : identifier;
QString result = widget.toLower() + htmlSuffix;
if (propPos != -1)
result += u'#' + identifier.sliced(propPos + propertySeparator.size()) + "-prop"_L1;
return result;
}
bool WebHelpClient::activateIdentifier(const QString &identifier, QString *errorMessage)
{
const QString url = identifier.startsWith("http"_L1)
? identifier : webPrefix + webPage(identifier);
return showPage(url, errorMessage);
}
QString WebHelpClient::documentUrl(const QString &) const
{
return webPrefix;
}
// Python: "QWidget::geometry" -> "QWidget.html" (no property anchors)
QString PythonWebHelpClient::webPage(const QString &identifier)
{
const auto propPos = identifier.lastIndexOf(propertySeparator);
const QString widget = propPos != -1 ? identifier.sliced(0, propPos) : identifier;
return widget + htmlSuffix;
}
// Python: "QWidget::geometry" ->
bool PythonWebHelpClient::activateIdentifier(const QString &identifier, QString *errorMessage)
{
QString url = identifier;
if (!identifier.startsWith("http"_L1)) {
const auto module = identifier.startsWith("QAction"_L1) ? "QtGui"_L1 : "QtWidgets"_L1;
url = pythonWebPrefix + module + u'/'+ webPage(identifier);
}
return showPage(url, errorMessage);
}
QT_END_NAMESPACE