otbQgisDescriptor.cxx 12.1 KB
Newer Older
1
/*
Julien Michel's avatar
Julien Michel committed
2
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "otbWrapperChoiceParameter.h"
#include "otbWrapperListViewParameter.h"
#include "otbWrapperBoolParameter.h"
#include "otbWrapperApplicationRegistry.h"

#include <iostream>
#include <cassert>
#include <fstream>

int main(int argc, char* argv[])
{
  if (argc < 3)
    {
34 35
    std::cerr << "Usage : " << argv[0] << " name OTB_APPLICATION_PATH [out_dir]" << std::endl;
    return EXIT_FAILURE;
36 37 38
    }
    
  using namespace otb::Wrapper;
39

40 41 42 43 44 45 46 47 48
  const std::string module(argv[1]);

  /* TestApplication is removed in CMakeLists.txt */
#if 0
  if (module == "TestApplication")
    return EXIT_SUCCESS;
#endif

  ApplicationRegistry::AddApplicationPath(argv[2]);
49
  Application::Pointer appli =  ApplicationRegistry::CreateApplicationFaster(module);
50 51 52
  
  assert(!appli.IsNull());

53 54 55
  const std::string group = appli->GetDocTags().size() > 0 ? appli->GetDocTags()[0] : "";
  assert(!group.empty());

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
  std::map<ParameterType, std::string> parameterTypeToString;
  parameterTypeToString[ParameterType_Bool] = "QgsProcessingParameterBoolean";
  parameterTypeToString[ParameterType_Int] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Float] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_RAM] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Radius] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Choice] = "OTBParameterChoice";
  parameterTypeToString[ParameterType_String] = "QgsProcessingParameterString";
  parameterTypeToString[ParameterType_InputImage] = "QgsProcessingParameterRasterLayer";
  parameterTypeToString[ParameterType_InputFilename] = "QgsProcessingParameterFile";
  parameterTypeToString[ParameterType_InputImageList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorData] = "QgsProcessingParameterVectorLayer";
  parameterTypeToString[ParameterType_InputFilenameList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorDataList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_OutputImage] = "QgsProcessingParameterRasterDestination";
  parameterTypeToString[ParameterType_OutputVectorData] = "QgsProcessingParameterVectorDestination";
  parameterTypeToString[ParameterType_OutputFilename] = "QgsProcessingParameterFileDestination";
  parameterTypeToString[ParameterType_Directory] = "QgsProcessingParameterFile";
Rashad Kanavath's avatar
Rashad Kanavath committed
74
  // TODO
75
  parameterTypeToString[ParameterType_StringList] = "QgsProcessingParameterString";
Rashad Kanavath's avatar
Rashad Kanavath committed
76 77 78 79 80
  // ListView parameters are treated as plain string (QLineEdit) in qgis processing ui.
  // This seems rather unpleasant when comparing Qgis processing with Monteverdi/Mapla in OTB
  // We tried to push something simple with checkboxes but its too risky for this version
  // and clock is ticking...

81 82
  parameterTypeToString[ParameterType_ListView] = "QgsProcessingParameterString";

Rashad Kanavath's avatar
Rashad Kanavath committed
83 84
  // For next update of plugin code ListView should use a custom widget wrapper and behave
  // exactly like OTB Mapla. And this #if 0 block is our TODO remainder.
85 86 87
  #if 0
  parameterTypeToString[ParameterType_ListView] = "OTBParameterListView";
  #endif
88 89 90 91

  const std::vector<std::string> appKeyList = appli->GetParametersKeys(true);
  const unsigned int nbOfParam = appKeyList.size();

92 93
  std::string output_file = module + ".txt";
  std::string  algs_txt = "algs.txt";
94 95
  if (argc > 3)
    {
96 97
    output_file = std::string(argv[3]) + module + ".txt";
    algs_txt = std::string(argv[3])  +  "algs.txt";
98
    }
99
  std::ofstream dFile;
100
  dFile.open (output_file, std::ios::out);
101 102 103

  std::string output_parameter_name;
  bool hasRasterOutput = false;
104
  {
105 106
  for (unsigned int i = 0; i < nbOfParam; i++)
    {
107 108 109
    Parameter::Pointer param = appli->GetParameterByKey(appKeyList[i]);
    if (param->GetMandatory())
      {
110 111 112 113 114
	if (appli->GetParameterType(appKeyList[i]) == ParameterType_OutputImage)
	  {
	    output_parameter_name = appKeyList[i];
	    hasRasterOutput = true;
	  }
115
      }
116
    }
117
  }
118 119 120 121 122 123 124 125 126 127 128

  if(output_parameter_name.empty())
    dFile << module << std::endl;
  else
    dFile << module << "|" <<  output_parameter_name << std::endl;
  
  dFile << appli->GetDescription() << std::endl;
  dFile << group << std::endl;
  
  for (unsigned int i = 0; i < nbOfParam; i++)
    {
129
    const std::string name = appKeyList[i];
130 131
    const Parameter::Pointer param = appli->GetParameterByKey(name);
    const ParameterType type = appli->GetParameterType(name);
132
    const std::string description = appli->GetParameterName(name);
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    if (  type == ParameterType_Group  ||
          type == ParameterType_RAM ||
          param->GetRole() == Role_Output )
      {
      // group parameter cannot have any value.
      // ram is added by qgis-otb processing provider plugin as an advanced parameter for all apps
      // parameter role cannot be of type Role_Output
      continue;
      }
    auto it = parameterTypeToString.find(type);
    assert(  it != parameterTypeToString.end() );
    if( it == parameterTypeToString.end() )
      {
      std::cerr << "No mapping found for parameter '" <<name <<"' type=" << type << std::endl;
      return EXIT_FAILURE;
      }
    std::string qgis_type = it->second;
150 151 152 153 154 155 156
#if 0
      if (type == ParameterType_ListView)
	{
	  ListViewParameter *lv_param = dynamic_cast<ListViewParameter*>(param.GetPointer());
	  std::cerr << "lv_param->GetSingleSelection()" << lv_param->GetSingleSelection() << std::endl;
	  if (lv_param->GetSingleSelection())
	    {
157

158 159 160 161 162 163 164 165 166 167
	      qgis_type = "QgsProcessingParameterEnum";
	      std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
	      std::string values = "";
	      for( auto k : key_list)
		values += k + ";";
	      values.pop_back();
	      dFile << "|" << values ;
	    }
	}
#endif
168

169 170
    bool isDestination = false;
    bool isEpsgCode = false;
171

172 173 174 175 176 177 178 179 180 181
    // use QgsProcessingParameterCrs if required.
    // TODO: do a regex on name to match ==epsg || *\.epsg.\*
    if ( name == "epsg"
	      || name == "map.epsg.code"
	      || name == "mapproj.epsg.code"
	      || name == "mode.epsg.code")
        {
        qgis_type = "QgsProcessingParameterCrs";
        isEpsgCode = true;
        }
182

183
    dFile << qgis_type << "|" << name << "|" << description;
184 185

      std::string default_value = "None";
186 187 188 189 190 191 192 193 194
    if (type == ParameterType_Int)
      {
      if (isEpsgCode)
        {
          if (param->HasValue() && appli->GetParameterInt(name) < 1)
    	default_value =  "EPSG: " + appli->GetParameterAsString(name);
          else
    	default_value =  "ProjectCrs";
        }
195
      else
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
        {
        dFile << "|QgsProcessingParameterNumber.Integer";
        default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
        }
      }
    else if (type == ParameterType_Float)
      {	
      dFile << "|QgsProcessingParameterNumber.Double";
      default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
      }
    else if (type == ParameterType_Radius)
      {	
      dFile << "|QgsProcessingParameterNumber.Integer";
      default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
      }
    else if(type == ParameterType_InputFilename)
      {
      // TODO: if parameter InputFilename can give supported extensions
      // we can use it gitlab #1559
215
      dFile << "|QgsProcessingParameterFile.File|None";
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
      }
    else if(type == ParameterType_Directory)
      {
      dFile << "|QgsProcessingParameterFile.Folder|False";
      }      
    else if (type == ParameterType_InputImageList)
      {
      dFile << "|3"; //QgsProcessing.TypeRaster
      }
    else if (type == ParameterType_InputVectorDataList)
      {
      dFile << "|-1"; //QgsProcessing.TypeVectorAnyGeometry
      }
    else if (type == ParameterType_InputVectorData)
      {
      dFile << "|-1"; //QgsProcessing.TypeVectorAnyGeometry
      }
    else if(type == ParameterType_InputFilenameList)
      {
      dFile << "|4"; //QgsProcessing.TypeFile"
      }
237
    else if(type == ParameterType_String)
238 239 240 241 242 243 244 245
      {
      // Below line is interpreted in qgis processing as
      // 1. default_value = None
      // 2. multiLine = False
      // For more details,
      // please refer to documetation of QgsProcessingParameterString.
      default_value = "None|False";
      }
246
    else if(type == ParameterType_StringList)
247 248 249 250 251 252 253 254 255
      {
      // Below line is interpreted in qgis processing as
      // 1. default_value = None
      // 2. multiLine = True
      // For more details,
      // please refer to documetation of QgsProcessingParameterString.
      // setting default_value this way is an exception for ParameterType_StringList and ParameterType_String
      default_value = "None|True";
      }
256
    else if (type == ParameterType_InputImage)
257 258 259
      {
      // default is None and nothing to add to dFile
      }
260
    else if(type == ParameterType_ListView)
261 262 263 264 265
      {
      // default is None and nothing to add to dFile
      }
    else if(type == ParameterType_Bool)
      {
266
      default_value = appli->GetParameterAsString(name);
267
      }
268 269 270 271 272 273
    else if(type == ParameterType_Choice)
      {
      std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
      std::string values = "";
      for( auto k : key_list)
        values += k + ";";
274

275 276 277 278 279 280 281
  	  values.pop_back();
  	  dFile << "|" << values ;
  	  ChoiceParameter *cparam = dynamic_cast<ChoiceParameter*>(param.GetPointer());
  	  default_value = std::to_string(cparam->GetValue());	  
      }
    else if(type == ParameterType_OutputVectorData ||
	          type == ParameterType_OutputImage ||
282
	          type == ParameterType_OutputFilename)
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
      {
      // No need for default_value, optional and extra fields in dFile.
      // If parameter is a destination type. qgis_type|name|description is enough.
      // So we simply set isDestination to true and skip to end to append a new line.
      isDestination =  true;
      }
    else
      {
      std::cout << "ERROR: default_value is empty for '" << name << "' type='" << qgis_type << "'" << std::endl;
      return EXIT_FAILURE;	  
      }

    if (!isDestination)
      {
      std::string optional;
      if (param->GetMandatory())
        {
        // TODO: avoid workaround for stringlist types (fix appengine)
        // type == ParameterType_StringList check is needed because:
        // If parameter is mandatory it can have no value
        // It is accepted in OTB that, string list could be generated dynamically
        // qgis has no such option to handle dynamic values yet..
        // So mandatory parameters whose type is StringList is considered optional
        optional = param->HasValue() || type == ParameterType_StringList  ? "True" : "False";
        }
      else
        {
        optional = "True";
        }
              #if 0
    	  std::cerr << name;
    	  std::cerr << " mandatory=" << param->GetMandatory();
    	  std::cerr << " HasValue=" << param->HasValue();
    	  std::cerr << " qgis_type=" << qgis_type;
    	  std::cerr << " optional=" << optional << std::endl;
              #endif
    	dFile << "|" << default_value << "|" << optional;
      }
    dFile << std::endl;
    }
323

324 325
  if(hasRasterOutput)
    {
326
    dFile << "*QgsProcessingParameterEnum|outputpixeltype|Output pixel type|uint8;int;float;double|False|2|True" << std::endl;
327
    }
328

329
  std::cerr << "Writing " << output_file << std::endl;
330
  dFile.close();
331 332
  
  std::ofstream indexFile;
333
  indexFile.open (algs_txt, std::ios::out | std::ios::app );
334 335
  indexFile << group << "|" << module << std::endl;
  indexFile.close();
336
  std::cerr << "Updated " << algs_txt << std::endl;
337 338 339 340

  appli = nullptr;
  ApplicationRegistry::CleanRegistry();

341
  return EXIT_SUCCESS;
342
  }
343 344