~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to python/plugins/osm/OsmSaveDlg.py

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
"""@package OsmSaveDlg
 
3
This module is used to save OSM data into XML file.
 
4
 
 
5
Of course, user is asked where to save the current data first.
 
6
"""
 
7
 
 
8
 
 
9
from ui_OsmSaveDlg import Ui_OsmSaveDlg
 
10
 
 
11
from PyQt4.QtCore import *
 
12
from PyQt4.QtGui import *
 
13
from PyQt4.QtXml import *
 
14
from PyQt4 import *
 
15
from sip import unwrapinstance
 
16
from qgis.core import QgsVectorLayer, QgsMapLayerRegistry
 
17
 
 
18
import sqlite3
 
19
 
 
20
 
 
21
 
 
22
class OsmSaveDlg(QDialog, Ui_OsmSaveDlg):
 
23
    """This class provides all structures and methods necessary for current OSM data saving.
 
24
 
 
25
    Saving is done to XML file.
 
26
    After XML file selection and confirming the dialog, process is started.
 
27
    """
 
28
 
 
29
    def __init__(self, plugin):
 
30
        """The constructor.
 
31
 
 
32
        @param plugin is pointer to instance of OSM Plugin
 
33
        """
 
34
 
 
35
        QDialog.__init__(self, None)
 
36
        self.setupUi(self)
 
37
 
 
38
        self.plugin=plugin
 
39
        self.ur=plugin.undoredo
 
40
        self.dbm=plugin.dbm
 
41
 
 
42
        self.progressDialog = QProgressDialog(self)
 
43
        self.progressDialog.setModal(True)
 
44
        self.progressDialog.setAutoClose(False)
 
45
 
 
46
        # variables for identifiers of all objects that will be saved to output file
 
47
        self.nodeIds=set()
 
48
 
 
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)
 
53
 
 
54
 
 
55
    def cancelSaving(self):
 
56
        """Function stops the whole OSM Saving process.
 
57
 
 
58
        Destination file is closed and removed.
 
59
        """
 
60
 
 
61
        # writing into output file was canceled, file must be enclosed
 
62
        self.outFile.close()
 
63
 
 
64
        # end removed
 
65
        self.outFile.remove()
 
66
        self.outFile=None
 
67
 
 
68
        # close the whole Save OSM dialog
 
69
        self.close()
 
70
 
 
71
 
 
72
    def showSaveFileDialog(self):
 
73
        """Function opens dialog for selecting XML file.
 
74
 
 
75
        Only files with extension .osm can be selected.
 
76
        Default directory for file selection is remembered/reload.
 
77
        """
 
78
 
 
79
        settings = QSettings()
 
80
        lastDir = settings.value("/OSM_Plugin/lastDir", QVariant(QString())).toString()
 
81
 
 
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)
 
87
 
 
88
            # remember directory
 
89
            fi = QFileInfo(fileSelected)
 
90
            settings.setValue("/OSM_Plugin/lastDir", QVariant(fi.path()) )
 
91
 
 
92
 
 
93
    def onOK(self):
 
94
        """Function is called after clicking on OK button of OSM Save dialog.
 
95
 
 
96
        It performs all actions necessary for OSM data saving.
 
97
        """
 
98
 
 
99
        # prepare data
 
100
 
 
101
        self.fname=self.OSMFileEdit.text()
 
102
        self.outFile=QFile(self.fname)
 
103
 
 
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()))
 
107
            self.outFile=None
 
108
            return
 
109
 
 
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()
 
115
 
 
116
        self.xml=QXmlStreamWriter(self.outFile)
 
117
        self.xml.setCodec(QTextCodec.codecForName("utf-8"))
 
118
        self.xml.setAutoFormatting(True)
 
119
 
 
120
        c=self.dbm.getConnection().cursor()
 
121
 
 
122
        cntPoints=cntLines=cntPolys=cntRels=0
 
123
        c.execute("select count(*) from node")
 
124
        for rec in c:
 
125
            cntPoints=rec[0]
 
126
        c.execute("select count(*) from way where closed=0")
 
127
        for rec in c:
 
128
            cntLines=rec[0]
 
129
        c.execute("select count(*) from way where closed=1")
 
130
        for rec in c:
 
131
            cntPolys=rec[0]
 
132
        c.execute("select count(*) from relation")
 
133
        for rec in c:
 
134
            cntRels=rec[0]
 
135
 
 
136
        self.xml.writeStartDocument()
 
137
        self.xml.writeStartElement("osm")
 
138
        self.xml.writeAttribute("version","0.6")
 
139
        self.xml.writeAttribute("generator","OpenStreetMap server")
 
140
 
 
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()
 
146
 
 
147
        # <bounds> element
 
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()))
 
154
 
 
155
        # todo: uid and changeset attributes are not compulsory! support for them in future!
 
156
 
 
157
        if points:
 
158
            self.progressDialog.setLabelText(self.tr("Saving nodes..."))
 
159
            self.progressDialog.setMaximum(cntPoints)
 
160
            self.progressDialog.setValue(0)
 
161
            i=0
 
162
 
 
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()})
 
168
 
 
169
            for (nid,lat,lon,ver,usr,tms) in c:
 
170
                anyTags=False
 
171
                tagList=[]
 
172
 
 
173
                self.nodeIds.add(nid)
 
174
 
 
175
                if tags:
 
176
                    tagList=self.dbm.getFeatureTags(nid,'Point')
 
177
                    if len(tagList)>0:
 
178
                        anyTags=True
 
179
 
 
180
                if anyTags:
 
181
                    self.xml.writeStartElement("node")
 
182
                else:
 
183
                    self.xml.writeEmptyElement("node")
 
184
 
 
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))
 
189
                if usr<>"":
 
190
                    self.xml.writeAttribute("user",usr)
 
191
                self.xml.writeAttribute("visible","true")
 
192
                self.xml.writeAttribute("timestamp",tms)
 
193
 
 
194
                if anyTags:
 
195
                    for r in tagList:
 
196
                        self.xml.writeEmptyElement("tag")
 
197
                        self.xml.writeAttribute("k",r[0])
 
198
                        self.xml.writeAttribute("v",r[1])
 
199
                    self.xml.writeEndElement()
 
200
 
 
201
                i=i+1
 
202
                self.progressDialog.setValue(i)
 
203
 
 
204
        if lines:
 
205
            self.progressDialog.setLabelText(self.tr("Saving lines..."))
 
206
            self.progressDialog.setMaximum(cntLines)
 
207
            self.progressDialog.setValue(0)
 
208
            i=0
 
209
 
 
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()})
 
216
 
 
217
            for (lid,ver,usr,tms) in c:
 
218
 
 
219
                geom=self.dbm.getFeatureGeometry(lid,'Line')
 
220
                if not geom.intersects(dataExtent):
 
221
                    continue
 
222
 
 
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))
 
228
                if usr<>"":
 
229
                    self.xml.writeAttribute("user",usr)
 
230
 
 
231
                d=self.dbm.getConnection().cursor()
 
232
                d.execute("select node_id from way_member where way_id=:wayId",{"wayId":lid})
 
233
                for r in d:
 
234
                    self.xml.writeEmptyElement("nd")
 
235
                    self.xml.writeAttribute("ref",str(r[0]))
 
236
                d.close()
 
237
 
 
238
                if tags:
 
239
                    tagList=self.dbm.getFeatureTags(lid,'Line')
 
240
                    for r in tagList:
 
241
                        self.xml.writeEmptyElement("tag")
 
242
                        self.xml.writeAttribute("k",r[0])
 
243
                        self.xml.writeAttribute("v",r[1])
 
244
 
 
245
                self.xml.writeEndElement()
 
246
 
 
247
                d=self.dbm.getConnection().cursor()
 
248
                d.execute("select node_id from way_member where way_id=:wayId",{"wayId":lid})
 
249
                for r in d:
 
250
                    if r[0] not in self.nodeIds:
 
251
 
 
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]})
 
255
                        for nodeRec in e:
 
256
                            nid=nodeRec[0]
 
257
                            lat=nodeRec[1]
 
258
                            lon=nodeRec[2]
 
259
                            ver=nodeRec[3]
 
260
                            usr=nodeRec[4]
 
261
                            tms=nodeRec[5]
 
262
                        e.close()
 
263
 
 
264
                        anyTags=False
 
265
                        tagList=[]
 
266
                        self.nodeIds.add(nid)
 
267
 
 
268
                        if tags:
 
269
                            tagList=self.dbm.getFeatureTags(nid,'Point')
 
270
                            if len(tagList)>0:
 
271
                                anyTags=True
 
272
 
 
273
                        if anyTags:
 
274
                            self.xml.writeStartElement("node")
 
275
                        else:
 
276
                            self.xml.writeEmptyElement("node")
 
277
 
 
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))
 
282
                        if usr<>"":
 
283
                            self.xml.writeAttribute("user",usr)
 
284
                        self.xml.writeAttribute("visible","true")
 
285
                        self.xml.writeAttribute("timestamp",tms)
 
286
 
 
287
                        if anyTags:
 
288
                            for r in tagList:
 
289
                                self.xml.writeEmptyElement("tag")
 
290
                                self.xml.writeAttribute("k",r[0])
 
291
                                self.xml.writeAttribute("v",r[1])
 
292
                            self.xml.writeEndElement()
 
293
 
 
294
                d.close()
 
295
                i=i+1
 
296
                self.progressDialog.setValue(i)
 
297
 
 
298
        if polys:
 
299
            self.progressDialog.setLabelText(self.tr("Saving polygons..."))
 
300
            self.progressDialog.setMaximum(cntPolys)
 
301
            self.progressDialog.setValue(0)
 
302
            i=0
 
303
 
 
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()})
 
310
 
 
311
            for (pid,ver,usr,tms) in c:
 
312
 
 
313
                geom=self.dbm.getFeatureGeometry(pid,'Polygon')
 
314
                if not geom.intersects(dataExtent):
 
315
                    continue
 
316
 
 
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))
 
322
                if usr<>"":
 
323
                    self.xml.writeAttribute("user",usr)
 
324
 
 
325
                d=self.dbm.getConnection().cursor()
 
326
                d.execute("select node_id from way_member where way_id=:wayId",{"wayId":pid})
 
327
                first=None
 
328
                for r in d:
 
329
                    self.xml.writeEmptyElement("nd")
 
330
                    self.xml.writeAttribute("ref",str(r[0]))
 
331
                    if first==None:
 
332
                        first=r[0]
 
333
                d.close()
 
334
                self.xml.writeEmptyElement("nd")
 
335
                self.xml.writeAttribute("ref",str(first))
 
336
 
 
337
                if tags:
 
338
                    tagList=self.dbm.getFeatureTags(pid,'Polygon')
 
339
                    for r in tagList:
 
340
                        self.xml.writeEmptyElement("tag")
 
341
                        self.xml.writeAttribute("k",r[0])
 
342
                        self.xml.writeAttribute("v",r[1])
 
343
 
 
344
                self.xml.writeEndElement()
 
345
 
 
346
                d=self.dbm.getConnection().cursor()
 
347
                d.execute("select node_id from way_member where way_id=:wayId",{"wayId":pid})
 
348
                for r in d:
 
349
                    if r[0] not in self.nodeIds:
 
350
 
 
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]})
 
354
                        for nodeRec in e:
 
355
                            nid=nodeRec[0]
 
356
                            lat=nodeRec[1]
 
357
                            lon=nodeRec[2]
 
358
                            ver=nodeRec[3]
 
359
                            usr=nodeRec[4]
 
360
                            tms=nodeRec[5]
 
361
                        e.close()
 
362
 
 
363
                        anyTags=False
 
364
                        tagList=[]
 
365
                        self.nodeIds.add(nid)
 
366
 
 
367
                        if tags:
 
368
                            tagList=self.dbm.getFeatureTags(nid,'Point')
 
369
                            if len(tagList)>0:
 
370
                                anyTags=True
 
371
 
 
372
                        if anyTags:
 
373
                            self.xml.writeStartElement("node")
 
374
                        else:
 
375
                            self.xml.writeEmptyElement("node")
 
376
 
 
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))
 
381
                        if usr<>"":
 
382
                            self.xml.writeAttribute("user",usr)
 
383
                        self.xml.writeAttribute("visible","true")
 
384
                        self.xml.writeAttribute("timestamp",tms)
 
385
 
 
386
                        if anyTags:
 
387
                            for r in tagList:
 
388
                                self.xml.writeEmptyElement("tag")
 
389
                                self.xml.writeAttribute("k",r[0])
 
390
                                self.xml.writeAttribute("v",r[1])
 
391
                            self.xml.writeEndElement()
 
392
 
 
393
                d.close()
 
394
                i=i+1
 
395
                self.progressDialog.setValue(i)
 
396
 
 
397
        if rels:
 
398
            self.progressDialog.setLabelText(self.tr("Saving relations..."))
 
399
            self.progressDialog.setMaximum(cntRels)
 
400
            self.progressDialog.setValue(0)
 
401
            i=0
 
402
 
 
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' \
 
405
                       and ( \
 
406
                           exists ( \
 
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 ) \
 
410
                           or exists ( \
 
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))) \
 
415
                                  ))"
 
416
                       ,{"minLat":dataExtent.yMinimum(),"maxLat":dataExtent.yMaximum()
 
417
                        ,"minLon":dataExtent.xMinimum(),"maxLon":dataExtent.xMaximum()})
 
418
 
 
419
            for (rid,ver,usr,tms) in c:
 
420
 
 
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))
 
426
                if usr<>"":
 
427
                    self.xml.writeAttribute("user",usr)
 
428
 
 
429
                d=self.dbm.getConnection().cursor()
 
430
                d.execute("select member_id,member_type,role from relation_member where relation_id=:relId",{"relId":rid})
 
431
                for r in d:
 
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])
 
436
                d.close()
 
437
 
 
438
                if tags:
 
439
                    tagList=self.dbm.getFeatureTags(rid,'Relation')
 
440
                    for r in tagList:
 
441
                        self.xml.writeEmptyElement("tag")
 
442
                        self.xml.writeAttribute("k",r[0])
 
443
                        self.xml.writeAttribute("v",r[1])
 
444
                self.xml.writeEndElement()
 
445
 
 
446
                i=i+1
 
447
                self.progressDialog.setValue(i)
 
448
 
 
449
 
 
450
        self.xml.writeEndElement()    # osm
 
451
        self.xml.writeEndDocument()
 
452
 
 
453
        c.close()
 
454
        self.disconnect(self.progressDialog, SIGNAL("canceled()"), self.cancelSaving)
 
455
        self.progressDialog.close()
 
456
 
 
457
        # writing into output file was finished, file can be enclosed
 
458
        if self.outFile and self.outFile.exists():
 
459
            self.outFile.close()
 
460
        self.close()
 
461
 
 
462
 
 
463