10

Is there is a signal in QGIS emitted when a project is about to be closed (QGIS closing or some other project opening)?

I want to programmatically save changes in layers if they are in edit mode.

4 Answers 4

4

I did not find it.

There is a "cleared" signal in QgsProject but fires after the project is closed.

QgsMapLayer has a "willBeDeleted" signal but also fires after system prompts the save dialog.

3

Not completely sure what you're asking as QGIS automatically prompts the user if they want to save layers which are in editing mode. But the following code can be used which saves all layers currently in edit mode:

for layer in QgsMapLayerRegistry.instance().mapLayers().values():
    layer.commitChanges()
1
  • 1
    I want to do it automatically before QGIS prompts. For that i need a corresponding signal if there is one. Commiting changes to layers is not a problem. Commented Sep 11, 2015 at 5:46
3
+50

If you have several options, you can combine them for different cases:

You can use QgsProject signals.

You have the signal cleared() but as @Jaume Figueras points out it runs after closing. You can complement it with projectSaved() signal when the user during the execution clicks on save.

Since you are interested in saving the changes of the layers by code, it would be best to focus on them with. The QgsProject signal, layersWillBeRemoved(), when closing the project is triggered before removing the layers.

But I think the ideal option is to use the signals on the layers (QgsMapLayer), specifically willBeDeleted (). As the API indicates:

Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid state: the last chance for other pieces of code for some cleanup if they use the layer.

To connect the events on the layers you can generate a list of all the layers and with a cycle connect the signal:

pry= QgsProject.instance() #Capture the project
listLayers= list(pry.mapLayers().values())
for i in listLayers:
    i.willBeDeleted.connect(self.your_function)

To connect and disconnect the signals to the layers that are added and removed during execution you use the QgsProject signals, layersWillBeRemoved, layersAdded, among others

3
  • 1
    It didn''t work. In edit mode, when clicking on the exit button or opening a new project it prompts if I want to save changes, then emits willBeDeleted (and other) signal. Commented Sep 15, 2020 at 14:16
  • This is not answering the question. But I award my bounty to this answer because of @Luis's effort. Commented Sep 21, 2020 at 14:52
  • In my case, I want to capture the "about to remove a layer" to save it, only to S3. I have bypassed the problem of the slot not getting the layer reference (or name) using a lambda to create the connection. But the slot is called when the layer is already gone (mapLayersByName won't find it).
    – olepinto
    Commented Mar 22, 2022 at 17:05
3

The signal QgsProject.instance().layersWillBeRemoved is emitted whenever one or more layers are about to be removed. The associated slot will get the list of layer ids, providing access to the layer data:

class xxx (object):
    def layers_will_be_removed(self, layer_ids: list):
        for id in layer_ids:
            try:
                layer = QgsProject.instance().mapLayer(id)
                layer_name = layer.name()
                message = "Ok"
            except Exception as e:
                message = e

            QMessageBox.information(self.iface.mainWindow(), "Warning", f"Closing {layer_name}, {has_changes}")

    def __init__(self):
        QgsProject.instance().layersWillBeRemoved.connect( self.layers_will_be_removed )

As said in the comment, when the function associated to willBeDeleted the layer is already deleted; while you could put into the lambda the layer name, you would be unable to get the layer itself and its data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.