File indexing completed on 2024-05-05 04:40:51

0001 /*
0002     SPDX-FileCopyrightText: 2009 Aleix Pol <aleixpol@kde.org>
0003     SPDX-FileCopyrightText: 2009 David Nolden <david.nolden.kdevelop@art-master.de>
0004     SPDX-FileCopyrightText: 2010 Benjamin Port <port.benjamin@gmail.com>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "qthelpprovider.h"
0010 
0011 #include <QHelpIndexModel>
0012 #include <QHelpContentModel>
0013 
0014 #include <QStandardPaths>
0015 
0016 #include <interfaces/icore.h>
0017 #include <interfaces/idocumentationcontroller.h>
0018 
0019 #include <language/duchain/duchain.h>
0020 #include <language/duchain/declaration.h>
0021 #include <language/duchain/duchainlock.h>
0022 #include <language/duchain/parsingenvironment.h>
0023 
0024 #include "qthelpnetwork.h"
0025 #include "qthelpdocumentation.h"
0026 #include "debug.h"
0027 
0028 using namespace KDevelop;
0029 
0030 namespace {
0031 IDocumentation::Ptr documentationPtrFromUrl(const QUrl& url)
0032 {
0033     const QList<QHelpLink> info{{url, url.toString()}};
0034     return IDocumentation::Ptr(new QtHelpDocumentation(url.toString(), info));
0035 }
0036 }
0037 
0038 QtHelpProviderAbstract::QtHelpProviderAbstract(QObject* parent, const QString& collectionFileName,
0039                                                const QVariantList& args)
0040     : QObject(parent)
0041     , m_engine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/')
0042                + collectionFileName)
0043     , m_nam(new HelpNetworkAccessManager(&m_engine, this))
0044 {
0045     Q_UNUSED(args);
0046     if( !m_engine.setupData() ) {
0047         qCWarning(QTHELP) << "Couldn't setup QtHelp Collection file";
0048     }
0049     m_engine.setUsesFilterEngine(true);
0050 }
0051 
0052 
0053 QtHelpProviderAbstract::~QtHelpProviderAbstract()
0054 {
0055 }
0056 
0057 IDocumentation::Ptr QtHelpProviderAbstract::documentationForDeclaration(Declaration* dec) const
0058 {
0059     QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this);
0060     if (dec) {
0061         static const IndexedString qmlJs("QML/JS");
0062         QString id;
0063 
0064         {
0065             DUChainReadLocker lock;
0066             id = dec->qualifiedIdentifier().toString(RemoveTemplateInformation);
0067             if (dec->topContext()->parsingEnvironmentFile()->language() == qmlJs && !id.isEmpty())
0068                 id = QLatin1String("QML.") + id;
0069         }
0070 
0071         if (!id.isEmpty()) {
0072             const QList<QHelpLink> links = m_engine.documentsForIdentifier(id);
0073             if(!links.isEmpty())
0074                 return IDocumentation::Ptr(new QtHelpDocumentation(id, links));
0075         }
0076     }
0077 
0078     return {};
0079 }
0080 
0081 KDevelop::IDocumentation::Ptr QtHelpProviderAbstract::documentation(const QUrl& url) const
0082 {
0083     QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this);
0084     //findFile returns a valid url even if we don't have a page for that documentationForURL
0085     auto data = m_engine.fileData(url);
0086     return data.isEmpty() ? IDocumentation::Ptr{} : documentationPtrFromUrl(url);
0087 }
0088 
0089 QAbstractItemModel* QtHelpProviderAbstract::indexModel() const
0090 {
0091     QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this);
0092     return m_engine.indexModel();
0093 }
0094 
0095 IDocumentation::Ptr QtHelpProviderAbstract::documentationForIndex(const QModelIndex& idx) const
0096 {
0097     QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this);
0098     QString name = idx.data(Qt::DisplayRole).toString();
0099     return IDocumentation::Ptr(new QtHelpDocumentation(name, m_engine.documentsForKeyword(name)));
0100 }
0101 
0102 void QtHelpProviderAbstract::jumpedTo(const QUrl& newUrl)
0103 {
0104     auto doc = documentation(newUrl);
0105     IDocumentationController* controller = ICore::self()->documentationController();
0106     if (!doc) {
0107         doc = controller->documentation(newUrl);
0108         if (!doc) {
0109             // Follow the unsupported link and run the risk of displaying a blank page
0110             // if this is a broken local link. If this is an external link, we can follow it
0111             // and show the webpage. Our support for website navigation is pretty good.
0112             doc = documentationPtrFromUrl(newUrl);
0113         }
0114     }
0115     controller->showDocumentation(doc);
0116 }
0117 
0118 IDocumentation::Ptr QtHelpProviderAbstract::homePage() const
0119 {
0120     QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this);
0121     return IDocumentation::Ptr(new HomeDocumentation);
0122 }
0123 
0124 bool QtHelpProviderAbstract::isValid() const
0125 {
0126     return !m_engine.registeredDocumentations().isEmpty();
0127 }
0128 
0129 HelpNetworkAccessManager * QtHelpProviderAbstract::networkAccess() const
0130 {
0131     return m_nam;
0132 }
0133 
0134 #include "moc_qthelpproviderabstract.cpp"