def call_changes_per_parcel_panel(self, item):
        with OverrideCursor(Qt.WaitCursor):

            inverse = item.data(Qt.UserRole)['inverse']
            base_db = self.utils._supplies_db if inverse else self.utils._db
            parcel_number = self.tbl_changes_all_parcels.item(item.row(),
                                                              0).text()

            # Obtain t_ids from parcels with NULL or duplicated parcel_number, before calling the per_parcel_panel
            parcels_t_ids = list()
            if parcel_number == QgsApplication.nullRepresentation(
            ):  # TODO: does it make sense if the NULL parcels is only one?
                parcels_t_ids = self.compared_parcels_data[NULL][
                    base_db.names.T_ID_F]
            elif parcel_number in self.compared_parcels_data and self.compared_parcels_data[
                    parcel_number][
                        PARCEL_STATUS] == CHANGE_DETECTION_SEVERAL_PARCELS:
                parcels_t_ids = self.compared_parcels_data[parcel_number][
                    base_db.names.T_ID_F]

        if parcels_t_ids:
            dlg_select_parcel = SelectDuplicateParcelDialog(
                self.utils, parcels_t_ids, self.parent)
            dlg_select_parcel.exec_()

            if dlg_select_parcel.parcel_t_id:  # User selected one of the duplicated parcels
                self.changes_per_parcel_panel_requested.emit(
                    dlg_select_parcel.parcel_number,
                    dlg_select_parcel.parcel_t_id)
        else:
            self.changes_per_parcel_panel_requested.emit(
                parcel_number,
                '')  # 2nd parameter is mandatory for the signal :)
Esempio n. 2
0
    def add_format_to_text(self, rule, layers, options):
        """
        Decorator used for registering log quality info
        :param self: QualityRuleEngine instance
        :param rule: Quality rule instance
        :param layers: layers
        :param options: Options for the quality rule
        """
        self.qr_logger.set_initial_progress_emitted.emit(rule.name())
        log_text_content = LOG_QUALITY_LIST_CONTAINER_OPEN

        start_time = time.time()
        with OverrideCursor(Qt.WaitCursor):
            qr_result = func_to_decorate(self, rule, layers, options)
        end_time = time.time()

        if qr_result.level == EnumQualityRuleResult.ERRORS:
            prefix = LOG_QUALITY_LIST_ITEM_ERROR_OPEN
            suffix = LOG_QUALITY_LIST_ITEM_ERROR_CLOSE
        elif qr_result.level == EnumQualityRuleResult.SUCCESS:
            prefix = LOG_QUALITY_LIST_ITEM_SUCCESS_OPEN
            suffix = LOG_QUALITY_LIST_ITEM_SUCCESS_CLOSE
        elif qr_result.level == EnumQualityRuleResult.CRITICAL:
            prefix = LOG_QUALITY_LIST_ITEM_CRITICAL_OPEN
            suffix = LOG_QUALITY_LIST_ITEM_CRITICAL_CLOSE
        else:  # EnumQualityRuleResult.UNDEFINED
            prefix = LOG_QUALITY_LIST_ITEM_OPEN
            suffix = LOG_QUALITY_LIST_ITEM_CLOSE

        log_text_content += "{}{}{}".format(prefix, qr_result.msg, suffix)

        self.qr_logger.log_total_time = self.qr_logger.log_total_time + (
            end_time - start_time)

        log_text_content += LOG_QUALITY_LIST_CONTAINER_CLOSE
        log_text_content += LOG_QUALITY_CONTENT_SEPARATOR

        self.qr_logger.log_text += "{}{} [{}]{}".format(
            LOG_QUALITY_PREFIX_TOPOLOGICAL_RULE_TITLE, rule.name(),
            Utils().set_time_format(end_time - start_time),
            LOG_QUALITY_SUFFIX_TOPOLOGICAL_RULE_TITLE)

        if options:
            # Try to get option titles instead of keys
            option_texts = list()
            for k, v in options.items():
                obj = rule.options.get_options().get(k, None)
                option_texts.append("{}: {}".format(obj.title() if obj else k,
                                                    v))

            self.qr_logger.log_text += "{}{} {}{}".format(
                LOG_QUALITY_OPTIONS_OPEN,
                QCoreApplication.translate("QualityRules", "(Options)"),
                "; ".join(option_texts), LOG_QUALITY_OPTIONS_CLOSE)

        self.qr_logger.log_text += log_text_content

        self.qr_logger.set_final_progress_emitted.emit(rule.name())

        return qr_result
Esempio n. 3
0
    def show_split_data_for_receivers_panel(self):
        with OverrideCursor(Qt.WaitCursor):
            self._reset_split_data_for_receivers_panel_vars()

            self.split_data_for_receivers_panel = self._get_split_data_for_receivers_panel()
            self.split_data_for_receivers_panel.refresh_parcel_data_clear_selection_requested.connect(
                self.allocate_panel.panel_accepted_refresh_and_clear_selection)
            self.widget.showPanel(self.split_data_for_receivers_panel)
            self.lst_split_data_for_receivers_panel.append(self.split_data_for_receivers_panel)
Esempio n. 4
0
    def show_configure_receivers_panel(self):
        with OverrideCursor(Qt.WaitCursor):
            self.__reset_receivers_panel_vars()

            self.configure_receivers_panel = self._get_receivers_panel()
            self.configure_receivers_panel.clear_message_bar_requested.connect(
                self.allocate_panel.panel_accepted_clear_message_bar)
            self.widget.showPanel(self.configure_receivers_panel)
            self.lst_configure_receivers_panel.append(self.configure_receivers_panel)
Esempio n. 5
0
    def show_allocate_parcels_to_receiver_panel(self, selected_parcels):
        with OverrideCursor(Qt.WaitCursor):
            self._reset_allocate_parcels_to_receiver_panel_vars()

            self.allocate_parcels_to_receiver_panel = self._get_allocate_to_receiver_panel(selected_parcels)
            self.allocate_parcels_to_receiver_panel.refresh_parcel_data_requested.connect(
                self.allocate_panel.panel_accepted_refresh_parcel_data)
            self.widget.showPanel(self.allocate_parcels_to_receiver_panel)
            self.lst_allocate_parcels_to_receiver_panel.append(self.allocate_parcels_to_receiver_panel)
Esempio n. 6
0
    def _search_data_by_plot(self, plot_feature):
        plot_t_id = plot_feature[self._controller.t_id_name()]
        self.app.gui.flash_features(self._controller.plot_layer(),
                                    [plot_feature.id()])

        with OverrideCursor(Qt.WaitCursor):
            if not self.isVisible():
                self.show()

            self._search_data_by_component(plot_t_ids=[plot_t_id],
                                           zoom_and_select=False)
            self._controller.plot_layer().selectByIds([plot_feature.id()])
    def show_error_results_panel(self):
        with OverrideCursor(Qt.WaitCursor):
            if self.__error_results_panel is not None:
                try:
                    self.widget.closePanel(self.__error_results_panel)
                except RuntimeError as e:  # Panel in C++ could be already closed...
                    pass

                self.__error_results_panel = None

            self.__error_results_panel = QualityRulesErrorResultsPanelWidget(self.__controller, self)
            self.__error_results_panel.panelAccepted.connect(self.__controller.reset_vars_for_error_results_panel)
            self.widget.showPanel(self.__error_results_panel)
Esempio n. 8
0
        def features_added(layer_id, features):
            modified_layer = QgsProject.instance().mapLayer(layer_id)
            if modified_layer is None or QgsDataSourceUri(
                    modified_layer.source()).table().lower() != layer.name(
                    ).lower():
                return

            with OverrideCursor(Qt.WaitCursor):
                new_values = self.upload_files(modified_layer, field_index,
                                               features)

            if new_values:
                modified_layer.dataProvider().changeAttributeValues(new_values)
Esempio n. 9
0
    def show_task_panel(self, task_id):
        with OverrideCursor(Qt.WaitCursor):
            if self.task_panel is not None:
                try:
                    self.widget.closePanel(self.task_panel)
                except RuntimeError as e:  # Panel in C++ could be already closed...
                    pass

                self.task_panel = None

            self.task_panel = TaskPanelWidget(task_id, self)
            self.task_panel.trigger_action_emitted.connect(self.trigger_action_emitted)
            self.task_panel.panelAccepted.connect(self.reload_tasks)
            self.widget.showPanel(self.task_panel)
Esempio n. 10
0
    def get_info_by_plot(self, plot_feature):
        plot_t_id = plot_feature[ID_FIELD]
        self.canvas.flashFeatureIds(self._plot_layer, [plot_feature.id()],
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)

        with OverrideCursor(Qt.WaitCursor):
            self._plot_layer.selectByIds([plot_feature.id()])
            if not self.isVisible():
                self.show()

            self.search_data_by_component(plot_t_id=plot_t_id)
    def show_all_parcels_panel(self, dict_parcels, types_change_detection):
        with OverrideCursor(Qt.WaitCursor):
            if self.lst_all_parcels_panels:
                for panel in self.lst_all_parcels_panels:
                    try:
                        self.widget.closePanel(panel)
                    except RuntimeError as e:  # Panel in C++ could be already closed...
                        pass

                self.lst_all_parcels_panels = list()
                self.all_parcels_panel = None

            self.all_parcels_panel = ChangesAllParcelsPanelWidget(self, self.utils, dict_parcels, types_change_detection)
            self.all_parcels_panel.changes_per_parcel_panel_requested.connect(self.show_parcel_panel)
            self.widget.showPanel(self.all_parcels_panel)
            self.lst_all_parcels_panels.append(self.all_parcels_panel)
    def get_info_by_plot(self, plot_feature):
        plot_t_id = plot_feature[self.names.T_ID_F]
        self.canvas.flashFeatureIds(self._layers[self.names.OP_PLOT_T][LAYER],
                                    [plot_feature.id()],
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)

        with OverrideCursor(Qt.WaitCursor):
            if not self.isVisible():
                self.show()

            self.search_data_by_component(plot_t_id=plot_t_id,
                                          zoom_and_select=False)
            self._layers[self.names.OP_PLOT_T][LAYER].selectByIds(
                [plot_feature.id()])
        def features_added(layer_id, features):
            modified_layer = QgsProject.instance().mapLayer(layer_id)

            if modified_layer is None:
                return

            modified_layer_name = db.get_ladm_layer_name(modified_layer, validate_is_ladm=True)
            if modified_layer_name is None:
                return

            if modified_layer_name.lower() != layer_name.lower():
                return

            with OverrideCursor(Qt.WaitCursor):
                new_values = self.upload_files(modified_layer, field_index, features)

            if new_values:
                modified_layer.dataProvider().changeAttributeValues(new_values)
    def show_general_results_panel(self, mode):
        """
        :params mode: EnumQualityRulePanelMode
        """
        with OverrideCursor(Qt.WaitCursor):
            self.__delete_general_result_panel()

            self.__general_results_panel = QualityRulesGeneralResultsPanelWidget(self.__controller, mode, self)
            self.__controller.total_progress_changed.connect(self.__general_results_panel.update_total_progress)
            self.__general_results_panel.panelAccepted.connect(self.__controller.reset_vars_for_general_results_panel)
            self.widget.showPanel(self.__general_results_panel)

            if mode == EnumQualityRulePanelMode.VALIDATE:
                self.logger.clear_message_bar()
                res, msg, db_qr = self.__controller.validate_qrs()
                if not res:
                    self.__general_results_panel.unblock_panel()
                    self.widget.acceptAllPanels()  # Go back to initial panel
                    self.logger.warning_msg(__name__, msg)
    def prepare_copy_csv_points_to_db(self):
        csv_path = self.txt_file_path.text().strip()

        if not csv_path or not os.path.exists(csv_path):
            self.logger.warning_msg(__name__, QCoreApplication.translate("WizardTranslations",
                                                                         "No CSV file given or file doesn't exist."))
            return

        target_layer_name = self.current_point_name()

        with OverrideCursor(Qt.WaitCursor):
            csv_layer = self.app.core.csv_to_layer(csv_path,
                                                   self.txt_delimiter.text(),
                                                   self.cbo_longitude.currentText(),
                                                   self.cbo_latitude.currentText(),
                                                   self.crs,
                                                   self.cbo_elevation.currentText() or None,
                                                   self.detect_decimal_point(csv_path))

            self.app.core.copy_csv_to_db(csv_layer, self._db, target_layer_name)
Esempio n. 16
0
    def add_format_to_text(self, rule_key, layers, **args):
        """
        Decorator used for registering log quality info
        :param self: QualityDialog instance
        :param rule_key: rule_key
        :param layers: layers
        :param args: 'rule_name' is the executed quality rule name
        """
        rule_name = args['rule_name']
        self.quality_rule_logger.set_initial_progress_emitted.emit(rule_name)
        log_text_content = LOG_QUALITY_LIST_CONTAINER_OPEN

        start_time = time.time()
        with OverrideCursor(Qt.WaitCursor):
            msg, level = func_to_decorate(self, rule_key, layers, **args)
        end_time = time.time()

        if level == Qgis.Critical:
            prefix = LOG_QUALITY_LIST_ITEM_ERROR_OPEN
            suffix = LOG_QUALITY_LIST_ITEM_ERROR_CLOSE
        elif level == Qgis.Success:
            prefix = LOG_QUALITY_LIST_ITEM_CORRECT_OPEN
            suffix = LOG_QUALITY_LIST_ITEM_CORRECT_CLOSE
        else:  # Qgis.Warning
            prefix = LOG_QUALITY_LIST_ITEM_OPEN
            suffix = LOG_QUALITY_LIST_ITEM_CLOSE
        log_text_content += "{}{}{}".format(prefix, msg, suffix)

        self.quality_rule_logger.log_total_time = self.quality_rule_logger.log_total_time + (
            end_time - start_time)

        log_text_content += LOG_QUALITY_LIST_CONTAINER_CLOSE
        log_text_content += LOG_QUALITY_CONTENT_SEPARATOR

        self.quality_rule_logger.log_text += "{}{} [{}]{}".format(
            LOG_QUALITY_PREFIX_TOPOLOGICAL_RULE_TITLE, rule_name,
            Utils().set_time_format(end_time - start_time),
            LOG_QUALITY_SUFFIX_TOPOLOGICAL_RULE_TITLE)
        self.quality_rule_logger.log_text += log_text_content

        self.quality_rule_logger.set_final_progress_emitted.emit(rule_name)
Esempio n. 17
0
    def add_format_to_text(self, db, **args):
        rule_name = args['rule_name']
        self.log_quality_set_initial_progress_emitted.emit(rule_name)
        self.log_dialog_quality_text_content += LOG_QUALITY_LIST_CONTAINER_OPEN

        start_time = time.time()
        with OverrideCursor(Qt.WaitCursor):
            func_to_decorate(self, db, **args)
        end_time = time.time()

        self.total_time = self.total_time + (end_time - start_time)

        self.log_dialog_quality_text_content += LOG_QUALITY_LIST_CONTAINER_CLOSE
        self.log_dialog_quality_text_content += LOG_QUALITY_CONTENT_SEPARATOR

        self.log_dialog_quality_text += "{}{} [{}]{}".format(LOG_QUALITY_PREFIX_TOPOLOGICAL_RULE_TITLE,
                                                              rule_name, self.utils.set_time_format(end_time - start_time), LOG_QUALITY_SUFFIX_TOPOLOGICAL_RULE_TITLE)
        self.log_dialog_quality_text += self.log_dialog_quality_text_content
        self.log_dialog_quality_text_content = ""

        self.log_quality_set_final_progress_emitted.emit(rule_name)
Esempio n. 18
0
    def accepted(self):
        self.bar.clearWidgets()
        self.save_settings(self.data_system)

        self.folder_path = self.txt_file_path_folder_supplies.text()
        self.file_names = self.txt_file_names_supplies.text().strip()
        self.gpkg_path = os.path.join(self.folder_path,
                                      '{}.gpkg'.format(self.file_names))
        self.xlsx_path = os.path.join(self.folder_path,
                                      '{}.xlsx'.format(self.file_names))

        reply = self.validate_files_in_folder()

        csv_paths = {'PREDIO': self.txt_file_path_predio.text().strip()}

        required_layers = [
            'R_TERRENO', 'U_TERRENO', 'R_VEREDA', 'U_MANZANA',
            'R_CONSTRUCCION', 'U_CONSTRUCCION', 'U_UNIDAD', 'R_UNIDAD'
        ]

        if reply == QMessageBox.Yes:
            with OverrideCursor(Qt.WaitCursor):
                self.set_gui_controls_enabled(False)
                res_csv, msg_csv = self.load_csv_files(csv_paths)
                if res_csv:
                    res_gdb, msg_gdb = self.load_gdb_files(required_layers)
                    if res_gdb:
                        self._running_tool = True
                        res_etl, msg_etl = self.run_model_missing_snc_supplies(
                        )
                        self.progress_base = 100  # We start counting a second step from 100

                        if res_etl:
                            # Since we have two steps, we need to check at this point if the user already canceled
                            if not self.custom_feedback.isCanceled():
                                self.logger.clear_status()
                                res_gpkg, msg_gpkg = self.package_results(
                                    self.output_etl_missing_snc)
                                if res_gpkg:
                                    self.generate_excel_report()
                                    if not self.custom_feedback.isCanceled():
                                        self.progress.setValue(
                                            self.progress_maximum)
                                        self.buttonBox.clear()
                                        self.buttonBox.setEnabled(True)
                                        self.buttonBox.addButton(
                                            QDialogButtonBox.Close)

                                        msg = QCoreApplication.translate(
                                            "Asistente-LADM-COL",
                                            "Missing supplies report successfully generated in folder <a href='file:///{normalized_path1}'>{path1}</a>! The output Geopackage database can be found in <a href='file:///{normalized_path2}'>{path2}</a>"
                                        ).format(normalized_path1=
                                                 normalize_local_url(
                                                     self.xlsx_path),
                                                 path1=self.xlsx_path,
                                                 normalized_path2=
                                                 normalize_local_url(
                                                     self.gpkg_path),
                                                 path2=self.gpkg_path)
                                        self.logger.clear_status()
                                        self.logger.success_msg(__name__, msg)
                                    else:
                                        self.initialize_feedback(
                                        )  # Get ready for an eventual new execution
                                        self.progress_base = 0
                                        self.logger.clear_status()

                                    self._running_tool = False
                                else:
                                    # User could have canceled while running the second algorithm
                                    if self.custom_feedback.isCanceled():
                                        self.initialize_feedback(
                                        )  # Get ready for an eventual new execution
                                        self.progress_base = 0
                                        self._running_tool = False
                                    else:
                                        self.show_message(
                                            msg_gpkg, Qgis.Warning)
                            else:  # User canceled in the first algorithm
                                self.initialize_feedback()
                                self.progress_base = 0
                                self._running_tool = False
                                self.logger.clear_status()
                        else:
                            self.show_message(msg_etl, Qgis.Warning)
                    else:
                        self.show_message(msg_gdb, Qgis.Warning)
                else:
                    self.show_message(msg_csv, Qgis.Warning)

            self.set_gui_controls_enabled(True)
Esempio n. 19
0
    def accepted(self):
        self._running_tool = True
        self.txtStdout.clear()
        self.progress_bar.setValue(0)
        self.bar.clearWidgets()

        if not os.path.isfile(self.xtf_file_line_edit.text().strip()):
            self._running_tool = False
            error_msg = QCoreApplication.translate(
                "DialogImportData",
                "Please set a valid XTF file before importing data. XTF file does not exist."
            )
            self.txtStdout.setText(error_msg)
            self.show_message(error_msg, Qgis.Warning)
            self.xtf_file_line_edit.setFocus()
            return

        java_home_set = self.java_dependency.set_java_home()
        if not java_home_set:
            message_java = QCoreApplication.translate(
                "DialogImportData",
                """Configuring Java {}...""").format(JAVA_REQUIRED_VERSION)
            self.txtStdout.setTextColor(QColor('#000000'))
            self.txtStdout.clear()
            self.txtStdout.setText(message_java)
            self.java_dependency.get_java_on_demand()
            self.disable()
            return

        configuration = self.update_configuration()

        if configuration.disable_validation:  # If data validation at import is disabled, we ask for confirmation
            self.msg = QMessageBox()
            self.msg.setIcon(QMessageBox.Question)
            self.msg.setText(
                QCoreApplication.translate(
                    "DialogImportData",
                    "Are you sure you want to import your data without validation?"
                ))
            self.msg.setWindowTitle(
                QCoreApplication.translate("DialogImportData",
                                           "Import XTF without validation?"))
            self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            res = self.msg.exec_()
            if res == QMessageBox.No:
                self._running_tool = False
                return

        if not self.xtf_file_line_edit.validator().validate(
                configuration.xtffile, 0)[0] == QValidator.Acceptable:
            self._running_tool = False
            error_msg = QCoreApplication.translate(
                "DialogImportData",
                "Please set a valid XTF before importing data.")
            self.txtStdout.setText(error_msg)
            self.show_message(error_msg, Qgis.Warning)
            self.xtf_file_line_edit.setFocus()
            return

        if not self.get_ili_models():
            self._running_tool = False
            error_msg = QCoreApplication.translate(
                "DialogImportData",
                "The selected XTF file does not have information according to the LADM-COL model to import."
            )
            self.txtStdout.setText(error_msg)
            self.show_message(error_msg, Qgis.Warning)
            self.import_models_list_view.setFocus()
            return

        # Get list of models present in the XTF file, in the DB and in the list of required models (by the plugin)
        ili_models = set([ili_model for ili_model in self.get_ili_models()])

        supported_models_in_ili = set([
            m.full_name() for m in self.__ladmcol_models.supported_models()
        ]).intersection(ili_models)

        if not supported_models_in_ili:
            self._running_tool = False
            error_msg = QCoreApplication.translate("DialogImportData",
                                                   "The selected XTF file does not have data from any LADM-COL model supported by the LADM-COL Assistant. " \
                                                   "Therefore, you cannot import it! These are the models supported:\n\n * {}").format(" \n * ".join([m.full_alias() for m in self.__ladmcol_models.supported_models()]))
            self.txtStdout.setText(error_msg)
            self.show_message(error_msg, Qgis.Warning)
            self.import_models_list_view.setFocus()
            return

        db_models = set(self.db.get_models())
        suggested_models = sorted(ili_models.difference(db_models))

        if not ili_models.issubset(db_models):
            self._running_tool = False
            error_msg = QCoreApplication.translate("DialogImportData",
                                                   "IMPORT ERROR: The XTF file to import does not have the same models as the target database schema. " \
                                                   "Please create a schema that also includes the following missing modules:\n\n * {}").format(
                " \n * ".join(suggested_models))
            self.txtStdout.clear()
            self.txtStdout.setTextColor(QColor('#000000'))
            self.txtStdout.setText(error_msg)
            self.show_message(error_msg, Qgis.Warning)
            self.xtf_file_line_edit.setFocus()

            # button is removed to define order in GUI
            for button in self.buttonBox.buttons():
                if button.text() == self.BUTTON_NAME_IMPORT_DATA:
                    self.buttonBox.removeButton(button)

            # Check if button was previously added
            self.remove_create_structure_button()

            if self.link_to_import_schema:
                self.buttonBox.addButton(
                    self.BUTTON_NAME_GO_TO_CREATE_STRUCTURE,
                    QDialogButtonBox.AcceptRole).setStyleSheet(
                        "color: #aa2222;")
            self.buttonBox.addButton(self.BUTTON_NAME_IMPORT_DATA,
                                     QDialogButtonBox.AcceptRole)

            return

        with OverrideCursor(Qt.WaitCursor):
            self.progress_bar.show()

            self.disable()
            self.txtStdout.setTextColor(QColor('#000000'))
            self.txtStdout.clear()

            dataImporter = iliimporter.Importer(dataImport=True)

            db_factory = self._dbs_supported.get_db_factory(self.db.engine)

            dataImporter.tool = db_factory.get_model_baker_db_ili_mode()
            dataImporter.configuration = configuration

            self.save_configuration(configuration)

            dataImporter.stdout.connect(self.print_info)
            dataImporter.stderr.connect(self.on_stderr)
            dataImporter.process_started.connect(self.on_process_started)
            dataImporter.process_finished.connect(self.on_process_finished)

            self.progress_bar.setValue(25)

            try:
                if dataImporter.run() != iliimporter.Importer.SUCCESS:
                    self._running_tool = False
                    self.show_message(
                        QCoreApplication.translate(
                            "DialogImportData",
                            "An error occurred when importing the data. For more information see the log..."
                        ), Qgis.Warning)
                    return
            except JavaNotFoundError:
                self._running_tool = False
                error_msg_java = QCoreApplication.translate(
                    "DialogImportData",
                    "Java {} could not be found. You can configure the JAVA_HOME environment variable manually, restart QGIS and try again."
                ).format(JAVA_REQUIRED_VERSION)
                self.txtStdout.setTextColor(QColor('#000000'))
                self.txtStdout.clear()
                self.txtStdout.setText(error_msg_java)
                self.show_message(error_msg_java, Qgis.Warning)
                return

            self._running_tool = False
            self.buttonBox.clear()
            self.buttonBox.setEnabled(True)
            self.buttonBox.addButton(QDialogButtonBox.Close)
            self.progress_bar.setValue(100)
            self.show_message(
                QCoreApplication.translate(
                    "DialogImportData",
                    "Import of the data was successfully completed"),
                Qgis.Success)
Esempio n. 20
0
    def export_baskets(self):
        java_home_set = self.java_dependency.set_java_home()
        if not java_home_set:
            message_java = QCoreApplication.translate("BasketExporter", """Configuring Java {}...""").format(
                JAVA_REQUIRED_VERSION)
            self.logger.status(message_java)
            self.java_dependency.get_java_on_demand()
            return

        self.base_configuration = BaseConfiguration()
        self.ilicache = IliCache(self.base_configuration)

        db_factory = self._dbs_supported.get_db_factory(self._db.engine)
        self.configuration = ExportConfiguration()
        db_factory.set_ili2db_configuration_params(self._db.dict_conn_params, self.configuration)
        self.configuration.with_exporttid = True
        full_java_exe_path = JavaDependency.get_full_java_exe_path()
        if full_java_exe_path:
            self.base_configuration.java_path = full_java_exe_path

        # Check custom model directories
        if QSettings().value('Asistente-LADM-COL/models/custom_model_directories_is_checked', DEFAULT_USE_CUSTOM_MODELS, type=bool):
            custom_model_directories = QSettings().value('Asistente-LADM-COL/models/custom_models', DEFAULT_MODELS_DIR)
            if not custom_model_directories:
                self.base_configuration.custom_model_directories_enabled = False
            else:
                self.base_configuration.custom_model_directories = custom_model_directories
                self.base_configuration.custom_model_directories_enabled = True

        self.ilicache.refresh()  # Always call it after setting custom_model_directories

        self.configuration.base_configuration = self.base_configuration
        if self.get_ili_models():
            self.configuration.ilimodels = ';'.join(self.get_ili_models())

        self.exporter = iliexporter.Exporter()
        self.exporter.tool = db_factory.get_model_baker_db_ili_mode()
        self.exporter.process_started.connect(self.on_process_started)
        self.exporter.stderr.connect(self.on_stderr)
        #self.exporter.process_finished.connect(self.on_process_finished)

        res = dict()
        count = 0
        total = len(self._basket_dict)

        with OverrideCursor(Qt.WaitCursor):
            for basket,name in self._basket_dict.items():
                self.log = ''
                self.configuration.xtffile = os.path.join(self._export_dir, "{}.xtf".format(name))
                self.configuration.baskets = basket
                self.exporter.configuration = self.configuration

                try:
                    if self.exporter.run() != iliexporter.Exporter.SUCCESS:
                        msg = QCoreApplication.translate("BasketExporter", "An error occurred when exporting the data for '{}' (check the QGIS log panel).").format(name)
                        res[basket] = (False, msg)
                        QgsMessageLog.logMessage(self.log, QCoreApplication.translate("BasketExporter", "Allocate to coordinators"), Qgis.Critical)
                    else:
                        res[basket] = (True, QCoreApplication.translate("BasketExporter", "XTF export for '{}' successful!").format(name) )
                except JavaNotFoundError:
                    msg = QCoreApplication.translate("BasketExporter", "Java {} could not be found. You can configure the JAVA_HOME environment variable manually, restart QGIS and try again.").format(JAVA_REQUIRED_VERSION)
                    res[basket] = (False, msg)

                count += 1
                self.total_progress_updated.emit(count/total*100)

        return res
    def import_button_clicked(self):
        self.bar.clearWidgets()
        self.save_settings()
        etl_result = False

        if self.rad_snc_data.isChecked():
            etl = ETLSNC(self.names, self._data_source_widget)
        else:  # Cobol
            etl = ETLCobol(self.names, self._data_source_widget)

        if self._db.test_connection()[0]:
            reply = QMessageBox.question(
                self, QCoreApplication.translate("SuppliesETLWizard",
                                                 "Warning"),
                QCoreApplication.translate(
                    "SuppliesETLWizard",
                    "The database <i>{}</i> already has a valid LADM-COL structure.<br/><br/>If such database has any data, loading data into it might cause invalid data.<br/><br/>Do you still want to continue?"
                ).format(self._db.get_description_conn_string()),
                QMessageBox.Yes, QMessageBox.No)

            if reply == QMessageBox.Yes:
                self.set_gui_controls_enabled(False)
                self.button(self.BackButton).setEnabled(False)
                self.button(self.CustomButton1).setEnabled(False)
                self.button(self.CancelButton).setText(
                    QCoreApplication.translate("SuppliesETLWizard", "Cancel"))

                with OverrideCursor(Qt.WaitCursor):
                    res_alpha, msg_alpha = etl.load_alphanumeric_layers()

                    if res_alpha:
                        res_spatial, msg_spatial = etl.load_spatial_layers()

                        if res_spatial:
                            res_model, msg_model = self.load_model_layers(
                                etl.layers)

                            if res_model:
                                layers_feature_count_before = {
                                    name: layer.featureCount()
                                    for name, layer in etl.layers.items()
                                }
                                self._running_tool = True
                                self.progress.setVisible(True)
                                res_etl_model = etl.run_etl_model(
                                    self.custom_feedback)
                                if not self.custom_feedback.isCanceled(
                                ) and res_etl_model:
                                    self.progress.setValue(100)

                                    self.button(
                                        self.NextButton).setVisible(True)
                                    self.button(
                                        self.CustomButton1).setVisible(False)
                                    self.button(self.CancelButton).setText(
                                        QCoreApplication.translate(
                                            "SuppliesETLWizard", "Close"))
                                    self.show_message(
                                        QCoreApplication.translate(
                                            "SuppliesETLWizard",
                                            "The {} has finished successfully!"
                                        ).format(self.tool_name), Qgis.Success,
                                        0)

                                    self.logger.clear_status()
                                    self.fill_summary(
                                        layers_feature_count_before,
                                        etl.layers)
                                    etl_result = True
                                else:
                                    self.initialize_feedback(
                                    )  # Get ready for an eventual new execution
                                    self.logger.clear_status()
                                self._running_tool = False
                            else:
                                self.show_message(msg_model, Qgis.Warning)
                        else:
                            self.show_message(msg_spatial, Qgis.Warning)
                    else:
                        self.show_message(msg_alpha, Qgis.Warning)
        else:
            with OverrideCursor(Qt.WaitCursor):
                # TODO: if an empty schema was selected, do the magic under the hood
                # self.create_model_into_database()
                # Now execute "accepted()"
                msg = QCoreApplication.translate(
                    "SuppliesETLWizard",
                    "To run the ETL, the database (schema) should have the Supplies LADM-COL structure. Choose a proper database (schema) and try again."
                )
                self.show_message(msg, Qgis.Warning)
                self.logger.warning(__name__, msg)

        self.on_result.emit(
            etl_result)  # Inform other classes if the execution was successful
    def accepted(self):
        self._running_tool = True
        self.txtStdout.clear()
        self.progress_bar.setValue(0)
        self.bar.clearWidgets()

        java_home_set = self.java_dependency.set_java_home()
        if not java_home_set:
            message_java = QCoreApplication.translate(
                "DialogImportSchema",
                """Configuring Java {}...""").format(JAVA_REQUIRED_VERSION)
            self.txtStdout.setTextColor(QColor('#000000'))
            self.txtStdout.clear()
            self.txtStdout.setText(message_java)
            self.java_dependency.get_java_on_demand()
            self.disable()
            return

        configuration = self.update_configuration()
        configuration = self.apply_role_model_configuration(configuration)

        if not self.get_checked_models():
            self._running_tool = False
            message_error = QCoreApplication.translate(
                "DialogImportSchema",
                "You should select a valid model(s) before creating the LADM-COL structure."
            )
            self.txtStdout.setText(message_error)
            self.show_message(message_error, Qgis.Warning)
            self.import_models_list_widget.setFocus()
            return

        self.save_configuration(configuration)

        with OverrideCursor(Qt.WaitCursor):
            self.progress_bar.show()
            self.disable()
            self.txtStdout.setTextColor(QColor('#000000'))
            self.txtStdout.clear()

            importer = iliimporter.Importer()

            db_factory = self._dbs_supported.get_db_factory(self.db.engine)

            importer.tool = db_factory.get_model_baker_db_ili_mode()
            importer.configuration = configuration
            importer.stdout.connect(self.print_info)
            importer.stderr.connect(self.on_stderr)
            importer.process_started.connect(self.on_process_started)
            importer.process_finished.connect(self.on_process_finished)

            try:
                if importer.run() != iliimporter.Importer.SUCCESS:
                    self._running_tool = False
                    self.show_message(
                        QCoreApplication.translate(
                            "DialogImportSchema",
                            "An error occurred when creating the LADM-COL structure. For more information see the log..."
                        ), Qgis.Warning)
                    self.on_result.emit(
                        False
                    )  # Inform other classes that the execution was not successful
                    return
            except JavaNotFoundError:
                self._running_tool = False
                message_error_java = QCoreApplication.translate(
                    "DialogImportSchema",
                    "Java {} could not be found. You can configure the JAVA_HOME environment variable manually, restart QGIS and try again."
                ).format(JAVA_REQUIRED_VERSION)
                self.txtStdout.setTextColor(QColor('#000000'))
                self.txtStdout.clear()
                self.txtStdout.setText(message_error_java)
                self.show_message(message_error_java, Qgis.Warning)
                return

            self._running_tool = False
            self.buttonBox.clear()
            if self.link_to_import_data:
                self.buttonBox.addButton(
                    self.BUTTON_NAME_GO_TO_IMPORT_DATA,
                    QDialogButtonBox.AcceptRole).setStyleSheet(
                        "color: #007208;")
            self.buttonBox.setEnabled(True)
            self.buttonBox.addButton(QDialogButtonBox.Close)
            self.progress_bar.setValue(100)
            self.print_info(
                QCoreApplication.translate("DialogImportSchema", "\nDone!"),
                '#004905')
            self.show_message(
                QCoreApplication.translate(
                    "DialogImportSchema",
                    "LADM-COL structure was successfully created!"),
                Qgis.Success)
            self.on_result.emit(
                True)  # Inform other classes that the execution was successful
            self._db_was_changed = True  # Schema could become LADM compliant after a schema import

            if self.db_source == COLLECTED_DB_SOURCE:
                self.logger.info(
                    __name__,
                    "Schedule a call to refresh db relations cache since a Schema Import was run on the current 'collected' DB."
                )
                self._schedule_layers_and_relations_refresh = True
Esempio n. 23
0
    def decorated_function(*args, **kwargs):

        with OverrideCursor(Qt.WaitCursor):
            func_to_decorate(*args, **kwargs)
    def accepted(self):
        self._running_tool = True
        self.bar.clearWidgets()

        java_home_set = self.java_utils.set_java_home()
        if not java_home_set:
            message_java = QCoreApplication.translate(
                "DialogExportData",
                """Configuring Java {}...""").format(JAVA_REQUIRED_VERSION)
            self.txtStdout.setTextColor(QColor('#000000'))
            self.txtStdout.clear()
            self.txtStdout.setText(message_java)
            self.java_utils.get_java_on_demand()
            self.disable()
            return

        configuration = self.update_configuration()

        if not self.xtf_file_line_edit.validator().validate(
                configuration.xtffile, 0)[0] == QValidator.Acceptable:
            self._running_tool = False
            message_error = QCoreApplication.translate(
                "DialogExportData",
                "Please set a valid XTF file before exporting data.")
            self.txtStdout.setText(message_error)
            self.show_message(message_error, Qgis.Warning)
            self.xtf_file_line_edit.setFocus()
            return

        if not self.get_ili_models():
            self._running_tool = False
            message_error = QCoreApplication.translate(
                "DialogExportData",
                "Please set a valid schema to export. This schema does not have information to export."
            )
            self.txtStdout.setText(message_error)
            self.show_message(message_error, Qgis.Warning)
            self.export_models_list_view.setFocus()
            return

        if not configuration.iliexportmodels:
            self._running_tool = False
            message_error = QCoreApplication.translate(
                "DialogExportData",
                "Please set a model before exporting data.")
            self.txtStdout.setText(message_error)
            self.show_message(message_error, Qgis.Warning)
            self.export_models_list_view.setFocus()
            return

        # If xtf browser was opened and the file exists, the user already chose
        # to overwrite the file
        if os.path.isfile(self.xtf_file_line_edit.text().strip()
                          ) and not self.xtf_browser_was_opened:
            self.msg = QMessageBox()
            self.msg.setIcon(QMessageBox.Warning)
            self.msg.setText(
                QCoreApplication.translate(
                    "DialogExportData",
                    "{filename} already exists.\nDo you want to replace it?").
                format(filename=os.path.basename(
                    self.xtf_file_line_edit.text().strip())))
            self.msg.setWindowTitle(
                QCoreApplication.translate("DialogExportData",
                                           "Save in XTF Transfer File"))
            self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            msg_box = self.msg.exec_()
            if msg_box == QMessageBox.No:
                self._running_tool = False
                return

        with OverrideCursor(Qt.WaitCursor):
            self.progress_bar.show()

            self.disable()
            self.txtStdout.setTextColor(QColor('#000000'))
            self.txtStdout.clear()

            exporter = iliexporter.Exporter()

            db_factory = self._dbs_supported.get_db_factory(self.db.engine)

            exporter.tool = db_factory.get_mbaker_db_ili_mode()
            exporter.configuration = configuration

            self.save_configuration(configuration)

            exporter.stdout.connect(self.print_info)
            exporter.stderr.connect(self.on_stderr)
            exporter.process_started.connect(self.on_process_started)
            exporter.process_finished.connect(self.on_process_finished)

            self.progress_bar.setValue(25)

            try:
                if exporter.run() != iliexporter.Exporter.SUCCESS:
                    self._running_tool = False
                    self.show_message(
                        QCoreApplication.translate(
                            "DialogExportData",
                            "An error occurred when exporting the data. For more information see the log..."
                        ), Qgis.Warning)
                    self.on_result.emit(
                        False
                    )  # Inform other classes that the execution was not successful
                    return
            except JavaNotFoundError:
                self._running_tool = False
                message_error_java = QCoreApplication.translate(
                    "DialogExportData",
                    "Java {} could not be found. You can configure the JAVA_HOME environment variable manually, restart QGIS and try again."
                ).format(JAVA_REQUIRED_VERSION)
                self.txtStdout.setTextColor(QColor('#000000'))
                self.txtStdout.clear()
                self.txtStdout.setText(message_error_java)
                self.show_message(message_error_java, Qgis.Warning)
                return

            self._running_tool = False
            self.buttonBox.clear()
            self.buttonBox.setEnabled(True)
            self.buttonBox.addButton(QDialogButtonBox.Close)
            self.progress_bar.setValue(100)
            self.show_message(
                QCoreApplication.translate(
                    "DialogExportData",
                    "Export of the data was successfully completed."),
                Qgis.Success)
            self.on_result.emit(
                True)  # Inform other classes that the execution was successful
Esempio n. 25
0
    def accepted(self):
        self.bar.clearWidgets()
        self.save_settings()

        if self._db.test_connection()[0]:
            reply = QMessageBox.question(
                self, QCoreApplication.translate("ETLCobolDialog", "Warning"),
                QCoreApplication.translate(
                    "ETLCobolDialog",
                    "The database <i>{}</i> already has a valid LADM_COL structure.<br/><br/>If such database has any data, loading data into it might cause invalid data.<br/><br/>Do you still want to continue?"
                ).format(self._db.get_description_conn_string()),
                QMessageBox.Yes, QMessageBox.No)

            lis_paths = {
                'blo': self.txt_file_path_blo.text().strip(),
                'uni': self.txt_file_path_uni.text().strip(),
                'ter': self.txt_file_path_ter.text().strip(),
                'pro': self.txt_file_path_pro.text().strip()
            }

            required_layers = [
                'R_TERRENO', 'U_TERRENO', 'R_SECTOR', 'U_SECTOR', 'R_VEREDA',
                'U_MANZANA', 'U_BARRIO', 'R_CONSTRUCCION', 'U_CONSTRUCCION',
                'U_UNIDAD', 'R_UNIDAD', 'U_NOMENCLATURA_DOMICILIARIA',
                'R_NOMENCLATURA_DOMICILIARIA', 'U_PERIMETRO'
            ]

            if reply == QMessageBox.Yes:
                self.set_gui_controls_enabled(False)
                with OverrideCursor(Qt.WaitCursor):
                    res_lis, msg_lis = self.load_lis_files(lis_paths)
                    if res_lis:
                        res_gdb, msg_gdb = self.load_gdb_files(required_layers)
                        if res_gdb:
                            res_model, msg_model = self.load_model_layers()
                            if res_model:
                                self._running_tool = True
                                self.run_model_etl_cobol()
                                if not self.custom_feedback.isCanceled():
                                    self.progress.setValue(100)
                                    self.buttonBox.clear()
                                    self.buttonBox.setEnabled(True)
                                    self.buttonBox.addButton(
                                        QDialogButtonBox.Close)
                                    self.logger.clear_status()
                                    self._etl_result = True
                                else:
                                    self.initialize_feedback(
                                    )  # Get ready for an eventual new execution
                                    self.logger.clear_status()
                                self._running_tool = False
                            else:
                                self.show_message(msg_model, Qgis.Warning)
                        else:
                            self.show_message(msg_gdb, Qgis.Warning)
                    else:
                        self.show_message(msg_lis, Qgis.Warning)

                self.set_gui_controls_enabled(True)
        else:
            with OverrideCursor(Qt.WaitCursor):
                # TODO: if an empty schema was selected, do the magic under the hood
                # self.create_model_into_database()
                # Now execute "accepted()"
                msg = QCoreApplication.translate(
                    "ETLCobolDialog",
                    "To run the ETL, the database (schema) should have the Supplies LADM_COL structure. Choose a proper database (schema) and try again."
                )
                self.show_message(msg, Qgis.Warning)
                self.logger.warning(__name__, msg)

        self.on_result.emit(
            self._etl_result
        )  # Inform other classes if the execution was successful
        self._etl_result = False  # Next run?
Esempio n. 26
0
    def generate_report(self, db, report_type):
        # Check if mapfish and Jasper are installed, otherwise show where to
        # download them from and return
        if not self.report_dependency.check_if_dependency_is_valid():
            self.report_dependency.download_dependency(URL_REPORTS_LIBRARIES)
            return

        java_home_set = self.java_dependency.set_java_home()
        if not java_home_set:
            self.java_dependency.get_java_on_demand()
            self.logger.info_msg(
                __name__,
                QCoreApplication.translate(
                    "ReportGenerator",
                    "Java is a prerequisite. Since it was not found, it is being configured..."
                ))
            return

        plot_layer = self.app.core.get_layer(db, db.names.LC_PLOT_T, load=True)
        if not plot_layer:
            return

        selected_plots = plot_layer.selectedFeatures()
        if not selected_plots:
            self.logger.warning_msg(
                __name__,
                QCoreApplication.translate(
                    "ReportGenerator",
                    "To generate reports, first select at least a plot!"))
            return

        # Where to store the reports?
        previous_folder = QSettings().value(
            "Asistente-LADM-COL/reports/save_into_dir", ".")
        save_into_folder = QFileDialog.getExistingDirectory(
            None,
            QCoreApplication.translate(
                "ReportGenerator",
                "Select a folder to save the reports to be generated"),
            previous_folder)
        if not save_into_folder:
            self.logger.warning_msg(
                __name__,
                QCoreApplication.translate(
                    "ReportGenerator",
                    "You need to select a folder where to save the reports before continuing."
                ))
            return
        QSettings().setValue("Asistente-LADM-COL/reports/save_into_dir",
                             save_into_folder)

        config_path = os.path.join(DEPENDENCY_REPORTS_DIR_NAME, report_type)
        json_spec_file = os.path.join(config_path, 'spec_json_file.json')

        script_name = ''
        if os.name == 'posix':
            script_name = 'print'
        elif os.name == 'nt':
            script_name = 'print.bat'

        script_path = os.path.join(DEPENDENCY_REPORTS_DIR_NAME, 'bin',
                                   script_name)
        if not os.path.isfile(script_path):
            self.logger.warning(
                __name__,
                "Script file for reports wasn't found! {}".format(script_path))
            return

        self.enable_action_requested.emit(report_type, False)

        # Update config file
        yaml_config_path = self.update_yaml_config(db, config_path)
        self.logger.debug(
            __name__, "Config file for reports: {}".format(yaml_config_path))

        total = len(selected_plots)
        step = 0
        count = 0
        tmp_dir = self.get_tmp_dir()

        # Progress bar setup
        progress = QProgressBar()
        if total == 1:
            progress.setRange(0, 0)
        else:
            progress.setRange(0, 100)
        progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.app.gui.create_progress_message_bar(
            QCoreApplication.translate("ReportGenerator",
                                       "Generating {} report{}...").format(
                                           total, '' if total == 1 else 's'),
            progress)

        polygons_with_holes = []

        with OverrideCursor(Qt.WaitCursor):
            for selected_plot in selected_plots:
                plot_id = selected_plot[db.names.T_ID_F]

                geometry = selected_plot.geometry()
                abstract_geometry = geometry.constGet()
                if abstract_geometry.ringCount() > 1:
                    polygons_with_holes.append(str(plot_id))
                    self.logger.warning(
                        __name__,
                        QCoreApplication.translate(
                            "ReportGenerator",
                            "Skipping Annex 17 for plot with {}={} because it has holes. The reporter module does not support such polygons."
                        ).format(db.names.T_ID_F, plot_id))
                    continue

                # Generate data file
                json_file = self.update_json_data(db, json_spec_file, plot_id,
                                                  tmp_dir, report_type)
                self.logger.debug(
                    __name__, "JSON file for reports: {}".format(json_file))

                # Run sh/bat passing config and data files
                proc = QProcess()
                proc.readyReadStandardError.connect(
                    functools.partial(self.stderr_ready, proc=proc))
                proc.readyReadStandardOutput.connect(
                    functools.partial(self.stdout_ready, proc=proc))

                parcel_number = self.ladm_data.get_parcels_related_to_plots(
                    db, [plot_id],
                    db.names.LC_PARCEL_T_PARCEL_NUMBER_F) or ['']
                self.app.gui.activate_layer(
                    plot_layer
                )  # Previous function changed the selected layer, so, select again plot layer
                file_name = '{}_{}_{}.pdf'.format(report_type, plot_id,
                                                  parcel_number[0])

                current_report_path = os.path.join(save_into_folder, file_name)
                proc.start(script_path, [
                    '-config', yaml_config_path, '-spec', json_file, '-output',
                    current_report_path
                ])

                if not proc.waitForStarted():
                    # Grant execution permissions
                    os.chmod(
                        script_path, stat.S_IXOTH | stat.S_IXGRP | stat.S_IXUSR
                        | stat.S_IRUSR | stat.S_IRGRP)
                    proc.start(script_path, [
                        '-config', yaml_config_path, '-spec', json_file,
                        '-output', current_report_path
                    ])

                if not proc.waitForStarted():
                    proc = None
                    self.logger.warning(
                        __name__,
                        "Couldn't execute script to generate report...")
                else:
                    loop = QEventLoop()
                    proc.finished.connect(loop.exit)
                    loop.exec()

                    self.logger.debug(__name__,
                                      "{}:{}".format(plot_id, proc.exitCode()))
                    if proc.exitCode() == 0:
                        count += 1

                    step += 1
                    try:
                        progress.setValue(step * 100 / total)
                    except RuntimeError:
                        pass  # progressBar was deleted

        os.remove(yaml_config_path)

        self.enable_action_requested.emit(report_type, True)
        self.logger.clear_message_bar()

        if total == count:
            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report <a href='file:///{}'>{}</a> was successfully generated!"
                ).format(normalize_local_url(save_into_folder), file_name)
            else:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "All reports were successfully generated in folder <a href='file:///{path}'>{path}</a>!"
                ).format(path=normalize_local_url(save_into_folder))

            self.logger.success_msg(__name__, msg)
        else:
            details_msg = ''
            if polygons_with_holes:
                details_msg += QCoreApplication.translate(
                    "ReportGenerator",
                    " The following polygons were skipped because they have holes and are not supported: {}."
                ).format(", ".join(polygons_with_holes))

            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report for plot {} couldn't be generated!{} See QGIS log (tab '{}') for details."
                ).format(plot_id, details_msg, self.LOG_TAB)
            else:
                if count == 0:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "No report could be generated!{} See QGIS log (tab '{}') for details."
                    ).format(details_msg, self.LOG_TAB)
                else:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "At least one report couldn't be generated!{details_msg} See QGIS log (tab '{log_tab}') for details. Go to <a href='file:///{path}'>{path}</a> to see the reports that were generated."
                    ).format(details_msg=details_msg,
                             path=normalize_local_url(save_into_folder),
                             log_tab=self.LOG_TAB)

            self.logger.warning_msg(__name__, msg)