1
# -*- coding: utf-8 -*-
3
This module is used to save OSM data into XML file.
5
Of course, user is asked where to save the current data first.
9
from ui_OsmSaveDlg import Ui_OsmSaveDlg
11
from PyQt4.QtCore import *
12
from PyQt4.QtGui import *
13
from PyQt4.QtXml import *
15
from sip import unwrapinstance
16
from qgis.core import QgsVectorLayer, QgsMapLayerRegistry
22
class OsmSaveDlg(QDialog, Ui_OsmSaveDlg):
23
"""This class provides all structures and methods necessary for current OSM data saving.
25
Saving is done to XML file.
26
After XML file selection and confirming the dialog, process is started.
29
def __init__(self, plugin):
32
@param plugin is pointer to instance of OSM Plugin
35
QDialog.__init__(self, None)
39
self.ur=plugin.undoredo
42
self.progressDialog = QProgressDialog(self)
43
self.progressDialog.setModal(True)
44
self.progressDialog.setAutoClose(False)
46
# variables for identifiers of all objects that will be saved to output file
49
# connecting dialog and progressbar signals
50
QObject.connect(self.browseOSMButton,SIGNAL("clicked()"),self.showSaveFileDialog)
51
QObject.connect(self.buttonBox,SIGNAL("accepted()"),self.onOK)
52
QObject.connect(self.progressDialog, SIGNAL("canceled()"), self.cancelSaving)
55
def cancelSaving(self):
56
"""Function stops the whole OSM Saving process.
58
Destination file is closed and removed.
61
# writing into output file was canceled, file must be enclosed
68
# close the whole Save OSM dialog
72
def showSaveFileDialog(self):
73
"""Function opens dialog for selecting XML file.
75
Only files with extension .osm can be selected.
76
Default directory for file selection is remembered/reload.
79
settings = QSettings()
80
lastDir = settings.value("/OSM_Plugin/lastDir", QVariant(QString())).toString()
82
# display file open dialog and get absolute path to selected file
83
fileSelected = QFileDialog.getSaveFileName(self,"Choose an Open Street Map file",lastDir,"OSM Files (*.osm)");
84
# insert OSM file path into line edit control
85
if not fileSelected.isNull():
86
self.OSMFileEdit.setText(fileSelected)
89
fi = QFileInfo(fileSelected)
90
settings.setValue("/OSM_Plugin/lastDir", QVariant(fi.path()) )
94
"""Function is called after clicking on OK button of OSM Save dialog.
96
It performs all actions necessary for OSM data saving.
101
self.fname=self.OSMFileEdit.text()
102
self.outFile=QFile(self.fname)
104
if not self.outFile.open(QIODevice.WriteOnly):
105
QMessageBox.information(self,self.tr("Save OSM to file"),self.tr("Unable to save the file %1: %2.")
106
.arg(self.fname).arg(self.outFile.errorString()))
110
points=self.chkPoints.isChecked()
111
lines=self.chkLines.isChecked()
112
polys=self.chkPolygons.isChecked()
113
rels=self.chkRelations.isChecked()
114
tags=self.chkTags.isChecked()
116
self.xml=QXmlStreamWriter(self.outFile)
117
self.xml.setCodec(QTextCodec.codecForName("utf-8"))
118
self.xml.setAutoFormatting(True)
120
c=self.dbm.getConnection().cursor()
122
cntPoints=cntLines=cntPolys=cntRels=0
123
c.execute("select count(*) from node")
126
c.execute("select count(*) from way where closed=0")
129
c.execute("select count(*) from way where closed=1")
132
c.execute("select count(*) from relation")
136
self.xml.writeStartDocument()
137
self.xml.writeStartElement("osm")
138
self.xml.writeAttribute("version","0.6")
139
self.xml.writeAttribute("generator","OpenStreetMap server")
141
self.progressDialog.setWindowTitle(self.tr("Save OSM to file"))
142
self.progressDialog.setLabelText(self.tr("Initializing..."))
143
self.progressDialog.setMaximum(1)
144
self.progressDialog.setValue(0)
145
self.progressDialog.show()
148
dataExtent=self.plugin.canvas.extent()
149
self.xml.writeEmptyElement("bounds")
150
self.xml.writeAttribute("minlat",str(dataExtent.yMinimum()))
151
self.xml.writeAttribute("minlon",str(dataExtent.xMinimum()))
152
self.xml.writeAttribute("maxlat",str(dataExtent.yMaximum()))
153
self.xml.writeAttribute("maxlon",str(dataExtent.xMaximum()))
155
# todo: uid and changeset attributes are not compulsory! support for them in future!
158
self.progressDialog.setLabelText(self.tr("Saving nodes..."))
159
self.progressDialog.setMaximum(cntPoints)
160
self.progressDialog.setValue(0)
163
c.execute("select n.id,n.lat,n.lon,v.version_id,n.user,n.timestamp from node n, version v \
164
where n.status<>'R' and n.u=1 and v.object_id=n.id and v.object_type='node' \
165
and n.lat>=:minLat AND n.lat<=:maxLat AND n.lon>=:minLon AND n.lon<=:maxLon"
166
,{"minLat":dataExtent.yMinimum(),"maxLat":dataExtent.yMaximum()
167
,"minLon":dataExtent.xMinimum(),"maxLon":dataExtent.xMaximum()})
169
for (nid,lat,lon,ver,usr,tms) in c:
173
self.nodeIds.add(nid)
176
tagList=self.dbm.getFeatureTags(nid,'Point')
181
self.xml.writeStartElement("node")
183
self.xml.writeEmptyElement("node")
185
self.xml.writeAttribute("id",str(nid))
186
self.xml.writeAttribute("lat",str(lat))
187
self.xml.writeAttribute("lon",str(lon))
188
self.xml.writeAttribute("version",str(ver))
190
self.xml.writeAttribute("user",usr)
191
self.xml.writeAttribute("visible","true")
192
self.xml.writeAttribute("timestamp",tms)
196
self.xml.writeEmptyElement("tag")
197
self.xml.writeAttribute("k",r[0])
198
self.xml.writeAttribute("v",r[1])
199
self.xml.writeEndElement()
202
self.progressDialog.setValue(i)
205
self.progressDialog.setLabelText(self.tr("Saving lines..."))
206
self.progressDialog.setMaximum(cntLines)
207
self.progressDialog.setValue(0)
210
c.execute("select w.id,v.version_id,w.user,w.timestamp from way w,version v \
211
where w.closed=0 and w.status<>'R' and w.u=1 and v.object_id=w.id and v.object_type='way' \
212
and (((w.max_lat between :minLat and :maxLat) or (w.min_lat between :minLat and :maxLat) or (w.min_lat<:minLat and w.max_lat>:maxLat)) \
213
and ((w.max_lon between :minLon and :maxLon) or (w.min_lon between :minLon and :maxLon) or (w.min_lon<:minLon and w.max_lon>:maxLon)))"
214
,{"minLat":dataExtent.yMinimum(),"maxLat":dataExtent.yMaximum()
215
,"minLon":dataExtent.xMinimum(),"maxLon":dataExtent.xMaximum()})
217
for (lid,ver,usr,tms) in c:
219
geom=self.dbm.getFeatureGeometry(lid,'Line')
220
if not geom.intersects(dataExtent):
223
self.xml.writeStartElement("way")
224
self.xml.writeAttribute("id",str(lid))
225
self.xml.writeAttribute("visible","true")
226
self.xml.writeAttribute("timestamp",tms)
227
self.xml.writeAttribute("version",str(ver))
229
self.xml.writeAttribute("user",usr)
231
d=self.dbm.getConnection().cursor()
232
d.execute("select node_id from way_member where way_id=:wayId",{"wayId":lid})
234
self.xml.writeEmptyElement("nd")
235
self.xml.writeAttribute("ref",str(r[0]))
239
tagList=self.dbm.getFeatureTags(lid,'Line')
241
self.xml.writeEmptyElement("tag")
242
self.xml.writeAttribute("k",r[0])
243
self.xml.writeAttribute("v",r[1])
245
self.xml.writeEndElement()
247
d=self.dbm.getConnection().cursor()
248
d.execute("select node_id from way_member where way_id=:wayId",{"wayId":lid})
250
if r[0] not in self.nodeIds:
252
e=self.dbm.getConnection().cursor()
253
e.execute("select n.id,n.lat,n.lon,v.version_id,n.user,n.timestamp from node n, version v \
254
where n.id=:nid",{"nid":r[0]})
266
self.nodeIds.add(nid)
269
tagList=self.dbm.getFeatureTags(nid,'Point')
274
self.xml.writeStartElement("node")
276
self.xml.writeEmptyElement("node")
278
self.xml.writeAttribute("id",str(nid))
279
self.xml.writeAttribute("lat",str(lat))
280
self.xml.writeAttribute("lon",str(lon))
281
self.xml.writeAttribute("version",str(ver))
283
self.xml.writeAttribute("user",usr)
284
self.xml.writeAttribute("visible","true")
285
self.xml.writeAttribute("timestamp",tms)
289
self.xml.writeEmptyElement("tag")
290
self.xml.writeAttribute("k",r[0])
291
self.xml.writeAttribute("v",r[1])
292
self.xml.writeEndElement()
296
self.progressDialog.setValue(i)
299
self.progressDialog.setLabelText(self.tr("Saving polygons..."))
300
self.progressDialog.setMaximum(cntPolys)
301
self.progressDialog.setValue(0)
304
c.execute("select w.id,v.version_id,w.user,w.timestamp from way w,version v \
305
where w.closed=1 and w.status<>'R' and w.u=1 and v.object_id=w.id and v.object_type='way' \
306
and (((w.max_lat between :minLat and :maxLat) or (w.min_lat between :minLat and :maxLat) or (w.min_lat<:minLat and w.max_lat>:maxLat)) \
307
and ((w.max_lon between :minLon and :maxLon) or (w.min_lon between :minLon and :maxLon) or (w.min_lon<:minLon and w.max_lon>:maxLon)))"
308
,{"minLat":dataExtent.yMinimum(),"maxLat":dataExtent.yMaximum()
309
,"minLon":dataExtent.xMinimum(),"maxLon":dataExtent.xMaximum()})
311
for (pid,ver,usr,tms) in c:
313
geom=self.dbm.getFeatureGeometry(pid,'Polygon')
314
if not geom.intersects(dataExtent):
317
self.xml.writeStartElement("way")
318
self.xml.writeAttribute("id",str(pid))
319
self.xml.writeAttribute("visible","true")
320
self.xml.writeAttribute("timestamp",tms)
321
self.xml.writeAttribute("version",str(ver))
323
self.xml.writeAttribute("user",usr)
325
d=self.dbm.getConnection().cursor()
326
d.execute("select node_id from way_member where way_id=:wayId",{"wayId":pid})
329
self.xml.writeEmptyElement("nd")
330
self.xml.writeAttribute("ref",str(r[0]))
334
self.xml.writeEmptyElement("nd")
335
self.xml.writeAttribute("ref",str(first))
338
tagList=self.dbm.getFeatureTags(pid,'Polygon')
340
self.xml.writeEmptyElement("tag")
341
self.xml.writeAttribute("k",r[0])
342
self.xml.writeAttribute("v",r[1])
344
self.xml.writeEndElement()
346
d=self.dbm.getConnection().cursor()
347
d.execute("select node_id from way_member where way_id=:wayId",{"wayId":pid})
349
if r[0] not in self.nodeIds:
351
e=self.dbm.getConnection().cursor()
352
e.execute("select n.id,n.lat,n.lon,v.version_id,n.user,n.timestamp from node n, version v \
353
where n.id=:nid",{"nid":r[0]})
365
self.nodeIds.add(nid)
368
tagList=self.dbm.getFeatureTags(nid,'Point')
373
self.xml.writeStartElement("node")
375
self.xml.writeEmptyElement("node")
377
self.xml.writeAttribute("id",str(nid))
378
self.xml.writeAttribute("lat",str(lat))
379
self.xml.writeAttribute("lon",str(lon))
380
self.xml.writeAttribute("version",str(ver))
382
self.xml.writeAttribute("user",usr)
383
self.xml.writeAttribute("visible","true")
384
self.xml.writeAttribute("timestamp",tms)
388
self.xml.writeEmptyElement("tag")
389
self.xml.writeAttribute("k",r[0])
390
self.xml.writeAttribute("v",r[1])
391
self.xml.writeEndElement()
395
self.progressDialog.setValue(i)
398
self.progressDialog.setLabelText(self.tr("Saving relations..."))
399
self.progressDialog.setMaximum(cntRels)
400
self.progressDialog.setValue(0)
403
c.execute("select r.id,v.version_id,r.user,r.timestamp from relation r,version v \
404
where r.status<>'R' and r.u=1 and v.object_id=r.id and v.object_type='relation' \
407
select 1 from node n, relation_member rm \
408
where rm.relation_id=r.id and n.status<>'R' and n.u=1 and rm.member_id=n.id and rm.member_type='node' \
409
and n.lat>=:minLat and n.lat<=:maxLat and n.lon>=:minLon and n.lon<=:maxLon ) \
411
select 1 from way w, relation_member rm \
412
where rm.relation_id=r.id and w.status<>'R' and w.u=1 and rm.member_id=w.id and rm.member_type='way' \
413
and (((w.max_lat between :minLat and :maxLat) or (w.min_lat between :minLat and :maxLat) or (w.min_lat<:minLat and w.max_lat>:maxLat)) \
414
and ((w.max_lon between :minLon and :maxLon) or (w.min_lon between :minLon and :maxLon) or (w.min_lon<:minLon and w.max_lon>:maxLon))) \
416
,{"minLat":dataExtent.yMinimum(),"maxLat":dataExtent.yMaximum()
417
,"minLon":dataExtent.xMinimum(),"maxLon":dataExtent.xMaximum()})
419
for (rid,ver,usr,tms) in c:
421
self.xml.writeStartElement("relation")
422
self.xml.writeAttribute("id",str(rid))
423
self.xml.writeAttribute("visible","true")
424
self.xml.writeAttribute("timestamp",tms)
425
self.xml.writeAttribute("version",str(ver))
427
self.xml.writeAttribute("user",usr)
429
d=self.dbm.getConnection().cursor()
430
d.execute("select member_id,member_type,role from relation_member where relation_id=:relId",{"relId":rid})
432
self.xml.writeEmptyElement("member")
433
self.xml.writeAttribute("type",r[1])
434
self.xml.writeAttribute("ref",str(r[0]))
435
self.xml.writeAttribute("role",r[2])
439
tagList=self.dbm.getFeatureTags(rid,'Relation')
441
self.xml.writeEmptyElement("tag")
442
self.xml.writeAttribute("k",r[0])
443
self.xml.writeAttribute("v",r[1])
444
self.xml.writeEndElement()
447
self.progressDialog.setValue(i)
450
self.xml.writeEndElement() # osm
451
self.xml.writeEndDocument()
454
self.disconnect(self.progressDialog, SIGNAL("canceled()"), self.cancelSaving)
455
self.progressDialog.close()
457
# writing into output file was finished, file can be enclosed
458
if self.outFile and self.outFile.exists():