Source code for svir.dialogs.download_layer_dialog

# -*- coding: utf-8 -*-
#/***************************************************************************
# Irmt
#                                 A QGIS plugin
# OpenQuake Integrated Risk Modelling Toolkit
#                              -------------------
#        begin                : 2013-10-24
#        copyright            : (C) 2014 by GEM Foundation
#        email                : devops@openquake.org
# ***************************************************************************/
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake.  If not, see <http://www.gnu.org/licenses/>.

import json
import os
import tempfile
from xml.etree import ElementTree
from PyQt4 import Qt

from PyQt4.QtCore import pyqtSlot
from PyQt4.QtGui import (QDialog, QDialogButtonBox, QListWidgetItem,
                         QMessageBox)
from qgis.gui import QgsMessageBar
from qgis.core import QgsVectorLayer,  QgsMapLayerRegistry
from svir.thread_worker.abstract_worker import start_worker
from svir.thread_worker.download_platform_project_worker import (
    DownloadPlatformProjectWorker)

from svir.ui.ui_download_layer import Ui_DownloadLayerDialog
from svir.utilities.utils import (WaitCursorManager,
                                  SvNetworkError,
                                  ask_for_download_destination,
                                  files_exist_in_destination,
                                  confirm_overwrite,
                                  tr,
                                  write_layer_suppl_info_to_qgs,
                                  )

NS_NET_OPENGIS_WFS = '{http://www.opengis.net/wfs}'


[docs]class DownloadLayerDialog(QDialog): """ Modal dialog giving to the user the possibility to select and download one of the projects available on the OQ-Platform """ def __init__(self, iface, downloader): QDialog.__init__(self) # Set up the user interface from Designer. self.ui = Ui_DownloadLayerDialog() self.ui.setupUi(self) self.iface = iface # login to platform, to be able to retrieve sv indices self.sv_downloader = downloader self.ok_button = self.ui.buttonBox.button(QDialogButtonBox.Ok) self.ui.layer_lbl.setText('Project definition') self.layer_id = None # needed after ok is pressed self.downloaded_layer_id = None # the id of the layer created self.extra_infos = {} self.set_ok_button() with WaitCursorManager(): self.get_capabilities() @pyqtSlot()
[docs] def on_layers_lst_itemSelectionChanged(self): layer_id = self.ui.layers_lst.currentItem().data(Qt.Qt.ToolTipRole) if layer_id is not None: self.layer_id = layer_id self.ui.layer_lbl.setText('Project details for "%s"' % layer_id) layer_infos = self.extra_infos[layer_id] bb = layer_infos['Bounding Box'] layer_infos_str = "Title:\n\t" + layer_infos['Title'] layer_infos_str += "\nAbstract:\n\t" + layer_infos['Abstract'] layer_infos_str += "\nBounding box:" layer_infos_str += "\n\tminx = " + bb['minx'] layer_infos_str += "\n\tminy = " + bb['miny'] layer_infos_str += "\n\tmaxx = " + bb['maxx'] layer_infos_str += "\n\tmaxy = " + bb['maxy'] layer_infos_str += "\nKeywords:\n\t" + layer_infos['Keywords'] self.ui.layer_detail.setText(layer_infos_str) self.set_ok_button()
@pyqtSlot(QListWidgetItem)
[docs] def on_layers_lst_itemDoubleClicked(self, item): self.accept()
[docs] def set_ok_button(self): self.ok_button.setDisabled( len(self.ui.layers_lst.selectedItems()) == 0)
[docs] def get_capabilities(self): wfs = '/geoserver/wfs?' params = ('SERVICE=WFS' '&VERSION=1.0.0' '&REQUEST=GetCapabilities' '&SRSNAME=EPSG:4326') url = '%s%s%s' % (self.sv_downloader.host, wfs, params) result = self.sv_downloader.sess.get(url) if result.status_code == 200: self.parse_get_capabilities(result.content) else: raise SvNetworkError( "Unable to download layers: %s" % result.error)
[docs] def parse_get_capabilities(self, xml): # this raises a IOError if the file doesn't exist root = ElementTree.fromstring(xml) layers = root.find('%sFeatureTypeList' % NS_NET_OPENGIS_WFS) for layer in layers: try: keywords = layer.find('%sKeywords' % NS_NET_OPENGIS_WFS).text if keywords is not None and ( 'IRMT_QGIS_Plugin' in keywords or # this is for backward compatibility 'SVIR_QGIS_Plugin' in keywords): title = layer.find('%sTitle' % NS_NET_OPENGIS_WFS).text layer_id = layer.find('%sName' % NS_NET_OPENGIS_WFS).text abstract = layer.find( '%sAbstract' % NS_NET_OPENGIS_WFS).text bbox = layer.find( '%sLatLongBoundingBox' % NS_NET_OPENGIS_WFS).attrib self.extra_infos[layer_id] = { 'Title': title, 'Abstract': abstract, 'Keywords': keywords, 'Bounding Box': bbox} # update combo box item = QListWidgetItem() item.setData(Qt.Qt.DisplayRole, title) item.setData(Qt.Qt.ToolTipRole, layer_id) self.ui.layers_lst.addItem(item) except AttributeError: continue
[docs] def accept(self): dest_dir = ask_for_download_destination(self) if not dest_dir: return worker = DownloadPlatformProjectWorker(self.sv_downloader, self.layer_id) worker.successfully_finished.connect( lambda zip_file: self._import_layer( zip_file, self.sv_downloader, dest_dir, self)) start_worker(worker, self.iface.messageBar(), 'Downloading data from platform')
def _import_layer(self, zip_file, sv_downloader, dest_dir, parent_dlg): files_in_zip = zip_file.namelist() shp_file = next( filename for filename in files_in_zip if '.shp' in filename) file_in_destination = files_exist_in_destination( dest_dir, files_in_zip) if file_in_destination: while confirm_overwrite(parent_dlg, file_in_destination) == \ QMessageBox.No: dest_dir = ask_for_download_destination(parent_dlg) if not dest_dir: return file_in_destination = files_exist_in_destination( dest_dir, zip_file.namelist()) if not file_in_destination: break zip_file.extractall(dest_dir) request_url = '%s/svir/get_supplemental_information?layer_name=%s' % ( sv_downloader.host, parent_dlg.layer_id) get_supplemental_information_resp = sv_downloader.sess.get(request_url) if not get_supplemental_information_resp.ok: self.iface.messageBar().pushMessage( tr("Download Error"), tr('Unable to retrieve the project definitions for the layer'), level=QgsMessageBar.CRITICAL) return supplemental_information = json.loads( get_supplemental_information_resp.content) # attempt to convert supplemental information in old list format # or those that did not nest project definitions into a # project_definitions attribute if (isinstance(supplemental_information, list) or 'project_definitions' not in supplemental_information): supplemental_information = { 'project_definitions': supplemental_information} dest_file = os.path.join(dest_dir, shp_file) layer = QgsVectorLayer( dest_file, parent_dlg.extra_infos[parent_dlg.layer_id]['Title'], 'ogr') if layer.isValid(): QgsMapLayerRegistry.instance().addMapLayer(layer) self.iface.messageBar().pushMessage( tr('Import successful'), tr('Shapefile imported to %s' % dest_file), duration=8) else: self.iface.messageBar().pushMessage( tr("Import Error"), tr('Layer invalid'), level=QgsMessageBar.CRITICAL) return try: # dlg.layer_id has the format "oqplatform:layername" style_name = parent_dlg.layer_id.split(':')[1] + '.sld' request_url = '%s/gs/rest/styles/%s' % ( sv_downloader.host, style_name) get_style_resp = sv_downloader.sess.get(request_url) if not get_style_resp.ok: raise SvNetworkError(get_style_resp.reason) fd, sld_file = tempfile.mkstemp(suffix=".sld") os.close(fd) with open(sld_file, 'w') as f: f.write(get_style_resp.text) layer.loadSldStyle(sld_file) except Exception as e: error_msg = ('Unable to download and apply the' ' style layer descriptor: %s' % e) self.iface.messageBar().pushMessage( 'Error downloading style', error_msg, level=QgsMessageBar.WARNING, duration=8) self.iface.setActiveLayer(layer) project_definitions = supplemental_information['project_definitions'] # ensure backwards compatibility with projects with a single # project definition if not isinstance(project_definitions, list): project_definitions = [project_definitions] supplemental_information['project_definitions'] = project_definitions supplemental_information['platform_layer_id'] = parent_dlg.layer_id if 'selected_project_definition_idx' not in supplemental_information: supplemental_information['selected_project_definition_idx'] = 0 self.downloaded_layer_id = layer.id() write_layer_suppl_info_to_qgs( self.downloaded_layer_id, supplemental_information) super(DownloadLayerDialog, self).accept()