9

My program opens a QGIS project, loads one layer, adds a point on this layer and then stops. My problem is - I don't save the project explicitly, but the added points are always saved (I have to remove them manually).

The question seems to be duplicate of How close project QGIS (* .qgs) without saving (PyQGIS), but the answer from there (project.clear()) - I cannot import qApp from PyQt5.QtGui, but processing the user interface is probably not important there. I just added project.clear() before qgs.exitQgis(), but the project is still saved. It's QGIS version 3.30 on Windows 10.

Commentators requested the code, so here is my code (without all the imports; I am running this with standalone PyQGIS):

# Supply path to qgis install location
QgsApplication.setPrefixPath("C:\OSGeo4W", True)

Create a reference to the QgsApplication. Setting the

second argument to False disables the GUI.

qgs = QgsApplication([], False)

Load providers

qgs.initQgis()

project.read('C:\Users\Tambet\Desktop\Barcelona qgis\planols1.qgs')

layers = QgsProject.instance().mapLayersByName('test') print(layers[0].name()) layer = layers[0] caps = layer.dataProvider().capabilities()

if caps & QgsVectorDataProvider.AddFeatures: print("Adding feature..") feat = QgsFeature(layer.fields()) feat.setAttributes([0, 'added programatically']) feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(431613.6, 4582819.9))) res, outFeats = layer.dataProvider().addFeatures([feat])

features = layer.getFeatures()

for feature in features: # retrieve every feature with its geometry and attributes print("Feature ID: ", feature.id()) # fetch geometry # show some information about the feature geometry geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type() == QgsWkbTypes.PointGeometry: # the geometry type can be of single or multi type if geomSingleType: x = geom.asPoint() print("Point: ", x)

layoutmanager = project.layoutManager() print(layoutmanager.layouts()) layout = layoutmanager.layoutByName("test1") #Layout name exporter = QgsLayoutExporter(layout) print(exporter.exportToPdf("C:\Users\Tambet\eclipse-workspace\qgis test\test.pdf", QgsLayoutExporter.PdfExportSettings() ))

project.clear() qgs.exitQgis()

Vince
  • 20,017
  • 15
  • 45
  • 64
Tambet Väli
  • 103
  • 5
  • Do you use dataProvider to add the point? Could you please share the code you use doing things you mentioned? It is hard to say something without seeing your script. – Kadir Şahbaz Apr 03 '23 at 09:19
  • 2
    Your question is not very clear. Editing a layer and saving the project is two different things. It's possible to edit data (and saving) without saving the project itself. Please share more context, like your code ? – etrimaille Apr 03 '23 at 09:23
  • I added the Python code. – Tambet Väli Apr 03 '23 at 09:32

1 Answers1

11

As @etrimaille stated, "editing a layer" and "saving the project" are two different things, and you can edit data (and saving) without saving the project itself.

A project is not a container of data, but it contains layers order, styles, source paths etc., not data itself. When you add or edit a feature, you change the data in data source, not project.

In your script, you use layer.dataProvider().addFeatures(). It adds the feature to the data source immediately.

If you want to add the feature (and to see in map canvas) but don't want to save it to the data source, you can start edit mode for the layer using layer.startEditing() without using layer.commitChanges().

In edit mode, you have to use layer.addFeature() instead of layer.dataProvider().addFeatures() as follows:

layer.startEditing()

if caps & QgsVectorDataProvider.AddFeatures: ... ...

is_added = layer.addFeature(feat) # is_added: boolean

...

use commitChanges only when you want to save the changes

layer.commitChanges()

layer.addFeature makes the changes in memory, it will not be saved to the data source unless layer.commitChanges is run.

Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
  • So can I do something to not add the data immediately? Should I make a copy of the data source every time or is there an easier way? Can I add features without touching the dataProvider? Is there any way to get a temporary link to dataProvider or add it as a temporary file? – Tambet Väli Apr 03 '23 at 09:45
  • Please check the edited answer. – Kadir Şahbaz Apr 03 '23 at 09:46
  • This is too temporary. It does not appear in the feature list afterwards and it does not appear in the PDF file I generate. I should appear in the PDF, yet not being saved with the project. Is this possible? – Tambet Väli Apr 03 '23 at 09:59
  • https://anitagraser.com/pyqgis-101-introduction-to-qgis-python-programming-for-non-programmers/pyqgis101-creating-editing-a-new-vector-layer/ - this example is using a memory data provider. Can I somehow convert it to the memory data provider on the fly? – Tambet Väli Apr 03 '23 at 10:05
  • 1
    Yes. Check this answer to duplicate the layer on the fly to work on it temporarily. – Kadir Şahbaz Apr 03 '23 at 10:06
  • I think with this information I can go. I mark it as an answer once I get the code working and have no more questions (and 6 hrs. have been passed, I suppose). – Tambet Väli Apr 03 '23 at 10:10
  • Perfect. It exported the point to PDF and did not save it to the QGIS project nor it's associated files. Now the last little problem is - it does not copy the layer properties; in my point layer, the points have raster image associated to the point to become map markers, in new layer this is not the case (visible as bare points). I added these lines of code to get it fully functional:

    clone_layer.styleManager().copyStylesFrom(layer.styleManager()) clone_layer.styleManager().setCurrentStyle(layer.styleManager().currentStyle())

    QgsProject.instance().removeMapLayer(layer)

    – Tambet Väli Apr 03 '23 at 10:45
  • Just to add a small note, you can add a layer.rollBack() to leave the edit mode but discard changes (instead of layer.commitChanges()). For your new question, maybe easier to share your code in a new question. – etrimaille Apr 03 '23 at 11:24
  • The code works for this new question. It would be nice to add code from mentioned answer and my code to copy layer styles as well to the answer? – Tambet Väli Apr 03 '23 at 13:39