QGIS API Documentation  3.6.0-Noosa (5873452)
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"
24 
25 #include <QUrl>
26 #include <QFileInfo>
27 #include <QTcpSocket>
28 #include <QDesktopServices>
29 #include <QRegularExpression>
30 #include <QNetworkProxy>
31 #include <QNetworkProxyFactory>
32 
33 #include <memory>
34 
35 
36 void QgsHelp::openHelp( const QString &key )
37 {
38  QDesktopServices::openUrl( QgsHelp::helpUrl( key ) );
39 }
40 
41 QUrl QgsHelp::helpUrl( const QString &key )
42 {
43  QUrl helpNotFound = QUrl::fromLocalFile( QgsApplication::pkgDataPath() + "/doc/nohelp.html" );
44 
45  QgsSettings settings;
46  QStringList paths = settings.value( QStringLiteral( "help/helpSearchPath" ) ).toStringList();
47  if ( paths.isEmpty() )
48  {
49  QgsMessageLog::logMessage( QObject::tr( "Help location is not configured!" ), QObject::tr( "QGIS Help" ) );
50  return helpNotFound;
51  }
52 
53  std::unique_ptr<QgsExpressionContextScope> scope( QgsExpressionContextUtils::globalScope() );
54 
55  QUrl helpUrl;
56  QString helpPath, fullPath;
57  bool helpFound = false;
58 
59  Q_FOREACH ( const QString &path, paths )
60  {
61  if ( path.endsWith( QLatin1String( "\\" ) ) || path.endsWith( QLatin1String( "/" ) ) )
62  {
63  fullPath = path.left( path.size() - 1 );
64  }
65  else
66  {
67  fullPath = path;
68  }
69 
70  Q_FOREACH ( const QString &var, scope->variableNames() )
71  {
72  QRegularExpression rx( QStringLiteral( "(<!\\$\\$)*(\\$%1)" ).arg( var ) );
73  fullPath.replace( rx, scope->variable( var ).toString() );
74  }
75  fullPath.replace( QRegularExpression( QStringLiteral( "(\\$\\$)" ) ), QStringLiteral( "$" ) );
76 
77  helpPath = QStringLiteral( "%1/%2" ).arg( fullPath, key );
78 
79  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 );
80 
81  if ( helpPath.startsWith( QLatin1String( "http" ) ) )
82  {
83  if ( !QgsHelp::urlExists( helpPath ) )
84  {
85  continue;
86  }
87  helpUrl = QUrl( helpPath );
88  }
89  else
90  {
91  QString filePath = helpPath.mid( 0, helpPath.lastIndexOf( QLatin1String( "#" ) ) );
92  if ( !QFileInfo::exists( filePath ) )
93  {
94  continue;
95  }
96  helpUrl = QUrl::fromLocalFile( filePath );
97  int pos = helpPath.lastIndexOf( QLatin1String( "#" ) );
98  if ( pos != -1 )
99  {
100  helpUrl.setFragment( helpPath.mid( helpPath.lastIndexOf( QLatin1String( "#" ) ) + 1, -1 ) );
101  }
102  }
103 
104  helpFound = true;
105  break;
106  }
107 
108  return helpFound ? helpUrl : helpNotFound;
109 }
110 
111 bool QgsHelp::urlExists( const QString &url )
112 {
113  QUrl helpUrl( url );
114  QTcpSocket socket;
115 
116  QgsSettings settings;
117  bool proxyEnabled = settings.value( QStringLiteral( "proxy/proxyEnabled" ), false ).toBool();
118  if ( proxyEnabled )
119  {
120  QNetworkProxy proxy;
121  QString proxyHost = settings.value( QStringLiteral( "proxy/proxyHost" ), QString() ).toString();
122  int proxyPort = settings.value( QStringLiteral( "proxy/proxyPort" ), QString() ).toString().toInt();
123  QString proxyUser = settings.value( QStringLiteral( "proxy/proxyUser" ), QString() ).toString();
124  QString proxyPassword = settings.value( QStringLiteral( "proxy/proxyPassword" ), QString() ).toString();
125 
126  QString proxyTypeString = settings.value( QStringLiteral( "proxy/proxyType" ), QString() ).toString();
127 
128  if ( proxyTypeString == QLatin1String( "DefaultProxy" ) )
129  {
130  QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery();
131  if ( !proxies.isEmpty() )
132  {
133  proxy = proxies.first();
134  }
135  }
136  else
137  {
138  QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
139  if ( proxyTypeString == QLatin1String( "Socks5Proxy" ) )
140  {
141  proxyType = QNetworkProxy::Socks5Proxy;
142  }
143  else if ( proxyTypeString == QLatin1String( "HttpProxy" ) )
144  {
145  proxyType = QNetworkProxy::HttpProxy;
146  }
147  else if ( proxyTypeString == QLatin1String( "HttpCachingProxy" ) )
148  {
149  proxyType = QNetworkProxy::HttpCachingProxy;
150  }
151  else if ( proxyTypeString == QLatin1String( "FtpCachingProxy" ) )
152  {
153  proxyType = QNetworkProxy::FtpCachingProxy;
154  }
155  proxy = QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword );
156  }
157  socket.setProxy( proxy );
158  }
159 
160  socket.connectToHost( helpUrl.host(), 80 );
161  if ( socket.waitForConnected() )
162  {
163  socket.write( "HEAD " + helpUrl.path().toUtf8() + " HTTP/1.1\r\n"
164  "Host: " + helpUrl.host().toUtf8() + "\r\n\r\n" );
165  if ( socket.waitForReadyRead() )
166  {
167  QByteArray bytes = socket.readAll();
168  if ( bytes.contains( "200 OK" ) || bytes.contains( "302 Found" ) || bytes.contains( "301 Moved" ) )
169  {
170  return true;
171  }
172  }
173  }
174 
175  return false;
176 }
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:41
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:36