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

« back to all changes in this revision

Viewing changes to python/plugins/osm/map_tools/OsmCreateLineMT.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
"""@package OsmCreateLineMT
 
2
This module holds all structures and methods required to perform
 
3
"create line" operation on current OSM data.
 
4
 
 
5
Snapping to existing points is supported when creating new line.
 
6
Process generates some rubberBands and vertexMarkers so that user can watch
 
7
the whole operation on the map in a nice way.
 
8
 
 
9
There is also an interaction with plugin's "OSM Feature" dockwidget.
 
10
Points to which snapping is performed are loaded to it dynamically.
 
11
"""
 
12
 
 
13
 
 
14
from PyQt4.QtCore import *
 
15
from PyQt4.QtGui import *
 
16
from qgis.core import *
 
17
from qgis.gui import *
 
18
 
 
19
 
 
20
class OsmCreateLineMT(QgsMapTool):
 
21
    """This class holds all structures and methods required to perform
 
22
    "create line" operation on current OSM data.
 
23
 
 
24
    Snapping to existing points is supported when creating new line.
 
25
    Process generates some rubberBands and vertexMarkers so that user can watch
 
26
    the whole operation on the map in a nice way.
 
27
 
 
28
    There is also an interaction with plugin's "OSM Feature" dockwidget.
 
29
    Points to which snapping is performed are loaded to it dynamically.
 
30
    """
 
31
 
 
32
 
 
33
    def __init__(self, plugin):
 
34
        """The constructor.
 
35
 
 
36
        Initializes the map tool, creates necessary snappers.
 
37
 
 
38
        @param plugin pointer to OSM Plugin instance
 
39
        """
 
40
 
 
41
        QgsMapTool.__init__(self,plugin.canvas)
 
42
 
 
43
        self.canvas=plugin.canvas
 
44
        self.dockWidget=plugin.dockWidget
 
45
        self.dbm=plugin.dbm
 
46
        self.ur=plugin.undoredo
 
47
 
 
48
        # initialization
 
49
        self.snappingEnabled=True
 
50
        self.lastPointIsStable=True
 
51
        self.linePoints=[]
 
52
        self.snappedPoint=None
 
53
        self.snapFeat=None
 
54
        self.snapFeatType=None
 
55
 
 
56
        # creating rubberband which will be on new line
 
57
        self.lineRubBand=self.createLineRubberband()
 
58
 
 
59
        # creating rubberband for snapped objects
 
60
        self.snapVerMarker=self.createSnapVertexMarker()
 
61
 
 
62
        # creating snapper to this map tool
 
63
        self.snapper=self.createSnapper(self.canvas.mapRenderer())
 
64
 
 
65
 
 
66
    def databaseChanged(self,dbKey):
 
67
        """This function is called automatically when current OSM database has changed.
 
68
 
 
69
        Function does re-initialization of maptool and create new snappers again (if necessary).
 
70
 
 
71
        @param dbKey key of database with new current OSM data
 
72
        """
 
73
 
 
74
        # re-initialization
 
75
        self.snappingEnabled=True
 
76
        self.snapFeat=None
 
77
        self.snapFeatType=None
 
78
        self.snapVerMarker.setCenter(QgsPoint(-1000,-1000))
 
79
        del self.snapVerMarker
 
80
        self.snapVerMarker=self.createSnapVertexMarker()
 
81
        self.lineRubBand.reset(False)
 
82
 
 
83
        self.lastPointIsStable=True
 
84
        self.linePoints=[]
 
85
        self.snappedPoint=None
 
86
 
 
87
        if dbKey:
 
88
            del self.snapper
 
89
            self.snapper=self.createSnapper(self.canvas.mapRenderer())
 
90
 
 
91
        self.dockWidget.plugin.iface.mainWindow().statusBar().showMessage("")
 
92
 
 
93
 
 
94
    def createLineRubberband(self):
 
95
        """Function creates rubberband that is used for marking new line on the map.
 
96
 
 
97
        @return rubberband that marks new line
 
98
        """
 
99
 
 
100
        # get qgis settings of line width and color for rubberband
 
101
        settings=QSettings()
 
102
        qgsLineWidth=2 # use fixed width
 
103
        qgsLineRed=settings.value("/qgis/digitizing/line_color_red",QVariant(255)).toInt()
 
104
        qgsLineGreen=settings.value("/qgis/digitizing/line_color_green",QVariant(0)).toInt()
 
105
        qgsLineBlue=settings.value("/qgis/digitizing/line_color_blue",QVariant(0)).toInt()
 
106
 
 
107
        rband=QgsRubberBand(self.canvas,False)
 
108
        rband.setColor(QColor(qgsLineRed[0],qgsLineGreen[0],qgsLineBlue[0]))
 
109
        rband.setWidth(qgsLineWidth)
 
110
 
 
111
        return rband
 
112
 
 
113
 
 
114
    def createSnapVertexMarker(self):
 
115
        """Function creates vertexMarker that is used for marking feature
 
116
        to which snapping was done.
 
117
 
 
118
        @return vertex marker - QgsVertexMarker object
 
119
        """
 
120
 
 
121
        # get qgis settings
 
122
        settings=QSettings()
 
123
        qgsLineWidth=2 # use fixed width
 
124
        qgsLineRed=settings.value("/qgis/digitizing/line_color_red",QVariant(255)).toInt()
 
125
        qgsLineGreen=settings.value("/qgis/digitizing/line_color_green",QVariant(0)).toInt()
 
126
        qgsLineBlue=settings.value("/qgis/digitizing/line_color_blue",QVariant(0)).toInt()
 
127
 
 
128
        verMarker=QgsVertexMarker(self.canvas)
 
129
        verMarker.setIconType(2)
 
130
        verMarker.setIconSize(13)
 
131
        verMarker.setColor(QColor(qgsLineRed[0],qgsLineGreen[0],qgsLineBlue[0]))
 
132
        verMarker.setPenWidth(qgsLineWidth)
 
133
        verMarker.setCenter(QgsPoint(-1000,-1000))
 
134
 
 
135
        return verMarker
 
136
 
 
137
 
 
138
    def createSnapper(self,canvasRenderer):
 
139
        """Function creates snapper that snaps within standard qgis tolerance.
 
140
 
 
141
        Snapping of this snapper is done to all segments and vertexes
 
142
        of all three layers of current OSM database.
 
143
 
 
144
        @param canvasRenderer renderer of current map canvas
 
145
        @return instance of vertex+segment QgsSnapper
 
146
        """
 
147
 
 
148
        if not self.dbm.currentKey:
 
149
            # there is no current database -> no layer for snapping
 
150
            return QgsSnapper(self.canvas.mapRenderer())
 
151
 
 
152
        snapper=QgsSnapper(self.canvas.mapRenderer())
 
153
        snapLayers=[]
 
154
 
 
155
        # snap to osm layers from current database only
 
156
        sLayer=QgsSnapper.SnapLayer()
 
157
        sLayer.mLayer=self.dbm.pointLayers[self.dbm.currentKey]
 
158
        sLayer.mTolerance=QgsTolerance.vertexSearchRadius(sLayer.mLayer,self.canvas.mapRenderer())
 
159
        sLayer.mSnapTo=QgsSnapper.SnapToVertex
 
160
        snapLayers.append(sLayer)
 
161
 
 
162
        sLayer=QgsSnapper.SnapLayer()
 
163
        sLayer.mLayer=self.dbm.lineLayers[self.dbm.currentKey]
 
164
        sLayer.mTolerance=QgsTolerance.vertexSearchRadius(sLayer.mLayer,self.canvas.mapRenderer())
 
165
        sLayer.mSnapTo=QgsSnapper.SnapToVertex
 
166
        snapLayers.append(sLayer)
 
167
 
 
168
        sLayer=QgsSnapper.SnapLayer()
 
169
        sLayer.mLayer=self.dbm.polygonLayers[self.dbm.currentKey]
 
170
        sLayer.mTolerance=QgsTolerance.vertexSearchRadius(sLayer.mLayer,self.canvas.mapRenderer())
 
171
        sLayer.mSnapTo=QgsSnapper.SnapToVertex
 
172
        snapLayers.append(sLayer)
 
173
 
 
174
        snapper.setSnapLayers(snapLayers)
 
175
        return snapper
 
176
 
 
177
 
 
178
    def deactivate(self):
 
179
        """Functions is called when create line map-tool is being deactivated.
 
180
 
 
181
        Function performs standard cleaning; re-initialization etc.
 
182
        """
 
183
 
 
184
        self.lineRubBand.reset()
 
185
        self.snapVerMarker.setCenter(QgsPoint(-1000,-1000))
 
186
        self.snappingEnabled=True
 
187
        self.lastPointIsStable=True
 
188
        self.linePoints=[]
 
189
 
 
190
        self.dockWidget.toolButtons.setExclusive(False)
 
191
        self.dockWidget.createLineButton.setChecked(False)
 
192
        self.dockWidget.toolButtons.setExclusive(True)
 
193
        self.dockWidget.activeEditButton=self.dockWidget.dummyButton
 
194
 
 
195
 
 
196
    def keyPressEvent(self, event):
 
197
        """This function is called after keyPressEvent(QKeyEvent *) signal
 
198
        is emmited when using this map tool.
 
199
 
 
200
        If Control key was pressed, function disables snapping til key is released again.
 
201
 
 
202
        @param event event that occured when key pressing
 
203
        """
 
204
 
 
205
        if (event.key() == Qt.Key_Control):
 
206
            self.snappingEnabled = False
 
207
            self.snapVerMarker.setCenter(QgsPoint(-1000,-1000))
 
208
            self.snappedPoint=None
 
209
            self.dockWidget.plugin.iface.mainWindow().statusBar().showMessage("Snapping OFF.")
 
210
 
 
211
 
 
212
    def keyReleaseEvent(self, event):
 
213
        """This function is called after keyReleaseEvent(QKeyEvent *) signal
 
214
        is emmited when using this map tool.
 
215
 
 
216
        If Control key was released, function enables snapping again.
 
217
 
 
218
        @param event event that occured when key releasing
 
219
        """
 
220
 
 
221
        if (event.key() == Qt.Key_Control):
 
222
            self.snappingEnabled = True
 
223
            self.dockWidget.plugin.iface.mainWindow().statusBar().showMessage("Snapping ON. Hold Ctrl to disable it.")
 
224
 
 
225
 
 
226
    def canvasMoveEvent(self, event):
 
227
        """This function is called when mouse moving.
 
228
 
 
229
        @param event event that occured when mouse moving.
 
230
        """
 
231
 
 
232
        self.mapPoint=self.dockWidget.canvasToOsmCoords(event.pos())
 
233
 
 
234
        if len(self.linePoints)>0:
 
235
            if not self.lastPointIsStable:
 
236
                self.lineRubBand.removeLastPoint()
 
237
            self.lineRubBand.addPoint(QgsPoint(self.mapPoint.x(),self.mapPoint.y()))
 
238
            self.lastPointIsStable=False
 
239
 
 
240
        if not self.snappingEnabled:
 
241
            self.snapVerMarker.setCenter(self.mapPoint)
 
242
            return
 
243
 
 
244
        # snapping! first reset old snapping vertexMarker
 
245
        self.snapVerMarker.setCenter(QgsPoint(-1000,-1000))
 
246
 
 
247
        # try snapping to the closest vertex/segment
 
248
        (retval,snappingResults)=self.snapper.snapPoint(event.pos(),[])
 
249
 
 
250
        if len(snappingResults)==0:
 
251
            self.snapVerMarker.setCenter(self.mapPoint)
 
252
            self.snappedPoint=None
 
253
            self.snapFeat=None
 
254
            self.snapFeatType=None
 
255
 
 
256
            if self.dockWidget.feature:
 
257
                self.dockWidget.clear()
 
258
            return
 
259
 
 
260
        # process snapping result (get point, set vertex marker)
 
261
        self.snappedPoint=QgsPoint(snappingResults[0].snappedVertex)
 
262
        self.snapVerMarker.setCenter(self.snappedPoint)
 
263
 
 
264
        if len(self.linePoints)>0:
 
265
            self.lineRubBand.removeLastPoint()
 
266
            self.lineRubBand.addPoint(QgsPoint(self.snappedPoint.x(),self.snappedPoint.y()))
 
267
 
 
268
        # start identification
 
269
        feature=self.dbm.findFeature(self.snappedPoint)
 
270
        if feature:
 
271
            (self.snapFeat,self.snapFeatType)=feature
 
272
            if not self.dockWidget.feature or self.snapFeat.id()<>self.dockWidget.feature.id():
 
273
                self.dockWidget.loadFeature(self.snapFeat,self.snapFeatType)
 
274
 
 
275
 
 
276
    def canvasReleaseEvent(self, event):
 
277
        """This function is called after mouse button releasing when using this map tool.
 
278
 
 
279
        If left button is released new vertex of line is created (pre-created).
 
280
        If right button is released the whole process of line creation is finished.
 
281
 
 
282
        @param event event that occured when button releasing
 
283
        """
 
284
 
 
285
        # we are interested in left/right button clicking only
 
286
        if event.button() not in (Qt.LeftButton,Qt.RightButton):
 
287
            return
 
288
 
 
289
        if event.button()==Qt.LeftButton:
 
290
 
 
291
            # where we are exactly?
 
292
            actualMapPoint = self.dockWidget.canvasToOsmCoords(event.pos())
 
293
 
 
294
            # what point will be the next line member?
 
295
            newLinePoint=actualMapPoint
 
296
            if self.snappedPoint:
 
297
                newLinePoint=self.snappedPoint
 
298
 
 
299
            # add new point into rubberband (and removing last one if necessary) and into new line members list
 
300
            if not self.lastPointIsStable:
 
301
                self.lineRubBand.removeLastPoint()
 
302
                self.lastPointIsStable=True
 
303
 
 
304
            self.lineRubBand.addPoint(newLinePoint)
 
305
            self.linePoints.append((newLinePoint,self.snapFeat,self.snapFeatType))
 
306
 
 
307
        # right button clicking signalizes the last line member!
 
308
        elif event.button()==Qt.RightButton:
 
309
 
 
310
            # line must have at least 2 member points (else it's point rather than line)
 
311
            if len(self.linePoints)<2:
 
312
 
 
313
                self.lineRubBand.reset()
 
314
                self.snapVerMarker.setCenter(QgsPoint(-1000,-1000))
 
315
                self.lastPointIsStable=True
 
316
                self.linePoints=[]
 
317
                return
 
318
 
 
319
            self.ur.startAction("Create a line.")
 
320
            # call function of database manager that will create new line
 
321
            (line,affected)=self.dbm.createLine(self.linePoints)
 
322
            self.ur.stopAction(affected)
 
323
            self.dbm.recacheAffectedNow(affected)
 
324
 
 
325
            if line:
 
326
                self.dockWidget.loadFeature(line,"Line",2)
 
327
 
 
328
            # cleaning..
 
329
            self.lineRubBand.reset()
 
330
            self.linePoints=[]
 
331
 
 
332
            # after line creation canvas must be refresh so that changes take effect on map
 
333
            self.canvas.refresh()
 
334
 
 
335
 
 
336
 
 
337