QGIS API Documentation 4.3.0-Master (ffcfc20b9b4)
Loading...
Searching...
No Matches
qgsalgorithmextractbinary.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmextractbinary.cpp
3 -----------------------------------
4 begin : November 2018
5 copyright : (C) 2018 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
19
20#include "qgsfeaturerequest.h"
21
22#include <QString>
23
24using namespace Qt::StringLiterals;
25
27
28QString QgsExtractBinaryFieldAlgorithm::name() const
29{
30 return u"extractbinary"_s;
31}
32
33QString QgsExtractBinaryFieldAlgorithm::displayName() const
34{
35 return QObject::tr( "Extract binary field" );
36}
37
38QString QgsExtractBinaryFieldAlgorithm::shortHelpString() const
39{
40 return QObject::tr(
41 "This algorithm extracts contents from a binary field, saving them to individual files.\n\n"
42 "Filenames can be generated using values taken from "
43 "an attribute in the source table or based on a more complex expression."
44 );
45}
46
47QString QgsExtractBinaryFieldAlgorithm::shortDescription() const
48{
49 return QObject::tr( "Extracts contents from a binary field, saving them to individual files." );
50}
51
52QStringList QgsExtractBinaryFieldAlgorithm::tags() const
53{
54 return QObject::tr( "blob,binaries,save,file,contents,field,column" ).split( ',' );
55}
56
57QString QgsExtractBinaryFieldAlgorithm::group() const
58{
59 return QObject::tr( "Vector table" );
60}
61
62QString QgsExtractBinaryFieldAlgorithm::groupId() const
63{
64 return u"vectortable"_s;
65}
66
67QgsExtractBinaryFieldAlgorithm *QgsExtractBinaryFieldAlgorithm::createInstance() const
68{
69 return new QgsExtractBinaryFieldAlgorithm();
70}
71
72void QgsExtractBinaryFieldAlgorithm::initAlgorithm( const QVariantMap & )
73{
74 addParameter( new QgsProcessingParameterFeatureSource( u"INPUT"_s, QObject::tr( "Input layer" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector ) ) );
75
76 addParameter( new QgsProcessingParameterField( u"FIELD"_s, QObject::tr( "Binary field" ), QVariant(), u"INPUT"_s, Qgis::ProcessingFieldParameterDataType::Any ) );
77
78 addParameter( new QgsProcessingParameterExpression( u"FILENAME"_s, QObject::tr( "File name" ), QVariant(), u"INPUT"_s ) );
79
80 addParameter( new QgsProcessingParameterFolderDestination( u"FOLDER"_s, QObject::tr( "Destination folder" ) ) );
81}
82
83QVariantMap QgsExtractBinaryFieldAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
84{
85 QGS_MARK_ALGORITHM_SOURCE
86
87 std::unique_ptr<QgsProcessingFeatureSource> input( parameterAsSource( parameters, u"INPUT"_s, context ) );
88 if ( !input )
89 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
90
91 const QString fieldName = parameterAsString( parameters, u"FIELD"_s, context );
92 const int fieldIndex = input->fields().lookupField( fieldName );
93 if ( fieldIndex < 0 )
94 throw QgsProcessingException( QObject::tr( "Invalid binary field" ) );
95
96 const QString folder = parameterAsString( parameters, u"FOLDER"_s, context );
97 if ( !QDir().mkpath( folder ) )
98 throw QgsProcessingException( QObject::tr( "Failed to create output directory." ) );
99
100 const QDir dir( folder );
101 const QString filenameExpressionString = parameterAsString( parameters, u"FILENAME"_s, context );
102 QgsExpressionContext expressionContext = createExpressionContext( parameters, context, input.get() );
103
104 QSet<QString> fields;
105 fields.insert( fieldName );
106 QgsFeatureRequest request;
107
108 QgsExpression filenameExpression( filenameExpressionString );
109 filenameExpression.prepare( &expressionContext );
110 fields.unite( filenameExpression.referencedColumns() );
111 request.setSubsetOfAttributes( fields, input->fields() );
112 if ( !filenameExpression.needsGeometry() )
114
116 const double step = input->featureCount() > 0 ? 100.0 / input->featureCount() : 1;
117 int i = 0;
118 QgsFeature feat;
119 while ( features.nextFeature( feat ) )
120 {
121 i++;
122 if ( feedback->isCanceled() )
123 {
124 break;
125 }
126
127 feedback->setProgress( i * step );
128
129 const QByteArray ba = feat.attribute( fieldIndex ).toByteArray();
130 if ( ba.isEmpty() )
131 continue;
132
133 expressionContext.setFeature( feat );
134 const QString name = filenameExpression.evaluate( &expressionContext ).toString();
135 if ( filenameExpression.hasEvalError() )
136 {
137 feedback->reportError( QObject::tr( "Error evaluating filename: %1" ).arg( filenameExpression.evalErrorString() ) );
138 continue;
139 }
140
141 const QString path = dir.filePath( name );
142 QFile file( path );
143 if ( !file.open( QIODevice::WriteOnly | QFile::Truncate ) )
144 {
145 feedback->reportError( QObject::tr( "Could not open %1 for writing" ).arg( path ) );
146 }
147 else
148 {
149 file.write( ba );
150 file.close();
151 feedback->pushInfo( QObject::tr( "Extracted %1" ).arg( path ) );
152 }
153 }
154
155 QVariantMap outputs;
156 outputs.insert( u"FOLDER"_s, folder );
157 return outputs;
158}
159
160
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3755
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2360
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition qgis.h:3930
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Handles parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:65
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
An expression parameter for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A vector layer or feature source field parameter for processing algorithms.
A folder destination parameter, for specifying the destination path for a folder created by the algor...