1 /***************************************************************************
2 qgsprocessingprovider.cpp
3 --------------------------
4 begin : December 2016
5 copyright : (C) 2016 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "qgsprocessingprovider.h"
19 #include "qgsapplication.h"
20 #include "qgsvectorfilewriter.h"
21 #include "qgsrasterfilewriter.h"
22 #include "qgssettings.h"
23
QgsProcessingProvider(QObject * parent SIP_TRANSFERTHIS)24 QgsProcessingProvider::QgsProcessingProvider( QObject *parent SIP_TRANSFERTHIS )
25 : QObject( parent )
26 {}
27
28
~QgsProcessingProvider()29 QgsProcessingProvider::~QgsProcessingProvider()
30 {
31 qDeleteAll( mAlgorithms );
32 }
33
icon() const34 QIcon QgsProcessingProvider::icon() const
35 {
36 return QgsApplication::getThemeIcon( "/processingAlgorithm.svg" );
37 }
38
svgIconPath() const39 QString QgsProcessingProvider::svgIconPath() const
40 {
41 return QgsApplication::iconPath( QStringLiteral( "processingAlgorithm.svg" ) );
42 }
43
flags() const44 QgsProcessingProvider::Flags QgsProcessingProvider::flags() const
45 {
46 return QgsProcessingProvider::Flags();
47 }
48
helpId() const49 QString QgsProcessingProvider::helpId() const
50 {
51 return QString();
52 }
53
longName() const54 QString QgsProcessingProvider::longName() const
55 {
56 return name();
57 }
58
versionInfo() const59 QString QgsProcessingProvider::versionInfo() const
60 {
61 return QString();
62 }
63
supportedOutputRasterLayerExtensions() const64 QStringList QgsProcessingProvider::supportedOutputRasterLayerExtensions() const
65 {
66 return QgsRasterFileWriter::supportedFormatExtensions();
67 }
68
refreshAlgorithms()69 void QgsProcessingProvider::refreshAlgorithms()
70 {
71 qDeleteAll( mAlgorithms );
72 mAlgorithms.clear();
73 if ( isActive() )
74 {
75 loadAlgorithms();
76 emit algorithmsLoaded();
77 }
78 }
79
algorithms() const80 QList<const QgsProcessingAlgorithm *> QgsProcessingProvider::algorithms() const
81 {
82 return mAlgorithms.values();
83 }
84
algorithm(const QString & name) const85 const QgsProcessingAlgorithm *QgsProcessingProvider::algorithm( const QString &name ) const
86 {
87 return mAlgorithms.value( name );
88 }
89
addAlgorithm(QgsProcessingAlgorithm * algorithm)90 bool QgsProcessingProvider::addAlgorithm( QgsProcessingAlgorithm *algorithm )
91 {
92 if ( !algorithm )
93 return false;
94
95 if ( mAlgorithms.contains( algorithm->name() ) )
96 {
97 QgsMessageLog::logMessage( tr( "Duplicate algorithm name %1 for provider %2" ).arg( algorithm->name(), id() ), QObject::tr( "Processing" ) );
98 return false;
99 }
100
101 // init the algorithm - this allows direct querying of the algorithm's parameters
102 // and outputs from the provider's copy
103 algorithm->initAlgorithm( QVariantMap() );
104
105 algorithm->setProvider( this );
106 mAlgorithms.insert( algorithm->name(), algorithm );
107 return true;
108 }
109
supportedOutputVectorLayerExtensions() const110 QStringList QgsProcessingProvider::supportedOutputVectorLayerExtensions() const
111 {
112 return QgsVectorFileWriter::supportedFormatExtensions();
113 }
114
supportedOutputTableExtensions() const115 QStringList QgsProcessingProvider::supportedOutputTableExtensions() const
116 {
117 return supportedOutputVectorLayerExtensions();
118 }
119
isSupportedOutputValue(const QVariant & outputValue,const QgsProcessingDestinationParameter * parameter,QgsProcessingContext & context,QString & error) const120 bool QgsProcessingProvider::isSupportedOutputValue( const QVariant &outputValue, const QgsProcessingDestinationParameter *parameter, QgsProcessingContext &context, QString &error ) const
121 {
122 error.clear();
123 QString outputPath = QgsProcessingParameters::parameterAsOutputLayer( parameter, outputValue, context ).trimmed();
124
125 if ( outputPath.isEmpty() )
126 {
127 if ( parameter->flags() & QgsProcessingParameterDefinition::FlagOptional )
128 {
129 return true;
130 }
131 else
132 {
133 error = tr( "Missing parameter value %1" ).arg( parameter->description() );
134 return false;
135 }
136 }
137
138 if ( parameter->type() == QgsProcessingParameterVectorDestination::typeName()
139 || parameter->type() == QgsProcessingParameterFeatureSink::typeName() )
140 {
141 if ( outputPath.startsWith( QLatin1String( "memory:" ) ) )
142 {
143 if ( !supportsNonFileBasedOutput() )
144 {
145 error = tr( "This algorithm only supports disk-based outputs" );
146 return false;
147 }
148 return true;
149 }
150
151 QString providerKey;
152 QString uri;
153 QString layerName;
154 QMap<QString, QVariant> options;
155 bool useWriter = false;
156 QString format;
157 QString extension;
158 QgsProcessingUtils::parseDestinationString( outputPath, providerKey, uri, layerName, format, options, useWriter, extension );
159
160 if ( providerKey != QLatin1String( "ogr" ) )
161 {
162 if ( !supportsNonFileBasedOutput() )
163 {
164 error = tr( "This algorithm only supports disk-based outputs" );
165 return false;
166 }
167 return true;
168 }
169
170 if ( !supportedOutputVectorLayerExtensions().contains( extension, Qt::CaseInsensitive ) )
171 {
172 error = tr( "“.%1” files are not supported as outputs for this algorithm" ).arg( extension );
173 return false;
174 }
175 return true;
176 }
177 else if ( parameter->type() == QgsProcessingParameterRasterDestination::typeName() )
178 {
179 QFileInfo fi( outputPath );
180 const QString extension = fi.completeSuffix();
181 if ( !supportedOutputRasterLayerExtensions().contains( extension, Qt::CaseInsensitive ) )
182 {
183 error = tr( "“.%1” files are not supported as outputs for this algorithm" ).arg( extension );
184 return false;
185 }
186 return true;
187 }
188 else
189 {
190 return true;
191 }
192 }
193
defaultVectorFileExtension(bool hasGeometry) const194 QString QgsProcessingProvider::defaultVectorFileExtension( bool hasGeometry ) const
195 {
196 QgsSettings settings;
197 const QString userDefault = QgsProcessingUtils::defaultVectorExtension();
198
199 const QStringList supportedExtensions = supportedOutputVectorLayerExtensions();
200 if ( supportedExtensions.contains( userDefault, Qt::CaseInsensitive ) )
201 {
202 // user set default is supported by provider, use that
203 return userDefault;
204 }
205 else if ( !supportedExtensions.empty() )
206 {
207 return supportedExtensions.at( 0 );
208 }
209 else
210 {
211 // who knows? provider says it has no file support at all...
212 // let's say shp. even MapInfo supports shapefiles.
213 return hasGeometry ? QStringLiteral( "shp" ) : QStringLiteral( "dbf" );
214 }
215 }
216
defaultRasterFileExtension() const217 QString QgsProcessingProvider::defaultRasterFileExtension() const
218 {
219 QgsSettings settings;
220 const QString userDefault = QgsProcessingUtils::defaultRasterExtension();
221
222 const QStringList supportedExtensions = supportedOutputRasterLayerExtensions();
223 if ( supportedExtensions.contains( userDefault, Qt::CaseInsensitive ) )
224 {
225 // user set default is supported by provider, use that
226 return userDefault;
227 }
228 else if ( !supportedExtensions.empty() )
229 {
230 return supportedExtensions.at( 0 );
231 }
232 else
233 {
234 // who knows? provider says it has no file support at all...
235 return QStringLiteral( "tif" );
236 }
237 }
238
supportsNonFileBasedOutput() const239 bool QgsProcessingProvider::supportsNonFileBasedOutput() const
240 {
241 return true;
242 }
243