def generate_layer_definition(self): try: service = QSettings().value("/IdahoLayerPlugin/service", "", type=str).strip('/') image_id = self.lineEdit_ImageId.text().strip() bucket_name = self.lineEdit_Bucket.text().strip() username, password, api_key, max_items_to_return = SettingsOps.get_settings() query = OAuth2Query.OAuth2Query(username, password, api_key) query.log_in() if not query.is_login_successful: QgsMessageLog.instance().logMessage("Login unsuccessful, verify your account settings.", TAG_NAME, level=QgsMessageLog.CRITICAL) raise Exception("Login unsuccessful, verify your account settings.") token = query.headers[OAuth2Query.HEADER_AUTHORIZATION].split(' ')[-1] props = self.getPropsFromID(service, bucket_name, image_id, token) _minlevel = props["levels"][0] _maxlevel = props["levels"][-1] bbox = BoundingBox(props["extents"][0], props["extents"][1], props["extents"][2], props["extents"][3]) self.layerdef = IdahoLayerDefinition(service, image_id, bucket_name, _minlevel, _maxlevel, bbox, 3857) # set parameters self.layerdef.parameters.colorinterpretation = props["color_interp"] self.layerdef.parameters.format = props["mimetype"].split('/')[-1] self.layerdef.parameters.token = str(token) self.layerdef.update() self.accept() except Exception as e: self.plugin.iface.messageBar().pushMessage(self.tr("IdahoLayerPlugin"), self.tr("{0}").format(unicode(e)), QgsMessageBar.WARNING, 5)
def readXml(self, node): self.readCustomProperties(node) service_url = self.customProperty("service_url", "") imageid = self.customProperty("imageid", "") bucket_name = self.customProperty("bucket_name", "") zmin = int(self.customProperty("zmin", TileDefaultSettings.ZMIN)) zmax = int(self.customProperty("zmax", TileDefaultSettings.ZMAX)) bbox = BoundingBox.fromString(self.customProperty("bbox", "")) epsg = int(self.customProperty("epsg", 3857)) max_connections = int(self.customProperty("max_connections", 16)) self.layerDef = IdahoLayerDefinition(service_url=service_url, imageid=imageid, bucket_name=bucket_name, zmin=zmin, zmax=zmax, bbox=bbox, epsg=epsg, max_connections=max_connections) # set parameters self.layerDef.parameters.colorinterpretation = self.customProperty("colorinterpretation", "UNSPECIFIED") self.layerDef.parameters.bands = self.customProperty("bands", [0]) self.layerDef.parameters.format = self.customProperty("format", None) self.layerDef.parameters.token = self.customProperty("token", None) self.layerDef.parameters.doDRA = self.customProperty("doDRA", None) self.layerDef.parameters.lowCutoff = self.customProperty("lowCutoff", None) self.layerDef.parameters.highCutoff = self.customProperty("highCutoff", None) self.layerDef.update() self.tile_manager = TileManager(self, self.layerDef) self.setExtent(BoundingBox.asPseudoMercator(self.layerDef.bbox, self.layerDef.epsg).toQgsRectangle()) # layer style self.setTransparency(int(self.customProperty("transparency", 0))) self.setBlendModeByName(self.customProperty("blendMode", self.DEFAULT_BLEND_MODE)) self.setSmoothRender(int(self.customProperty("smoothRender", self.DEFAULT_SMOOTH_RENDER))) return True
class AddLayerDialog(QDialog, FORM_CLASS): def __init__(self, plugin): QDialog.__init__(self, plugin.iface.mainWindow()) self.plugin = plugin # set up the user interface self.setupUi(self) self.lineEdit_ImageId.textChanged.connect(self.verifyInput) self.lineEdit_Bucket.textChanged.connect(self.verifyInput) self.pushButton_Add.setEnabled(False) self.pushButton_Add.clicked.connect(self.generate_layer_definition) self.pushButton_Close.clicked.connect(self.reject) self.pushButton_Settings.clicked.connect(self.settingsClicked) self.pushButton_AccountSettings.clicked.connect(self.accountSettingsClicked) self.layerdef = None # downloader maxConnections = 12 cacheExpiry = QSettings().value("/qgis/defaultTileExpiry", 24, type=int) userAgent = "QGIS/{0} IdahoLayerPlugin/{1}".format(QGis.QGIS_VERSION, "0.02") settings = QSettings() self.lineEdit_Bucket.setText(settings.value("/IdahoLayerPlugin/bucket", "", type=str)) self.lineEdit_ImageId.setText(settings.value("/IdahoLayerPlugin/imageid", "", type=str)) self.downloader = Downloader(None, maxConnections, cacheExpiry, userAgent) def settingsClicked(self): if self.plugin.settings(): i = 0 def accountSettingsClicked(self): SettingsTool.SettingsTool(self.plugin.iface) def verifyInput(self, val): image_id = self.lineEdit_ImageId.text().strip() bucket_name = self.lineEdit_Bucket.text().strip() #todo: fixed length check if len(image_id) == 36 and len(bucket_name) >1: self.pushButton_Add.setEnabled(True) else: self.pushButton_Add.setEnabled(False) def generate_layer_definition(self): try: service = QSettings().value("/IdahoLayerPlugin/service", "", type=str).strip('/') image_id = self.lineEdit_ImageId.text().strip() bucket_name = self.lineEdit_Bucket.text().strip() username, password, api_key, max_items_to_return = SettingsOps.get_settings() query = OAuth2Query.OAuth2Query(username, password, api_key) query.log_in() if not query.is_login_successful: QgsMessageLog.instance().logMessage("Login unsuccessful, verify your account settings.", TAG_NAME, level=QgsMessageLog.CRITICAL) raise Exception("Login unsuccessful, verify your account settings.") token = query.headers[OAuth2Query.HEADER_AUTHORIZATION].split(' ')[-1] props = self.getPropsFromID(service, bucket_name, image_id, token) _minlevel = props["levels"][0] _maxlevel = props["levels"][-1] bbox = BoundingBox(props["extents"][0], props["extents"][1], props["extents"][2], props["extents"][3]) self.layerdef = IdahoLayerDefinition(service, image_id, bucket_name, _minlevel, _maxlevel, bbox, 3857) # set parameters self.layerdef.parameters.colorinterpretation = props["color_interp"] self.layerdef.parameters.format = props["mimetype"].split('/')[-1] self.layerdef.parameters.token = str(token) self.layerdef.update() self.accept() except Exception as e: self.plugin.iface.messageBar().pushMessage(self.tr("IdahoLayerPlugin"), self.tr("{0}").format(unicode(e)), QgsMessageBar.WARNING, 5) def getPropsFromID(self, input_url, bucket_name, idaho_id, token): # get the metadata from the server url = "{_url}/v1/metadata/{_bucket_name}/{_idaho_id}".format(_url=input_url, _bucket_name=bucket_name, _idaho_id=idaho_id) # get the metadata from the service req = urllib2.Request(url) opener = urllib2.build_opener() opener.addheaders = [('Authorization', 'Bearer '+token), ('Content-Type', 'application/json')] f = opener.open(req) metadata = json.loads(f.read()) # get the metadata from the server url = "{_url}/v1/metadata/{_bucket_name}/{_idaho_id}/image.json".format(_url=input_url, _bucket_name=bucket_name, _idaho_id=idaho_id) # get the metadata from the service req = urllib2.Request(url) opener = urllib2.build_opener() opener.addheaders = [('Authorization', 'Bearer '+token), ('Content-Type', 'application/json')] f = opener.open(req) metadata_image = json.loads(f.read()) # get a list of the avaible z levels levels = metadata.get('tileSets') levels = [int(i) for i in levels] levels = sorted(levels) src = QgsCoordinateReferenceSystem(int(4326), QgsCoordinateReferenceSystem.PostgisCrsId) dest = QgsCoordinateReferenceSystem(3857, QgsCoordinateReferenceSystem.PostgisCrsId) xfrm = QgsCoordinateTransform(src, dest) minX = min(metadata.get('lowerLeftLongitude'),metadata.get('upperRightLongitude')) maxX = max(metadata.get('lowerLeftLongitude'),metadata.get('upperRightLongitude')) minY = min(metadata.get('lowerLeftLatitude'),metadata.get('upperRightLatitude')) maxY = max(metadata.get('lowerLeftLatitude'),metadata.get('upperRightLatitude')) rect = QgsRectangle(minX, minY, maxX, maxY) dr = xfrm.transform(rect) minX = dr.xMinimum() maxX = dr.xMaximum() minY = dr.yMinimum() maxY = dr.yMaximum() return {"extents": (minX, minY, maxX, maxY), "levels": levels, "mimetype": metadata["defaultTileFormat"], "color_interp": metadata_image["colorInterpretation"]} def band_combination_string_from_color_interp(self, colorinterp): bandcombo = "0" try: idx = next(index for (index, d) in enumerate(self.colorinterps) if d["name"] == colorinterp) bandcombo = self.colorinterps[idx]["value"] except Exception as e: bandcombo = "0" return bandcombo def accept(self): QDialog.accept(self) # save dialog prop settings = QSettings() settings.setValue("/IdahoLayerPlugin/bucket", self.lineEdit_Bucket.text().strip()) settings.setValue("/IdahoLayerPlugin/imageid", self.lineEdit_ImageId.text().strip())
def createLayer(self): return IdahoLayer(self.plugin, IdahoLayerDefinition.createEmptyInfo())
class IdahoLayer(QgsPluginLayer): LAYER_TYPE = "IdahoLayer" MAX_TILE_COUNT = 256 DEFAULT_BLEND_MODE = "SourceOver" DEFAULT_SMOOTH_RENDER = True # PyQt signals statusSignal = pyqtSignal(str, int) messageBarSignal = pyqtSignal(str, str, int, int) def __init__(self, plugin, layerDef): QgsPluginLayer.__init__(self, IdahoLayer.LAYER_TYPE, layerDef.imageid) self.plugin = plugin self.iface = plugin.iface self.layerDef = layerDef self.tile_manager = TileManager(self, layerDef) self.zoom = 0 self.tile_range = None # set custom properties self.setCustomProperty("service_url", layerDef.service_url) self.setCustomProperty("bucket_name", layerDef.bucket_name) self.setCustomProperty("imageid", layerDef.imageid) self.setCustomProperty("zmin", layerDef.zmin) self.setCustomProperty("zmax", layerDef.zmax) self.setCustomProperty("bbox", layerDef.bbox.toString()) self.setCustomProperty("epsg", layerDef.epsg) self.setCustomProperty("max_connections", layerDef.max_connections) # set crs default to Pseudo Mercator if plugin.crs3857 is None: # create a QgsCoordinateReferenceSystem instance if plugin has no instance yet plugin.crs3857 = QgsCoordinateReferenceSystem(3857) self.setCrs(plugin.crs3857) # set QGIS extent as QgsRectangle if not layerDef.epsg: layerDef.epsg = 4326 if layerDef.epsg == 3857 or layerDef.epsg == 900913: self.setExtent(layerDef.bbox.toQgsRectangle()) else: self.setExtent(BoundingBox.asPseudoMercator(layerDef.bbox, layerDef.epsg).toQgsRectangle()) # set styles self.setTransparency(0) self.setBrightness(0) self.setContrast(1.0) self.setSaturation(1.0) self.setBlendModeByName(self.DEFAULT_BLEND_MODE) self.setSmoothRender(self.DEFAULT_SMOOTH_RENDER) if self.iface: self.statusSignal.connect(self.showStatusMessageSlot) self.messageBarSignal.connect(self.showMessageBarSlot) self.setValid(True) def setBlendModeByName(self, modeName): self.blendModeName = modeName blendMode = getattr(QPainter, "CompositionMode_" + modeName, 0) self.setBlendMode(blendMode) self.setCustomProperty("blendMode", modeName) def setTransparency(self, transparency): self.transparency = transparency self.setCustomProperty("transparency", transparency) def setBrightness(self, brightness): self.brightness = brightness self.setCustomProperty("brightness", brightness) def setContrast(self, contrast): self.contrast = contrast self.setCustomProperty("contrast", contrast) def setSaturation(self, saturation): self.saturation = saturation self.setCustomProperty("saturation", saturation) def setSmoothRender(self, isSmooth): self.smoothRender = isSmooth self.setCustomProperty("smoothRender", 1 if isSmooth else 0) def calculate_tile_range(self, extent): size = self.layerDef.PSEUDO_MERCATOR_MAX_COORD / 2 ** (self.zoom - 1) matrixSize = 2 ** self.zoom ulx = max(0, int((extent.xMinimum() + self.layerDef.PSEUDO_MERCATOR_MAX_COORD) / size)) uly = max(0, int((self.layerDef.PSEUDO_MERCATOR_MAX_COORD - extent.yMaximum()) / size)) lrx = min(int((extent.xMaximum() + self.layerDef.PSEUDO_MERCATOR_MAX_COORD) / size), matrixSize - 1) lry = min(int((self.layerDef.PSEUDO_MERCATOR_MAX_COORD - extent.yMinimum()) / size), matrixSize - 1) # bounding box limit if self.layerDef.bbox: valid = True trange = None if not self.layerDef.epsg: self.layerDef.epsg = 4326 elif self.layerDef.epsg == 3857 or self.layerDef.epsg == 900913: trange = self.layerDef.bboxMercatorToTileRange(self.zoom, self.layerDef.bbox) else: trange = self.layerDef.epsgToTileRange(self.zoom, self.layerDef.bbox) if trange: ulx = max(ulx, trange.xmin) uly = max(uly, trange.ymin) lrx = min(lrx, trange.xmax) lry = min(lry, trange.ymax) if lrx < ulx or lry < uly: # tile range is out of the bounding box valid = False self.tile_range = TileRange(ulx=ulx, uly=uly, lrx=lrx, lry=lry, valid=valid) def draw(self, renderContext): self.renderContext = renderContext painter = renderContext.painter() viewport = painter.viewport() extent = renderContext.extent() if extent.isEmpty() or extent.width() == float("inf"): qDebug("Drawing is skipped because map extent is empty or inf.") return True map2pixel = renderContext.mapToPixel() mupp = map2pixel.mapUnitsPerPixel() rotation = map2pixel.mapRotation() if self.plugin.apiChanged27 else 0.0 mpp = mupp # meters per pixel if rotation != 0.0: # get bounding box of the extent mapExtent = RotatedRect(extent.center(), mupp * viewport.width(), mupp * viewport.height(), rotation) extent = mapExtent.boundingBox() # calculate zoom level tile_mpp1 = self.layerDef.PSEUDO_MERCATOR_MAX_COORD / self.layerDef.TILE_SIZE self.zoom = int(math.ceil(math.log(tile_mpp1 / mpp, 2) + 1)) self.zoom = max(0, min(self.zoom, self.layerDef.zmax)) #if current zoom is not in layer range then bail if not self.zoom_is_in_range(): return True self.calculate_tile_range(extent) #if tile range is not good if not self.tile_range.valid: return True if not self.tilecount_is_in_range(): return True self.tile_manager.update(self.zoom, self.tile_range) tiles = self.tile_manager.get_tiles() # apply layer style # save painter state painter.save() oldOpacity = painter.opacity() painter.setOpacity(0.01 * (100 - self.transparency)) oldSmoothRenderHint = painter.testRenderHint(QPainter.SmoothPixmapTransform) if self.smoothRender: painter.setRenderHint(QPainter.SmoothPixmapTransform) # draw tiles if rotation == 0.0: # no need to reproject tiles self.render_tiles(renderContext, tiles) else: # reproject tiles cx, cy = 0.5 * viewport.width(), 0.5 * viewport.height() center = map2pixel.toMapCoordinatesF(cx, cy) mapExtent = RotatedRect(center, mupp * viewport.width(), mupp * viewport.height(), rotation) self.render_tiles_warp_on_the_fly(renderContext, mapExtent, tiles) # restore layer style painter.setOpacity(oldOpacity) if self.smoothRender: painter.setRenderHint(QPainter.SmoothPixmapTransform, oldSmoothRenderHint) # restore painter state painter.restore() return True def render_tiles(self, renderContext, tiles, sdx=1.0, sdy=1.0): # create an compose_image that has the same resolution as the tiles image = tiles.compose_image() QgsImageOperation.adjustBrightnessContrast(image, self.brightness, self.contrast) QgsImageOperation.adjustHueSaturation(image, self.saturation) # tile extent to pixel map2pixel = renderContext.mapToPixel() extent = tiles.extent() topLeft = map2pixel.transform(extent.xMinimum(), extent.yMaximum()) bottomRight = map2pixel.transform(extent.xMaximum(), extent.yMinimum()) rect = QRectF(QPointF(topLeft.x() * sdx, topLeft.y() * sdy), QPointF(bottomRight.x() * sdx, bottomRight.y() * sdy)) # draw the compose_image on the map canvas renderContext.painter().drawImage(rect, image) self.log("TilesCollection extent: " + str(extent)) self.log("Draw into canvas rect: " + str(rect)) def render_tiles_warp_on_the_fly(self, renderContext, mapExtent, tiles, sdx=1.0, sdy=1.0): if not hasGdal: msg = self.tr("Rotation/Reprojection requires python-gdal") self.showMessageBar(msg, QgsMessageBar.INFO, 2) return transform = renderContext.coordinateTransform() if transform: sourceCrs = transform.sourceCrs() destCrs = transform.destCRS() else: sourceCrs = destCrs = self.crs() # create compose_image from the tiles image = tiles.compose_image() # tile extent extent = tiles.extent() geotransform = [extent.xMinimum(), extent.width() / image.width(), 0, extent.yMaximum(), 0, -extent.height() / image.height()] # source raster dataset driver = gdal.GetDriverByName("MEM") tile_ds = driver.Create("", image.width(), image.height(), 1, gdal.GDT_UInt32) tile_ds.SetProjection(str(sourceCrs.toWkt())) tile_ds.SetGeoTransform(geotransform) # QImage to raster ba = image.bits().asstring(image.numBytes()) tile_ds.GetRasterBand(1).WriteRaster(0, 0, image.width(), image.height(), ba) # target raster size - if smoothing is enabled, create raster of twice each of width and height of viewport size # in order to get high quality compose_image oversampl = 2 if self.smoothRender else 1 painter = renderContext.painter() viewport = painter.viewport() width, height = viewport.width() * oversampl, viewport.height() * oversampl # target raster dataset canvas_ds = driver.Create("", width, height, 1, gdal.GDT_UInt32) canvas_ds.SetProjection(str(destCrs.toWkt())) canvas_ds.SetGeoTransform(mapExtent.geotransform(width, height, is_grid_point=False)) # reproject compose_image gdal.ReprojectImage(tile_ds, canvas_ds) # raster to QImage ba = canvas_ds.GetRasterBand(1).ReadRaster(0, 0, width, height) reprojected_image = QImage(ba, width, height, QImage.Format_ARGB32_Premultiplied) # draw the compose_image on the map canvas rect = QRectF(QPointF(0, 0), QPointF(viewport.width() * sdx, viewport.height() * sdy)) painter.drawImage(rect, reprojected_image) def drawDebugInfo(self, renderContext, zoom, ulx, uly, lrx, lry): painter = renderContext.painter() scaleX, scaleY = self.getScaleToVisibleExtent(renderContext) painter.scale(scaleX, scaleY) self.drawFrames(renderContext, zoom, ulx, uly, lrx, lry, 1.0 / scaleX, 1.0 / scaleY) self.drawNumbers(renderContext, zoom, ulx, uly, lrx, lry, 1.0 / scaleX, 1.0 / scaleY) def drawFrame(self, renderContext, zoom, x, y, sdx, sdy): rect = self.getTileRect(renderContext, zoom, x, y, sdx, sdy) p = renderContext.painter() # p.drawRect(rect) # A slash appears on the top-right tile without Antialiasing render hint. pts = [rect.topLeft(), rect.topRight(), rect.bottomRight(), rect.bottomLeft(), rect.topLeft()] for i in range(4): p.drawLine(pts[i], pts[i + 1]) def drawFrames(self, renderContext, zoom, xmin, ymin, xmax, ymax, sdx, sdy): for y in range(ymin, ymax + 1): for x in range(xmin, xmax + 1): self.drawFrame(renderContext, zoom, x, y, sdx, sdy) def drawNumber(self, renderContext, zoom, x, y, sdx, sdy): rect = self.getTileRect(renderContext, zoom, x, y, sdx, sdy) p = renderContext.painter() y = (2 ** zoom - 1) - y p.drawText(rect, Qt.AlignCenter, "(%d, %d)\nzoom: %d" % (x, y, zoom)); def drawNumbers(self, renderContext, zoom, xmin, ymin, xmax, ymax, sdx, sdy): for y in range(ymin, ymax + 1): for x in range(xmin, xmax + 1): self.drawNumber(renderContext, zoom, x, y, sdx, sdy) def getScaleToVisibleExtent(self, renderContext): mapSettings = self.iface.mapCanvas().mapSettings() if self.plugin.apiChanged23 else self.iface.mapCanvas().mapRenderer() painter = renderContext.painter() if painter.device().logicalDpiX() == mapSettings.outputDpi(): return 1.0, 1.0 # scale should be 1.0 in rendering on map canvas extent = renderContext.extent() ct = renderContext.coordinateTransform() if ct: # FIX ME: want to get original visible extent in project CRS or visible view size in pixels # extent = ct.transformBoundingBox(extent) # xmax, ymin = extent.xMaximum(), extent.yMinimum() pt1 = ct.transform(extent.xMaximum(), extent.yMaximum()) pt2 = ct.transform(extent.xMaximum(), extent.yMinimum()) pt3 = ct.transform(extent.xMinimum(), extent.yMinimum()) xmax, ymin = min(pt1.x(), pt2.x()), max(pt2.y(), pt3.y()) else: xmax, ymin = extent.xMaximum(), extent.yMinimum() bottomRight = renderContext.mapToPixel().transform(xmax, ymin) viewport = painter.viewport() scaleX = bottomRight.x() / viewport.width() scaleY = bottomRight.y() / viewport.height() return scaleX, scaleY def getTileRect(self, renderContext, zoom, x, y, sdx=1.0, sdy=1.0, toInt=True): """ get tile pixel rect in the render context """ r = self.layerDef.getTileRect(zoom, x, y) map2pix = renderContext.mapToPixel() topLeft = map2pix.transform(r.xMinimum(), r.yMaximum()) bottomRight = map2pix.transform(r.xMaximum(), r.yMinimum()) if toInt: return QRect(QPoint(round(topLeft.x() * sdx), round(topLeft.y() * sdy)), QPoint(round(bottomRight.x() * sdx), round(bottomRight.y() * sdy))) else: return QRectF(QPointF(topLeft.x() * sdx, topLeft.y() * sdy), QPointF(bottomRight.x() * sdx, bottomRight.y() * sdy)) def isProjectCrsWebMercator(self): mapSettings = self.iface.mapCanvas().mapSettings() if self.plugin.apiChanged23 else self.iface.mapCanvas().mapRenderer() return mapSettings.destinationCrs().postgisSrid() == 3857 def zoom_is_in_range(self): # zoom limit if self.zoom < self.layerDef.zmin: if self.plugin.navigationMessagesEnabled: # or zoom > self.layerDef.zmax is not necessary because it will use the last zoom level when zooming in msg = None tpl = "Zoom {_direction} to see {_layer}. Zoom levels {_min}-{_max} in layer. Currently at zoom level {_cur}." if self.zoom < self.layerDef.zmin: msg = self.tr(tpl).format(_min=self.layerDef.zmin, _max=self.layerDef.zmax, _cur=self.zoom, _layer=self.layerDef.imageid, _direction="in") if msg: self.showMessageBar(msg, QgsMessageBar.INFO, 2) return False return True #TODO: check this logic... seems a little off def tilecount_is_in_range(self): # tile count limit tileCount = (self.tile_range.lrx - self.tile_range.ulx + 1) * (self.tile_range.lry - self.tile_range.uly + 1) if tileCount > self.MAX_TILE_COUNT: # if the zoom level is less than the minimum, do not draw if self.zoom < self.layerDef.zmin: msg = self.tr("Tile count is over limit ({0}, max={1})").format(tileCount, self.MAX_TILE_COUNT) self.showMessageBar(msg, QgsMessageBar.WARNING, 4) return False return True def readXml(self, node): self.readCustomProperties(node) service_url = self.customProperty("service_url", "") imageid = self.customProperty("imageid", "") bucket_name = self.customProperty("bucket_name", "") zmin = int(self.customProperty("zmin", TileDefaultSettings.ZMIN)) zmax = int(self.customProperty("zmax", TileDefaultSettings.ZMAX)) bbox = BoundingBox.fromString(self.customProperty("bbox", "")) epsg = int(self.customProperty("epsg", 3857)) max_connections = int(self.customProperty("max_connections", 16)) self.layerDef = IdahoLayerDefinition(service_url=service_url, imageid=imageid, bucket_name=bucket_name, zmin=zmin, zmax=zmax, bbox=bbox, epsg=epsg, max_connections=max_connections) # set parameters self.layerDef.parameters.colorinterpretation = self.customProperty("colorinterpretation", "UNSPECIFIED") self.layerDef.parameters.bands = self.customProperty("bands", [0]) self.layerDef.parameters.format = self.customProperty("format", None) self.layerDef.parameters.token = self.customProperty("token", None) self.layerDef.parameters.doDRA = self.customProperty("doDRA", None) self.layerDef.parameters.lowCutoff = self.customProperty("lowCutoff", None) self.layerDef.parameters.highCutoff = self.customProperty("highCutoff", None) self.layerDef.update() self.tile_manager = TileManager(self, self.layerDef) self.setExtent(BoundingBox.asPseudoMercator(self.layerDef.bbox, self.layerDef.epsg).toQgsRectangle()) # layer style self.setTransparency(int(self.customProperty("transparency", 0))) self.setBlendModeByName(self.customProperty("blendMode", self.DEFAULT_BLEND_MODE)) self.setSmoothRender(int(self.customProperty("smoothRender", self.DEFAULT_SMOOTH_RENDER))) return True def writeXml(self, node, doc): self.setCustomProperty("colorinterpretation", self.layerDef.parameters.colorinterpretation) self.setCustomProperty("bands", self.layerDef.parameters.bands) self.setCustomProperty("format", self.layerDef.parameters.format) self.setCustomProperty("token", self.layerDef.parameters.token) self.setCustomProperty("doDRA", self.layerDef.parameters.doDRA) self.setCustomProperty("lowCutoff", self.layerDef.parameters.lowCutoff) self.setCustomProperty("highCutoff", self.layerDef.parameters.highCutoff) self.writeCustomProperties(node, doc) element = node.toElement(); element.setAttribute("type", "plugin") element.setAttribute("name", IdahoLayer.LAYER_TYPE); return True def readSymbology(self, node, errorMessage): return False def writeSymbology(self, node, doc, errorMessage): return False def metadata(self): lines = [] fmt = u"%s:\t%s" lines.append(fmt % (self.tr("Image ID"), self.layerDef.imageid)) if self.layerDef.bbox: extent = self.layerDef.bbox.toString() else: extent = self.tr("Not set") lines.append(fmt % (self.tr("Zoom range"), "%d - %d" % (self.layerDef.zmin, self.layerDef.zmax))) lines.append(fmt % (self.tr("Layer Extent"), extent)) return "\n".join(lines) def showStatusMessage(self, msg, timeout=0): self.statusSignal.emit(msg, timeout) def showStatusMessageSlot(self, msg, timeout): self.iface.mainWindow().statusBar().showMessage(msg, timeout) def showMessageBar(self, text, level=QgsMessageBar.INFO, duration=0, imageid=None): if imageid is None: imageid = self.plugin.pluginName self.messageBarSignal.emit(imageid, text, level, duration) def showMessageBarSlot(self, imageid, text, level, duration): self.iface.messageBar().pushMessage(imageid, text, level, duration) def log(self, msg): if debug_mode: qDebug(msg) def logT(self, msg): if debug_mode: qDebug("%s: %s" % (str(threading.current_thread()), msg))