def validate_input(self): """Validate the input before saving a scenario. Those validations are: 1. self.exposure_layer must be not None 2. self.hazard_layer must be not None 3. self.function_id is not an empty string or None """ self.exposure_layer = layer_from_combo(self.dock.exposure_layer_combo) self.hazard_layer = layer_from_combo(self.dock.hazard_layer_combo) self.aggregation_layer = layer_from_combo( self.dock.aggregation_layer_combo) is_valid = True warning_message = None if self.exposure_layer is None: warning_message = tr( 'Exposure layer is not found, can not save scenario. Please ' 'add exposure layer to do so.') is_valid = False if self.hazard_layer is None: warning_message = tr( 'Hazard layer is not found, can not save scenario. Please add ' 'hazard layer to do so.') is_valid = False return is_valid, warning_message
def test_relative_path(self): """Test we calculate the relative paths correctly when saving scenario. """ result, message = setup_scenario(self.DOCK, hazard='Classified Flood', exposure='Population') self.assertTrue(result, message) fake_dir = standard_data_path() scenario_file = unique_filename(prefix='scenarioTest', suffix='.txt', dir=fake_dir) exposure_layer = layer_from_combo( self.DOCK.exposure_layer_combo).publicSource() hazard_layer = layer_from_combo( self.DOCK.hazard_layer_combo).publicSource() relative_exposure = self.save_scenario_dialog.relative_path( scenario_file, exposure_layer) relative_hazard = self.save_scenario_dialog.relative_path( scenario_file, hazard_layer) if 'win32' in sys.platform: # windows self.assertEqual('exposure\\pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual('hazard\\classified_flood_20_20.asc', relative_hazard) else: self.assertEqual('exposure/pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual('hazard/classified_flood_20_20.asc', relative_hazard)
def accept(self): """Upload the layer to Geonode.""" enable_busy_cursor() self.button_box.setEnabled(False) layer = layer_from_combo(self.layers) login = self.login.text() if self.save_login.isChecked(): set_setting(GEONODE_USER, login) else: set_setting(GEONODE_USER, '') password = self.password.text() if self.save_password.isChecked(): set_setting(GEONODE_PASSWORD, password) else: set_setting(GEONODE_PASSWORD, '') url = self.url.text() if self.save_url.isChecked(): set_setting(GEONODE_URL, url) else: set_setting(GEONODE_URL, '') geonode_session = login_user(url, login, password) try: result = upload(url, geonode_session, layer.source()) except GeoNodeLayerUploadError as e: result = { 'success': False, 'message': str(e) } finally: self.button_box.setEnabled(True) disable_busy_cursor() if result['success']: self.done(QDialog.Accepted) layer_url = urljoin(url, result['url']) # Link is not working in QGIS 2. # It's gonna work in QGIS 3. if qgis_version() >= 29900: external_link = '<a href=\"{url}\">{url}</a>'.format( url=layer_url) else: external_link = layer_url display_success_message_bar( tr('Uploading done'), tr('Successfully uploaded to {external_link}').format( external_link=external_link), ) else: display_warning_message_box( self, tr('Error while uploading the layer.'), str(result) )
def validate_impact_function(self): """Check validity of the current impact function.""" # Always set it to False self.btn_run.setEnabled(False) for combo in list(self.combos_exposures.values()): if combo.count() == 1: combo.setEnabled(False) hazard = layer_from_combo(self.cbx_hazard) aggregation = layer_from_combo(self.cbx_aggregation) exposures = [] for combo in list(self.combos_exposures.values()): exposures.append(layer_from_combo(combo)) exposures = [layer for layer in exposures if layer] multi_exposure_if = MultiExposureImpactFunction() multi_exposure_if.hazard = hazard multi_exposure_if.exposures = exposures multi_exposure_if.debug = False multi_exposure_if.callback = self.progress_callback if aggregation: multi_exposure_if.use_selected_features_only = ( self.use_selected_only) multi_exposure_if.aggregation = aggregation else: multi_exposure_if.crs = ( self.iface.mapCanvas().mapSettings().destinationCrs()) if len(self.ordered_expected_layers()) != 0: self._multi_exposure_if.output_layers_ordered = ( self.ordered_expected_layers()) status, message = multi_exposure_if.prepare() if status == PREPARE_SUCCESS: self._multi_exposure_if = multi_exposure_if self.btn_run.setEnabled(True) send_static_message(self, ready_message()) self.list_layers_in_map_report.clear() return else: disable_busy_cursor() send_error_message(self, message) self._multi_exposure_if = None
def test_relative_path(self): """Test we calculate the relative paths correctly when saving scenario. """ result, message = setup_scenario( self.DOCK, hazard='Classified Flood', exposure='Population') self.assertTrue(result, message) fake_dir = standard_data_path() scenario_file = unique_filename( prefix='scenarioTest', suffix='.txt', dir=fake_dir) exposure_layer = layer_from_combo( self.DOCK.exposure_layer_combo).publicSource() hazard_layer = layer_from_combo( self.DOCK.hazard_layer_combo).publicSource() relative_exposure = self.save_scenario_dialog.relative_path( scenario_file, exposure_layer) relative_hazard = self.save_scenario_dialog.relative_path( scenario_file, hazard_layer) if 'win32' in sys.platform: # windows self.assertEqual( 'exposure\\pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual( 'hazard\\classified_flood_20_20.asc', relative_hazard) else: self.assertEqual( 'exposure/pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual( 'hazard/classified_flood_20_20.asc', relative_hazard)
def accept(self): """Launch the multi exposure analysis.""" if not isinstance(self._multi_exposure_if, MultiExposureImpactFunction): # This should not happen as the "accept" button must be disabled if # the impact function is not ready. return ANALYSIS_FAILED_BAD_CODE, None self.tab_widget.setCurrentIndex(2) self.set_enabled_buttons(False) enable_busy_cursor() try: code, message, exposure = self._multi_exposure_if.run() message = basestring_to_message(message) if code == ANALYSIS_FAILED_BAD_INPUT: LOGGER.warning( tr('The impact function could not run because of the inputs.' )) send_error_message(self, message) LOGGER.warning(message.to_text()) disable_busy_cursor() self.set_enabled_buttons(True) return code, message elif code == ANALYSIS_FAILED_BAD_CODE: LOGGER.warning( tr('The impact function could not run because of a bug.')) LOGGER.exception(message.to_text()) send_error_message(self, message) disable_busy_cursor() self.set_enabled_buttons(True) return code, message if setting('generate_report', True, bool): LOGGER.info( 'Reports are going to be generated for the multiexposure.') # Report for the multi exposure report = [standard_multi_exposure_impact_report_metadata_html] error_code, message = ( self._multi_exposure_if.generate_report(report)) message = basestring_to_message(message) if error_code == ImpactReport.REPORT_GENERATION_FAILED: LOGGER.warning('The impact report could not be generated.') send_error_message(self, message) LOGGER.exception(message.to_text()) disable_busy_cursor() self.set_enabled_buttons(True) return error_code, message else: LOGGER.warning( 'Reports are not generated because of your settings.') display_warning_message_bar( tr('Reports'), tr('Reports are not going to be generated because of your ' 'InaSAFE settings.'), duration=10, iface_object=self.iface) # We always create the multi exposure group because we need # reports to be generated. root = QgsProject.instance().layerTreeRoot() if len(self.ordered_expected_layers()) == 0: group_analysis = root.insertGroup(0, self._multi_exposure_if.name) group_analysis.setItemVisibilityChecked(True) group_analysis.setCustomProperty(MULTI_EXPOSURE_ANALYSIS_FLAG, True) for layer in self._multi_exposure_if.outputs: QgsProject.instance().addMapLayer(layer, False) layer_node = group_analysis.addLayer(layer) layer_node.setItemVisibilityChecked(False) # set layer title if any try: title = layer.keywords['title'] if qgis_version() >= 21800: layer.setName(title) else: layer.setLayerName(title) except KeyError: pass for analysis in self._multi_exposure_if.impact_functions: detailed_group = group_analysis.insertGroup( 0, analysis.name) detailed_group.setItemVisibilityChecked(True) add_impact_layers_to_canvas(analysis, group=detailed_group) if self.iface: self.iface.setActiveLayer( self._multi_exposure_if.analysis_impacted) else: add_layers_to_canvas_with_custom_orders( self.ordered_expected_layers(), self._multi_exposure_if, self.iface) if setting('generate_report', True, bool): LOGGER.info( 'Reports are going to be generated for each single ' 'exposure.') # Report for the single exposure with hazard for analysis in self._multi_exposure_if.impact_functions: # we only want to generate non pdf/qpt report html_components = [standard_impact_report_metadata_html] error_code, message = ( analysis.generate_report(html_components)) message = basestring_to_message(message) if error_code == (ImpactReport.REPORT_GENERATION_FAILED): LOGGER.info( 'The impact report could not be generated.') send_error_message(self, message) LOGGER.info(message.to_text()) disable_busy_cursor() self.set_enabled_buttons(True) return error_code, message else: LOGGER.info( 'Reports are not generated because of your settings.') display_warning_message_bar( tr('Reports'), tr('Reports are not going to be generated because of your ' 'InaSAFE settings.'), duration=10, iface_object=self.iface) # If zoom to impact is enabled if setting('setZoomToImpactFlag', expected_type=bool): self.iface.zoomToActiveLayer() # If hide exposure layers if setting('setHideExposureFlag', expected_type=bool): treeroot = QgsProject.instance().layerTreeRoot() for combo in list(self.combos_exposures.values()): layer = layer_from_combo(combo) if layer is not None: treelayer = treeroot.findLayer(layer.id()) if treelayer: treelayer.setItemVisibilityChecked(False) # Set last analysis extent self._extent.set_last_analysis_extent( self._multi_exposure_if.analysis_extent, self._multi_exposure_if.crs) self.done(QDialog.Accepted) except Exception as e: error_message = get_error_message(e) send_error_message(self, error_message) LOGGER.exception(e) LOGGER.debug(error_message.to_text()) finally: disable_busy_cursor() self.set_enabled_buttons(True)