4

I'm using the following python script to open a QGIS project, modify some things, and save it under a different name:

from PyQt4.QtCore import QFileInfo
from qgis.core import *

def main():
    QgsApplication([], True)
    QgsApplication.setPrefixPath('/usr/share/qgis', False) #If this is set to true qgis can't find resources..
    QgsApplication.initQgis()

    proj=QgsProject.instance()
    proj.read(QFileInfo("source.qgs"))

    #do other stuff to the project

    proj.write(QFileInfo("target.qgs"))
    QgsApplication.exitQgis()

if __name__ == "__main__":
    main()

While this seems to work fine at first, the XML nodes <mapcanvas>,<layer-tree-legend> and a few others are omitted in the now smaller target file. I want to serve the target file via QGIS Server, but QGIS Server doesn't pick up on all the available layers due to these missing nodes in the XML file. The GetProjectSettings request doesn't show any of the available layers even though they're clearly still in the project.

Opening the target file in QGIS Desktop and saving it again works fine, and then the missing nodes are added again to the qgs file.

Does anyone know why this information is lost when saving a project, and what I could do to preserve or regenerate it?

Edit: added setPrefixPath

8
  • It sounds like a bug to me; it might be worth asking on the QGIS-dev list, and depending on the reply there, report it to the QGIS tracker. Commented Nov 20, 2014 at 14:34
  • Which QGIS version are you trying with?
    – lrssvt
    Commented Nov 20, 2014 at 15:07
  • QGIS version is 2.6.0-Brighton
    – user39235
    Commented Nov 20, 2014 at 15:12
  • but <layer-tree-legend> tag does not exist, I suppose you mean <layer-tree-canvas> or <layer-tree-group> or only <legend>. Also Do you define the map canvas somewhere in your script?
    – lrssvt
    Commented Nov 20, 2014 at 15:20
  • Yes sorry! A diff between the source and target qgs files shows <mapcanvas>, <visibility-presets>, <layer-tree-canvas>, <legend>, and various <edittype> tags have gone missing from somewhere within various <maplayer> tags.
    – user39235
    Commented Nov 20, 2014 at 15:29

3 Answers 3

2

I just noticed that you missed to set the QGIS installation path, so no provider may be loaded properly and probably this is the root of the problem. Try to change your script as follow:

def main():
    ## second argument (GUI Enabled) may be False 
    ## if you do not need of GUI stuff
    QgsApplication([], False)
    ## installation path for Linux: /usr/local or /usr
    ## installation path for Windows: C:\\OSGeo4W\\apps\\qgis
    QgsApplication.setPrefixPath('qgis/installation/path', True)
    QgsApplication.initQgis()

    proj=QgsProject.instance()
    proj.read(QFileInfo("source.qgs"))

    ## [do other stuff on project] ##

    proj.write(QFileInfo("target.qgs"))
    QgsApplication.exitQgis()

Besides, make sure that layers are in project directory or setting to absolute the Save paths option (Project->Project properties) for the source.qgs project (not necessary if your layers are in a database format).

1
  • Apologies for the late reply, I was away for a few days. I set the prefix path (see edit above) and absolute paths in the project properties, but still no result. I think the providers are loaded properly because when I use an incorrect path (or set the second argument to True) in setPrefixPath all the layers are missing too in the target file. As is the layers are fine, but still no sign of the <mapcanvas> node.
    – user39235
    Commented Dec 1, 2014 at 9:05
1

I have no experience in C++ and am just learning to write QGIS plugins so this answer may be questionable...

Looking at the c++ source ( http://qgis.org/api/qgsproject_8cpp_source.html ) for the "write" method, I noticed the following code in the middle of the write and thought it might be relevant to your problem:

1091   // let map canvas and legend write their information
1092   emit writeProject( *doc );
1093 

It seems that your missing parts are responsible for writing their own data. Maybe you need to instantiate these objects so they can respond to the signal?

-1

@user39235 faced same problem and solved it by tweak.Please find the script.Please share info if you have found a direct solution.

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.