diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ab75d65aa..9ec87ba537 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,176 +1,176 @@ cmake_minimum_required(VERSION 2.8.12) # kdevplatform version set(KDEVPLATFORM_VERSION_MAJOR 5) set(KDEVPLATFORM_VERSION_MINOR 1) set(KDEVPLATFORM_VERSION_PATCH 40) # plugin versions listed in the .desktop files set(KDEV_PLUGIN_VERSION 27) # Increase this to reset incompatible item-repositories set(KDEV_ITEMREPOSITORY_VERSION 86) # library version / SO version set(KDEVPLATFORM_LIB_VERSION 10.0.0) set(KDEVPLATFORM_LIB_SOVERSION 10) project(KDevPlatform) # we need some parts of the ECM CMake helpers find_package (ECM 0.0.9 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${KDevPlatform_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH}) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMAddTests) include(ECMOptionalAddSubdirectory) include(ECMInstallIcons) include(ECMSetupVersion) include(ECMMarkAsTest) include(ECMMarkNonGuiExecutable) include(ECMGenerateHeaders) include(ECMPackageConfigHelpers) include(GenerateExportHeader) include(FeatureSummary) include(WriteBasicConfigVersionFile) include(CheckFunctionExists) include(KDEInstallDirs) include(KDECMakeSettings) include(KDevPlatformMacros) set(QT_MIN_VERSION "5.4.0") -find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Core DBus Widgets WebKitWidgets Concurrent Test) +find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Core DBus Widgets Concurrent Test) find_package(Qt5QuickWidgets ${QT_MIN_VERSION}) set_package_properties(Qt5QuickWidgets PROPERTIES PURPOSE "Qt5 QuickWidgets library (part of Qt >=5.3). Required for the Welcome Page plugin." ) set(KF5_DEP_VERSION "5.18.0") # need KAboutData::fromPluginMetaData in kcoreaddons find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS Archive Config GuiAddons WidgetsAddons IconThemes I18n ItemModels ItemViews JobWidgets KCMUtils KIO NewStuff Notifications NotifyConfig Parts Service Sonnet TextEditor ThreadWeaver WindowSystem Declarative XmlGui ) find_package(Grantlee5) set_package_properties(Grantlee5 PROPERTIES PURPOSE "Grantlee templating library, needed for file templates" URL "http://www.grantlee.org/" TYPE RECOMMENDED) set(Boost_ADDITIONAL_VERSIONS 1.39.0 1.39) find_package(Boost 1.35.0) set_package_properties(Boost PROPERTIES PURPOSE "Boost libraries for enabling the classbrowser" URL "http://www.boost.org" TYPE 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 for GCC 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() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config-kdevplatform.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kdevplatform.h ) include_directories(${KDevPlatform_SOURCE_DIR} ${KDevPlatform_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() add_subdirectory(sublime) add_subdirectory(interfaces) add_subdirectory(project) add_subdirectory(language) add_subdirectory(shell) add_subdirectory(util) add_subdirectory(outputview) add_subdirectory(vcs) add_subdirectory(pics) add_subdirectory(debugger) add_subdirectory(documentation) add_subdirectory(serialization) add_subdirectory(template) add_subdirectory(tests) add_subdirectory(plugins) set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KDevPlatform") ecm_configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KDevPlatformConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KDevPlatformConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) ecm_setup_version(${KDEVPLATFORM_VERSION_MAJOR}.${KDEVPLATFORM_VERSION_MINOR}.${KDEVPLATFORM_VERSION_PATCH} VARIABLE_PREFIX KDEVPLATFORM VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdevplatform_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KDevPlatformConfigVersion.cmake" SOVERSION ${KDEVPLATFORM_LIB_SOVERSION}) install( FILES "${KDevPlatform_BINARY_DIR}/kdevplatform_version.h" "${KDevPlatform_BINARY_DIR}/config-kdevplatform.h" DESTINATION "${KDE_INSTALL_INCLUDEDIR}/kdevplatform" ) install( FILES "${KDevPlatform_BINARY_DIR}/KDevPlatformConfig.cmake" "${KDevPlatform_BINARY_DIR}/KDevPlatformConfigVersion.cmake" cmake/modules/KDevPlatformMacros.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" ) install( EXPORT KDevPlatformTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" NAMESPACE KDev:: FILE KDevPlatformTargets.cmake ) include(CTest) # 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) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/documentation/CMakeLists.txt b/documentation/CMakeLists.txt index ff57e258ab..b8076cdef7 100644 --- a/documentation/CMakeLists.txt +++ b/documentation/CMakeLists.txt @@ -1,24 +1,40 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kdevplatform\") -set_package_properties(Qt5WebKitWidgets PROPERTIES - PURPOSE "QtWebKit, for integrated documentation" - URL "http://qt-project.org/" - TYPE REQUIRED) +find_package(Qt5WebEngineWidgets) +if(TARGET Qt5::WebEngineWidgets) + set_package_properties(Qt5WebEngineWidgets PROPERTIES + PURPOSE "QtWebKit, for integrated documentation" + URL "http://qt-project.org/" + TYPE REQUIRED) +else() + find_package(Qt5WebKitWidgets) + set_package_properties(Qt5WebKitWidgets PROPERTIES + PURPOSE "QtWebKit, for integrated documentation" + URL "http://qt-project.org/" + TYPE REQUIRED) + set(USE_QTWEBKIT 1) +endif() set(KDevPlatformDocumentation_LIB_SRCS standarddocumentationview.cpp documentationfindwidget.cpp documentationview.cpp ) ki18n_wrap_ui(KDevPlatformDocumentation_LIB_SRCS documentationfindwidget.ui) kdevplatform_add_library(KDevPlatformDocumentation SOURCES ${KDevPlatformDocumentation_LIB_SRCS}) -target_link_libraries(KDevPlatformDocumentation - LINK_PUBLIC KDev::Interfaces Qt5::WebKitWidgets) +target_link_libraries(KDevPlatformDocumentation PUBLIC KDev::Interfaces) + +if(USE_QTWEBKIT) + target_link_libraries(KDevPlatformDocumentation PRIVATE Qt5::WebKitWidgets) + target_compile_definitions(KDevPlatformDocumentation PRIVATE -DUSE_QTWEBKIT) +else() + target_link_libraries(KDevPlatformDocumentation PRIVATE Qt5::WebEngineWidgets) +endif() install(FILES documentationfindwidget.h standarddocumentationview.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/documentation COMPONENT Devel ) diff --git a/documentation/standarddocumentationview.cpp b/documentation/standarddocumentationview.cpp index a192e6fd9f..48654b6dd0 100644 --- a/documentation/standarddocumentationview.cpp +++ b/documentation/standarddocumentationview.cpp @@ -1,110 +1,251 @@ /* * This file is part of KDevelop * Copyright 2010 Aleix Pol Gonzalez * * This program 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 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 "standarddocumentationview.h" #include "documentationfindwidget.h" #include "debug.h" +#include + +#ifdef USE_QTWEBKIT #include +#include #include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif using namespace KDevelop; +struct KDevelop::StandardDocumentationViewPrivate +{ + IDocumentation::Ptr m_doc; + +#ifdef USE_QTWEBKIT + QWebView *m_view = nullptr; + void init(QWidget* parent) { m_view = new QWebView(parent); } +#else + QWebEngineView* m_view = nullptr; + void init(QWidget* parent) { m_view = new QWebEngineView(parent); } +#endif +}; + StandardDocumentationView::StandardDocumentationView(DocumentationFindWidget* findWidget, QWidget* parent) - : QWebView(parent) + : QWidget(parent) + , d(new StandardDocumentationViewPrivate) { + setLayout(new QVBoxLayout(this)); + d->init(this); + layout()->addWidget(d->m_view); + findWidget->setEnabled(true); connect(findWidget, &DocumentationFindWidget::newSearch, this, &StandardDocumentationView::search); +#ifdef USE_QTWEBKIT QFont sansSerifFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); QFont monospaceFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); QFont minimalFont = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); - QWebSettings* s = settings(); + QWebSettings* s = d->m_view->settings(); s->setFontFamily(QWebSettings::StandardFont, sansSerifFont.family()); s->setFontFamily(QWebSettings::SerifFont, "Serif"); s->setFontFamily(QWebSettings::SansSerifFont, sansSerifFont.family()); s->setFontFamily(QWebSettings::FixedFont, monospaceFont.family()); s->setFontSize(QWebSettings::DefaultFontSize, QFontInfo(sansSerifFont).pixelSize()); s->setFontSize(QWebSettings::DefaultFixedFontSize, QFontInfo(monospaceFont).pixelSize()); s->setFontSize(QWebSettings::MinimumFontSize, QFontInfo(minimalFont).pixelSize()); // Fixes for correct positioning. The problem looks like the following: // // 1) Some page is loaded and loadFinished() signal is emitted, // after this QWebView set right position inside page. // // 2) After loadFinished() emitting, page JS code finishes it's work and changes // font settings (size). This leads to page contents "moving" inside view widget // and as a result we have wrong position. // // Such behavior occurs for example with QtHelp pages. // // To fix the problem, first, we disable view painter updates during load to avoid content // "flickering" and also to hide font size "jumping". Secondly, we reset position inside page // after loading with using standard QWebFrame method scrollToAnchor(). - connect(this, &QWebView::loadStarted, this, [this]() { - setUpdatesEnabled(false); + connect(d->m_view, &QWebView::loadStarted, d->m_view, [this]() { + d->m_view->setUpdatesEnabled(false); }); - connect(this, &QWebView::loadFinished, this, [this](bool) { - if (url().isValid()) { - page()->mainFrame()->scrollToAnchor(url().fragment()); + connect(d->m_view, &QWebView::loadFinished, this, [this](bool) { + if (d->m_view->url().isValid()) { + d->m_view->page()->mainFrame()->scrollToAnchor(d->m_view->url().fragment()); } setUpdatesEnabled(true); }); - +#endif } +KDevelop::StandardDocumentationView::~StandardDocumentationView() = default; + void StandardDocumentationView::search ( const QString& text, DocumentationFindWidget::FindOptions options ) { - //Highlighting has been commented because it doesn't let me jump around all occurrences -// page()->findText(QString(), QWebPage::HighlightAllOccurrences); - - QWebPage::FindFlags ff=QWebPage::FindWrapsAroundDocument /*| QWebPage::HighlightAllOccurrences*/; +#ifdef USE_QTWEBKIT + typedef QWebPage WebkitThing; +#else + typedef QWebEnginePage WebkitThing; +#endif + WebkitThing::FindFlags ff = 0; if(options & DocumentationFindWidget::Previous) - ff |= QWebPage::FindBackward; + ff |= WebkitThing::FindBackward; if(options & DocumentationFindWidget::MatchCase) - ff |= QWebPage::FindCaseSensitively; + ff |= WebkitThing::FindCaseSensitively; - page()->findText(text, ff); + d->m_view->page()->findText(text, ff); } void StandardDocumentationView::setDocumentation(const IDocumentation::Ptr& doc) { - if(m_doc) - disconnect(m_doc.data()); - m_doc = doc; + if(d->m_doc) + disconnect(d->m_doc.data()); + d->m_doc = doc; update(); - if(m_doc) - connect(m_doc.data(), &IDocumentation::descriptionChanged, this, &StandardDocumentationView::update); + if(d->m_doc) + connect(d->m_doc.data(), &IDocumentation::descriptionChanged, this, &StandardDocumentationView::update); } void StandardDocumentationView::update() { - if(m_doc) - setHtml(m_doc->description()); - else + if(d->m_doc) { + setHtml(d->m_doc->description()); + } else qCDebug(DOCUMENTATION) << "calling StandardDocumentationView::update() on an uninitialized view"; } + +void KDevelop::StandardDocumentationView::setOverrideCss(const QUrl& url) +{ +#ifdef USE_QTWEBKIT + d->m_view->settings()->setUserStyleSheetUrl(url); +#else + d->m_view->page()->runJavaScript( + "var link = document.createElement( 'link' );" + "link.href = " + url.toString().toUtf8() + ";" + "link.type = 'text/css';" + "link.rel = 'stylesheet';" + "link.media = 'screen,print';" + "document.getElementsByTagName( 'head' )[0].appendChild( link );" + ); +#endif +} + +void KDevelop::StandardDocumentationView::load(const QUrl& url) +{ +#ifdef USE_QTWEBKIT + d->m_view->load(url); +#else + d->m_view->page()->load(url); +#endif +} + +void KDevelop::StandardDocumentationView::setHtml(const QString& html) +{ +#ifdef USE_QTWEBKIT + d->m_view->setHtml(html); +#else + d->m_view->page()->setHtml(html); +#endif +} + +#ifndef USE_QTWEBKIT +class CustomSchemeHandler : public QWebEngineUrlSchemeHandler +{ +public: + explicit CustomSchemeHandler(QNetworkAccessManager* nam, QObject *parent = 0) + : QWebEngineUrlSchemeHandler(parent), m_nam(nam) {} + + void requestStarted(QWebEngineUrlRequestJob *job) override { + const QUrl url = job->requestUrl(); + + auto reply = m_nam->get(QNetworkRequest(url)); + job->reply("text/html", reply); + } + +private: + QNetworkAccessManager* m_nam; +}; +#endif + +void KDevelop::StandardDocumentationView::setNetworkAccessManager(QNetworkAccessManager* manager) +{ +#ifdef USE_QTWEBKIT + d->m_view->page()->setNetworkAccessManager(manager); +#else + d->m_view->page()->profile()->installUrlSchemeHandler("qthelp", new CustomSchemeHandler(manager, this)); +#endif +} + +#ifndef USE_QTWEBKIT +class PageInterceptor : public QWebEnginePage +{ +public: + PageInterceptor(KDevelop::StandardDocumentationView* parent) : QWebEnginePage(parent), m_view(parent) {} + + bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool /*isMainFrame*/) override { + qCDebug(DOCUMENTATION) << "navigating to..." << url << type; + if (type == NavigationTypeLinkClicked) { + m_view->load(url); + return false; + } + return true; + } + + KDevelop::StandardDocumentationView* m_view; +}; +#endif + +void KDevelop::StandardDocumentationView::setDelegateLinks(bool delegate) +{ +#ifdef USE_QTWEBKIT + d->m_view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); +#else + if (delegate) + d->m_view->setPage(new PageInterceptor(this)); + else + d->m_view->setPage(new QWebEnginePage(this)); +#endif +} + +QAction * KDevelop::StandardDocumentationView::copyAction() const +{ +#ifdef USE_QTWEBKIT + typedef QWebPage WebkitThing; +#else + typedef QWebEnginePage WebkitThing; +#endif + return d->m_view->pageAction(WebkitThing::Copy); +} diff --git a/documentation/standarddocumentationview.h b/documentation/standarddocumentationview.h index 3f42975203..989890fbb1 100644 --- a/documentation/standarddocumentationview.h +++ b/documentation/standarddocumentationview.h @@ -1,61 +1,82 @@ /* * This file is part of KDevelop * Copyright 2010 Aleix Pol Gonzalez * * This program 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 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. */ #ifndef KDEVPLATFORM_STANDARDDOCUMENTATIONVIEW_H #define KDEVPLATFORM_STANDARDDOCUMENTATIONVIEW_H -#include +#include #include "documentationexport.h" #include "documentationfindwidget.h" #include +class QNetworkAccessManager; + namespace KDevelop { +struct StandardDocumentationViewPrivate; /** - * The standard documentation view, based on QWebView. + * A standard documentation view, based on QtWebKit or QtWebEngine, depending on your distribution preferences. */ -class KDEVPLATFORMDOCUMENTATION_EXPORT StandardDocumentationView : public QWebView +class KDEVPLATFORMDOCUMENTATION_EXPORT StandardDocumentationView : public QWidget { Q_OBJECT + Q_DISABLE_COPY(StandardDocumentationView) public: explicit StandardDocumentationView(DocumentationFindWidget* findWidget, QWidget* parent = nullptr ); + ~StandardDocumentationView() override; void setDocumentation(const IDocumentation::Ptr& doc); + void setOverrideCss(const QUrl &url); + + void load(const QUrl &url); + void setHtml(const QString &html); + void setNetworkAccessManager(QNetworkAccessManager* manager); + + /** + * + */ + void setDelegateLinks(bool delegate); + + QAction* copyAction() const; + +Q_SIGNALS: + void linkClicked(const QUrl &link); + public slots: /** * Search for @p text in the documentation view. */ void search(const QString& text, KDevelop::DocumentationFindWidget::FindOptions options); /** * Updates the contents, in case it was initialized with a documentation instance, * doesn't change anything otherwise * * @sa setDocumentation(IDocumentation::Ptr) */ void update(); private: - IDocumentation::Ptr m_doc; + const QScopedPointer d; }; } #endif // KDEVPLATFORM_STANDARDDOCUMENTATIONVIEW_H