Restore previously selected layer after closing form

Me again. I’m making good progress but stumbling on a small, but annoying thing. In my plugin (I will try to give you a minimum example, stripping a lot of complexity) I try to write to a given layer, even if another one is selected. However as a courtesy to the user, I want afterwards to return to the originally selected layer. I also want to use the existing feature form, rather than redesigning it.

To give an example: assume we have layer1 and layer2. the targetLayer is layer2. Currently, layer1 is selected in the layer tree. When the user creates a feature, I want to open the form for layer2, write the feature to layer2, and THEN ensure that the active layer is still layer1 when the user is done.

So my current code looks like that:

function writeFeaturetoSelectedLayer() {
// preserve the currently selected layer
      var currentLayer = dashBoard.activeLayer

// select the layer where we actually want to write
     var layer = qgisProject.mapLayersByName("layer2")[0]
     dashBoard.activeLayer = layer

// Create a blank object and its geometry
      let geometry = ....
      let feature = FeatureUtils.createBlankFeature(dashBoard.activeLayer.fields, geometry)
// .. do all sort of clever things to pre-fill some attributes ...

// Transfert to the editing form
      overlayFeatureFormDrawer.featureModel.feature = feature
      overlayFeatureFormDrawer.featureModel.resetAttributes(true)
      overlayFeatureFormDrawer.state = 'Add'

// Close the dialog where we currently are, open the drawer
      mainDialog.close()
      overlayFeatureFormDrawer.open()

// Restore the originally selected layer
      dashBoard.activeLayer = currentLayer
   
}

However, this fails because the drawer form opens on currentLayer, rather than on targetLayerName. It looks like the open() command is deferred until I’m done with my function, rather than operating immediately - so when it finally fires, the active layer has changed already (if this makes sense).
In terms of the example above - the form opens for layer1, not for layer2.

If I omit the last line, the form opens for the right layer, but then it stays selected, which was not my intention.
At the end of the operation, I created a feature on layer2 (good) but now layer2 is the active layer (bad).

Any clue ?

Hello @Jean-Francois_Moyen , I have zero experience with QField plugins and QML, but what you describe does make sense, the .open() looks like a sort of asynchronous function. Doing a quick look at the plugin examples, that method seems to always be called pretty much last on a function.

Some components do have an onOpened() callback on which I assume the programmer can re-synchronise the code, for example the Dialog component on this example. Maybe it’s worth a try to see if your overlayFeatureFormDrawer object has one too; if that’s the case, maybe all you need is to move your last line inside overlayFeatureFormDrawer.onOpened

Hmm. Thanks, but I’m not sure I can modify the code of overlayFeatureFormDrawer.onOpened : it is a QField object, which I cannot modify, as far as I understand ?

As I understand it, this page of the QML documentation makes me believe that if you write something like:

overlayFeatureFormDrawer.onOpened: {
    dashBoard.activeLayer = currentLayer
}

you should be “adding a handler to a signal”, although it does look like you are assigning/overwriting the contents of the function. The “signal” in this case would be the “opening” of the overlayFeatureFormDrawer.

Thanks, good hint. Right now I have a strange syntax error :

expected token : ,

(a comma, instead of the colon) which makes little sense to me (why on Earth would a comma be required anywhere in this statement???).
But it seems to me that I need to do it in a somewhat more elaborate way, using Connection. I don’t have time for that right now but I will report back :slight_smile:

it may be that whatever thing you are calling on the line that error pops out, it’s expecting at least a second “parameter” of sorts. Check the section “Signal parameters” of my previous link. Maybe you’ll need to essentially make a lambda function in there, which makes the syntax a bit more wonky. And who knows what each parameter might be (if I have to guess, maybe the first one would be the callback function and the second a sort of error code/object that lets you know if the “opening” went ok or not). On that section you can see an example on how to write what it calls an “arrow function”.

Good luck in your findings!

@Jean-Francois_Moyen , you can use a Connections {} item to list to signals from the onClosed signal. It’d be something like this:

Connections {
  target: overlayFeatureFormDrawer // I assume you stored this already after finding it via iface

  function onClosed() {
    // restore the original layer
  }
}

Hi all. Thanks to @Mathieu_Pellerin , @cuprico and @fggs-pascal , I managed to build not one, but two plugins using the tricks we discussed - and then some.

One is a geological compass, long wished by fellow (structural) geologists; it is based on the original code by Mark Jessell (GitHub - swaxi/compass: compass plugin for QFIELD · GitHub) with, I hope, some improvements :
GitHub - jfmoyen/QField_qml_Geological_compass: A QField plugin adding a geological compass app to record plane and line orientation · GitHub

The other one is a small modification of Snap!(GitHub - opengisch/qfield-snap: Allow for snapping of photos to create a feature at the current device location. · GitHub), simply by sending the new photo to a pre-defined layer (rather than the active one): GitHub - jfmoyen/QField_MySnap: The snap! plugin, slightly modified · GitHub

It seems to work on my device (I will try more next week, I’ll be in the field). Now bracing for the unavoidable bug reports… :face_holding_back_tears:

2 Likes