1 /***************************************************************************
2   qgsprocessingparameterdxflayers.cpp
3   ---------------------
4   Date                 : September 2020
5   Copyright            : (C) 2020 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 "qgsprocessingparameterdxflayers.h"
17 #include "qgsvectorlayer.h"
18 
19 
QgsProcessingParameterDxfLayers(const QString & name,const QString & description)20 QgsProcessingParameterDxfLayers::QgsProcessingParameterDxfLayers( const QString &name, const QString &description )
21   : QgsProcessingParameterDefinition( name, description, QVariant(), false )
22 {
23 }
24 
clone() const25 QgsProcessingParameterDefinition *QgsProcessingParameterDxfLayers::clone() const
26 {
27   return new QgsProcessingParameterDxfLayers( *this );
28 }
29 
type() const30 QString QgsProcessingParameterDxfLayers::type() const
31 {
32   return typeName();
33 }
34 
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext * context) const35 bool QgsProcessingParameterDxfLayers::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context ) const
36 {
37   if ( !input.isValid() )
38     return mFlags & FlagOptional;
39 
40   if ( qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( input ) ) )
41   {
42     return true;
43   }
44 
45   if ( input.type() == QVariant::String )
46   {
47     if ( input.toString().isEmpty() )
48       return mFlags & FlagOptional;
49 
50     if ( !context )
51       return true;
52 
53     QgsMapLayer *mapLayer = QgsProcessingUtils::mapLayerFromString( input.toString(), *context );
54     return mapLayer && ( mapLayer->type() == QgsMapLayerType::VectorLayer );
55   }
56   else if ( input.type() == QVariant::List )
57   {
58     if ( input.toList().isEmpty() )
59       return mFlags & FlagOptional;;
60 
61     const QVariantList layerList = input.toList();
62     for ( const QVariant &variantLayer : layerList )
63     {
64       if ( qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( variantLayer ) ) )
65         continue;
66 
67       if ( variantLayer.type() == QVariant::String )
68       {
69         if ( !context )
70           return true;
71 
72         QgsMapLayer *mapLayer = QgsProcessingUtils::mapLayerFromString( variantLayer.toString(), *context );
73         if ( !mapLayer || mapLayer->type() != QgsMapLayerType::VectorLayer )
74           return false;
75       }
76       else if ( variantLayer.type() == QVariant::Map )
77       {
78         const QVariantMap layerMap = variantLayer.toMap();
79 
80         if ( !layerMap.contains( QStringLiteral( "layer" ) ) && !layerMap.contains( QStringLiteral( "attributeIndex" ) ) )
81           return false;
82 
83         if ( !context )
84           return true;
85 
86         QgsMapLayer *mapLayer = QgsProcessingUtils::mapLayerFromString( layerMap.value( QStringLiteral( "layer" ) ).toString(), *context );
87         if ( !mapLayer || mapLayer->type() != QgsMapLayerType::VectorLayer )
88           return false;
89 
90         QgsVectorLayer *vectorLayer = static_cast<QgsVectorLayer *>( mapLayer );
91 
92         if ( !vectorLayer )
93           return false;
94 
95         if ( layerMap.value( QStringLiteral( "attributeIndex" ) ).toInt() >= vectorLayer->fields().count() )
96           return false;
97       }
98       else
99       {
100         return false;
101       }
102     }
103     return true;
104   }
105   else if ( input.type() == QVariant::StringList )
106   {
107     const auto constToStringList = input.toStringList();
108     if ( constToStringList.isEmpty() )
109       return mFlags & FlagOptional;
110 
111     if ( !context )
112       return true;
113 
114     for ( const QString &v : constToStringList )
115     {
116       if ( !QgsProcessingUtils::mapLayerFromString( v, *context ) )
117         return false;
118     }
119     return true;
120   }
121 
122   return false;
123 }
124 
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const125 QString QgsProcessingParameterDxfLayers::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
126 {
127   QStringList parts;
128   const QList<QgsDxfExport::DxfLayer> layers = parameterAsLayers( value, context );
129   for ( const QgsDxfExport::DxfLayer &layer : layers )
130   {
131     QStringList layerDefParts;
132     layerDefParts << QStringLiteral( "'layer': " ) + QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer.layer()->source() ) );
133     if ( layer.layerOutputAttributeIndex() >= -1 )
134       layerDefParts << QStringLiteral( "'attributeIndex': " ) + QgsProcessingUtils::variantToPythonLiteral( layer.layerOutputAttributeIndex() );
135 
136     const QString layerDef = QStringLiteral( "{%1}" ).arg( layerDefParts.join( ',' ) );
137     parts << layerDef;
138   }
139   return parts.join( ',' ).prepend( '[' ).append( ']' );
140 }
141 
asPythonString(QgsProcessing::PythonOutputType outputType) const142 QString QgsProcessingParameterDxfLayers::asPythonString( QgsProcessing::PythonOutputType outputType ) const
143 {
144   switch ( outputType )
145   {
146     case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
147     {
148       QString code = QStringLiteral( "QgsProcessingParameterDxfLayers('%1', %2)" )
149                      .arg( name(), QgsProcessingUtils::stringToPythonLiteral( description() ) );
150       return code;
151     }
152   }
153   return QString();
154 }
155 
parameterAsLayers(const QVariant & layersVariant,QgsProcessingContext & context)156 QList<QgsDxfExport::DxfLayer> QgsProcessingParameterDxfLayers::parameterAsLayers( const QVariant &layersVariant, QgsProcessingContext &context )
157 {
158   QList<QgsDxfExport::DxfLayer> layers;
159 
160   if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( layersVariant ) ) )
161   {
162     layers << QgsDxfExport::DxfLayer( layer );
163   }
164 
165   if ( layersVariant.type() == QVariant::String )
166   {
167     QgsMapLayer *mapLayer = QgsProcessingUtils::mapLayerFromString( layersVariant.toString(), context );
168     layers << QgsDxfExport::DxfLayer( static_cast<QgsVectorLayer *>( mapLayer ) );
169   }
170   else if ( layersVariant.type() == QVariant::List )
171   {
172     const QVariantList layersVariantList = layersVariant.toList();
173     for ( const QVariant &layerItem : layersVariantList )
174     {
175       if ( layerItem.type() == QVariant::Map )
176       {
177         const QVariantMap layerVariantMap = layerItem.toMap();
178         layers << variantMapAsLayer( layerVariantMap, context );
179       }
180       else if ( layerItem.type() == QVariant::String )
181       {
182         QgsMapLayer *mapLayer = QgsProcessingUtils::mapLayerFromString( layerItem.toString(), context );
183         layers << QgsDxfExport::DxfLayer( static_cast<QgsVectorLayer *>( mapLayer ) );
184       }
185     }
186   }
187   else if ( layersVariant.type() == QVariant::StringList )
188   {
189     const auto layersStringList = layersVariant.toStringList();
190     for ( const QString &layerItem : layersStringList )
191     {
192       QgsMapLayer *mapLayer = QgsProcessingUtils::mapLayerFromString( layerItem, context );
193       layers << QgsDxfExport::DxfLayer( static_cast<QgsVectorLayer *>( mapLayer ) );
194     }
195   }
196 
197   return layers;
198 }
199 
variantMapAsLayer(const QVariantMap & layerVariantMap,QgsProcessingContext & context)200 QgsDxfExport::DxfLayer QgsProcessingParameterDxfLayers::variantMapAsLayer( const QVariantMap &layerVariantMap, QgsProcessingContext &context )
201 {
202   const QVariant layerVariant = layerVariantMap[ QStringLiteral( "layer" ) ];
203 
204   QgsVectorLayer *inputLayer = nullptr;
205   if ( ( inputLayer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( layerVariant ) ) ) )
206   {
207     // good
208   }
209   else if ( ( inputLayer = qobject_cast< QgsVectorLayer * >( QgsProcessingUtils::mapLayerFromString( layerVariant.toString(), context ) ) ) )
210   {
211     // good
212   }
213   else
214   {
215     // bad
216   }
217 
218   QgsDxfExport::DxfLayer dxfLayer( inputLayer, layerVariantMap[ QStringLiteral( "attributeIndex" ) ].toInt() );
219   return dxfLayer;
220 }
221 
layerAsVariantMap(const QgsDxfExport::DxfLayer & layer)222 QVariantMap QgsProcessingParameterDxfLayers::layerAsVariantMap( const QgsDxfExport::DxfLayer &layer )
223 {
224   QVariantMap vm;
225   if ( !layer.layer() )
226     return vm;
227 
228   vm[ QStringLiteral( "layer" )] = layer.layer()->id();
229   vm[ QStringLiteral( "attributeIndex" ) ] = layer.layerOutputAttributeIndex();
230   return vm;
231 }
232