0.7.0 migration notes
Parameter kinds (decision-46 point 1). Six kinds join
LayerInput/CrsInput/Metres: FileInput(filters=), DirectoryInput(),
FieldInput(of=), Range(min, max), Colour() and Literal[...] choices
(the table under “Providers” above). What changes for existing code:
- A
Literal[...]of strings is now theenumkind for algorithms: it was refused at declaration in 0.6 and now renders aQgsProcessingParameterEnum. Actions and jobs already acceptedLiteral; they are unchanged. - Declared inputs with a marker carry
"x-qgis-sdk": {"kind": ...}in their schema (aRangealso carriesminimum/maximum). The keyword is accepted by both validators and the generator; a generatedbridge.schema.tsgains/** @qgis-sdk-kind ... */on those fields and itsCONTRACT_FINGERPRINTmoves - regenerate withqgis-sdk bridge generate. Pages readingrequest.properties[...]see one more key. FileRefmoved toqgis_sdk.models(qgis_sdk.bridge.authoritystill re-exports it) and gainedkind = "directory";FILE_REFlists both kinds, so the host contract’sHOST_FINGERPRINTmoved (sha256:af91deac…); the schema and protocol versions did not.HostAuthority.grant_directorymints a directory read ref;resolve_filechecks the ref’s kind against the grant.NativeProcessing(..., authority=)andregister_provider(..., authority=)accept the host authority the toolbox mints picker refs through; without one each provider owns its own.FieldSpecgaineddetails;FieldSpec.to_dict()emits it.qgis_sdk.algorithms.input_refusalis the one rule a toolbox run, a page call and a form use to refuse a value;parameter_kindkeeps its name and now delegates toqgis_sdk.declarations.resolve_kind.
Input components and ctx.files.
qgis_sdk.uiexports the eleven input components (LayerPicker,FieldPicker,CrsPicker,FileInput,DirectoryInput,Distance,Number,Text,Toggle,Choice,Colour),Component,Optionandcoerce_value; see Input components above.Surface.build()may return a component; the host attaches and mounts it.PluginContextgained thefilescapability (qgis_sdk.services.Files, implemented byqgis_sdk.files.FilesService);UiContextgainedfiles,layersandproject. A context that lacks them refuses by name as before, andhas("layers")on aUiContextis now a real probe rather than aValueError.- The Desktop host builds one
HostAuthorityper runtime and hands it to Processing (NativeProcessing(authority=)), toctx.filesand - throughHostServices.from_context, which now defaults to the context’sfiles.authority- to the WebEngine host. A host that built its ownHostServices(authority=...)keeps it; pass none to share. qgis_sdk.testing.FakeFiles.- Form coercion (
coerce_values, and soUiContext.actions, the declared form dialog and the bridge) now refuses a negativeMetresvalue (“a distance of 0 or more metres”), matching the spin box and the Processing parameter; refusal messages keep theiraction '<id>': field <name> expects ...shape.
Form, Button, Column; NativeForms and DeclaredFormDialog
removed. See Forms: an action’s inputs as a window.
-
qgis_sdk.adapters.qgis.uiis gone:NativeForms(runtime),.fields(id),.render(id),.run(id),.dispatch(id, values)andDeclaredFormDialog. Migration, line by line:0.6 0.7 NativeForms(runtime).fields("buffer")Form.for_action(ctx, "buffer").fields(components;form_fields(description)still gives theFieldSpecs)dialog = forms.render("buffer");dialog.widget("layer_id")form = Form.for_action(self.ctx, "buffer")inside aDialog.build();form.field("layer_id").widgetafter mountdialog.values()form.values()forms.dispatch("buffer", values)form.submit()(orself.ctx.actions.buffer(**values))forms.run("buffer")(modal,Noneon cancel)a Dialogsubclass returningColumn([form, Button]), opened by a binding orctx.ui.open; add your own cancelButtoncallingself.ctx.view.request_close()A form carries the view’s authority, so
FileInput/DirectoryInputfields, which the 0.6 dialog refused by name, now render and submitFileRefs. -
qgis_sdk.uiexportsForm,Button,Column,Input,input_for,schema_fields,ViewActions,ActionCall.Componentis now the identity/lifecycle base shared with containers; the eleven inputs subclassInputand acceptrequired=.Component.attach(ctx)with the same context is a no-op (a container attaches its children); a second context is still refused. -
ViewActions.describe(action_id)is public: the declared description a form builds from. -
form_fieldsrefusals name their owner (action 'x': field ...) as before;schema_fields(schema, owner=)is the same rule for a bare schema (form: field ...). -
ctx.notificationsgainedsuccess,warning,criticalandwith_action(label, action_id, **arguments);infois unchanged. A hand-writtenNotificationsdouble withinfoonly keeps working for code that callsinfo; subclassqgis_sdk.services.NotificationsBaseand implement_deliver(notification)to get all four plus the button.RecordingNotifications.messagesis unchanged;records,press()andbind_actions()are new.NativeNotifications(sink=)now receives aNotification, not a string.MessageBarNotificationspushes at the level and growsbind_actions, whichDesktopHost.initGuicalls. -
qgis-sdk checkreportsUI001; the scaffold’sPingDialogalready names its widgets. The desktop-adapter qualification fixture gained aForm-built dialog and theform_submittedstage.
Wiring, mixins, containers, feedback, Custom, ctx.log.
See Wiring, Containers, feedback, buttons and Custom, Behaviour
mixins, Designer files and the pure-PyQt path and Testing surfaces
without QGIS above.
qgis_sdk.uiexportson,subscribe,wire_surface,wires_of,StreamEvent,ViewStreams,ViewSubscription,load_ui, the containersPanel/Group/Tabs/Row(next toColumn), the feedbackJobProgress/LogView/ResultTable, the buttonsRunButton/AcceptCancel(next toButton),Custom,ui_snapshotand the mixinsRunsJobs/SubscribesStreams/HasAcceptCancel.Surfacegained theuiclass attribute and theon_accept()/on_close()hooks; a plain class withkindand actxconstructor argument is accepted insurfaces(the widget form).- A
Button/Formlistener connected by hand insidebuild()keeps working; the@onform is the one the fake wires for you, so a test that calledbuild()directly and clicked should move tobuild_surface. UiContextgainedlogandstreamsand theon(stream, callback)method;PluginContextgainedlog(qgis_sdk.services.Log,NativeLogon the Desktop,RecordingLoginqgis_sdk.testing).fake_ui_context(runtime=)buildsactionsandstreams.- A view’s own synchronous push during
ctx.actions.<id>()is delivered withStreamEvent.echo = True; bridge subscribers are unchanged. qgis-sdk checkreportsUI002and the warningUI004;check_bindings(..., directory=)is how the Designer file is found.- The
simpleexample gainedResultsDock, aDockof the catalogue; the scaffold’sPingDialoguses@on("ping").clickedinstead ofbutton.clicked.connect.
The declarative surface form (decision-55 amendment). See The declarative form above.
- Every component’s
nameis optional and every catalogue class has a keyword form;Componentgained__set_name__,named, lazylabelandobject_name,Button.textis a property,RunButton.progressis readable. AContainerchecks for clashing child names when built and when attached (declared children get their names after the class body). Surface.build()’s default returns the declared tree before refusing;qgis_sdk.ui.declarative(declared_components,materialise,declared_root,resolve_declared) is what the host,build_surfaceandwire_surfaceuse;Wire.targetmay be aComponent.derive_titlecapitalises a lower-camel name (fieldTools→Field Tools); it readfield Toolsbefore.ResultsDockin the example is declared; its button isbuttons/fixture(wasbuttons/open) and the tableself.results(wasself.table).- Adoption:
Formaccepts unnamed inputs and keys them by name lazily (Form._fieldsresolves on first use; a form of inputs that never get a name refuses when read); the defaultbuild()seeds declared inputs frominitialand refuses an unknown key (qgis_sdk.ui.declarative.apply_initial,declared_inputs); snapshot nodes of declared components carry"attribute"(Component.attribute);qgis-sdk checkgainedUI005; the scaffold’sPingDialogis declared (form/value,buttons/ping,feedback/answers; it wasvalue,pingandanswerbuilt in PyQt).
Any registered algorithm (decision-64). See Any registered algorithm above. Nothing existing breaks; what is new:
Algorithmsgainsproviders(),list(provider=None),describe(id)andrun(request, params=None);executeandBufferRequest/CentroidRequeststay as they are and are documented as the predecessors ofnative.Buffer/native.Centroids.FakeAlgorithmsanswerslist/describefrom the shipped snapshot andrunfromscript_run(...); itsrunslist records everyrunas anAlgorithmRun.- New generated subpackage
qgis_sdk.processing(native,qgis,gdal,p3d,pdal,catalogue.json) and new modelsProviderInfo,AlgorithmInfo,ParameterInfo,OutputInfo,AlgorithmRun,RunResult,RunOutput; new errorsQgisSdkAlgorithmNotFoundError,QgisSdkAlgorithmRejectedError,QgisSdkAlgorithmFailedError. - Host operations
algorithms.providers/list/describe/runbehind the grantsalgorithms.read/algorithms.run;HOST_FINGERPRINTmoved once tosha256:16790dc8….qgis-sdk new --webgrantsalgorithms.run, writesweb/src/processing.schema.tsand runsqgis-sdk processing generate --checkfrombindings. - New developer command
qgis-sdk processing generate(tools never import QGIS: the reader runs in the project’s interpreter) and the repo scriptscripts/generate_processing_snapshot.pywith a CI drift check.