[{"data":1,"prerenderedAt":1869},["ShallowReactive",2],{"doc:\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Fadd-parameters-to-processing-algorithm-pyqgis":3},{"id":4,"title":5,"body":6,"description":1858,"extension":1859,"meta":1860,"navigation":315,"path":1865,"seo":1866,"stem":1867,"__hash__":1868},"docs\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Fadd-parameters-to-processing-algorithm-pyqgis\u002Findex.md","Add Parameters to a Processing Algorithm",{"type":7,"value":8,"toc":1845},"minimark",[9,13,17,31,213,218,243,247,740,762,766,773,945,977,981,984,1114,1129,1249,1253,1256,1407,1422,1489,1493,1499,1572,1589,1593,1660,1667,1671,1727,1731,1737,1741,1747,1761,1770,1776,1782,1796,1810,1814,1841],[10,11,5],"h1",{"id":12},"add-parameters-to-a-processing-algorithm",[14,15,16],"p",{},"The parameters are the algorithm's interface. Get them right and the framework builds a dialog, validates the input, populates the field picker from the chosen layer, exposes everything to batch mode and the modeller, and hands your code clean typed values. Get them wrong and users type layer names into text boxes.",[14,18,19,20,25,26,30],{},"This recipe belongs to ",[21,22,24],"a",{"href":23},"\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002F","Processing Provider Plugins",". It covers the parameter types you will actually use, defaults and optional inputs, parameters that depend on each other, and the correct way to read each kind inside ",[27,28,29],"code",{},"processAlgorithm()",".",[14,32,33],{},[34,35,40,44,48,55,72,81,90,96,104,110,112,116,119,123,126,131,138,142,146,149,151,154,156,159,161,164,171,176,180,184,187,191,194,198,205,210],"svg",{"viewBox":36,"role":37,"ariaLabel":38,"xmlns":39},"0 0 760 272","img","Diagram showing parameter definitions producing a generated dialog with the matching widget for each type, and the same definitions being reused by batch mode and scripting","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[41,42,43],"title",{},"One definition, three interfaces",[45,46,47],"desc",{},"Each parameter definition declares a type, a label, a default and whether it is optional. From that single declaration the framework generates a widget in the algorithm dialog, a column in the batch interface, and a named key in the parameters dictionary that scripts pass to processing dot run. Nothing about the interface is written by the plugin author.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","272","#f6f3ea",[56,57,58],"defs",{},[59,60,67],"marker",{"id":61,"viewBox":62,"refX":63,"refY":64,"markerWidth":65,"markerHeight":65,"orient":66},"paramArrow","0 0 10 10","8","5","7","auto-start-reverse",[68,69],"path",{"d":70,"fill":71},"M0 0 L10 5 L0 10 z","#0f766e",[73,74,80],"text",{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"380","28","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Declare the input; the framework builds the rest",[49,82],{"x":83,"y":84,"width":85,"height":86,"rx":87,"fill":88,"stroke":71,"style":89},"20","52","220","180","10","#eef7f4","stroke-width:2.5",[73,91,95],{"x":92,"y":93,"style":94,"fill":71,"textAnchor":79},"130","78","text-anchor:middle;font-size:12px;font-weight:bold;font-family:sans-serif","your definitions",[49,97],{"x":98,"y":99,"width":86,"height":100,"rx":64,"fill":101,"stroke":102,"style":103},"40","94","30","#fffdf7","#59645f","stroke-width:1.5",[73,105,109],{"x":92,"y":106,"style":107,"fill":108,"textAnchor":79},"114","text-anchor:middle;font-size:11px;font-family:sans-serif","#2f3b35","FeatureSource INPUT",[49,111],{"x":98,"y":92,"width":86,"height":100,"rx":64,"fill":101,"stroke":102,"style":103},[73,113,115],{"x":92,"y":114,"style":107,"fill":108,"textAnchor":79},"150","Field GROUP FIELD",[49,117],{"x":98,"y":118,"width":86,"height":100,"rx":64,"fill":101,"stroke":102,"style":103},"166",[73,120,122],{"x":92,"y":121,"style":107,"fill":108,"textAnchor":79},"186","Number MIN AREA",[49,124],{"x":98,"y":125,"width":86,"height":83,"rx":64,"fill":101,"stroke":102,"style":103},"202",[73,127,130],{"x":92,"y":128,"style":129,"fill":108,"textAnchor":79},"217","text-anchor:middle;font-size:10px;font-family:sans-serif","Sink OUTPUT",[49,132],{"x":133,"y":84,"width":134,"height":86,"rx":87,"fill":135,"stroke":136,"style":137},"292","200","#eff3ff","#2563eb","stroke-width:2",[73,139,141],{"x":140,"y":93,"style":94,"fill":136,"textAnchor":79},"392","the generated dialog",[49,143],{"x":144,"y":99,"width":145,"height":100,"rx":64,"fill":101,"stroke":102,"style":103},"310","164",[73,147,148],{"x":140,"y":106,"style":107,"fill":108,"textAnchor":79},"layer picker",[49,150],{"x":144,"y":92,"width":145,"height":100,"rx":64,"fill":101,"stroke":102,"style":103},[73,152,153],{"x":140,"y":114,"style":107,"fill":108,"textAnchor":79},"field list from that layer",[49,155],{"x":144,"y":118,"width":145,"height":100,"rx":64,"fill":101,"stroke":102,"style":103},[73,157,158],{"x":140,"y":121,"style":107,"fill":108,"textAnchor":79},"spin box with limits",[49,160],{"x":144,"y":125,"width":145,"height":83,"rx":64,"fill":101,"stroke":102,"style":103},[73,162,163],{"x":140,"y":128,"style":129,"fill":108,"textAnchor":79},"output file chooser",[49,165],{"x":166,"y":84,"width":167,"height":168,"rx":87,"fill":169,"stroke":170,"style":137},"544","196","84","#edf8e9","#15803d",[73,172,175],{"x":173,"y":93,"style":174,"fill":170,"textAnchor":79},"642","text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","batch mode",[73,177,179],{"x":173,"y":178,"style":107,"fill":108,"textAnchor":79},"100","one column each",[73,181,183],{"x":173,"y":182,"style":107,"fill":108,"textAnchor":79},"120","filled per row",[49,185],{"x":166,"y":186,"width":167,"height":168,"rx":87,"fill":169,"stroke":170,"style":137},"148",[73,188,190],{"x":173,"y":189,"style":174,"fill":170,"textAnchor":79},"174","processing.run",[73,192,193],{"x":173,"y":167,"style":107,"fill":108,"textAnchor":79},"a dictionary keyed",[73,195,197],{"x":173,"y":196,"style":107,"fill":108,"textAnchor":79},"216","by your names",[199,200],"line",{"x1":201,"y1":202,"x2":203,"y2":202,"stroke":71,"style":204},"240","140","286","stroke-width:2;marker-end:url(#paramArrow)",[199,206],{"x1":207,"y1":208,"x2":209,"y2":99,"stroke":71,"style":204},"492","110","538",[199,211],{"x1":207,"y1":212,"x2":209,"y2":121,"stroke":71,"style":204},"170",[214,215,217],"h2",{"id":216},"prerequisites","Prerequisites",[219,220,221,229,236],"ul",{},[222,223,224,228],"li",{},[225,226,227],"strong",{},"QGIS 3.34 LTR"," (bundled Python 3.12) or newer.",[222,230,231,232,30],{},"An algorithm class — see ",[21,233,235],{"href":234},"\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Fwrite-custom-processing-algorithm-pyqgis\u002F","Write a Custom Processing Algorithm in PyQGIS",[222,237,238,239,30],{},"A provider to register it with, from ",[21,240,242],{"href":241},"\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Fregister-processing-provider-in-plugin\u002F","Register a Processing Provider in a Plugin",[214,244,246],{"id":245},"declare-the-parameters","Declare the parameters",[248,249,254],"pre",{"className":250,"code":251,"language":252,"meta":253,"style":253},"language-python shiki shiki-themes github-dark","from qgis.core import (QgsProcessingAlgorithm, QgsProcessing,\n                       QgsProcessingParameterFeatureSource,\n                       QgsProcessingParameterField,\n                       QgsProcessingParameterNumber,\n                       QgsProcessingParameterEnum,\n                       QgsProcessingParameterBoolean,\n                       QgsProcessingParameterFeatureSink)\n\nINPUT = \"INPUT\"\nGROUP_FIELD = \"GROUP_FIELD\"\nMIN_AREA = \"MIN_AREA\"\nUNITS = \"UNITS\"\nKEEP_EMPTY = \"KEEP_EMPTY\"\nOUTPUT = \"OUTPUT\"\n\n\nclass SummariseParcelsAlgorithm(QgsProcessingAlgorithm):\n\n    def initAlgorithm(self, config=None):\n        self.addParameter(QgsProcessingParameterFeatureSource(\n            INPUT, self.tr(\"Parcel layer\"),\n            [QgsProcessing.TypeVectorPolygon]))\n\n        self.addParameter(QgsProcessingParameterField(\n            GROUP_FIELD, self.tr(\"Group by field\"),\n            parentLayerParameterName=INPUT,\n            type=QgsProcessingParameterField.Any))\n\n        self.addParameter(QgsProcessingParameterNumber(\n            MIN_AREA, self.tr(\"Minimum area\"),\n            type=QgsProcessingParameterNumber.Double,\n            defaultValue=0.0, minValue=0.0))\n\n        self.addParameter(QgsProcessingParameterEnum(\n            UNITS, self.tr(\"Report units\"),\n            options=[self.tr(\"square metres\"), self.tr(\"hectares\")],\n            defaultValue=1))\n\n        self.addParameter(QgsProcessingParameterBoolean(\n            KEEP_EMPTY, self.tr(\"Keep groups with no parcels\"),\n            defaultValue=False))\n\n        self.addParameter(QgsProcessingParameterFeatureSink(\n            OUTPUT, self.tr(\"Summary\")))\n","python","",[27,255,256,274,280,286,292,298,304,310,317,331,342,353,364,375,386,391,396,415,420,440,449,470,476,481,489,506,520,531,536,544,561,571,594,599,607,624,655,667,672,680,697,709,714,722],{"__ignoreMap":253},[257,258,260,264,268,271],"span",{"class":199,"line":259},1,[257,261,263],{"class":262},"snl16","from",[257,265,267],{"class":266},"s95oV"," qgis.core ",[257,269,270],{"class":262},"import",[257,272,273],{"class":266}," (QgsProcessingAlgorithm, QgsProcessing,\n",[257,275,277],{"class":199,"line":276},2,[257,278,279],{"class":266},"                       QgsProcessingParameterFeatureSource,\n",[257,281,283],{"class":199,"line":282},3,[257,284,285],{"class":266},"                       QgsProcessingParameterField,\n",[257,287,289],{"class":199,"line":288},4,[257,290,291],{"class":266},"                       QgsProcessingParameterNumber,\n",[257,293,295],{"class":199,"line":294},5,[257,296,297],{"class":266},"                       QgsProcessingParameterEnum,\n",[257,299,301],{"class":199,"line":300},6,[257,302,303],{"class":266},"                       QgsProcessingParameterBoolean,\n",[257,305,307],{"class":199,"line":306},7,[257,308,309],{"class":266},"                       QgsProcessingParameterFeatureSink)\n",[257,311,313],{"class":199,"line":312},8,[257,314,316],{"emptyLinePlaceholder":315},true,"\n",[257,318,320,324,327],{"class":199,"line":319},9,[257,321,323],{"class":322},"sDLfK","INPUT",[257,325,326],{"class":262}," =",[257,328,330],{"class":329},"sU2Wk"," \"INPUT\"\n",[257,332,334,337,339],{"class":199,"line":333},10,[257,335,336],{"class":322},"GROUP_FIELD",[257,338,326],{"class":262},[257,340,341],{"class":329}," \"GROUP_FIELD\"\n",[257,343,345,348,350],{"class":199,"line":344},11,[257,346,347],{"class":322},"MIN_AREA",[257,349,326],{"class":262},[257,351,352],{"class":329}," \"MIN_AREA\"\n",[257,354,356,359,361],{"class":199,"line":355},12,[257,357,358],{"class":322},"UNITS",[257,360,326],{"class":262},[257,362,363],{"class":329}," \"UNITS\"\n",[257,365,367,370,372],{"class":199,"line":366},13,[257,368,369],{"class":322},"KEEP_EMPTY",[257,371,326],{"class":262},[257,373,374],{"class":329}," \"KEEP_EMPTY\"\n",[257,376,378,381,383],{"class":199,"line":377},14,[257,379,380],{"class":322},"OUTPUT",[257,382,326],{"class":262},[257,384,385],{"class":329}," \"OUTPUT\"\n",[257,387,389],{"class":199,"line":388},15,[257,390,316],{"emptyLinePlaceholder":315},[257,392,394],{"class":199,"line":393},16,[257,395,316],{"emptyLinePlaceholder":315},[257,397,399,402,406,409,412],{"class":199,"line":398},17,[257,400,401],{"class":262},"class",[257,403,405],{"class":404},"svObZ"," SummariseParcelsAlgorithm",[257,407,408],{"class":266},"(",[257,410,411],{"class":404},"QgsProcessingAlgorithm",[257,413,414],{"class":266},"):\n",[257,416,418],{"class":199,"line":417},18,[257,419,316],{"emptyLinePlaceholder":315},[257,421,423,426,429,432,435,438],{"class":199,"line":422},19,[257,424,425],{"class":262},"    def",[257,427,428],{"class":404}," initAlgorithm",[257,430,431],{"class":266},"(self, config",[257,433,434],{"class":262},"=",[257,436,437],{"class":322},"None",[257,439,414],{"class":266},[257,441,443,446],{"class":199,"line":442},20,[257,444,445],{"class":322},"        self",[257,447,448],{"class":266},".addParameter(QgsProcessingParameterFeatureSource(\n",[257,450,452,455,458,461,464,467],{"class":199,"line":451},21,[257,453,454],{"class":322},"            INPUT",[257,456,457],{"class":266},", ",[257,459,460],{"class":322},"self",[257,462,463],{"class":266},".tr(",[257,465,466],{"class":329},"\"Parcel layer\"",[257,468,469],{"class":266},"),\n",[257,471,473],{"class":199,"line":472},22,[257,474,475],{"class":266},"            [QgsProcessing.TypeVectorPolygon]))\n",[257,477,479],{"class":199,"line":478},23,[257,480,316],{"emptyLinePlaceholder":315},[257,482,484,486],{"class":199,"line":483},24,[257,485,445],{"class":322},[257,487,488],{"class":266},".addParameter(QgsProcessingParameterField(\n",[257,490,492,495,497,499,501,504],{"class":199,"line":491},25,[257,493,494],{"class":322},"            GROUP_FIELD",[257,496,457],{"class":266},[257,498,460],{"class":322},[257,500,463],{"class":266},[257,502,503],{"class":329},"\"Group by field\"",[257,505,469],{"class":266},[257,507,509,513,515,517],{"class":199,"line":508},26,[257,510,512],{"class":511},"s9osk","            parentLayerParameterName",[257,514,434],{"class":262},[257,516,323],{"class":322},[257,518,519],{"class":266},",\n",[257,521,523,526,528],{"class":199,"line":522},27,[257,524,525],{"class":511},"            type",[257,527,434],{"class":262},[257,529,530],{"class":266},"QgsProcessingParameterField.Any))\n",[257,532,534],{"class":199,"line":533},28,[257,535,316],{"emptyLinePlaceholder":315},[257,537,539,541],{"class":199,"line":538},29,[257,540,445],{"class":322},[257,542,543],{"class":266},".addParameter(QgsProcessingParameterNumber(\n",[257,545,547,550,552,554,556,559],{"class":199,"line":546},30,[257,548,549],{"class":322},"            MIN_AREA",[257,551,457],{"class":266},[257,553,460],{"class":322},[257,555,463],{"class":266},[257,557,558],{"class":329},"\"Minimum area\"",[257,560,469],{"class":266},[257,562,564,566,568],{"class":199,"line":563},31,[257,565,525],{"class":511},[257,567,434],{"class":262},[257,569,570],{"class":266},"QgsProcessingParameterNumber.Double,\n",[257,572,574,577,579,582,584,587,589,591],{"class":199,"line":573},32,[257,575,576],{"class":511},"            defaultValue",[257,578,434],{"class":262},[257,580,581],{"class":322},"0.0",[257,583,457],{"class":266},[257,585,586],{"class":511},"minValue",[257,588,434],{"class":262},[257,590,581],{"class":322},[257,592,593],{"class":266},"))\n",[257,595,597],{"class":199,"line":596},33,[257,598,316],{"emptyLinePlaceholder":315},[257,600,602,604],{"class":199,"line":601},34,[257,603,445],{"class":322},[257,605,606],{"class":266},".addParameter(QgsProcessingParameterEnum(\n",[257,608,610,613,615,617,619,622],{"class":199,"line":609},35,[257,611,612],{"class":322},"            UNITS",[257,614,457],{"class":266},[257,616,460],{"class":322},[257,618,463],{"class":266},[257,620,621],{"class":329},"\"Report units\"",[257,623,469],{"class":266},[257,625,627,630,632,635,637,639,642,645,647,649,652],{"class":199,"line":626},36,[257,628,629],{"class":511},"            options",[257,631,434],{"class":262},[257,633,634],{"class":266},"[",[257,636,460],{"class":322},[257,638,463],{"class":266},[257,640,641],{"class":329},"\"square metres\"",[257,643,644],{"class":266},"), ",[257,646,460],{"class":322},[257,648,463],{"class":266},[257,650,651],{"class":329},"\"hectares\"",[257,653,654],{"class":266},")],\n",[257,656,658,660,662,665],{"class":199,"line":657},37,[257,659,576],{"class":511},[257,661,434],{"class":262},[257,663,664],{"class":322},"1",[257,666,593],{"class":266},[257,668,670],{"class":199,"line":669},38,[257,671,316],{"emptyLinePlaceholder":315},[257,673,675,677],{"class":199,"line":674},39,[257,676,445],{"class":322},[257,678,679],{"class":266},".addParameter(QgsProcessingParameterBoolean(\n",[257,681,683,686,688,690,692,695],{"class":199,"line":682},40,[257,684,685],{"class":322},"            KEEP_EMPTY",[257,687,457],{"class":266},[257,689,460],{"class":322},[257,691,463],{"class":266},[257,693,694],{"class":329},"\"Keep groups with no parcels\"",[257,696,469],{"class":266},[257,698,700,702,704,707],{"class":199,"line":699},41,[257,701,576],{"class":511},[257,703,434],{"class":262},[257,705,706],{"class":322},"False",[257,708,593],{"class":266},[257,710,712],{"class":199,"line":711},42,[257,713,316],{"emptyLinePlaceholder":315},[257,715,717,719],{"class":199,"line":716},43,[257,718,445],{"class":322},[257,720,721],{"class":266},".addParameter(QgsProcessingParameterFeatureSink(\n",[257,723,725,728,730,732,734,737],{"class":199,"line":724},44,[257,726,727],{"class":322},"            OUTPUT",[257,729,457],{"class":266},[257,731,460],{"class":322},[257,733,463],{"class":266},[257,735,736],{"class":329},"\"Summary\"",[257,738,739],{"class":266},")))\n",[14,741,742,745,746,748,749,752,753,756,757,761],{},[225,743,744],{},"Breakdown:"," Constants for the parameter names keep the definition and the reads in sync — a typo in a string literal produces ",[27,747,437],{}," at run time rather than an error at load time. ",[27,750,751],{},"QgsProcessingParameterFeatureSource"," restricted to polygons means the picker only offers polygon layers, which removes a whole class of user mistake; it also accepts a selection-only checkbox and a file path, all for free. The field parameter's ",[27,754,755],{},"parentLayerParameterName"," is what makes its dropdown populate from whichever layer the user picked, and it is the difference between a field picker and a text box. The enum stores an ",[758,759,760],"em",{},"index",", not the label, which is the most common misreading of the parameters dictionary.",[214,763,765],{"id":764},"read-them-correctly","Read them correctly",[14,767,768,769,772],{},"Each parameter type has its own accessor, and using the wrong one is the usual source of a ",[27,770,771],{},"TypeError"," deep in an algorithm.",[248,774,776],{"className":250,"code":775,"language":252,"meta":253,"style":253},"    def processAlgorithm(self, parameters, context, feedback):\n        source = self.parameterAsSource(parameters, INPUT, context)\n        field = self.parameterAsString(parameters, GROUP_FIELD, context)\n        minimum = self.parameterAsDouble(parameters, MIN_AREA, context)\n        units_index = self.parameterAsEnum(parameters, UNITS, context)\n        keep_empty = self.parameterAsBool(parameters, KEEP_EMPTY, context)\n\n        if source is None:\n            raise QgsProcessingException(self.invalidSourceError(parameters, INPUT))\n\n        divisor = 10000.0 if units_index == 1 else 1.0\n        ...\n",[27,777,778,788,806,822,838,854,870,874,891,908,912,940],{"__ignoreMap":253},[257,779,780,782,785],{"class":199,"line":259},[257,781,425],{"class":262},[257,783,784],{"class":404}," processAlgorithm",[257,786,787],{"class":266},"(self, parameters, context, feedback):\n",[257,789,790,793,795,798,801,803],{"class":199,"line":276},[257,791,792],{"class":266},"        source ",[257,794,434],{"class":262},[257,796,797],{"class":322}," self",[257,799,800],{"class":266},".parameterAsSource(parameters, ",[257,802,323],{"class":322},[257,804,805],{"class":266},", context)\n",[257,807,808,811,813,815,818,820],{"class":199,"line":282},[257,809,810],{"class":266},"        field ",[257,812,434],{"class":262},[257,814,797],{"class":322},[257,816,817],{"class":266},".parameterAsString(parameters, ",[257,819,336],{"class":322},[257,821,805],{"class":266},[257,823,824,827,829,831,834,836],{"class":199,"line":288},[257,825,826],{"class":266},"        minimum ",[257,828,434],{"class":262},[257,830,797],{"class":322},[257,832,833],{"class":266},".parameterAsDouble(parameters, ",[257,835,347],{"class":322},[257,837,805],{"class":266},[257,839,840,843,845,847,850,852],{"class":199,"line":294},[257,841,842],{"class":266},"        units_index ",[257,844,434],{"class":262},[257,846,797],{"class":322},[257,848,849],{"class":266},".parameterAsEnum(parameters, ",[257,851,358],{"class":322},[257,853,805],{"class":266},[257,855,856,859,861,863,866,868],{"class":199,"line":300},[257,857,858],{"class":266},"        keep_empty ",[257,860,434],{"class":262},[257,862,797],{"class":322},[257,864,865],{"class":266},".parameterAsBool(parameters, ",[257,867,369],{"class":322},[257,869,805],{"class":266},[257,871,872],{"class":199,"line":306},[257,873,316],{"emptyLinePlaceholder":315},[257,875,876,879,882,885,888],{"class":199,"line":312},[257,877,878],{"class":262},"        if",[257,880,881],{"class":266}," source ",[257,883,884],{"class":262},"is",[257,886,887],{"class":322}," None",[257,889,890],{"class":266},":\n",[257,892,893,896,899,901,904,906],{"class":199,"line":319},[257,894,895],{"class":262},"            raise",[257,897,898],{"class":266}," QgsProcessingException(",[257,900,460],{"class":322},[257,902,903],{"class":266},".invalidSourceError(parameters, ",[257,905,323],{"class":322},[257,907,593],{"class":266},[257,909,910],{"class":199,"line":333},[257,911,316],{"emptyLinePlaceholder":315},[257,913,914,917,919,922,925,928,931,934,937],{"class":199,"line":344},[257,915,916],{"class":266},"        divisor ",[257,918,434],{"class":262},[257,920,921],{"class":322}," 10000.0",[257,923,924],{"class":262}," if",[257,926,927],{"class":266}," units_index ",[257,929,930],{"class":262},"==",[257,932,933],{"class":322}," 1",[257,935,936],{"class":262}," else",[257,938,939],{"class":322}," 1.0\n",[257,941,942],{"class":199,"line":355},[257,943,944],{"class":322},"        ...\n",[14,946,947,949,950,953,954,957,958,961,962,965,966,968,969,972,973,976],{},[225,948,744],{}," ",[27,951,952],{},"parameterAsSource()"," returns a ",[27,955,956],{},"QgsProcessingFeatureSource",", which honours the user's \"selected features only\" choice automatically — this is why algorithms should take a source rather than a layer. The enum accessor returns the index into the options list you declared, so map it to meaning explicitly rather than comparing against a translated string, which would break in any other language. ",[27,959,960],{},"parameterAsDouble"," and ",[27,963,964],{},"parameterAsBool"," handle the conversion from whatever the caller passed, including the strings that arrive from the command line. Checking the source for ",[27,967,437],{}," and raising with ",[27,970,971],{},"invalidSourceError()"," gives the framework's standard, translated message instead of an ",[27,974,975],{},"AttributeError"," three lines later.",[214,978,980],{"id":979},"optional-parameters-and-advanced-sections","Optional parameters and advanced sections",[14,982,983],{},"Not every input belongs on the front of the dialog.",[248,985,987],{"className":250,"code":986,"language":252,"meta":253,"style":253},"        overlay = QgsProcessingParameterFeatureSource(\n            \"OVERLAY\", self.tr(\"Clip to boundary\"),\n            [QgsProcessing.TypeVectorPolygon], optional=True)\n        overlay.setFlags(overlay.flags() | QgsProcessingParameterDefinition.FlagAdvanced)\n        self.addParameter(overlay)\n\n        tolerance = QgsProcessingParameterNumber(\n            \"TOLERANCE\", self.tr(\"Snapping tolerance\"),\n            type=QgsProcessingParameterNumber.Double, defaultValue=0.01)\n        tolerance.setFlags(tolerance.flags() | QgsProcessingParameterDefinition.FlagAdvanced)\n        self.addParameter(tolerance)\n",[27,988,989,999,1015,1031,1042,1049,1053,1063,1079,1098,1107],{"__ignoreMap":253},[257,990,991,994,996],{"class":199,"line":259},[257,992,993],{"class":266},"        overlay ",[257,995,434],{"class":262},[257,997,998],{"class":266}," QgsProcessingParameterFeatureSource(\n",[257,1000,1001,1004,1006,1008,1010,1013],{"class":199,"line":276},[257,1002,1003],{"class":329},"            \"OVERLAY\"",[257,1005,457],{"class":266},[257,1007,460],{"class":322},[257,1009,463],{"class":266},[257,1011,1012],{"class":329},"\"Clip to boundary\"",[257,1014,469],{"class":266},[257,1016,1017,1020,1023,1025,1028],{"class":199,"line":282},[257,1018,1019],{"class":266},"            [QgsProcessing.TypeVectorPolygon], ",[257,1021,1022],{"class":511},"optional",[257,1024,434],{"class":262},[257,1026,1027],{"class":322},"True",[257,1029,1030],{"class":266},")\n",[257,1032,1033,1036,1039],{"class":199,"line":288},[257,1034,1035],{"class":266},"        overlay.setFlags(overlay.flags() ",[257,1037,1038],{"class":262},"|",[257,1040,1041],{"class":266}," QgsProcessingParameterDefinition.FlagAdvanced)\n",[257,1043,1044,1046],{"class":199,"line":294},[257,1045,445],{"class":322},[257,1047,1048],{"class":266},".addParameter(overlay)\n",[257,1050,1051],{"class":199,"line":300},[257,1052,316],{"emptyLinePlaceholder":315},[257,1054,1055,1058,1060],{"class":199,"line":306},[257,1056,1057],{"class":266},"        tolerance ",[257,1059,434],{"class":262},[257,1061,1062],{"class":266}," QgsProcessingParameterNumber(\n",[257,1064,1065,1068,1070,1072,1074,1077],{"class":199,"line":312},[257,1066,1067],{"class":329},"            \"TOLERANCE\"",[257,1069,457],{"class":266},[257,1071,460],{"class":322},[257,1073,463],{"class":266},[257,1075,1076],{"class":329},"\"Snapping tolerance\"",[257,1078,469],{"class":266},[257,1080,1081,1083,1085,1088,1091,1093,1096],{"class":199,"line":319},[257,1082,525],{"class":511},[257,1084,434],{"class":262},[257,1086,1087],{"class":266},"QgsProcessingParameterNumber.Double, ",[257,1089,1090],{"class":511},"defaultValue",[257,1092,434],{"class":262},[257,1094,1095],{"class":322},"0.01",[257,1097,1030],{"class":266},[257,1099,1100,1103,1105],{"class":199,"line":333},[257,1101,1102],{"class":266},"        tolerance.setFlags(tolerance.flags() ",[257,1104,1038],{"class":262},[257,1106,1041],{"class":266},[257,1108,1109,1111],{"class":199,"line":344},[257,1110,445],{"class":322},[257,1112,1113],{"class":266},".addParameter(tolerance)\n",[14,1115,1116,949,1118,1121,1122,1124,1125,1128],{},[225,1117,744],{},[27,1119,1120],{},"optional=True"," lets the user leave it blank, and your code must then handle ",[27,1123,437],{}," — which is exactly the point, because an optional clip layer is a genuinely different code path. ",[27,1126,1127],{},"FlagAdvanced"," moves the parameter into the collapsible Advanced section, which is where anything with a good default belongs; a dialog with four visible fields and six advanced ones is far more approachable than one with ten. Both flags are combined with the existing flags rather than replacing them, using the bitwise or — assigning the flag directly clears everything else, including the hidden and expression flags.",[14,1130,1131],{},[34,1132,1135,1138,1141,1144,1147,1154,1159,1162,1166,1170,1174,1179,1184,1186,1190,1192,1196,1199,1203,1205,1208,1210,1213,1216,1220,1222,1225,1229,1232,1235,1239,1241,1244,1246],{"viewBox":1133,"role":37,"ariaLabel":1134,"xmlns":39},"0 0 760 250","Table of common processing parameter types with the widget each produces and the accessor used to read it inside the algorithm",[41,1136,1137],{},"Parameter type, widget, accessor",[45,1139,1140],{},"Feature source parameters produce a layer picker and are read with parameter as source. Field parameters produce a field dropdown tied to a parent layer and are read as a string. Number parameters produce a spin box and are read as double or integer. Enum parameters produce a dropdown and are read as an index. Feature sink parameters produce an output chooser and are read with parameter as sink.",[49,1142],{"x":51,"y":51,"width":52,"height":1143,"fill":54},"250",[73,1145,1146],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"Reading a parameter with the wrong accessor is the usual bug",[49,1148],{"x":1149,"y":1150,"width":1151,"height":76,"rx":1152,"fill":1153,"stroke":102,"style":103},"16","46","238","6","#efeadd",[73,1155,1158],{"x":1156,"y":1157,"style":174,"fill":78,"textAnchor":79},"135","65","parameter type",[49,1160],{"x":1161,"y":1150,"width":1151,"height":76,"rx":1152,"fill":1153,"stroke":102,"style":103},"262",[73,1163,1165],{"x":1164,"y":1157,"style":174,"fill":78,"textAnchor":79},"381","widget",[49,1167],{"x":1168,"y":1150,"width":1169,"height":76,"rx":1152,"fill":1153,"stroke":102,"style":103},"508","236",[73,1171,1173],{"x":1172,"y":1157,"style":174,"fill":78,"textAnchor":79},"626","accessor",[49,1175],{"x":1149,"y":1176,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},"80","32","stroke-width:1.2",[73,1180,1183],{"x":100,"y":1181,"style":1182,"fill":108},"101","font-size:11px;font-family:sans-serif","FeatureSource",[49,1185],{"x":1161,"y":1176,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},[73,1187,1189],{"x":1188,"y":1181,"style":1182,"fill":108},"276","layer picker plus selection",[49,1191],{"x":1168,"y":1176,"width":1169,"height":1177,"rx":1152,"fill":88,"stroke":71,"style":103},[73,1193,1195],{"x":1194,"y":1181,"style":1182,"fill":108},"522","parameterAsSource",[49,1197],{"x":1149,"y":1198,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},"118",[73,1200,1202],{"x":100,"y":1201,"style":1182,"fill":108},"139","Field",[49,1204],{"x":1161,"y":1198,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},[73,1206,1207],{"x":1188,"y":1201,"style":1182,"fill":108},"dropdown from parent layer",[49,1209],{"x":1168,"y":1198,"width":1169,"height":1177,"rx":1152,"fill":88,"stroke":71,"style":103},[73,1211,1212],{"x":1194,"y":1201,"style":1182,"fill":108},"parameterAsString",[49,1214],{"x":1149,"y":1215,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},"156",[73,1217,1219],{"x":100,"y":1218,"style":1182,"fill":108},"177","Enum",[49,1221],{"x":1161,"y":1215,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},[73,1223,1224],{"x":1188,"y":1218,"style":1182,"fill":108},"dropdown of your options",[49,1226],{"x":1168,"y":1215,"width":1169,"height":1177,"rx":1152,"fill":1227,"stroke":1228,"style":103},"#fdf2e2","#b45309",[73,1230,1231],{"x":1194,"y":1218,"style":1182,"fill":108},"parameterAsEnum — an index",[49,1233],{"x":1149,"y":1234,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},"194",[73,1236,1238],{"x":100,"y":1237,"style":1182,"fill":108},"215","FeatureSink",[49,1240],{"x":1161,"y":1234,"width":1151,"height":1177,"rx":1152,"fill":101,"stroke":102,"style":1178},[73,1242,1243],{"x":1188,"y":1237,"style":1182,"fill":108},"output chooser",[49,1245],{"x":1168,"y":1234,"width":1169,"height":1177,"rx":1152,"fill":88,"stroke":71,"style":103},[73,1247,1248],{"x":1194,"y":1237,"style":1182,"fill":108},"parameterAsSink — two values",[214,1250,1252],{"id":1251},"validate-before-the-work-starts","Validate before the work starts",[14,1254,1255],{},"Parameters that are individually valid can be jointly wrong — a field that is not numeric, a distance in the wrong units for the layer's CRS, two layers in incompatible projections.",[248,1257,1259],{"className":250,"code":1258,"language":252,"meta":253,"style":253},"    def checkParameterValues(self, parameters, context):\n        source = self.parameterAsSource(parameters, INPUT, context)\n        field = self.parameterAsString(parameters, GROUP_FIELD, context)\n\n        if source is not None and field:\n            index = source.fields().lookupField(field)\n            if index >= 0 and not source.fields().at(index).isNumeric():\n                if self.parameterAsEnum(parameters, UNITS, context) == 1:\n                    return False, self.tr(\"Hectare output needs a numeric field\")\n\n        return super().checkParameterValues(parameters, context)\n",[27,1260,1261,1271,1285,1299,1303,1322,1332,1353,1373,1392,1396],{"__ignoreMap":253},[257,1262,1263,1265,1268],{"class":199,"line":259},[257,1264,425],{"class":262},[257,1266,1267],{"class":404}," checkParameterValues",[257,1269,1270],{"class":266},"(self, parameters, context):\n",[257,1272,1273,1275,1277,1279,1281,1283],{"class":199,"line":276},[257,1274,792],{"class":266},[257,1276,434],{"class":262},[257,1278,797],{"class":322},[257,1280,800],{"class":266},[257,1282,323],{"class":322},[257,1284,805],{"class":266},[257,1286,1287,1289,1291,1293,1295,1297],{"class":199,"line":282},[257,1288,810],{"class":266},[257,1290,434],{"class":262},[257,1292,797],{"class":322},[257,1294,817],{"class":266},[257,1296,336],{"class":322},[257,1298,805],{"class":266},[257,1300,1301],{"class":199,"line":288},[257,1302,316],{"emptyLinePlaceholder":315},[257,1304,1305,1307,1309,1311,1314,1316,1319],{"class":199,"line":294},[257,1306,878],{"class":262},[257,1308,881],{"class":266},[257,1310,884],{"class":262},[257,1312,1313],{"class":262}," not",[257,1315,887],{"class":322},[257,1317,1318],{"class":262}," and",[257,1320,1321],{"class":266}," field:\n",[257,1323,1324,1327,1329],{"class":199,"line":300},[257,1325,1326],{"class":266},"            index ",[257,1328,434],{"class":262},[257,1330,1331],{"class":266}," source.fields().lookupField(field)\n",[257,1333,1334,1337,1340,1343,1346,1348,1350],{"class":199,"line":306},[257,1335,1336],{"class":262},"            if",[257,1338,1339],{"class":266}," index ",[257,1341,1342],{"class":262},">=",[257,1344,1345],{"class":322}," 0",[257,1347,1318],{"class":262},[257,1349,1313],{"class":262},[257,1351,1352],{"class":266}," source.fields().at(index).isNumeric():\n",[257,1354,1355,1358,1360,1362,1364,1367,1369,1371],{"class":199,"line":312},[257,1356,1357],{"class":262},"                if",[257,1359,797],{"class":322},[257,1361,849],{"class":266},[257,1363,358],{"class":322},[257,1365,1366],{"class":266},", context) ",[257,1368,930],{"class":262},[257,1370,933],{"class":322},[257,1372,890],{"class":266},[257,1374,1375,1378,1381,1383,1385,1387,1390],{"class":199,"line":319},[257,1376,1377],{"class":262},"                    return",[257,1379,1380],{"class":322}," False",[257,1382,457],{"class":266},[257,1384,460],{"class":322},[257,1386,463],{"class":266},[257,1388,1389],{"class":329},"\"Hectare output needs a numeric field\"",[257,1391,1030],{"class":266},[257,1393,1394],{"class":199,"line":333},[257,1395,316],{"emptyLinePlaceholder":315},[257,1397,1398,1401,1404],{"class":199,"line":344},[257,1399,1400],{"class":262},"        return",[257,1402,1403],{"class":322}," super",[257,1405,1406],{"class":266},"().checkParameterValues(parameters, context)\n",[14,1408,1409,949,1411,1414,1415,1417,1418,1421],{},[225,1410,744],{},[27,1412,1413],{},"checkParameterValues()"," runs before the algorithm starts and returns a tuple of validity and message; the framework shows the message in the dialog and refuses to run. Doing this here rather than raising inside ",[27,1416,29],{}," matters in batch mode, where a hundred rows should be validated before any of them execute rather than failing on row sixty. Always delegate to ",[27,1419,1420],{},"super()"," at the end so the framework's own checks — mandatory parameters, writable outputs — still apply.",[14,1423,1424],{},[34,1425,1428,1431,1434,1437,1440,1444,1447,1451,1455,1457,1460,1462,1466,1468,1472,1475,1479,1481,1484,1486],{"viewBox":1426,"role":37,"ariaLabel":1427,"xmlns":39},"0 0 760 246","Diagram comparing validation inside checkParameterValues which stops a batch before it starts against validation inside processAlgorithm which fails partway through a hundred rows",[41,1429,1430],{},"Where validation belongs in batch mode",[45,1432,1433],{},"Validating in checkParameterValues runs before execution, so a batch of a hundred rows reports the problem immediately and nothing is written. Validating inside processAlgorithm runs per row, so sixty rows are processed and written before the bad one fails, leaving a partial output nobody asked for.",[49,1435],{"x":51,"y":51,"width":52,"height":1436,"fill":54},"246",[73,1438,1439],{"x":75,"y":76,"style":77,"fill":78,"textAnchor":79},"A hundred rows deserve to fail before the first one runs",[49,1441],{"x":83,"y":84,"width":1442,"height":1443,"rx":87,"fill":169,"stroke":170,"style":89},"348","176",[73,1445,1446],{"x":1234,"y":93,"style":94,"fill":170,"textAnchor":79},"checkParameterValues",[49,1448],{"x":1449,"y":99,"width":1450,"height":100,"rx":1152,"fill":101,"stroke":102,"style":103},"44","300",[73,1452,1454],{"x":1453,"y":106,"style":1182,"fill":108},"60","runs before execution",[49,1456],{"x":1449,"y":92,"width":1450,"height":100,"rx":1152,"fill":101,"stroke":102,"style":103},[73,1458,1459],{"x":1453,"y":114,"style":1182,"fill":108},"message shown in the dialog",[49,1461],{"x":1449,"y":118,"width":1450,"height":1449,"rx":1152,"fill":101,"stroke":170,"style":137},[73,1463,1465],{"x":1234,"y":1464,"style":174,"fill":170,"textAnchor":79},"193","nothing written, nothing to undo",[49,1467],{"x":140,"y":84,"width":1442,"height":1443,"rx":87,"fill":1227,"stroke":1228,"style":89},[73,1469,1471],{"x":1470,"y":93,"style":94,"fill":1228,"textAnchor":79},"566","inside processAlgorithm",[49,1473],{"x":1474,"y":99,"width":1450,"height":100,"rx":1152,"fill":101,"stroke":102,"style":103},"416",[73,1476,1478],{"x":1477,"y":106,"style":1182,"fill":108},"432","runs per row",[49,1480],{"x":1474,"y":92,"width":1450,"height":100,"rx":1152,"fill":101,"stroke":102,"style":103},[73,1482,1483],{"x":1477,"y":114,"style":1182,"fill":108},"row 61 raises",[49,1485],{"x":1474,"y":118,"width":1450,"height":1449,"rx":1152,"fill":101,"stroke":1228,"style":137},[73,1487,1488],{"x":1470,"y":1464,"style":174,"fill":1228,"textAnchor":79},"60 outputs already written",[214,1490,1492],{"id":1491},"outputs-are-parameters-too","Outputs are parameters too",[14,1494,1495,1496,1498],{},"The sink declared alongside the inputs above is what gives the user an output chooser, and reading it inside ",[27,1497,29],{}," is slightly unusual because it returns two values.",[248,1500,1502],{"className":250,"code":1501,"language":252,"meta":253,"style":253},"        # inside processAlgorithm\n        sink, dest_id = self.parameterAsSink(\n            parameters, OUTPUT, context, fields, QgsWkbTypes.NoGeometry, source.sourceCrs())\n        if sink is None:\n            raise QgsProcessingException(self.invalidSinkError(parameters, OUTPUT))\n        return {OUTPUT: dest_id}\n",[27,1503,1504,1510,1522,1532,1545,1560],{"__ignoreMap":253},[257,1505,1506],{"class":199,"line":259},[257,1507,1509],{"class":1508},"sjoCn","        # inside processAlgorithm\n",[257,1511,1512,1515,1517,1519],{"class":199,"line":276},[257,1513,1514],{"class":266},"        sink, dest_id ",[257,1516,434],{"class":262},[257,1518,797],{"class":322},[257,1520,1521],{"class":266},".parameterAsSink(\n",[257,1523,1524,1527,1529],{"class":199,"line":282},[257,1525,1526],{"class":266},"            parameters, ",[257,1528,380],{"class":322},[257,1530,1531],{"class":266},", context, fields, QgsWkbTypes.NoGeometry, source.sourceCrs())\n",[257,1533,1534,1536,1539,1541,1543],{"class":199,"line":288},[257,1535,878],{"class":262},[257,1537,1538],{"class":266}," sink ",[257,1540,884],{"class":262},[257,1542,887],{"class":322},[257,1544,890],{"class":266},[257,1546,1547,1549,1551,1553,1556,1558],{"class":199,"line":294},[257,1548,895],{"class":262},[257,1550,898],{"class":266},[257,1552,460],{"class":322},[257,1554,1555],{"class":266},".invalidSinkError(parameters, ",[257,1557,380],{"class":322},[257,1559,593],{"class":266},[257,1561,1562,1564,1567,1569],{"class":199,"line":300},[257,1563,1400],{"class":262},[257,1565,1566],{"class":266}," {",[257,1568,380],{"class":322},[257,1570,1571],{"class":266},": dest_id}\n",[14,1573,1574,1576,1577,1580,1581,1584,1585,1588],{},[225,1575,744],{}," A sink parameter gives the user the full output chooser — a file, a GeoPackage layer, a PostGIS table, a temporary layer — without your code caring which. ",[27,1578,1579],{},"parameterAsSink()"," returns ",[758,1582,1583],{},"two"," values, the sink to write to and the destination id to return, and returning the id is what lets the framework add the result to the map, chain it into a model, or report its path. Declaring ",[27,1586,1587],{},"NoGeometry"," here produces an attribute-only table, which is exactly right for a summary and a common thing to get wrong by copying a geometry-carrying example.",[214,1590,1592],{"id":1591},"qgis-version-compatibility","QGIS version compatibility",[1594,1595,1596,1612],"table",{},[1597,1598,1599],"thead",{},[1600,1601,1602,1606,1609],"tr",{},[1603,1604,1605],"th",{},"QGIS version",[1603,1607,1608],{},"Python",[1603,1610,1611],{},"Notes",[1613,1614,1615,1629,1639,1650],"tbody",{},[1600,1616,1617,1621,1624],{},[1618,1619,1620],"td",{},"3.22 LTR",[1618,1622,1623],{},"3.9",[1618,1625,1626,1627,30],{},"All parameter types shown, plus flags and ",[27,1628,1446],{},[1600,1630,1631,1634,1636],{},[1618,1632,1633],{},"3.28 LTR",[1618,1635,1623],{},[1618,1637,1638],{},"Identical.",[1600,1640,1641,1644,1647],{},[1618,1642,1643],{},"3.34 LTR",[1618,1645,1646],{},"3.12",[1618,1648,1649],{},"Baseline for this page.",[1600,1651,1652,1655,1657],{},[1618,1653,1654],{},"3.40 \u002F 3.44",[1618,1656,1646],{},[1618,1658,1659],{},"Adds further parameter types (point cloud layers, area and volume numbers); existing ones unchanged.",[14,1661,1662,1663,1666],{},"Parameter ",[758,1664,1665],{},"names"," are part of your public interface: models and scripts reference them. Renaming one breaks every saved model that uses the algorithm, so choose plain uppercase names early and keep them.",[214,1668,1670],{"id":1669},"troubleshooting","Troubleshooting",[219,1672,1673,1681,1693,1702,1708,1719],{},[222,1674,1675,949,1678,1680],{},[225,1676,1677],{},"The field dropdown is empty.",[27,1679,755],{}," is missing or names a parameter that does not exist.",[222,1682,1683,1689,1690,30],{},[225,1684,1685,1688],{},[27,1686,1687],{},"parameterAsEnum()"," returns 0 for everything."," You are comparing against labels; it returns the index into ",[27,1691,1692],{},"options",[222,1694,1695,1698,1699,1701],{},[225,1696,1697],{},"An optional parameter crashes the algorithm."," It is ",[27,1700,437],{}," when blank. Handle that branch explicitly.",[222,1703,1704,1707],{},[225,1705,1706],{},"The advanced section is empty and everything is visible."," The flag was assigned rather than combined with the existing flags.",[222,1709,1710,1713,1714,1716,1717,30],{},[225,1711,1712],{},"Batch mode fails on every row."," Validation is inside ",[27,1715,29],{}," instead of ",[27,1718,1413],{},[222,1720,1721,949,1724,1726],{},[225,1722,1723],{},"The output never appears on the map.",[27,1725,29],{}," did not return the destination id in its dictionary.",[214,1728,1730],{"id":1729},"conclusion","Conclusion",[14,1732,1733,1734,1736],{},"Declare parameters with the specific type that matches the input — feature source, field with a parent layer, number with limits, enum with options — give everything a sensible default, and push anything with a good default into the advanced section. Read each with its matching accessor, remembering that enums give indices and sinks give two values, and validate combinations in ",[27,1735,1413],{}," so batch runs fail before they start rather than halfway through.",[214,1738,1740],{"id":1739},"frequently-asked-questions","Frequently Asked Questions",[14,1742,1743,1746],{},[225,1744,1745],{},"Should I take a layer or a feature source?","\nA source. It honours the \"selected features only\" option and accepts a file path as well as a loaded layer, so the algorithm works in more contexts for no extra code.",[14,1748,1749,1752,1753,1756,1757,30],{},[225,1750,1751],{},"How do I let the user enter an expression?","\nUse ",[27,1754,1755],{},"QgsProcessingParameterExpression"," with a parent layer, which gives the expression builder with the right fields — see ",[21,1758,1760],{"href":1759},"\u002Fpyqgis-fundamentals-environment-setup\u002Fworking-with-qgis-expressions\u002Fevaluate-qgis-expression-in-pyqgis\u002F","Evaluate a QGIS Expression in PyQGIS",[14,1762,1763,1766,1767,1769],{},[225,1764,1765],{},"Can a parameter depend on another parameter's value?","\nField, expression and band parameters can name a parent layer. Beyond that, validate the combination in ",[27,1768,1413],{},"; the dialog cannot rebuild itself dynamically.",[14,1771,1772,1775],{},[225,1773,1774],{},"What is the difference between a sink and a file output?","\nA sink writes features and can target any provider; a file destination parameter is just a path, for algorithms writing something that is not a layer, such as a report.",[14,1777,1778,1781],{},[225,1779,1780],{},"How do defaults appear in batch mode?","\nEach row starts from the declared defaults, so good defaults save the most typing exactly where there is the most of it.",[14,1783,1784,1787,1788,1791,1792,1795],{},[225,1785,1786],{},"Can I give a parameter its own help text?","\nYes — ",[27,1789,1790],{},"setHelp()"," on the definition adds a tooltip, and ",[27,1793,1794],{},"shortHelpString()"," on the algorithm can describe each parameter in the panel beside the dialog. Both are worth filling in for anything whose units or expectations are not obvious from the label alone.",[14,1797,1798,1801,1802,1805,1806,30],{},[225,1799,1800],{},"Do parameter labels need translating?","\nYes — wrap them in ",[27,1803,1804],{},"self.tr()",". They are the algorithm's entire visible interface, as covered in ",[21,1807,1809],{"href":1808},"\u002Fqgis-plugin-development\u002Fplugin-settings-and-localization\u002Ftranslate-qgis-plugin-with-qt-linguist\u002F","Translate a QGIS Plugin with Qt Linguist",[214,1811,1813],{"id":1812},"related","Related",[219,1815,1816,1821,1825,1829,1835],{},[222,1817,1818,1820],{},[21,1819,24],{"href":23}," — the guide this recipe belongs to",[222,1822,1823],{},[21,1824,235],{"href":234},[222,1826,1827],{},[21,1828,242],{"href":241},[222,1830,1831],{},[21,1832,1834],{"href":1833},"\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Freport-progress-and-cancel-processing-algorithm\u002F","Report Progress and Cancellation in a Processing Algorithm",[222,1836,1837],{},[21,1838,1840],{"href":1839},"\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script\u002F","Run a Processing Algorithm from a Script",[1842,1843,1844],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}",{"title":253,"searchDepth":276,"depth":276,"links":1846},[1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857],{"id":216,"depth":276,"text":217},{"id":245,"depth":276,"text":246},{"id":764,"depth":276,"text":765},{"id":979,"depth":276,"text":980},{"id":1251,"depth":276,"text":1252},{"id":1491,"depth":276,"text":1492},{"id":1591,"depth":276,"text":1592},{"id":1669,"depth":276,"text":1670},{"id":1729,"depth":276,"text":1730},{"id":1739,"depth":276,"text":1740},{"id":1812,"depth":276,"text":1813},"Define inputs users can actually fill in — layer, field, number, enum and file parameters, sensible defaults and optional flags, dependent field pickers, and reading values correctly inside processAlgorithm.","md",{"slug":1861,"type":1862,"breadcrumb":1863,"datePublished":1864,"dateModified":1864},"add-parameters-to-processing-algorithm-pyqgis","article","Algorithm Parameters","2026-08-15","\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Fadd-parameters-to-processing-algorithm-pyqgis",{"title":5,"description":1858},"qgis-plugin-development\u002Fprocessing-provider-plugins\u002Fadd-parameters-to-processing-algorithm-pyqgis\u002Findex","yatZ_dj-liJvS30WerLf8b6LxWH3qlSeNNi4Il8tAjo",1786789584642]