Пример #1
0
    def accept(self):
        """Method invoked when OK button is clicked."""

        self.save_state()
        self.dock.show_busy()

        # The order of the components are matter.
        components = self.prepare_components()
        error_code, message = self.impact_function.generate_report(
            components, iface=self.iface)

        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.dock.hide_busy()
            LOGGER.info(tr('The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.info(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        sender_name = self.sender().objectName()

        try:
            if sender_name == 'button_print_pdf':
                self.create_pdf = True
                self.open_as_pdf()
            else:
                self.create_pdf = False
                self.open_in_composer()
            self.dock.hide_busy()
        except Exception:
            self.dock.hide_busy()

        QtWidgets.QDialog.accept(self)
Пример #2
0
    def accept(self):
        """Method invoked when OK button is clicked."""

        self.save_state()
        self.dock.show_busy()

        # The order of the components are matter.
        components = self.prepare_components()
        error_code, message = self.impact_function.generate_report(
            components, iface=self.iface)

        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.dock.hide_busy()
            LOGGER.info(tr(
                'The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.info(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        sender_name = self.sender().objectName()

        try:
            if sender_name == 'button_print_pdf':
                self.create_pdf = True
                self.open_as_pdf()
            else:
                self.create_pdf = False
                self.open_in_composer()
            self.dock.hide_busy()
        except Exception:
            self.dock.hide_busy()

        QtWidgets.QDialog.accept(self)
Пример #3
0
    def analysis_error(self, exception, message):
        """A helper to spawn an error and halt processing.

        An exception will be logged, busy status removed and a message
        displayed.

        .. note:: Copied from the dock

        :param message: an ErrorMessage to display
        :type message: ErrorMessage, Message

        :param exception: An exception that was raised
        :type exception: Exception
        """
        self.hide_busy()
        LOGGER.exception(message)
        message = get_error_message(exception, context=message)
        send_error_message(self, message)
        self.analysisDone.emit(False)
Пример #4
0
    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
Пример #5
0
    def analysis_error(self, exception, message):
        """A helper to spawn an error and halt processing.

        An exception will be logged, busy status removed and a message
        displayed.

        .. note:: Copied from the dock

        :param message: an ErrorMessage to display
        :type message: ErrorMessage, Message

        :param exception: An exception that was raised
        :type exception: Exception
        """
        self.hide_busy()
        LOGGER.exception(message)
        message = get_error_message(exception, context=message)
        send_error_message(self, message)
        self.analysisDone.emit(False)
Пример #6
0
    def print_map_to_pdf(self, impact_report):
        """Print map to PDF given MapReport instance.

        :param impact_report: Impact Report instance that is ready to print
        :type impact_report: ImpactReport
        """
        impact_report.setup_composition()

        # Get Filename
        map_title = impact_report.map_title
        if map_title is not None:
            default_file_name = map_title + '.pdf'
            default_file_name = default_file_name.replace(' ', '_')
        else:
            send_error_message(
                self, self.tr('Keyword "map_title" not found.'))
            return

        # Get output path
        # noinspection PyCallByClass,PyTypeChecker
        output_path = QtGui.QFileDialog.getSaveFileName(
            self.parent,
            self.tr('Write to PDF'),
            os.path.join(temp_dir(), default_file_name),
            self.tr('Pdf File (*.pdf)'))
        output_path = str(output_path)

        if output_path is None or output_path == '':
            # noinspection PyTypeChecker
            self.show_dynamic_message(
                self,
                m.Message(
                    m.Heading(self.tr('Map Creator'), **WARNING_STYLE),
                    m.Text(self.tr('Printing cancelled!'))))
            return

        try:
            map_pdf_path, table_pdf_path = impact_report.print_to_pdf(
                output_path)

            # Make sure the file paths can wrap nicely:
            wrapped_map_path = map_pdf_path.replace(os.sep, '<wbr>' + os.sep)
            wrapped_table_path = table_pdf_path.replace(
                os.sep, '<wbr>' + os.sep)
            status = m.Message(
                m.Heading(self.tr('Map Creator'), **INFO_STYLE),
                m.Paragraph(self.tr('Your PDF was created....')),
                m.Paragraph(self.tr(
                    'Opening using the default PDF viewer on your system. '
                    'The generated pdfs were saved as:')),
                m.Paragraph(wrapped_map_path),
                m.Paragraph(self.tr('and')),
                m.Paragraph(wrapped_table_path))

            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(table_pdf_path))
            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(map_pdf_path))

            # noinspection PyTypeChecker
            self.show_dynamic_message(self, status)
        except TemplateLoadingError, e:
            send_error_message(self, get_error_message(e))
Пример #7
0
                m.Paragraph(self.tr('and')),
                m.Paragraph(wrapped_table_path))

            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(table_pdf_path))
            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(map_pdf_path))

            # noinspection PyTypeChecker
            self.show_dynamic_message(self, status)
        except TemplateLoadingError, e:
            send_error_message(self, get_error_message(e))
        except Exception, e:  # pylint: disable=broad-except
            send_error_message(self, get_error_message(e))

    def open_map_in_composer(self, impact_report):
        """Open map in composer given MapReport instance.

        ..note:: (AG) See https://github.com/AIFDR/inasafe/issues/911. We
            need to set the composition to the composer before loading the
            template.

        :param impact_report: Impact Report to be opened in composer.
        :type impact_report: ImpactReport
        """
        impact_report.setup_composition()
        self.composer = self.iface.createNewComposer()
        self.composer.setComposition(impact_report.composition)
        impact_report.load_template()
Пример #8
0
    def run_task(self, task_item, status_item, count=0, index=''):
        """Run a single task.

        :param task_item: Table task_item containing task name / details.
        :type task_item: QTableWidgetItem

        :param status_item: Table task_item that holds the task status.
        :type status_item: QTableWidgetItem

        :param count: Count of scenarios that have been run already.
        :type count:

        :param index: The index for the table item that will be run.
        :type index: int

        :returns: Flag indicating if the task succeeded or not.
        :rtype: bool
        """
        self.enable_busy_cursor()
        for layer_group in self.layer_group_container:
            layer_group.setVisible(False)

        # set status to 'running'
        status_item.setText(self.tr('Running'))

        # .. see also:: :func:`appendRow` to understand the next 2 lines
        variant = task_item.data(QtCore.Qt.UserRole)
        value = variant[0]
        result = True

        if isinstance(value, str):
            filename = value
            # run script
            try:
                self.run_script(filename)
                # set status to 'OK'
                status_item.setText(self.tr('Script OK'))
            except Exception as e:  # pylint: disable=W0703
                # set status to 'fail'
                status_item.setText(self.tr('Script Fail'))

                LOGGER.exception('Running macro failed. The exception: ' +
                    str(e))
                result = False
        elif isinstance(value, dict):
            # start in new project if toggle is active
            if self.start_in_new_project:
                self.iface.newProject()
            # create layer group
            group_name = value['scenario_name']
            self.layer_group = self.root.addGroup(group_name)
            self.layer_group_container.append(self.layer_group)

            # Its a dict containing files for a scenario
            success, parameters = self.prepare_task(value)
            if not success:
                # set status to 'running'
                status_item.setText(self.tr('Please update scenario'))
                self.disable_busy_cursor()
                return False
            # If impact function parameters loaded successfully, initiate IF.
            impact_function = ImpactFunction()
            impact_function.hazard = parameters[layer_purpose_hazard['key']]
            impact_function.exposure = (
                parameters[layer_purpose_exposure['key']])
            if parameters[layer_purpose_aggregation['key']]:
                impact_function.aggregation = (
                    parameters[layer_purpose_aggregation['key']])
            elif parameters['extent']:
                impact_function.requested_extent = parameters['extent']
                impact_function.requested_extent_crs = parameters['crs']
            prepare_status, prepare_message = impact_function.prepare()
            if prepare_status == PREPARE_SUCCESS:
                LOGGER.info('Impact function ready')
                status, message = impact_function.run()
                if status == ANALYSIS_SUCCESS:
                    status_item.setText(self.tr('Analysis Success'))
                    impact_layer = impact_function.impact
                    if impact_layer.isValid():
                        layer_list = [
                            impact_layer,
                            parameters[layer_purpose_hazard['key']],
                            parameters[layer_purpose_exposure['key']],
                            parameters[layer_purpose_aggregation['key']]]
                        QgsMapLayerRegistry.instance().addMapLayers(
                            layer_list, False)
                        for layer in layer_list:
                            self.layer_group.addLayer(layer)
                        map_canvas = QgsMapLayerRegistry.instance().mapLayers()
                        for layer in map_canvas:
                            # turn of layer visibility if not impact layer
                            if map_canvas[layer].id() == impact_layer.id():
                                self.legend.setLayerVisible(
                                    map_canvas[layer], True)
                            else:
                                self.legend.setLayerVisible(
                                    map_canvas[layer], False)

                        # generate map report and impact report
                        try:
                            # this line is to save the impact report in default
                            # InaSAFE directory.
                            generate_impact_report(impact_function, self.iface)
                            generate_impact_map_report(
                                impact_function,
                                self.iface)
                            # this line is to save the report in user specified
                            # directory.
                            self.generate_pdf_report(
                                impact_function,
                                self.iface,
                                group_name)
                        except:
                            status_item.setText(
                                self.tr('Report failed to generate.'))
                    else:
                        LOGGER.info('Impact layer is invalid')

                elif status == ANALYSIS_FAILED_BAD_INPUT:
                    LOGGER.info('Bad input detected')

                elif status == ANALYSIS_FAILED_BAD_CODE:
                    LOGGER.info('Impact function encountered a bug')

            else:
                LOGGER.warning('Impact function not ready')
                send_error_message(self, prepare_message)

        else:
            LOGGER.exception('Data type not supported: "%s"' % value)
            result = False

        self.disable_busy_cursor()
        return result
Пример #9
0
    def run_task(self, task_item, status_item, count=0, index=''):
        """Run a single task.

        :param task_item: Table task_item containing task name / details.
        :type task_item: QTableWidgetItem

        :param status_item: Table task_item that holds the task status.
        :type status_item: QTableWidgetItem

        :param count: Count of scenarios that have been run already.
        :type count:

        :param index: The index for the table item that will be run.
        :type index: int

        :returns: Flag indicating if the task succeeded or not.
        :rtype: bool
        """
        self.enable_busy_cursor()
        for layer_group in self.layer_group_container:
            layer_group.setItemVisibilityChecked(False)

        # set status to 'running'
        status_item.setText(self.tr('Running'))

        # .. see also:: :func:`appendRow` to understand the next 2 lines
        variant = task_item.data(QtCore.Qt.UserRole)
        value = variant[0]
        result = True

        if isinstance(value, str):
            filename = value
            # run script
            try:
                self.run_script(filename)
                # set status to 'OK'
                status_item.setText(self.tr('Script OK'))
            except Exception as e:  # pylint: disable=W0703
                # set status to 'fail'
                status_item.setText(self.tr('Script Fail'))

                LOGGER.exception(
                    'Running macro failed. The exception: ' + str(e))
                result = False
        elif isinstance(value, dict):
            # start in new project if toggle is active
            if self.start_in_new_project:
                self.iface.newProject()
            # create layer group
            group_name = value['scenario_name']
            self.layer_group = self.root.addGroup(group_name)
            self.layer_group_container.append(self.layer_group)

            # Its a dict containing files for a scenario
            success, parameters = self.prepare_task(value)
            if not success:
                # set status to 'running'
                status_item.setText(self.tr('Please update scenario'))
                self.disable_busy_cursor()
                return False

            directory = self.output_directory.text()
            if self.scenario_directory_radio.isChecked():
                directory = self.source_directory.text()

            output_directory = os.path.join(directory, group_name)
            if not os.path.exists(output_directory):
                os.makedirs(output_directory)

            # If impact function parameters loaded successfully, initiate IF.
            impact_function = ImpactFunction()
            impact_function.datastore = Folder(output_directory)
            impact_function.datastore.default_vector_format = "geojson"
            impact_function.hazard = parameters[layer_purpose_hazard['key']]
            impact_function.exposure = (
                parameters[layer_purpose_exposure['key']])
            if parameters[layer_purpose_aggregation['key']]:
                impact_function.aggregation = (
                    parameters[layer_purpose_aggregation['key']])
            elif parameters['extent']:
                impact_function.requested_extent = parameters['extent']
                impact_function.crs = parameters['crs']
            prepare_status, prepare_message = impact_function.prepare()
            if prepare_status == PREPARE_SUCCESS:
                LOGGER.info('Impact function ready')
                status, message = impact_function.run()
                if status == ANALYSIS_SUCCESS:
                    status_item.setText(self.tr('Analysis Success'))
                    impact_layer = impact_function.impact
                    if impact_layer.isValid():
                        layer_list = [
                            impact_layer,
                            impact_function.analysis_impacted,
                            parameters[layer_purpose_hazard['key']],
                            parameters[layer_purpose_exposure['key']],
                            parameters[layer_purpose_aggregation['key']]]
                        QgsProject.instance().addMapLayers(
                            layer_list, False)
                        for layer in layer_list:
                            self.layer_group.addLayer(layer)
                        map_canvas = QgsProject.instance().mapLayers()
                        for layer in map_canvas:
                            # turn of layer visibility if not impact layer
                            if map_canvas[layer].id() == impact_layer.id():
                                self.set_layer_visible(
                                    map_canvas[layer], True)
                            else:
                                self.set_layer_visible(
                                    map_canvas[layer], False)

                        # we need to set analysis_impacted as an active layer
                        # because we need to get all qgis variables that we
                        # need from this layer for infographic.
                        if self.iface:
                            self.iface.setActiveLayer(
                                impact_function.analysis_impacted)

                        report_directory = os.path.join(
                            output_directory, 'output')

                        # generate map report and impact report
                        try:
                            error_code, message = (
                                impact_function.generate_report(
                                    all_default_report_components,
                                    report_directory))

                        except BaseException:
                            status_item.setText(
                                self.tr('Report failed to generate.'))
                    else:
                        LOGGER.info('Impact layer is invalid')

                elif status == ANALYSIS_FAILED_BAD_INPUT:
                    LOGGER.info('Bad input detected')

                elif status == ANALYSIS_FAILED_BAD_CODE:
                    LOGGER.info(
                        'Impact function encountered a bug: %s' % message)

            else:
                LOGGER.warning('Impact function not ready')
                send_error_message(self, prepare_message)

        else:
            LOGGER.exception('Data type not supported: "%s"' % value)
            result = False

        self.disable_busy_cursor()
        return result
Пример #10
0
    def setup_and_run_analysis(self):
        """Execute analysis after the tab is displayed.

        Please check the code in dock.py accept(). It should follow
        approximately the same code.
        """
        self.show_busy()
        # Read user's settings
        self.read_settings()
        # Prepare impact function from wizard dialog user input
        self.impact_function = self.prepare_impact_function()

        # Prepare impact function
        status, message = self.impact_function.prepare()
        # Check status
        if status == PREPARE_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.info(tr(
                'The impact function will not be able to run because of the '
                'inputs.'))
            LOGGER.info(message.to_text())
            send_error_message(self, message)
            return status, message
        if status == PREPARE_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.exception(tr(
                'The impact function was not able to be prepared because of a '
                'bug.'))
            LOGGER.info(message.to_text())
            send_error_message(self, message)
            return status, message

        # Start the analysis
        status, message = self.impact_function.run()
        # Check status
        if status == ANALYSIS_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.info(tr(
                'The impact function could not run because of the inputs.'))
            LOGGER.info(message.to_text())
            send_error_message(self, message)
            return status, message
        elif status == ANALYSIS_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.exception(tr(
                'The impact function could not run because of a bug.'))
            LOGGER.exception(message.to_text())
            send_error_message(self, message)
            return status, message

        LOGGER.info(tr('The impact function could run without errors.'))

        # Add result layer to QGIS
        add_impact_layers_to_canvas(self.impact_function, self.parent.iface)

        # Some if-s i.e. zoom, debug, hide exposure
        if self.zoom_to_impact_flag:
            self.iface.zoomToActiveLayer()

        qgis_exposure = (
            QgsMapLayerRegistry.instance().mapLayer(
                self.parent.exposure_layer.id()))
        if self.hide_exposure_flag:
            legend = self.iface.legendInterface()
            legend.setLayerVisible(qgis_exposure, False)

        # Generate impact report
        error_code, message = generate_impact_report(
            self.impact_function, self.parent.iface)

        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.hide_busy()
            LOGGER.info(tr(
                'The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.info(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        # Generate Impact Map Report
        error_code, message = generate_impact_map_report(
            self.impact_function, self.iface)

        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.hide_busy()
            LOGGER.info(tr(
                'The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.info(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        self.extent.set_last_analysis_extent(
            self.impact_function.analysis_extent,
            qgis_exposure.crs())

        # Hide busy
        self.hide_busy()
        # Setup gui if analysis is done
        self.setup_gui_analysis_done()
        return ANALYSIS_SUCCESS, None
Пример #11
0
    def setup_and_run_analysis(self):
        """Execute analysis after the tab is displayed.

        Please check the code in dock.py accept(). It should follow
        approximately the same code.
        """
        self.show_busy()
        # Read user's settings
        self.read_settings()
        # Prepare impact function from wizard dialog user input
        self.impact_function = self.prepare_impact_function()

        # Prepare impact function
        status, message = self.impact_function.prepare()
        # Check status
        if status == PREPARE_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.info(
                tr('The impact function will not be able to run because of the '
                   'inputs.'))
            LOGGER.info(message.to_text())
            send_error_message(self, message)
            return status, message
        if status == PREPARE_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.exception(
                tr('The impact function was not able to be prepared because of a '
                   'bug.'))
            LOGGER.info(message.to_text())
            send_error_message(self, message)
            return status, message

        # Start the analysis
        status, message = self.impact_function.run()
        # Check status
        if status == ANALYSIS_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.info(
                tr('The impact function could not run because of the inputs.'))
            LOGGER.info(message.to_text())
            send_error_message(self, message)
            return status, message
        elif status == ANALYSIS_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.exception(
                tr('The impact function could not run because of a bug.'))
            LOGGER.exception(message.to_text())
            send_error_message(self, message)
            return status, message

        LOGGER.info(tr('The impact function could run without errors.'))

        # Add result layer to QGIS
        add_impact_layers_to_canvas(self.impact_function, self.parent.iface)

        # Some if-s i.e. zoom, debug, hide exposure
        if self.zoom_to_impact_flag:
            self.iface.zoomToActiveLayer()

        qgis_exposure = (QgsMapLayerRegistry.instance().mapLayer(
            self.parent.exposure_layer.id()))
        if self.hide_exposure_flag:
            legend = self.iface.legendInterface()
            legend.setLayerVisible(qgis_exposure, False)

        # Generate impact report
        error_code, message = generate_impact_report(self.impact_function,
                                                     self.parent.iface)

        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.hide_busy()
            LOGGER.info(tr('The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.info(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        # Generate Impact Map Report
        error_code, message = generate_impact_map_report(
            self.impact_function, self.iface)

        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.hide_busy()
            LOGGER.info(tr('The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.info(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        self.extent.set_last_analysis_extent(
            self.impact_function.analysis_extent, qgis_exposure.crs())

        # Hide busy
        self.hide_busy()
        # Setup gui if analysis is done
        self.setup_gui_analysis_done()
        return ANALYSIS_SUCCESS, None
Пример #12
0
    def setup_and_run_analysis(self):
        """Execute analysis after the tab is displayed.

        Please check the code in dock.py accept(). It should follow
        approximately the same code.
        """
        self.show_busy()
        # Read user's settings
        self.read_settings()
        # Prepare impact function from wizard dialog user input
        self.impact_function = self.prepare_impact_function()

        # Prepare impact function
        status, message = self.impact_function.prepare()
        message = basestring_to_message(message)
        # Check status
        if status == PREPARE_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.warning(
                tr('The impact function will not be able to run because of the '
                   'inputs.'))
            LOGGER.warning(message.to_text())
            send_error_message(self, message)
            return status, message
        if status == PREPARE_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.warning(
                tr('The impact function was not able to be prepared because of a '
                   'bug.'))
            LOGGER.exception(message.to_text())
            send_error_message(self, message)
            return status, message

        # Start the analysis
        status, message = self.impact_function.run()
        message = basestring_to_message(message)
        # Check status
        if status == ANALYSIS_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.warning(
                tr('The impact function could not run because of the inputs.'))
            LOGGER.warning(message.to_text())
            send_error_message(self, message)
            return status, message
        elif status == ANALYSIS_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.warning(
                tr('The impact function could not run because of a bug.'))
            LOGGER.exception(message.to_text())
            send_error_message(self, message)
            return status, message

        LOGGER.info(tr('The impact function could run without errors.'))

        # Add result layer to QGIS
        add_impact_layers_to_canvas(self.impact_function,
                                    iface=self.parent.iface)

        # Some if-s i.e. zoom, debug, hide exposure
        if self.zoom_to_impact_flag:
            self.iface.zoomToActiveLayer()

        qgis_exposure = (QgsProject.instance().mapLayer(
            self.parent.exposure_layer.id()))
        if self.hide_exposure_flag and qgis_exposure is not None:
            treeroot = QgsProject.instance().layerTreeRoot()
            treelayer = treeroot.findLayer(qgis_exposure.id())
            if treelayer:
                treelayer.setItemVisibilityChecked(False)

        # we only want to generate non pdf/qpt report
        html_components = [standard_impact_report_metadata_html]
        error_code, message = self.impact_function.generate_report(
            html_components)
        message = basestring_to_message(message)
        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.hide_busy()
            LOGGER.info(tr('The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.exception(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        self.extent.set_last_analysis_extent(
            self.impact_function.analysis_extent, qgis_exposure.crs())

        # Hide busy
        self.hide_busy()
        # Setup gui if analysis is done
        self.setup_gui_analysis_done()
        return ANALYSIS_SUCCESS, None
Пример #13
0
    def setup_and_run_analysis(self):
        """Execute analysis after the tab is displayed.

        Please check the code in dock.py accept(). It should follow
        approximately the same code.
        """
        self.show_busy()
        # Read user's settings
        self.read_settings()
        # Prepare impact function from wizard dialog user input
        self.impact_function = self.prepare_impact_function()

        # Prepare impact function
        status, message = self.impact_function.prepare()
        message = basestring_to_message(message)
        # Check status
        if status == PREPARE_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.warning(tr(
                'The impact function will not be able to run because of the '
                'inputs.'))
            LOGGER.warning(message.to_text())
            send_error_message(self, message)
            return status, message
        if status == PREPARE_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.warning(tr(
                'The impact function was not able to be prepared because of a '
                'bug.'))
            LOGGER.exception(message.to_text())
            send_error_message(self, message)
            return status, message

        # Start the analysis
        status, message = self.impact_function.run()
        message = basestring_to_message(message)
        # Check status
        if status == ANALYSIS_FAILED_BAD_INPUT:
            self.hide_busy()
            LOGGER.warning(tr(
                'The impact function could not run because of the inputs.'))
            LOGGER.warning(message.to_text())
            send_error_message(self, message)
            return status, message
        elif status == ANALYSIS_FAILED_BAD_CODE:
            self.hide_busy()
            LOGGER.warning(tr(
                'The impact function could not run because of a bug.'))
            LOGGER.exception(message.to_text())
            send_error_message(self, message)
            return status, message

        LOGGER.info(tr('The impact function could run without errors.'))

        # Add result layer to QGIS
        add_impact_layers_to_canvas(
            self.impact_function, iface=self.parent.iface)

        # Some if-s i.e. zoom, debug, hide exposure
        if self.zoom_to_impact_flag:
            self.iface.zoomToActiveLayer()

        qgis_exposure = (
            QgsProject.instance().mapLayer(
                self.parent.exposure_layer.id()))
        if self.hide_exposure_flag and qgis_exposure is not None:
            treeroot = QgsProject.instance().layerTreeRoot()
            treelayer = treeroot.findLayer(qgis_exposure.id())
            if treelayer:
                treelayer.setItemVisibilityChecked(False)

        # we only want to generate non pdf/qpt report
        html_components = [standard_impact_report_metadata_html]
        error_code, message = self.impact_function.generate_report(
            html_components)
        message = basestring_to_message(message)
        if error_code == ImpactReport.REPORT_GENERATION_FAILED:
            self.hide_busy()
            LOGGER.info(tr(
                'The impact report could not be generated.'))
            send_error_message(self, message)
            LOGGER.exception(message.to_text())
            return ANALYSIS_FAILED_BAD_CODE, message

        self.extent.set_last_analysis_extent(
            self.impact_function.analysis_extent,
            qgis_exposure.crs())

        # Hide busy
        self.hide_busy()
        # Setup gui if analysis is done
        self.setup_gui_analysis_done()
        return ANALYSIS_SUCCESS, None
Пример #14
0
    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)
Пример #15
0
    def print_map_to_pdf(self, impact_report):
        """Print map to PDF given MapReport instance.

        :param impact_report: Impact Report instance that is ready to print
        :type impact_report: ImpactReport
        """
        impact_report.setup_composition()

        # Get Filename
        map_title = impact_report.map_title
        if map_title is not None:
            default_file_name = map_title + '.pdf'
            default_file_name = default_file_name.replace(' ', '_')
        else:
            send_error_message(
                self, self.tr('Keyword "map_title" not found.'))
            return

        # Get output path
        # noinspection PyCallByClass,PyTypeChecker
        output_path = QtGui.QFileDialog.getSaveFileName(
            self.parent,
            self.tr('Write to PDF'),
            os.path.join(temp_dir(), default_file_name),
            self.tr('Pdf File (*.pdf)'))
        output_path = str(output_path)

        if output_path is None or output_path == '':
            # noinspection PyTypeChecker
            self.show_dynamic_message(
                self,
                m.Message(
                    m.Heading(self.tr('Map Creator'), **WARNING_STYLE),
                    m.Text(self.tr('Printing cancelled!'))))
            return

        try:
            map_pdf_path, table_pdf_path = impact_report.print_to_pdf(
                output_path)

            # Make sure the file paths can wrap nicely:
            wrapped_map_path = map_pdf_path.replace(os.sep, '<wbr>' + os.sep)
            wrapped_table_path = table_pdf_path.replace(
                os.sep, '<wbr>' + os.sep)
            status = m.Message(
                m.Heading(self.tr('Map Creator'), **INFO_STYLE),
                m.Paragraph(self.tr('Your PDF was created....')),
                m.Paragraph(self.tr(
                    'Opening using the default PDF viewer on your system. '
                    'The generated pdfs were saved as:')),
                m.Paragraph(wrapped_map_path),
                m.Paragraph(self.tr('and')),
                m.Paragraph(wrapped_table_path))

            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(table_pdf_path))
            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(map_pdf_path))

            # noinspection PyTypeChecker
            self.show_dynamic_message(self, status)
        except TemplateLoadingError, e:
            send_error_message(self, get_error_message(e))
Пример #16
0
                m.Paragraph(self.tr('and')),
                m.Paragraph(wrapped_table_path))

            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(table_pdf_path))
            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            QtGui.QDesktopServices.openUrl(
                QtCore.QUrl.fromLocalFile(map_pdf_path))

            # noinspection PyTypeChecker
            self.show_dynamic_message(self, status)
        except TemplateLoadingError, e:
            send_error_message(self, get_error_message(e))
        except Exception, e:  # pylint: disable=broad-except
            send_error_message(self, get_error_message(e))

    def open_map_in_composer(self, impact_report):
        """Open map in composer given MapReport instance.

        ..note:: (AG) See https://github.com/AIFDR/inasafe/issues/911. We
            need to set the composition to the composer before loading the
            template.

        :param impact_report: Impact Report to be opened in composer.
        :type impact_report: ImpactReport
        """
        impact_report.setup_composition()
        self.composer = self.iface.createNewComposer()
        self.composer.setComposition(impact_report.composition)
        impact_report.load_template()