diff --git a/CMakeLists.txt b/CMakeLists.txt index 4230cbfa34..22d9b1ca8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,153 +1,153 @@ cmake_minimum_required(VERSION 2.8.12) # KDevelop version set(KDEVELOP_VERSION_MAJOR 5) set(KDEVELOP_VERSION_MINOR 1) set(KDEVELOP_VERSION_PATCH 40) set( KDEVELOP_VERSION "${KDEVELOP_VERSION_MAJOR}.${KDEVELOP_VERSION_MINOR}.${KDEVELOP_VERSION_PATCH}" ) project(KDevelop) # we need some parts of the ECM CMake helpers find_package (ECM 0.0.9 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${KDevelop_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH}) include(KDECompilerSettings NO_POLICY_SCOPE) # needs to be first, as set policies influence following macros include(ECMOptionalAddSubdirectory) include(ECMInstallIcons) include(ECMAddAppIcon) include(ECMSetupVersion) include(ECMAddTests) include(ECMMarkNonGuiExecutable) include(ECMGenerateHeaders) include(ECMPackageConfigHelpers) include(CTest) include(GenerateExportHeader) include(CMakePackageConfigHelpers) include(FeatureSummary) include(WriteBasicConfigVersionFile) include(CheckFunctionExists) include(KDEInstallDirs) include(KDECMakeSettings) set(QT_MIN_VERSION "5.4.0") -find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Widgets Concurrent Quick QuickWidgets WebKitWidgets Test) +find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Widgets Concurrent Quick QuickWidgets WebEngineWidgets Test) set(KF5_DEP_VERSION "5.15.0") # we need KCrash::initialize find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS Config Declarative DocTools IconThemes I18n ItemModels ItemViews JobWidgets KCMUtils KIO NewStuff NotifyConfig Parts Service TextEditor ThreadWeaver XmlGui WindowSystem Crash ) find_package(KF5SysGuard) set_package_properties(KF5SysGuard PROPERTIES PURPOSE "Framework for process listing. Required for the 'Attach to Process' feature" ) find_package(KDevelop-PG-Qt 1.90.90) set_package_properties(KDevelop-PG-Qt PROPERTIES PURPOSE "KDevelop parser generator library. Required for the QMake Builder/Manager plugin." ) find_package(KDevPlatform ${KDEVELOP_VERSION} REQUIRED) add_definitions( -DQT_DEPRECATED_WARNINGS -DQT_DISABLE_DEPRECATED_BEFORE=0x050400 -DQT_NO_URL_CAST_FROM_STRING -DQT_STRICT_ITERATORS -DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS ) # Turn off missing-field-initializers warning to avoid noise from false positives with empty {} # See discussion: http://mail.kde.org/pipermail/kdevelop-devel/2014-February/046910.html check_cxx_compiler_flag(-Wno-missing-field-initializers HAVE_MFI_FLAG) check_cxx_compiler_flag(-Werror=undefined-bool-conversion HAVE_UBC_FLAG) check_cxx_compiler_flag(-Werror=tautological-undefined-compare HAVE_TUC_FLAG) if (HAVE_MFI_FLAG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers") endif() if (HAVE_UBC_FLAG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=undefined-bool-conversion") endif() if (HAVE_TUC_FLAG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=tautological-undefined-compare") endif() if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdocumentation") endif() include_directories(${KDevelop_SOURCE_DIR} ${KDevelop_BINARY_DIR} ) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_TOLOWER) if(CMAKE_BUILD_TYPE_TOLOWER MATCHES "debug" OR CMAKE_BUILD_TYPE_TOLOWER STREQUAL "") set(COMPILER_OPTIMIZATIONS_DISABLED TRUE) else() set(COMPILER_OPTIMIZATIONS_DISABLED FALSE) endif() # create config.h configure_file (config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h ) add_subdirectory(pics) add_subdirectory(app) add_subdirectory(analyzers) add_subdirectory(formatters) add_subdirectory(languages) add_subdirectory(projectbuilders) add_subdirectory(projectmanagers) add_subdirectory(debuggers) add_subdirectory(app_templates) add_subdirectory(documentation) add_subdirectory(kdeintegration) add_subdirectory(utils) add_subdirectory(file_templates) add_subdirectory(providers) add_subdirectory(shortcuts) add_subdirectory(doc) set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KDevelop") ecm_configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KDevelopConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KDevelopConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) ecm_setup_version(${KDEVELOP_VERSION_MAJOR}.${KDEVELOP_VERSION_MINOR}.${KDEVELOP_VERSION_PATCH} VARIABLE_PREFIX KDEVELOP VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdevelop_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KDevelopConfigVersion.cmake" SOVERSION ${KDEVELOP_LIB_SOVERSION} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kdevelop_version.h" DESTINATION "${KDE_INSTALL_INCLUDEDIR}/kdevelop") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KDevelopConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KDevelopConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" ) install(EXPORT KDevelopTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" NAMESPACE KDev:: FILE KDevelopTargets.cmake) # CTestCustom.cmake has to be in the CTEST_BINARY_DIR. # in the KDE build system, this is the same as CMAKE_BINARY_DIR. configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_BINARY_DIR}/CTestCustom.cmake) install(FILES org.kde.kdevelop.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/documentation/manpage/manpagedocumentation.cpp b/documentation/manpage/manpagedocumentation.cpp index 15c91e6b0e..69e9009dda 100644 --- a/documentation/manpage/manpagedocumentation.cpp +++ b/documentation/manpage/manpagedocumentation.cpp @@ -1,100 +1,97 @@ /* This file is part of KDevelop Copyright 2010 Yannick Motta Copyright 2010 Benjamin Port This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "manpagedocumentation.h" #include "manpageplugin.h" #include "manpagedocumentationwidget.h" #include #include #include ManPagePlugin* ManPageDocumentation::s_provider=nullptr; - ManPageDocumentation::ManPageDocumentation(const QString& name, const QUrl& url) : m_url(url), m_name(name) { KIO::StoredTransferJob* transferJob = KIO::storedGet(m_url, KIO::NoReload, KIO::HideProgressInfo); connect( transferJob, &KIO::StoredTransferJob::finished, this, &ManPageDocumentation::finished); transferJob->start(); } void ManPageDocumentation::finished(KJob* j) { KIO::StoredTransferJob* job = qobject_cast(j); if(job && job->error()==0) { m_description = QString::fromUtf8(job->data()); } else { m_description.clear(); } emit descriptionChanged(); } KDevelop::IDocumentationProvider* ManPageDocumentation::provider() const { return s_provider; } QString ManPageDocumentation::description() const { return m_description; } QWidget* ManPageDocumentation::documentationWidget(KDevelop::DocumentationFindWidget* findWidget, QWidget* parent ) { KDevelop::StandardDocumentationView* view = new KDevelop::StandardDocumentationView(findWidget, parent); view->setDocumentation(IDocumentation::Ptr(this)); + view->setDelegateLinks(true); + QObject::connect(view, &KDevelop::StandardDocumentationView::linkClicked, ManPageDocumentation::s_provider->model(), &ManPageModel::showItemFromUrl); // apply custom style-sheet to normalize look of the page const QString cssFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kdevmanpage/manpagedocumentation.css"); - QWebSettings* settings = view->settings(); - settings->setUserStyleSheetUrl(QUrl::fromLocalFile(cssFile)); - - view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); - QObject::connect(view, &KDevelop::StandardDocumentationView::linkClicked, ManPageDocumentation::s_provider->model(), &ManPageModel::showItemFromUrl); + view->setOverrideCss(QUrl::fromLocalFile(cssFile)); return view; } bool ManPageDocumentation::providesWidget() const { return false; } QWidget* ManPageHomeDocumentation::documentationWidget(KDevelop::DocumentationFindWidget *findWidget, QWidget *parent){ Q_UNUSED(findWidget); return new ManPageDocumentationWidget(parent); } QString ManPageHomeDocumentation::name() const { return i18n("Man Content Page"); } KDevelop::IDocumentationProvider* ManPageHomeDocumentation::provider() const { return ManPageDocumentation::s_provider; } diff --git a/documentation/qthelp/qthelpdocumentation.cpp b/documentation/qthelp/qthelpdocumentation.cpp index a1f292bca9..dc8850faf4 100644 --- a/documentation/qthelp/qthelpdocumentation.cpp +++ b/documentation/qthelp/qthelpdocumentation.cpp @@ -1,357 +1,352 @@ /* This file is part of KDevelop Copyright 2009 Aleix Pol Copyright 2009 David Nolden Copyright 2010 Benjamin Port This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "qthelpdocumentation.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "qthelpnetwork.h" #include "qthelpproviderabstract.h" using namespace KDevelop; namespace { #if QT_VERSION >= 0x050500 int indexOf(const QString& str, const QRegularExpression& re, int from, QRegularExpressionMatch* rmatch) { return str.indexOf(re, from, rmatch); } int lastIndexOf(const QString& str, const QRegularExpression& re, int from, QRegularExpressionMatch* rmatch) { return str.lastIndexOf(re, from, rmatch); } #else int indexOf(const QString& str, const QRegularExpression& re, int from, QRegularExpressionMatch* rmatch) { if (!re.isValid()) { qWarning("QString::indexOf: invalid QRegularExpression object"); return -1; } QRegularExpressionMatch match = re.match(str, from); if (match.hasMatch()) { const int ret = match.capturedStart(); if (rmatch) *rmatch = qMove(match); return ret; } return -1; } int lastIndexOf(const QString &str, const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) { if (!re.isValid()) { qWarning("QString::lastIndexOf: invalid QRegularExpression object"); return -1; } int endpos = (from < 0) ? (str.size() + from + 1) : (from + 1); QRegularExpressionMatchIterator iterator = re.globalMatch(str); int lastIndex = -1; while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); int start = match.capturedStart(); if (start < endpos) { lastIndex = start; if (rmatch) *rmatch = qMove(match); } else { break; } } return lastIndex; } #endif } QtHelpProviderAbstract* QtHelpDocumentation::s_provider=nullptr; QtHelpDocumentation::QtHelpDocumentation(const QString& name, const QMap& info) : m_provider(s_provider), m_name(name), m_info(info), m_current(info.constBegin()), lastView(nullptr) {} QtHelpDocumentation::QtHelpDocumentation(const QString& name, const QMap& info, const QString& key) : m_provider(s_provider), m_name(name), m_info(info), m_current(m_info.find(key)), lastView(nullptr) { Q_ASSERT(m_current!=m_info.constEnd()); } QtHelpDocumentation::~QtHelpDocumentation() { } QString QtHelpDocumentation::description() const { QUrl url(m_current.value()); QByteArray data = m_provider->engine()->fileData(url); //Extract a short description from the html data const QString dataString = QString::fromLatin1(data); ///@todo encoding const QString fragment = url.fragment(); const QString p = QStringLiteral("((\\\")|(\\\'))"); const QString optionalSpace = QStringLiteral("( )*"); const QString exp = QString("< a name = " + p + fragment + p + " > < / a >").replace(' ', optionalSpace); const QRegularExpression findFragment(exp); QRegularExpressionMatch findFragmentMatch; int pos = indexOf(dataString, findFragment, 0, &findFragmentMatch); if(fragment.isEmpty()) { pos = 0; } else { //Check if there is a title opening-tag right before the fragment, and if yes add it, so we have a nicely formatted caption const QString titleRegExp = QStringLiteral("< h\\d class = \".*\" >").replace(' ', optionalSpace); const QRegularExpression findTitle(titleRegExp); const QRegularExpressionMatch match = findTitle.match(dataString, pos); const int titleStart = match.capturedStart(); const int titleEnd = titleStart + match.capturedEnd(); if(titleStart != -1) { const QStringRef between = dataString.midRef(titleEnd, pos-titleEnd).trimmed(); if(between.isEmpty()) pos = titleStart; } } if(pos != -1) { const QString exp = QString("< a name = " + p + "((\\S)*)" + p + " > < / a >").replace(' ', optionalSpace); const QRegularExpression nextFragmentExpression(exp); int endPos = dataString.indexOf(nextFragmentExpression, pos+(fragment.size() ? findFragmentMatch.capturedLength() : 0)); if(endPos == -1) { endPos = dataString.size(); } { //Find the end of the last paragraph or newline, so we don't add prefixes of the following fragment const QString newLineRegExp = QStringLiteral ("< br / > | < / p >").replace(' ', optionalSpace); const QRegularExpression lastNewLine(newLineRegExp); QRegularExpressionMatch match; const int newEnd = lastIndexOf(dataString, lastNewLine, endPos, &match); if(match.isValid() && newEnd > pos) endPos = newEnd + match.capturedLength(); } { //Find the title, and start from there const QString titleRegExp = QStringLiteral("< h\\d class = \"title\" >").replace(' ', optionalSpace); const QRegularExpression findTitle(titleRegExp); const QRegularExpressionMatch match = findTitle.match(dataString); if (match.isValid()) pos = qBound(pos, match.capturedStart(), endPos); } QString thisFragment = dataString.mid(pos, endPos - pos); { //Completely remove the first large header found, since we don't need a header const QString headerRegExp = QStringLiteral("< h\\d.*>.*?< / h\\d >").replace(' ', optionalSpace); const QRegularExpression findHeader(headerRegExp); const QRegularExpressionMatch match = findHeader.match(thisFragment); if(match.isValid()) { thisFragment.remove(match.capturedStart(), match.capturedLength()); } } { //Replace all gigantic header-font sizes with { const QString sizeRegExp = QStringLiteral("< h\\d ").replace(' ', optionalSpace); const QRegularExpression findSize(sizeRegExp); thisFragment.replace(findSize, "").replace(' ', optionalSpace); const QRegularExpression closeSize(sizeCloseRegExp); thisFragment.replace(closeSize, "
"); } } { //Replace paragraphs by newlines const QString begin = QStringLiteral("< p >").replace(' ', optionalSpace); const QRegularExpression findBegin(begin); thisFragment.replace(findBegin, {}); const QString end = QStringLiteral("< /p >").replace(' ', optionalSpace); const QRegularExpression findEnd(end); thisFragment.replace(findEnd, "
"); } { //Remove links, because they won't work const QString link = QString("< a href = " + p + ".*?" + p).replace(' ', optionalSpace); const QRegularExpression exp(link, QRegularExpression::CaseInsensitiveOption); thisFragment.replace(exp, "open(); QTextStream ts(file); ts << "html { background: white !important; }\n"; if (url.scheme() == "qthelp" && url.host().startsWith("com.trolltech.qt.")) { ts << ".content .toc + .title + p { clear:left; }\n" << "#qtdocheader .qtref { position: absolute !important; top: 5px !important; right: 0 !important; }\n"; } file->close(); - view->settings()->setUserStyleSheetUrl(QUrl::fromLocalFile(file->fileName())); + view->setOverrideCss(QUrl::fromLocalFile(file->fileName())); delete m_lastStyleSheet.data(); m_lastStyleSheet = file; } QWidget* QtHelpDocumentation::documentationWidget(DocumentationFindWidget* findWidget, QWidget* parent) { if(m_info.isEmpty()) { //QtHelp sometimes has empty info maps. e.g. availableaudioeffects i 4.5.2 return new QLabel(i18n("Could not find any documentation for '%1'", m_name), parent); } else { StandardDocumentationView* view = new StandardDocumentationView(findWidget, parent); // QCH files created by doxygen can come with JavaScript - view->settings()->setAttribute(QWebSettings::JavascriptEnabled, true); if (!m_sharedQNAM) { m_sharedQNAM.reset(new HelpNetworkAccessManager(m_provider->engine())); } - view->page()->setNetworkAccessManager(m_sharedQNAM.data()); - view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); + view->setNetworkAccessManager(m_sharedQNAM.data()); view->setContextMenuPolicy(Qt::CustomContextMenu); connect(view, &StandardDocumentationView::customContextMenuRequested, this, &QtHelpDocumentation::viewContextMenuRequested); - QObject::connect(view, &StandardDocumentationView::linkClicked, this, &QtHelpDocumentation::jumpedTo); - setUserStyleSheet(view, m_current.value()); - view->setHtml(m_provider->engine()->fileData(m_current.value())); - view->setUrl(m_current.value()); + view->load(m_current.value()); lastView = view; return view; } } void QtHelpDocumentation::viewContextMenuRequested(const QPoint& pos) { StandardDocumentationView* view = qobject_cast(sender()); if (!view) return; QMenu menu; - QAction* copyAction = view->pageAction(QWebPage::Copy); + QAction* copyAction = view->copyAction(); copyAction->setIcon(QIcon::fromTheme("edit-copy")); menu.addAction(copyAction); if (m_info.count() > 1) { menu.addSeparator(); QActionGroup* actionGroup = new QActionGroup(&menu); foreach(const QString& name, m_info.keys()) { QtHelpAlternativeLink* act=new QtHelpAlternativeLink(name, this, actionGroup); act->setCheckable(true); act->setChecked(name==m_current.key()); menu.addAction(act); } } menu.exec(view->mapToGlobal(pos)); } void QtHelpDocumentation::jumpedTo(const QUrl& newUrl) { Q_ASSERT(lastView); m_provider->jumpedTo(newUrl); setUserStyleSheet(lastView, newUrl); lastView->load(newUrl); } IDocumentationProvider* QtHelpDocumentation::provider() const { return m_provider; } QtHelpAlternativeLink::QtHelpAlternativeLink(const QString& name, const QtHelpDocumentation* doc, QObject* parent) : QAction(name, parent), mDoc(doc), mName(name) { connect(this, &QtHelpAlternativeLink::triggered, this, &QtHelpAlternativeLink::showUrl); } void QtHelpAlternativeLink::showUrl() { IDocumentation::Ptr newDoc(new QtHelpDocumentation(mName, mDoc->info(), mName)); ICore::self()->documentationController()->showDocumentation(newDoc); } HomeDocumentation::HomeDocumentation() : m_provider(QtHelpDocumentation::s_provider) { } QWidget* HomeDocumentation::documentationWidget(DocumentationFindWidget*, QWidget* parent) { QTreeView* w=new QTreeView(parent); w->header()->setVisible(false); w->setModel(m_provider->engine()->contentModel()); connect(w, &QTreeView::clicked, this, &HomeDocumentation::clicked); return w; } void HomeDocumentation::clicked(const QModelIndex& idx) { QHelpContentModel* model = m_provider->engine()->contentModel(); QHelpContentItem* it=model->contentItemAt(idx); QMap info; info.insert(it->title(), it->url()); IDocumentation::Ptr newDoc(new QtHelpDocumentation(it->title(), info)); ICore::self()->documentationController()->showDocumentation(newDoc); } QString HomeDocumentation::name() const { return i18n("QtHelp Home Page"); } IDocumentationProvider* HomeDocumentation::provider() const { return m_provider; } diff --git a/documentation/qthelp/qthelpdocumentation.h b/documentation/qthelp/qthelpdocumentation.h index 97f27aa72d..99690e7313 100644 --- a/documentation/qthelp/qthelpdocumentation.h +++ b/documentation/qthelp/qthelpdocumentation.h @@ -1,107 +1,107 @@ /* This file is part of KDevelop Copyright 2009 Aleix Pol Copyright 2009 David Nolden Copyright 2010 Benjamin Port This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef QTHELPDOCUMENTATION_H #define QTHELPDOCUMENTATION_H #include #include #include #include #include +namespace KDevelop { class StandardDocumentationView; } class QModelIndex; class QNetworkAccessManager; -class QWebView; class QtHelpProviderAbstract; class QTemporaryFile; class QtHelpDocumentation : public KDevelop::IDocumentation { Q_OBJECT public: QtHelpDocumentation(const QString& name, const QMap& info); QtHelpDocumentation(const QString& name, const QMap& info, const QString& key); ~QtHelpDocumentation() override; QString name() const override { return m_name; } QString description() const override; QWidget* documentationWidget(KDevelop::DocumentationFindWidget* findWidget, QWidget* parent) override; KDevelop::IDocumentationProvider* provider() const override; QMap info() const { return m_info; } static QtHelpProviderAbstract* s_provider; public slots: void viewContextMenuRequested(const QPoint& pos); private slots: void jumpedTo(const QUrl& newUrl); private: - void setUserStyleSheet(QWebView* view, const QUrl& url); + void setUserStyleSheet(KDevelop::StandardDocumentationView* view, const QUrl& url); private: QtHelpProviderAbstract *m_provider; const QString m_name; const QMap m_info; const QMap::const_iterator m_current; - QWebView* lastView; + KDevelop::StandardDocumentationView* lastView; QPointer m_lastStyleSheet; QScopedPointer m_sharedQNAM; }; class HomeDocumentation : public KDevelop::IDocumentation { Q_OBJECT public: HomeDocumentation(); QWidget* documentationWidget(KDevelop::DocumentationFindWidget* findWidget, QWidget* parent = nullptr) override; QString description() const override { return QString(); } QString name() const override; KDevelop::IDocumentationProvider* provider() const override; public slots: void clicked(const QModelIndex& idx); private: QtHelpProviderAbstract *m_provider; }; class QtHelpAlternativeLink : public QAction { Q_OBJECT public: QtHelpAlternativeLink(const QString& name, const QtHelpDocumentation* doc, QObject* parent); public slots: void showUrl(); private: const QtHelpDocumentation* mDoc; const QString mName; }; #endif diff --git a/projectmanagers/cmake/cmakedocumentation.cpp b/projectmanagers/cmake/cmakedocumentation.cpp index 3d67b6c15f..d9fdb4bcb6 100644 --- a/projectmanagers/cmake/cmakedocumentation.cpp +++ b/projectmanagers/cmake/cmakedocumentation.cpp @@ -1,203 +1,204 @@ /* KDevelop CMake Support * * Copyright 2009 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "cmakedocumentation.h" #include "cmakeutils.h" #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include "cmakemanager.h" #include "cmakehelpdocumentation.h" #include "cmakedoc.h" #include "debug.h" K_PLUGIN_FACTORY_WITH_JSON(CMakeSupportDocFactory, "kdevcmakedocumentation.json", registerPlugin(); ) CMakeDocumentation* CMakeDoc::s_provider=nullptr; KDevelop::IDocumentationProvider* CMakeDoc::provider() const { return s_provider; } CMakeDocumentation::CMakeDocumentation(QObject* parent, const QVariantList&) : KDevelop::IPlugin( "kdevcmakedocumentation", parent ) , m_cmakeExecutable(CMake::findExecutable()) , m_index(nullptr) { if (m_cmakeExecutable.isEmpty()) { setErrorDescription(i18n("Unable to find a CMake executable. Is one installed on the system?")); return; } CMakeDoc::s_provider=this; m_index= new QStringListModel(this); initializeModel(); } static const char* const args[] = { "--help-command", "--help-variable", "--help-module", "--help-property", nullptr, nullptr }; void CMakeDocumentation::delayedInitialization() { for(int i=0; i<=Property; i++) { collectIds(QString(args[i])+"-list", (Type) i); } m_index->setStringList(m_typeForName.keys()); } void CMakeDocumentation::collectIds(const QString& param, Type type) { QStringList ids = CMake::executeProcess(m_cmakeExecutable, QStringList(param)).split(QLatin1Char('\n')); ids.takeFirst(); foreach(const QString& name, ids) { m_typeForName[name]=type; } } QStringList CMakeDocumentation::names(CMakeDocumentation::Type t) const { return m_typeForName.keys(t); } QString CMakeDocumentation::descriptionForIdentifier(const QString& id, Type t) const { QString desc; if(args[t]) { desc = CMake::executeProcess(m_cmakeExecutable, { args[t], id.simplified() }); desc = desc.remove(":ref:"); const QString rst2html = QStandardPaths::findExecutable(QStringLiteral("rst2html")); if (rst2html.isEmpty()) { desc = ("
" + desc.toHtmlEscaped() + "
" + i18n("

For better cmake documentation rendering, install rst2html

") + ""); } else { QProcess p; p.start(rst2html, { "--no-toc-backlinks" }); p.write(desc.toUtf8()); p.closeWriteChannel(); p.waitForFinished(); desc = QString::fromUtf8(p.readAllStandardOutput()); } } return desc; } KDevelop::IDocumentation::Ptr CMakeDocumentation::description(const QString& identifier, const QUrl &file) const { initializeModel(); //make it not queued if (!file.isEmpty() && !QMimeDatabase().mimeTypeForUrl(file).inherits("text/x-cmake")) { return KDevelop::IDocumentation::Ptr(); } QString desc; if(m_typeForName.contains(identifier)) { desc=descriptionForIdentifier(identifier, m_typeForName[identifier]); } else if(m_typeForName.contains(identifier.toLower())) { desc=descriptionForIdentifier(identifier, m_typeForName[identifier.toLower()]); } else if(m_typeForName.contains(identifier.toUpper())) { desc=descriptionForIdentifier(identifier, m_typeForName[identifier.toUpper()]); } KDevelop::IProject* p=KDevelop::ICore::self()->projectController()->findProjectForUrl(file); ICMakeManager* m=nullptr; if(p) m=p->managerPlugin()->extension(); if(m) { QPair entry = m->cacheValue(p, identifier); if(!entry.first.isEmpty()) desc += i18n("
Cache Value: %1\n", entry.first); if(!entry.second.isEmpty()) desc += i18n("
Cache Documentation: %1\n", entry.second); } if(desc.isEmpty()) return KDevelop::IDocumentation::Ptr(); else return KDevelop::IDocumentation::Ptr(new CMakeDoc(identifier, desc)); } KDevelop::IDocumentation::Ptr CMakeDocumentation::documentationForDeclaration(KDevelop::Declaration* decl) const { return description(decl->identifier().toString(), decl->url().toUrl()); } KDevelop::IDocumentation::Ptr CMakeDocumentation::documentationForIndex(const QModelIndex& idx) const { return description(idx.data().toString(), QUrl()); } QAbstractListModel* CMakeDocumentation::indexModel() const { initializeModel(); return m_index; } QIcon CMakeDocumentation::icon() const { return QIcon::fromTheme("cmake"); } QString CMakeDocumentation::name() const { return "CMake"; } KDevelop::IDocumentation::Ptr CMakeDocumentation::homePage() const { if(m_typeForName.isEmpty()) const_cast(this)->delayedInitialization(); // initializeModel(); return KDevelop::IDocumentation::Ptr(new CMakeHomeDocumentation); } void CMakeDocumentation::initializeModel() const { if(!m_typeForName.isEmpty()) return; QMetaObject::invokeMethod(const_cast(this), "delayedInitialization", Qt::QueuedConnection); } //////////CMakeDoc QWidget* CMakeDoc::documentationWidget(KDevelop::DocumentationFindWidget* findWidget, QWidget* parent) { KDevelop::StandardDocumentationView* view = new KDevelop::StandardDocumentationView(findWidget, parent); view->setHtml(mDesc); return view; } #include "cmakedocumentation.moc"