openlayers_plugin.py

Salvatore Larosa, 2013-01-12 10:14 AM

Download (9.99 KB)

 
1
# -*- coding: utf-8 -*-
2
"""
3
/***************************************************************************
4
OpenLayers Plugin
5
A QGIS plugin
6

7
                             -------------------
8
begin                : 2009-11-30
9
copyright            : (C) 2009 by Pirmin Kalberer, Sourcepole
10
email                : pka at sourcepole.ch
11
 ***************************************************************************/
12

13
/***************************************************************************
14
 *                                                                         *
15
 *   This program is free software; you can redistribute it and/or modify  *
16
 *   it under the terms of the GNU General Public License as published by  *
17
 *   the Free Software Foundation; either version 2 of the License, or     *
18
 *   (at your option) any later version.                                   *
19
 *                                                                         *
20
 ***************************************************************************/
21
"""
22

    
23
import os.path
24

    
25
from PyQt4.QtCore import *
26
from PyQt4.QtGui import *
27
from PyQt4.QtWebKit import *
28
from qgis.core import *
29

    
30
import resources_rc
31
import math
32

    
33
from openlayers_layer import OpenlayersLayer
34
from openlayers_plugin_layer_type import OpenlayersPluginLayerType
35
from openlayers_ovwidget import OpenLayersOverviewWidget
36

    
37
class OlLayerType:
38

    
39
  def __init__(self, plugin, name, icon, html, emitsLoadEnd = False):
40
    self.__plugin = plugin
41
    self.name = name
42
    self.icon = icon
43
    self.html = html
44
    self.emitsLoadEnd = emitsLoadEnd
45
    self.id = None
46

    
47
  def addLayer(self):
48
    self.__plugin.addLayer(self)
49

    
50

    
51
class OlLayerTypeRegistry:
52

    
53
  def __init__(self):
54
    self.__olLayerTypes = {}
55
    self.__layerTypeId = 0
56

    
57
  def add(self, layerType):
58
    layerType.id = self.__layerTypeId
59
    self.__olLayerTypes[self.__layerTypeId] = layerType
60
    self.__layerTypeId += 1
61

    
62
  def types(self):
63
    return self.__olLayerTypes.values()
64

    
65
  def getById(self, id):
66
    return self.__olLayerTypes[id]
67

    
68

    
69
class OLOverview(object):
70

    
71
  def __init__(self, iface, olLayerTypeRegistry):
72
    self.__iface = iface
73
    self.__olLayerTypeRegistry = olLayerTypeRegistry
74
    self.__dockwidget = None
75
    self.__oloWidget = None
76

    
77
  # Private
78
  def __setDocWidget(self):
79
    self.__dockwidget = QDockWidget(QApplication.translate("OpenLayersOverviewWidget", "OpenLayers Overview"), self.__iface.mainWindow() )
80
    self.__dockwidget.setObjectName("dwOpenlayersOverview")
81
    self.__oloWidget = OpenLayersOverviewWidget(self.__iface, self.__dockwidget, self.__olLayerTypeRegistry)
82
    self.__dockwidget.setWidget(self.__oloWidget)
83

    
84
  def __initGui(self):
85
    self.__setDocWidget()
86
    self.__iface.addDockWidget( Qt.LeftDockWidgetArea, self.__dockwidget)
87

    
88
  def __unload(self):
89
    self.__dockwidget.close()
90
    self.__iface.removeDockWidget( self.__dockwidget )
91
    del self.__oloWidget
92
    self.__dockwidget = None
93

    
94
  # Public
95
  def setVisible(self, visible):
96
    if visible:
97
      if self.__dockwidget is None:
98
        self.__initGui()
99
    else:
100
      if not self.__dockwidget is None:
101
        self.__unload()
102
 
103

    
104
class OpenlayersPlugin:
105

    
106
  def __init__(self, iface):
107
    # Save reference to the QGIS interface
108
    self.iface = iface
109

    
110
    # setup locale
111
    pluginDir = os.path.dirname( __file__ )
112
    localePath = ""
113
    locale = QSettings().value("locale/userLocale").toString()[0:2]
114
    if QFileInfo(pluginDir).exists():
115
      localePath = pluginDir + "/i18n/openlayers_" + locale + ".qm"
116
    if QFileInfo(localePath).exists():
117
      self.translator = QTranslator()
118
      self.translator.load(localePath)
119
      if qVersion() > '4.3.3':
120
        QCoreApplication.installTranslator(self.translator)
121

    
122
    # Layers
123
    self.olLayerTypeRegistry = OlLayerTypeRegistry()
124
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Google Physical', 'google_icon.png', 'google_physical.html', True) )
125
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Google Streets', 'google_icon.png', 'google_streets.html', True) )
126
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Google Hybrid', 'google_icon.png', 'google_hybrid.html', True) )
127
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Google Satellite', 'google_icon.png', 'google_satellite.html', True) )
128
    self.olLayerTypeRegistry.add( OlLayerType(self, 'OpenStreetMap', 'osm_icon.png', 'osm.html', True) )
129
    self.olLayerTypeRegistry.add( OlLayerType(self, 'OpenCycleMap', 'osm_icon.png', 'ocm.html', True) )
130
    self.olLayerTypeRegistry.add( OlLayerType(self, 'OCM Landscape', 'osm_icon.png', 'ocm_landscape.html', True) )
131
    self.olLayerTypeRegistry.add( OlLayerType(self, 'OCM Public Transport', 'osm_icon.png', 'ocm_transport.html', True) )
132
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Yahoo Street', 'yahoo_icon.png', 'yahoo_street.html') )
133
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Yahoo Hybrid', 'yahoo_icon.png', 'yahoo_hybrid.html') )
134
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Yahoo Satellite', 'yahoo_icon.png',  'yahoo_satellite.html') )
135
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Road', 'bing_icon.png',   'bing_road.html', True) )
136
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Bing Aerial', 'bing_icon.png',  'bing_aerial.html', True) )
137
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Bing Aerial with labels', 'bing_icon.png',  'bing_aerial-labels.html', True) )
138
    self.olLayerTypeRegistry.add( OlLayerType(self, 'Apple iPhoto map', 'apple_icon.png', 'apple.html', True) )
139
    # Overview
140
    self.olOverview = OLOverview( iface, self.olLayerTypeRegistry )
141

    
142
  def initGui(self):
143
    # Overview
144
    self.overviewAddAction = QAction(QApplication.translate("OpenlayersPlugin", "OpenLayers Overview"), self.iface.mainWindow())
145
    self.overviewAddAction.setCheckable(True)
146
    self.overviewAddAction.setChecked(False)
147
    QObject.connect(self.overviewAddAction, SIGNAL("toggled(bool)"), self.olOverview.setVisible )
148
    self.iface.addPluginToMenu("OpenLayers plugin", self.overviewAddAction)
149
    # Layers
150
    self.layerAddActions = []
151
    pathPlugin = "%s%s%%s" % ( os.path.dirname( __file__ ), os.path.sep )
152
    for layerType in self.olLayerTypeRegistry.types():
153
      # Create actions for adding layers
154
      action = QAction(QIcon(pathPlugin % layerType.icon), QApplication.translate("OpenlayersPlugin", "Add %1 layer").arg(layerType.name), self.iface.mainWindow())
155
      self.layerAddActions.append(action)
156
      QObject.connect(action, SIGNAL("triggered()"), layerType.addLayer)
157
      # Add toolbar button and menu item
158
      self.iface.addPluginToMenu("OpenLayers plugin", action)
159

    
160
    if not self.__setCoordRSGoogle():
161
      QMessageBox.critical(self.iface.mainWindow(), "OpenLayers Plugin", QApplication.translate("OpenlayersPlugin", "Could not set Google projection!"))
162
      return
163

    
164
    # Register plugin layer type
165
    QgsPluginLayerRegistry.instance().addPluginLayerType(OpenlayersPluginLayerType(self.iface, self.setReferenceLayer, self.__coordRSGoogle, self.olLayerTypeRegistry))
166

    
167
    self.layer = None
168
    QObject.connect(QgsMapLayerRegistry.instance(), SIGNAL("layerWillBeRemoved(QString)"), self.removeLayer)
169
    
170
  def unload(self):
171
    # Remove the plugin menu item and icon
172
    for action in self.layerAddActions:
173
      self.iface.removePluginMenu("OpenLayers plugin", action)
174

    
175
    self.iface.removePluginMenu("OpenLayers plugin", self.overviewAddAction)  
176

    
177
    # Unregister plugin layer type
178
    QgsPluginLayerRegistry.instance().removePluginLayerType(OpenlayersLayer.LAYER_TYPE)
179

    
180
    QObject.disconnect(QgsMapLayerRegistry.instance(), SIGNAL("layerWillBeRemoved(QString)"), self.removeLayer)
181
    
182
    self.olOverview.setVisible( False )
183
    del self.olOverview
184

    
185
  def addLayer(self, layerType):
186

    
187
    self.__setMapSrsGoogle()
188

    
189
    layer = OpenlayersLayer(self.iface, self.__coordRSGoogle, self.olLayerTypeRegistry)
190
    layer.setLayerName(layerType.name)
191
    layer.setLayerType(layerType)
192
    if layer.isValid():
193
      if QGis.QGIS_VERSION_INT >= 10900:
194
        QgsMapLayerRegistry.instance().addMapLayers([layer])
195
      else:
196
        QgsMapLayerRegistry.instance().addMapLayer(layer)
197

    
198
      # last added layer is new reference
199
      self.setReferenceLayer(layer)
200

    
201
  def setReferenceLayer(self, layer):
202
    self.layer = layer
203
    # TODO: update initial scale
204

    
205
  def removeLayer(self, layerId):
206
    layerToRemove = None
207
    if QGis.QGIS_VERSION_INT >= 10900:
208
      if self.layer != None and self.layer.id() == layerId:
209
        self.layer = None
210
    else:
211
      if self.layer != None and self.layer.getLayerID() == layerId:
212
        self.layer = None
213
    
214
      # TODO: switch to next available OpenLayers layer?
215

    
216
  def __setCoordRSGoogle(self):
217
    self.__coordRSGoogle = QgsCoordinateReferenceSystem()
218
    if QGis.QGIS_VERSION_INT >= 10900:
219
      idEpsgRSGoogle = 'EPSG:3857'
220
      createCrs = self.__coordRSGoogle.createFromOgcWmsCrs(idEpsgRSGoogle)
221
    else:
222
      idEpsgRSGoogle = 3857
223
      createCrs = self.__coordRSGoogle.createFromEpsg(idEpsgRSGoogle)
224
    if not createCrs:
225
      google_proj_def = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 "
226
      google_proj_def += "+units=m +nadgrids=@null +wktext +no_defs"
227
      isOk = self.__coordRSGoogle.createFromProj4(google_proj_def)
228
      if isOk:
229
        return True
230
      else:
231
        return False
232
    else:
233
      return True
234

    
235
  def __setMapSrsGoogle(self):
236
    mapCanvas = self.iface.mapCanvas()
237
    # On the fly
238
    mapCanvas.mapRenderer().setProjectionsEnabled(True) 
239
    if QGis.QGIS_VERSION_INT >= 10900:
240
      theCoodRS = mapCanvas.mapRenderer().destinationCrs()
241
    else:
242
      theCoodRS = mapCanvas.mapRenderer().destinationSrs()
243
    if theCoodRS != self.__coordRSGoogle:
244
      coodTrans = QgsCoordinateTransform(theCoodRS, self.__coordRSGoogle)
245
      extMap = mapCanvas.extent()
246
      extMap = coodTrans.transform(extMap, QgsCoordinateTransform.ForwardTransform)
247
      if QGis.QGIS_VERSION_INT >= 10900:
248
        mapCanvas.mapRenderer().setDestinationCrs(self.__coordRSGoogle)
249
      else:
250
        mapCanvas.mapRenderer().setDestinationSrs(self.__coordRSGoogle)
251
      mapCanvas.freeze(False)
252
      mapCanvas.setMapUnits(self.__coordRSGoogle.mapUnits())
253
      mapCanvas.setExtent(extMap)