QGIS API Documentation  3.2.0-Bonn (bc43194)
qgshelp.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgshelp.cpp
3  --------------------------------------
4  Date : December 2016
5  Copyright : (C) 2016 by Alexander Bruy
6  Email : alexander dot bruy at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgshelp.h"
17 
18 #include "qgis.h"
19 #include "qgssettings.h"
20 #include "qgsapplication.h"
21 #include "qgsexpressioncontext.h"
22 #include "qgsmessagelog.h"
23 
24 #include <QUrl>
25 #include <QFileInfo>
26 #include <QTcpSocket>
27 #include <QDesktopServices>
28 #include <QRegularExpression>
29 #include <QNetworkProxy>
30 #include <QNetworkProxyFactory>
31 
32 #include <memory>
33 
34 
35 void QgsHelp::openHelp( const QString &key )
36 {
37  QDesktopServices::openUrl( QgsHelp::helpUrl( key ) );
38 }
39 
40 QUrl QgsHelp::helpUrl( const QString &key )
41 {
42  QUrl helpNotFound = QUrl::fromLocalFile( QgsApplication::pkgDataPath() + "/doc/nohelp.html" );
43 
44  QgsSettings settings;
45  QStringList paths = settings.value( QStringLiteral( "help/helpSearchPath" ) ).toStringList();
46  if ( paths.isEmpty() )
47  {
48  QgsMessageLog::logMessage( QObject::tr( "Help location is not configured!" ), QObject::tr( "QGIS Help" ) );
49  return helpNotFound;
50  }
51 
52  std::unique_ptr<QgsExpressionContextScope> scope( QgsExpressionContextUtils::globalScope() );
53 
54  QUrl helpUrl;
55  QString helpPath, fullPath;
56  bool helpFound = false;
57 
58  Q_FOREACH ( const QString &path, paths )
59  {
60  if ( path.endsWith( QLatin1String( "\\" ) ) || path.endsWith( QLatin1String( "/" ) ) )
61  {
62  fullPath = path.left( path.size() - 1 );
63  }
64  else
65  {
66  fullPath = path;
67  }
68 
69  Q_FOREACH ( const QString &var, scope->variableNames() )
70  {
71  QRegularExpression rx( QStringLiteral( "(<!\\$\\$)*(\\$%1)" ).arg( var ) );
72  fullPath.replace( rx, scope->variable( var ).toString() );
73  }
74  fullPath.replace( QRegularExpression( QStringLiteral( "(\\$\\$)" ) ), QStringLiteral( "$" ) );
75 
76  helpPath = QStringLiteral( "%1/%2" ).arg( fullPath, key );
77 
78  QgsMessageLog::logMessage( QObject::tr( "Trying to open help using key '%1'. Full URI is '%2'…" ).arg( key ).arg( helpPath ), QObject::tr( "QGIS Help" ), Qgis::Info );
79 
80  if ( helpPath.startsWith( QStringLiteral( "http" ) ) )
81  {
82  if ( !QgsHelp::urlExists( helpPath ) )
83  {
84  continue;
85  }
86  helpUrl = QUrl( helpPath );
87  }
88  else
89  {
90  QString filePath = helpPath.mid( 0, helpPath.lastIndexOf( QLatin1String( "#" ) ) );
91  if ( !QFileInfo::exists( filePath ) )
92  {
93  continue;
94  }
95  helpUrl = QUrl::fromLocalFile( filePath );
96  int pos = helpPath.lastIndexOf( QLatin1String( "#" ) );
97  if ( pos != -1 )
98  {
99  helpUrl.setFragment( helpPath.mid( helpPath.lastIndexOf( QLatin1String( "#" ) ) + 1, -1 ) );
100  }
101  }
102 
103  helpFound = true;
104  break;
105  }
106 
107  return helpFound ? helpUrl : helpNotFound;
108 }
109 
110 bool QgsHelp::urlExists( const QString &url )
111 {
112  QUrl helpUrl( url );
113  QTcpSocket socket;
114 
115  QgsSettings settings;
116  bool proxyEnabled = settings.value( QStringLiteral( "proxy/proxyEnabled" ), false ).toBool();
117  if ( proxyEnabled )
118  {
119  QNetworkProxy proxy;
120  QString proxyHost = settings.value( QStringLiteral( "proxy/proxyHost" ), QString() ).toString();
121  int proxyPort = settings.value( QStringLiteral( "proxy/proxyPort" ), QString() ).toString().toInt();
122  QString proxyUser = settings.value( QStringLiteral( "proxy/proxyUser" ), QString() ).toString();
123  QString proxyPassword = settings.value( QStringLiteral( "proxy/proxyPassword" ), QString() ).toString();
124 
125  QString proxyTypeString = settings.value( QStringLiteral( "proxy/proxyType" ), QString() ).toString();
126 
127  if ( proxyTypeString == QLatin1String( "DefaultProxy" ) )
128  {
129  QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery();
130  if ( !proxies.isEmpty() )
131  {
132  proxy = proxies.first();
133  }
134  }
135  else
136  {
137  QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
138  if ( proxyTypeString == QLatin1String( "Socks5Proxy" ) )
139  {
140  proxyType = QNetworkProxy::Socks5Proxy;
141  }
142  else if ( proxyTypeString == QLatin1String( "HttpProxy" ) )
143  {
144  proxyType = QNetworkProxy::HttpProxy;
145  }
146  else if ( proxyTypeString == QLatin1String( "HttpCachingProxy" ) )
147  {
148  proxyType = QNetworkProxy::HttpCachingProxy;
149  }
150  else if ( proxyTypeString == QLatin1String( "FtpCachingProxy" ) )
151  {
152  proxyType = QNetworkProxy::FtpCachingProxy;
153  }
154  proxy = QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword );
155  }
156  socket.setProxy( proxy );
157  }
158 
159  socket.connectToHost( helpUrl.host(), 80 );
160  if ( socket.waitForConnected() )
161  {
162  socket.write( "HEAD " + helpUrl.path().toUtf8() + " HTTP/1.1\r\n"
163  "Host: " + helpUrl.host().toUtf8() + "\r\n\r\n" );
164  if ( socket.waitForReadyRead() )
165  {
166  QByteArray bytes = socket.readAll();
167  if ( bytes.contains( "200 OK" ) || bytes.contains( "302 Found" ) || bytes.contains( "301 Moved" ) )
168  {
169  return true;
170  }
171  }
172  }
173 
174  return false;
175 }
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static QUrl helpUrl(const QString &key)
Returns URI of the help topic for the given key.
Definition: qgshelp.cpp:40
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QString pkgDataPath()
Returns the common root path of all application data directories.
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:35