diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index b6b34e6b3c3..afc8eec3e27 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -22,7 +22,7 @@ ELSE(TXT2TAGS_EXECUTABLE) ) ENDIF(TXT2TAGS_EXECUTABLE) -SET(QGIS_DOC_FILES ${QGIS_DOC_FILES} index.html news.html developersmap.html contributors.json favicon.ico style.css release-sponsors.html AUTHORS CONTRIBUTORS SPONSORS DONORS TRANSLATORS LICENSE) +SET(QGIS_DOC_FILES ${QGIS_DOC_FILES} index.html news.html developersmap.html nohelp.html contributors.json favicon.ico style.css release-sponsors.html AUTHORS CONTRIBUTORS SPONSORS DONORS TRANSLATORS LICENSE) INSTALL(FILES ${QGIS_DOC_FILES} DESTINATION ${QGIS_DATA_DIR}/doc) INSTALL(FILES ../images/icons/qgis-icon-60x60.png DESTINATION ${QGIS_DATA_DIR}/doc/images) diff --git a/doc/nohelp.html b/doc/nohelp.html new file mode 100644 index 00000000000..ff46d27cdc6 --- /dev/null +++ b/doc/nohelp.html @@ -0,0 +1,19 @@ + + + + No help found + + + + +
+

Oops!

+

Sorry, help is not available. Probably you have no Internet connection, +location of the help files is not configured or there is no help content +for requested topic.

+

Please make sure that correct location of the help files specified +in the QGIS options dialog (Settings → Options → +System).

+ + + diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ecfc306243c..bcf06ac5a03 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -135,6 +135,7 @@ SET(QGIS_CORE_SRCS qgsgeometryvalidator.cpp qgsgml.cpp qgsgmlschema.cpp + qgshelp.cpp qgshistogram.cpp qgsinterval.cpp qgsjsonutils.cpp @@ -481,6 +482,7 @@ SET(QGIS_CORE_MOC_HDRS qgsgeometryvalidator.h qgsgml.h qgsgmlschema.h + qgshelp.h qgsmaplayer.h qgsmaplayerlegend.h qgsmaplayermodel.h diff --git a/src/core/qgshelp.cpp b/src/core/qgshelp.cpp new file mode 100644 index 00000000000..2fb71147b46 --- /dev/null +++ b/src/core/qgshelp.cpp @@ -0,0 +1,145 @@ +/*************************************************************************** + qgshelp.cpp + -------------------------------------- + Date : December 2016 + Copyright : (C) 2016 by Alexander Bruy + Email : alexander dot bruy at gmail dot com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "qgshelp.h" + +#include +#include +#include +#include +#include +#include + +#include "qgis.h" +#include "qgsapplication.h" + +QgsHelp *QgsHelp::sHelp = nullptr; // Singleton instance + +void QgsHelp::openHelp( const QString& key ) +{ + if ( !sHelp ) + { + sHelp = new QgsHelp(); + } + + QDesktopServices::openUrl( sHelp->helpUrl( key ) ); +} + +QUrl QgsHelp::helpUrl( const QString& key ) +{ + if ( !sHelp ) + { + sHelp = new QgsHelp(); + } + + QSettings settings; + QUrl helpNotFound = QUrl::fromLocalFile( QgsApplication::pkgDataPath() + "/doc/nohelp.html" ); + + QString paths = settings.value( QStringLiteral( "help/helpSearchPath" ), "" ).toString(); + if ( paths.isEmpty() ) + { + return helpNotFound; + } + + QString qgisLocale; + bool overrideLocale = settings.value( QStringLiteral( "locale/overrideFlag" ), false ).toBool(); + if ( overrideLocale ) + { + qgisLocale = settings.value( QStringLiteral( "locale/userLocale" ), "" ).toString(); + } + else + { + qgisLocale = QLocale::system().name().left( 2 ); + } + + QString qgisVersion; + if ( Qgis::QGIS_VERSION_INT / 100 % 100 == 99 ) + { + qgisVersion = QStringLiteral( "testing" ); + qgisLocale = QStringLiteral( "en" ); + } + else + { + qgisVersion = QStringLiteral( "%1.%2" ).arg( Qgis::QGIS_VERSION_INT / 10000 ).arg( Qgis::QGIS_VERSION_INT / 100 % 100 ); + } + + QString suffix = QStringLiteral( "%1/%2/docs/user_manual/%3" ).arg( qgisVersion ).arg( qgisLocale ).arg( key ); + + QUrl myUrl; + QString helpPath; + bool helpFound = false; + + QStringList pathList = paths.split( '|' ); + QStringList::const_iterator pathIt = pathList.constBegin(); + for ( ; pathIt != pathList.constEnd(); ++pathIt ) + { + helpPath = QStringLiteral( "%1/%2" ).arg( *pathIt ).arg( suffix ); + + if (( *pathIt ).startsWith( QStringLiteral( "http://" ) ) ) + { + if ( !sHelp->urlExists( helpPath ) ) + { + continue; + } + myUrl = QUrl( helpPath ); + } + else + { + if ( !QFileInfo( helpPath.mid( 0, helpPath.lastIndexOf( "#" ) ) ).exists() ) + { + continue; + } + myUrl = QUrl::fromLocalFile( helpPath ); + myUrl.setFragment( helpPath.mid( helpPath.lastIndexOf( "#" ), -1 ) ); + } + + helpFound = true; + break; + } + + return helpFound ? myUrl : helpNotFound; +} + + +QgsHelp::QgsHelp() +{ +} + +QgsHelp::~QgsHelp() +{ +} + +bool QgsHelp::urlExists( const QString& url ) const +{ + QUrl myUrl( url ); + QTcpSocket socket; + + socket.connectToHost( myUrl.host(), 80 ); + if ( socket.waitForConnected() ) + { + socket.write( "HEAD " + myUrl.path().toUtf8() + " HTTP/1.1\r\n" + "Host: " + myUrl.host().toUtf8() + "\r\n\r\n" ); + if ( socket.waitForReadyRead() ) + { + QByteArray bytes = socket.readAll(); + if ( bytes.contains( "200 OK" ) || bytes.contains( "302 Found" ) ) + { + return true; + } + } + } + + return false; +} diff --git a/src/core/qgshelp.h b/src/core/qgshelp.h new file mode 100644 index 00000000000..c71faa27bc4 --- /dev/null +++ b/src/core/qgshelp.h @@ -0,0 +1,73 @@ +/*************************************************************************** + qgshelp.h + -------------------------------------- + Date : December 2016 + Copyright : (C) 2016 by Alexander Bruy + Email : alexander dot bruy at gmail dot com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSHELP_H +#define QGSHELP_H + +#include + +/** \ingroup core + * @brief The class provides help URI for the given key. + * + * Help can be stored online, on the local directory or on the intranet + * server. Location of the QGIS help can be configured in QGIS options. + * Multiple locations are supported, they will be used in order of + * preference, from top to bottom. + * + * URI construction takes in account following information: + * - QGIS version + * - language of the QGIS UI + * + * If no help found, default error page with information how to setup + * help system will be shown. + * + * @note added in QGIS 3.0 + */ +class CORE_EXPORT QgsHelp : public QObject +{ + Q_OBJECT + public: + /** Opens help topic for the given help key using default system + * web browser. If help topic not found, builtin error page shown. + * @param key key which identified help topic + * @note added in QGIS 3.0 + */ + static void openHelp( const QString& key ); + + /** Returns URI of the help topic for the given key. If help topic + * not found, URI of the builtin error page returned. + * @param key key which identified help topic + * @note added in QGIS 3.0 + */ + static QUrl helpUrl( const QString& key ); + + private: + //! Constructor + QgsHelp(); + + //! Destructor + ~QgsHelp(); + + /** Check if given URL accessible by issuing HTTP HEAD request. + * Returns true if URL accessible, false otherwise. + * @param url URL to check + * @note added in QGIS 3.0 + */ + bool urlExists( const QString& url ) const; + + static QgsHelp* sHelp; +}; + +#endif // QGSHELP_H