File indexing completed on 2024-12-08 12:18:39
0001 /* 0002 SPDX-FileCopyrightText: 2013 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "kurlhandler_p.h" 0008 0009 #include <kguiaddons_debug.h> 0010 0011 #include <QCoreApplication> 0012 #include <QDebug> 0013 #include <QDesktopServices> 0014 #include <QLocale> 0015 #include <QProcess> 0016 #include <QStandardPaths> 0017 #include <QUrl> 0018 0019 static const char s_khelpcenter_exec[] = "khelpcenter"; 0020 0021 static bool openWithKHelpCenter(const QUrl &url) 0022 { 0023 const QString helpcenter = QStandardPaths::findExecutable(QString::fromLatin1(s_khelpcenter_exec)); 0024 if (!helpcenter.isEmpty()) { 0025 QUrl u(url); 0026 if (u.path() == QLatin1Char('/')) { 0027 const QString appName = QCoreApplication::applicationName(); 0028 u.setPath(appName); 0029 } 0030 0031 QProcess::startDetached(helpcenter, QStringList(u.toString())); 0032 return true; 0033 } 0034 0035 return false; 0036 } 0037 0038 KUrlHandler::KUrlHandler(QObject *parent) 0039 : QObject(parent) 0040 { 0041 } 0042 0043 void KUrlHandler::openHelp(const QUrl &url) const 0044 { 0045 if (openWithKHelpCenter(url)) { 0046 return; 0047 } 0048 0049 const QUrl docUrl = concatDocsUrl(url); 0050 if (docUrl.isValid()) { 0051 QDesktopServices::openUrl(docUrl); 0052 } else { 0053 qCWarning(KGUIADDONS_LOG) << "Could not find a suitable handler for" << url.toString(); 0054 } 0055 } 0056 0057 QUrl KUrlHandler::concatDocsUrl(const QUrl &url) const 0058 { 0059 if (QCoreApplication::organizationDomain() != QLatin1String("kde.org")) { 0060 return {}; 0061 } 0062 0063 // KHelpCenter is not available and it's a KDE application, open the docs at docs.kde.org 0064 // with the default web browser on the system 0065 0066 QString path = url.path(); 0067 const QString fragment = url.fragment(); 0068 const QString common = QLatin1String("https://docs.kde.org/index.php?branch=stable5&language=") + QLocale().name(); 0069 0070 const QString appName = QCoreApplication::applicationName(); 0071 0072 // Special case for KCModules 0073 if (appName == QLatin1String("systemsettings") && path.startsWith(QLatin1String("/kcontrol"))) { 0074 // E.g. change "/kcontrol/fonts/index.html" to "&application=kcontrol/fonts&path=index.html" 0075 // docs.kde.org will resolve the url and add the proper package name, e.g. plasma-workspace: 0076 // https://docs.kde.org/stable5/en/plasma-workspace/kcontrol/fonts/index.html 0077 QString kcmAppName(path); 0078 kcmAppName.remove(0, 1); // Remove leading "/" 0079 const int idx = kcmAppName.indexOf(QLatin1String("/index.html")); 0080 if (idx > 0) { 0081 kcmAppName.truncate(idx); 0082 } 0083 0084 // Some KCModules have a valid fragment, e.g. kcontrol/powerdevil/index.html#advanced-settings 0085 const QString tail = QLatin1String("index.html") + (!fragment.isEmpty() ? QLatin1Char('#') + fragment : QString{}); 0086 0087 return QUrl(common + QLatin1String("&application=") + kcmAppName + QLatin1String("&path=") + tail); 0088 } 0089 0090 // E.g. "help:/" and appName is "okular", e.g. opening Help -> Okular HandBook 0091 if (path == QLatin1Char('/')) { 0092 return QUrl(common + QLatin1String("&application=") + appName + QLatin1String("&path=") + QLatin1String("index.html")); 0093 } 0094 0095 // E.g. "help:/okular/configure.html", don't repeat "appName"; e.g. clicking Help button in 0096 // the "Settings -> Configure Okular" dialog 0097 const QString redundant = QLatin1Char('/') + appName + QLatin1Char('/'); 0098 if (path.startsWith(redundant)) { 0099 path.remove(0, redundant.size()); 0100 0101 if (!fragment.isEmpty()) { 0102 // E.g. "help:/kinfocenter/index.html#kcm_memory", it's actually "kinfocenter/kcm_memory.html" 0103 if (path == QLatin1String("index.html")) { 0104 qCWarning(KGUIADDONS_LOG) << "X-DocPath entry in a .desktop file in" << appName << "is:" << appName + QLatin1String("/index.html#") + fragment 0105 << ", however it should be:" << appName + QLatin1Char('/') + fragment + QLatin1String(".html"); 0106 0107 path = fragment + QLatin1String(".html"); 0108 } else { 0109 // E.g. "help:/okular/signatures.html#adding_digital_signatures" 0110 path += QLatin1Char('#') + fragment; 0111 } 0112 } 0113 0114 return QUrl(common + QLatin1String("&application=") + appName + QLatin1String("&path=") + path); 0115 } 0116 0117 return {}; 0118 } 0119 0120 Q_GLOBAL_STATIC(KUrlHandler, s_handler) 0121 0122 static void initializeGlobalSettings() 0123 { 0124 QDesktopServices::setUrlHandler(QStringLiteral("help"), s_handler, "openHelp"); 0125 } 0126 0127 Q_COREAPP_STARTUP_FUNCTION(initializeGlobalSettings) 0128 0129 #include "moc_kurlhandler_p.cpp"