예제 #1
0
    def _get_gui_config(self, role_key):
        """
        Get a basic GUI config (still unfiltered).

        :param role_key: Active role key to whom we will ask for its GUI config. Normally, it should be the active one.
        :return: Dictionary in the form of a gui_config dict (still unfiltered).
        """
        if self._test_conn_result:
            self.logger.info(__name__,
                             "Using template gui_config from the role.")
            return RoleRegistry().get_role_gui_config(role_key)
        else:
            default_gui = RoleRegistry().get_role_gui_config(
                role_key, DEFAULT_GUI)
            if default_gui:
                self.logger.info(
                    __name__,
                    "Using default gui_config (minimal) from the role.")
                return default_gui
            else:
                self.logger.info(
                    __name__,
                    "Using gui_config from the default GUI (minimal).")
                return GUI_Config().get_gui_dict(
                    DEFAULT_GUI
                )  # Use a default gui config given by the plugin
예제 #2
0
    def refresh_models_for_active_role(self, only_for_model=''):
        role_key = RoleRegistry().get_active_role()
        role_models = RoleRegistry().get_role_models(role_key)

        # ili2db params may come from the model config itself or overwritten by the current user.
        # If the user does not have such config, we grab it from MODEL_CONFIG.
        ili2db_params = role_models.get(ROLE_MODEL_ILI2DB_PARAMETERS, dict())

        for model_key, model in self.__models.items():
            if only_for_model and model_key != only_for_model:
                continue  # Avoid overwriting data of the other models (useful for refreshing a just-registered model)

            model.set_is_supported(
                model_key in role_models[ROLE_SUPPORTED_MODELS])
            model.set_is_hidden(model_key in role_models[ROLE_HIDDEN_MODELS])
            model.set_is_checked(model_key in role_models[ROLE_CHECKED_MODELS])

            # First attempt to get ili2db parameters from role, otherwise from model config
            model_ili2db_params = ili2db_params.get(
                model_key, dict()) or model.get_default_ili2db_params()
            model.set_ili2db_params(model_ili2db_params)
            if model_ili2db_params:
                self.logger.debug(
                    __name__,
                    "Model ili2db params are: {}".format(model_ili2db_params))

        self.logger.debug(
            __name__, "Supported models for active role '{}': {}".format(
                role_key, role_models[ROLE_SUPPORTED_MODELS]))
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.logger = Logger()
        self.help_strings = HelpStrings()

        #self.txt_help_page.setHtml(self.help_strings.DLG_WELCOME_SCREEN)
        #self.txt_help_page.anchorClicked.connect(self.save_template)

        self.finished.connect(self.finish_dialog)
        self.buttonBox.helpRequested.connect(self.show_help)

        self.gbx_layout = QVBoxLayout()
        self.roles = RoleRegistry()
        self.dict_roles = self.roles.get_roles_info()
        checked = False
        active_role = self.roles.get_active_role()

        # Initialize radio buttons
        for k,v in self.dict_roles.items():
            radio = QRadioButton(v)
            if not checked:
                if k == active_role:
                    radio.setChecked(True)
                    checked = True
                    self.show_description(self.roles.get_role_description(k), checked)  # Initialize help page

            radio.toggled.connect(partial(self.show_description, self.roles.get_role_description(k)))
            self.gbx_layout.addWidget(radio)

        self.gbx_options.setLayout(self.gbx_layout)
예제 #4
0
    def refresh_models_for_role(self):
        role_key = RoleRegistry().get_active_role()
        role_models = RoleRegistry().get_role_models(role_key)

        # ili2db params may come from the model config itself or overwritten by the current user.
        # It the user does not have such config, we grab it from MODEL_CONFIG.
        ili2db_params = role_models[
            ROLE_MODEL_ILI2DB_PARAMETERS] if ROLE_MODEL_ILI2DB_PARAMETERS in role_models else dict(
            )

        for model_key, model in self.__models.items():
            model.set_is_supported(
                model_key in role_models[ROLE_SUPPORTED_MODELS])
            model.set_is_hidden(model_key in role_models[ROLE_HIDDEN_MODELS])
            model.set_is_checked(model_key in role_models[ROLE_CHECKED_MODELS])

            if model_key in ili2db_params and ili2db_params[model_key]:
                model_ili2db_params = ili2db_params[model_key]
            else:
                model_ili2db_params = self.__get_model_iili2db_params_from_config(
                    model_key)
            if model_ili2db_params:
                self.logger.debug(
                    __name__,
                    "Model ili2db params are: {}".format(model_ili2db_params))
            model.set_ili2db_params(model_ili2db_params)

        self.logger.debug(
            __name__, "Supported models for role '{}': {}".format(
                role_key, role_models[ROLE_SUPPORTED_MODELS]))
예제 #5
0
    def __init__(self):
        self.logger = Logger()
        self.__quality_rules_data = QualityRuleConfig.get_quality_rules_config(
        )
        self.__translated_strings = TranslatableConfigStrings(
        ).get_translatable_config_strings()
        self._quality_rule_groups = dict()
        self.__quality_rules = dict()

        self.role_registry = RoleRegistry()

        self._initialize_quality_rule_manager()
예제 #6
0
    def _get_filtered_gui_config(self):
        """
        Rebuilds a gui_config dict removing not allowed actions.

        :return: Dictionary in the form of a gui_config dict, but only with allowed actions for the role_key passed.
        """
        role_key = RoleRegistry().get_active_role()
        self.logger.info(
            __name__,
            "Active role: {}".format(RoleRegistry().get_role_name(role_key)))

        gui_config = self._get_gui_config(role_key)
        # self.logger.debug(__name__, "Filtered gui_config: {}".format(gui_config))
        role_actions = self._get_role_actions(role_key)
        model_actions = self._get_model_actions(
        ) if self._test_conn_result else list()

        # If you want to take models into account, combine role_actions and model_actions as you like, and store the
        # result in allowed_actions.
        #
        # Here we define how to deal with actions, role permissions and models present
        # We decided to prefer always the rol's actions. Like this (R: Role, M: Model, Res: Result):
        # R  M   Res
        # V  V    V
        # V  F    V
        # F  V    F
        # F  F    F
        #
        # Therefore:
        allowed_actions = role_actions  # It's safe to make use of this list, no need to copy it, as it's a sum of lists
        self.logger.debug(
            __name__,
            "Allowed actions for role '{}': {}".format(role_key,
                                                       allowed_actions))

        # Now, use only allowed actions and remove other actions from gui_config
        filtered_gui_config = dict()
        for k, v in gui_config.items():
            if k == MAIN_MENU or k == TOOLBAR:
                for menu_def in v:
                    actions = self._get_filtered_actions(
                        menu_def[ACTIONS], allowed_actions)
                    if actions:
                        menu_def[ACTIONS] = actions
                        if not k in filtered_gui_config:
                            filtered_gui_config[k] = [menu_def]
                        else:
                            filtered_gui_config[k].append(menu_def)

        return filtered_gui_config
예제 #7
0
    def _get_role_actions(self, role_key):
        """
        Get actions a given role has access to.

        :param role_key: Role key.
        :return: List of actions a role has access to.
        """
        return RoleRegistry().get_role_actions(role_key)
예제 #8
0
    def get_qrs_per_role_and_models(self, db, as_dict=True):
        """
        :param as_dict: Boolean. If False, the result is returned as a list or rule keys
        """
        qrs = dict()
        role_registry = RoleRegistry()
        role_qrs = role_registry.get_role_quality_rules(role_registry.get_active_role())
        if role_qrs == ALL_QUALITY_RULES:
            role_qrs = self.__quality_rules

        if role_qrs:
            db_models = db.get_models()
            model_registry = LADMColModelRegistry()

            for qr in role_qrs:
                # First check if the role QR is registered
                if qr in self.__quality_rules:
                    # Then check if the models required by the QR are in the DB
                    req_models = self.__quality_rules[qr].models()
                    num_models = len(req_models)

                    all_models_found = True
                    if num_models:  # We don't check models if a QR has no required models (e.g., iliValidator)
                        for req_model in req_models:
                            model = model_registry.model(req_model)
                            model_key = model.full_name()
                            if model_key and model_key not in db_models:
                                all_models_found = False
                                self.logger.debug(__name__,
                                                  "Model '{}' not found in the DB. QR '{}' cannot be listed.".format(
                                                      model_key, qr
                                                  ))
                                break

                    if all_models_found:
                        qrs[qr] = self.__quality_rules[qr]

        return qrs if as_dict else list(qrs.keys())
예제 #9
0
    def _get_gui_config(self, role_key):
        """
        Get a basic GUI config (still unfiltered).

        :param role_key: Active role key to whom we will ask for its GUI config. Normally, it should be the active one.
        :return: Dictionary in the form of a gui_config dict (still unfiltered).
        """
        gui_type = DEFAULT_GUI  # If test_connection is False, we use a default gui config

        if self._test_conn_result:
            gui_config = RoleRegistry().get_role_gui_config(role_key)
            if gui_config:
                self.logger.info(__name__, "Using gui_config from the role.")
                return gui_config
            else:
                self.logger.info(__name__,
                                 "Using gui_config from the template.")
                gui_type = TEMPLATE_GUI

        if gui_type == DEFAULT_GUI:
            self.logger.info(
                __name__, "Using gui_config from the default GUI (minimal).")

        return GUI_Config().get_gui_dict(gui_type)
예제 #10
0
    def login(self, user, password):
        msg = ""
        should_emit_role_changed = False
        st_config = TransitionalSystemConfig()
        payload = st_config.ST_LOGIN_SERVICE_PAYLOAD.format(user, password)
        headers = {
            'Content-Type': "application/x-www-form-urlencoded",
            'Authorization': st_config.ST_LOGIN_AUTHORIZATION_CLIENT,
            'Accept': "*/*",
            'Cache-Control': "no-cache",
            'Accept-Encoding': "gzip, deflate",
            'Connection': "keep-alive",
            'cache-control': "no-cache"
        }
        s = requests.Session()
        s.mount(st_config.ST_LOGIN_SERVICE_URL, HTTPAdapter(max_retries=0))

        try:
            response = s.request("POST", st_config.ST_LOGIN_SERVICE_URL, data=payload, headers=headers)
        except requests.ConnectionError as e:
            msg = QCoreApplication.translate("STSession", "There was an error accessing the login service. Details: {}").format(e)
            self.logger.warning(__name__, msg)
            return False, msg, False

        status_OK = response.status_code == 200
        self.logger.info(__name__, "Login response status code: {}".format(response.status_code))
        if status_OK:
            logged_data = json.loads(response.text)

            # Check if ST role is recognized by LADM-COL Assistant. Otherwise, do not login.
            st_role = logged_data['roles'][0]['id']
            if st_role not in st_config.ROLE_MAPPING:
                return status_OK, \
                       QCoreApplication.translate("STSession",
                           "The user cannot log-in into the Transitional System because the '{}' ST role has no tasks assigned in LADM-COL Assistant!".format(logged_data['roles'][0]['name'])), \
                       False

            msg = QCoreApplication.translate("STSession", "User logged in successfully in the Transitional System!")
            self.__logged_user = STLoggedUser("{} {}".format(logged_data['first_name'],
                                                             logged_data['last_name']),
                                              logged_data['email'],
                                              logged_data['roles'][0]['name'],
                                              logged_data['access_token'])
            QSettings().setValue(self.TOKEN_KEY, logged_data['access_token'])  # Register (login) the user
            # self.login_status_changed.emit(True) Don't emit now, a GUI refresh comes, so updates will be lost
            self.logger.info(__name__, msg)

            # Make LADM-COL Assistant's current role correspond to the logged in user role in ST
            if st_config.ROLE_MAPPING[st_role] != RoleRegistry().get_active_role():
                RoleRegistry().set_active_role(st_config.ROLE_MAPPING[st_role], emit_signal=False)
                should_emit_role_changed = True  # Safer to let the dialog deal with that SIGNAL (refreshes the GUI!)
        else:
            if response.status_code == 400:
                msg = QCoreApplication.translate("STSession",
                                                 "Wrong user name or password, change credentials and try again.")
            elif response.status_code == 500:
                msg = QCoreApplication.translate("STSession", "There is an error in the login server!")
            elif response.status_code > 500 and response.status_code < 600:
                msg = st_config.ST_STATUS_GT_500_MSG
                self.logger.warning(__name__, st_config.ST_STATUS_GT_500_MSG)
            elif response.status_code == 401:
                msg = QCoreApplication.translate("STSession", "Unauthorized client! The server won't allow requests from this client.")
            self.logger.warning(__name__, msg)

        return status_OK, msg, should_emit_role_changed
예제 #11
0
 def show_welcome_screen(self):
     return not RoleRegistry().active_role_already_set()
예제 #12
0
    def __init__(self, conn_manager=None, context=None, parent=None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.parent = parent
        self.logger = Logger()
        self.conn_manager = conn_manager
        self.app = AppInterface()

        self.sbx_tolerance.setMaximum(TOLERANCE_MAX_VALUE)
        self._valid_document_repository = False  # Needs to be True if users want to enable doc repo (using test button)

        context = context if context else SettingsContext()

        self.db_source = context.db_source  # default db source is COLLECTED_DB_SOURCE
        self._required_models = context.required_models
        self._tab_pages_list = context.tab_pages_list
        self._blocking_mode = context.blocking_mode  # Whether the dialog can only be accepted on valid DB connections or not
        self._action_type = context.action_type  # By default "config"
        self.setWindowTitle(context.title)

        self._db = None
        self.init_db_engine = None
        self.dbs_supported = ConfigDBsSupported()
        self._open_dlg_import_schema = False  # After accepting, if non-valid DB is configured, we can go to import schema

        self.online_models_radio_button.setEnabled(
            False)  # This option is disabled until we have online models back!
        self.online_models_radio_button.setChecked(True)
        self.online_models_radio_button.toggled.connect(
            self.model_provider_toggle)
        self.custom_model_directories_line_edit.setText("")
        self.custom_models_dir_button.clicked.connect(
            self.show_custom_model_dir)
        self.custom_model_directories_line_edit.setVisible(False)
        self.custom_models_dir_button.setVisible(False)

        # Set connections
        self.buttonBox.accepted.disconnect()
        self.buttonBox.accepted.connect(self.accepted)
        self.buttonBox.helpRequested.connect(self.show_help)
        self.finished.connect(self.finished_slot)
        self.btn_test_connection.clicked.connect(self.test_connection)
        self.btn_test_ladm_col_structure.clicked.connect(
            self.test_ladm_col_structure)

        self.btn_test_service.clicked.connect(self.test_service)
        self.btn_test_service_transitional_system.clicked.connect(
            self.test_service_transitional_system)
        self.txt_service_endpoint.textEdited.connect(
            self.source_service_endpoint_changed)  # For manual changes only

        self.btn_default_value_sources.clicked.connect(
            self.set_default_value_source_service)
        self.btn_default_value_transitional_system.clicked.connect(
            self.set_default_value_transitional_system_service)

        self.chk_use_roads.toggled.connect(self.update_images_state)

        self.bar = QgsMessageBar()
        self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop)

        self.cbo_db_engine.clear()

        self._lst_db = self.dbs_supported.get_db_factories()
        self._lst_panel = dict()

        for key, value in self._lst_db.items():
            self.cbo_db_engine.addItem(value.get_name(), key)
            self._lst_panel[key] = value.get_config_panel(self)
            self._lst_panel[key].notify_message_requested.connect(
                self.show_message)
            self.db_layout.addWidget(self._lst_panel[key])

        self.db_engine_changed()

        # Trigger some default behaviours
        self.restore_db_source_settings(
        )  # restore settings with default db source
        self.restore_settings()

        self.roles = RoleRegistry()
        self.load_roles()

        self.cbo_db_engine.currentIndexChanged.connect(self.db_engine_changed)
        self.rejected.connect(self.close_dialog)

        self._update_tabs()

        if context.tip:
            self.show_tip(context.tip)
예제 #13
0
class SettingsDialog(QDialog, DIALOG_UI):
    """
    Customizable dialog to configure LADM-COL Assistant.

    It can be created passing a SettingsContext with specific params
    or it can be instantiated and then set params one by one.
    """
    db_connection_changed = pyqtSignal(DBConnector, bool,
                                       str)  # dbconn, ladm_col_db, source
    open_dlg_import_schema = pyqtSignal(
        Context)  # Context for the import schema dialog

    def __init__(self, conn_manager=None, context=None, parent=None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.parent = parent
        self.logger = Logger()
        self.conn_manager = conn_manager
        self.app = AppInterface()

        self.sbx_tolerance.setMaximum(TOLERANCE_MAX_VALUE)
        self._valid_document_repository = False  # Needs to be True if users want to enable doc repo (using test button)

        context = context if context else SettingsContext()

        self.db_source = context.db_source  # default db source is COLLECTED_DB_SOURCE
        self._required_models = context.required_models
        self._tab_pages_list = context.tab_pages_list
        self._blocking_mode = context.blocking_mode  # Whether the dialog can only be accepted on valid DB connections or not
        self._action_type = context.action_type  # By default "config"
        self.setWindowTitle(context.title)

        self._db = None
        self.init_db_engine = None
        self.dbs_supported = ConfigDBsSupported()
        self._open_dlg_import_schema = False  # After accepting, if non-valid DB is configured, we can go to import schema

        self.online_models_radio_button.setEnabled(
            False)  # This option is disabled until we have online models back!
        self.online_models_radio_button.setChecked(True)
        self.online_models_radio_button.toggled.connect(
            self.model_provider_toggle)
        self.custom_model_directories_line_edit.setText("")
        self.custom_models_dir_button.clicked.connect(
            self.show_custom_model_dir)
        self.custom_model_directories_line_edit.setVisible(False)
        self.custom_models_dir_button.setVisible(False)

        # Set connections
        self.buttonBox.accepted.disconnect()
        self.buttonBox.accepted.connect(self.accepted)
        self.buttonBox.helpRequested.connect(self.show_help)
        self.finished.connect(self.finished_slot)
        self.btn_test_connection.clicked.connect(self.test_connection)
        self.btn_test_ladm_col_structure.clicked.connect(
            self.test_ladm_col_structure)

        self.btn_test_service.clicked.connect(self.test_service)
        self.btn_test_service_transitional_system.clicked.connect(
            self.test_service_transitional_system)
        self.txt_service_endpoint.textEdited.connect(
            self.source_service_endpoint_changed)  # For manual changes only

        self.btn_default_value_sources.clicked.connect(
            self.set_default_value_source_service)
        self.btn_default_value_transitional_system.clicked.connect(
            self.set_default_value_transitional_system_service)

        self.chk_use_roads.toggled.connect(self.update_images_state)

        self.bar = QgsMessageBar()
        self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop)

        self.cbo_db_engine.clear()

        self._lst_db = self.dbs_supported.get_db_factories()
        self._lst_panel = dict()

        for key, value in self._lst_db.items():
            self.cbo_db_engine.addItem(value.get_name(), key)
            self._lst_panel[key] = value.get_config_panel(self)
            self._lst_panel[key].notify_message_requested.connect(
                self.show_message)
            self.db_layout.addWidget(self._lst_panel[key])

        self.db_engine_changed()

        # Trigger some default behaviours
        self.restore_db_source_settings(
        )  # restore settings with default db source
        self.restore_settings()

        self.roles = RoleRegistry()
        self.load_roles()

        self.cbo_db_engine.currentIndexChanged.connect(self.db_engine_changed)
        self.rejected.connect(self.close_dialog)

        self._update_tabs()

        if context.tip:
            self.show_tip(context.tip)

    def set_db_source(self, db_source):
        self.db_source = db_source
        self.restore_db_source_settings()

    def set_tab_pages_list(self, tab_pages_list):
        self._tab_pages_list = tab_pages_list
        self._update_tabs()

    def set_required_models(self, required_models):
        self._required_models = required_models

    def set_blocking_mode(self, block):
        self._blocking_mode = block

    def _update_tabs(self):
        """
        Show only those tabs that are listed in tab_pages_list, if any. If it's an empty list, show all tabs.
        """
        if self._tab_pages_list:
            for i in reversed(range(self.tabWidget.count())):
                if i not in self._tab_pages_list:
                    self.tabWidget.removeTab(i)

    def load_roles(self):
        """
        Initialize group box for selecting the active role
        """
        self.gbx_active_role_layout = QVBoxLayout()
        dict_roles = self.roles.get_roles_info()
        checked = False
        active_role = self.roles.get_active_role()

        # Initialize radio buttons
        for k, v in dict_roles.items():
            radio = QRadioButton(v)
            radio.setToolTip(self.roles.get_role_description(k))

            if not checked:
                if k == active_role:
                    radio.setChecked(True)
                    checked = True

            self.gbx_active_role_layout.addWidget(radio)

        self.gbx_active_role.setLayout(self.gbx_active_role_layout)

    def close_dialog(self):
        self.close()

    def showEvent(self, event):
        # It is necessary to reload the variables
        # to load the database and schema name
        self.restore_settings()

        self.btn_test_ladm_col_structure.setVisible(
            self._action_type != EnumDbActionType.SCHEMA_IMPORT)

    def model_provider_toggle(self):
        if self.offline_models_radio_button.isChecked():
            self.custom_model_directories_line_edit.setVisible(True)
            self.custom_models_dir_button.setVisible(True)
        else:
            self.custom_model_directories_line_edit.setVisible(False)
            self.custom_models_dir_button.setVisible(False)
            self.custom_model_directories_line_edit.setText("")

    def _get_db_connector_from_gui(self):
        current_db_engine = self.cbo_db_engine.currentData()
        params = self._lst_panel[current_db_engine].read_connection_parameters(
        )
        db = self._lst_db[current_db_engine].get_db_connector(params)
        return db

    def get_db_connection(self):
        if self._db is not None:
            self.logger.info(__name__, "Returning existing db connection...")
        else:
            self.logger.info(__name__, "Getting new db connection...")
            self._db = self._get_db_connector_from_gui()
            self._db.open_connection()

        return self._db

    def show_custom_model_dir(self):
        dlg = CustomModelDirDialog(
            self.custom_model_directories_line_edit.text(), self)
        dlg.exec_()

    def accepted(self):
        """
        We start checking the document repository configuration and only allow to continue if we have a valid repo or
        if the repo won't be used.

        Then, check if connection to DB/schema is valid, if not, block the dialog.
        If valid, check it complies with LADM. If not, block the dialog. If it complies, we have two options: To emit
        db_connection changed or not. Finally, we store options in QSettings.
        """
        res_doc_repo, msg_doc_repo = self.check_document_repository_before_saving_settings(
        )
        if not res_doc_repo:
            self.show_message(msg_doc_repo, Qgis.Warning, 0)
            return  # Do not close the dialog

        ladm_col_schema = False

        db = self._get_db_connector_from_gui()

        test_level = EnumTestLevel.DB_SCHEMA

        if self._action_type == EnumDbActionType.SCHEMA_IMPORT:
            # Limit the validation (used in GeoPackage)
            test_level |= EnumTestLevel.SCHEMA_IMPORT

        res, code, msg = db.test_connection(
            test_level
        )  # No need to pass required_models, we don't test that much

        if res:
            if self._action_type != EnumDbActionType.SCHEMA_IMPORT:
                # Only check LADM-schema if we are not in an SCHEMA IMPORT.
                # We know in an SCHEMA IMPORT, at this point the schema is still not LADM.
                ladm_col_schema, code, msg = db.test_connection(
                    EnumTestLevel.LADM, required_models=self._required_models)

            if not ladm_col_schema and self._action_type != EnumDbActionType.SCHEMA_IMPORT:
                if self._blocking_mode:
                    self.show_message(msg, Qgis.Warning)
                    return  # Do not close the dialog

        else:
            if self._blocking_mode:
                self.show_message(msg, Qgis.Warning)
                return  # Do not close the dialog

        # Connection is valid and complies with LADM
        current_db_engine = self.cbo_db_engine.currentData()
        if self._lst_panel[current_db_engine].state_changed(
        ) or self.init_db_engine != current_db_engine:
            # Emit db_connection_changed
            if self._db is not None:
                self._db.close_connection()

            self._db = db

            # Update db connect with new db conn
            self.conn_manager.set_db_connector_for_source(
                self._db, self.db_source)

            # Emmit signal when db source changes
            self.db_connection_changed.emit(self._db, ladm_col_schema,
                                            self.db_source)
            self.logger.debug(
                __name__, "Settings dialog emitted a db_connection_changed.")

        if not ladm_col_schema and self._action_type == EnumDbActionType.CONFIG:
            msg_box = QMessageBox(self)
            msg_box.setIcon(QMessageBox.Question)
            msg_box.setText(
                QCoreApplication.translate(
                    "SettingsDialog",
                    "No LADM-COL DB has been configured! You'll continue with limited functionality until you configure a LADM-COL DB.\n\nDo you want to go to 'Create LADM-COL structure' dialog?"
                ))
            msg_box.setWindowTitle(
                QCoreApplication.translate("SettingsDialog", "Important"))
            msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.Ignore)
            msg_box.setDefaultButton(QMessageBox.Ignore)
            msg_box.button(QMessageBox.Yes).setText(
                QCoreApplication.translate("SettingsDialog",
                                           "Yes, go to create structure"))
            msg_box.button(QMessageBox.Ignore).setText(
                QCoreApplication.translate("SettingsDialog",
                                           "No, I'll do it later"))
            reply = msg_box.exec_()

            if reply == QMessageBox.Yes:
                self._open_dlg_import_schema = True  # We will open it when we've closed this Settings dialog

        # If active role is changed (a check and confirmation may be needed), refresh the GUI
        # Note: Better to leave this check as the last one in the accepted() method.
        selected_role = self.get_selected_role()
        if self.roles.get_active_role() != selected_role:
            b_change_role = True
            if STSession().is_user_logged():
                reply = QMessageBox.question(
                    self.parent,
                    QCoreApplication.translate("SettingsDialog", "Warning"),
                    QCoreApplication.translate(
                        "SettingsDialog",
                        "You have a ST connection opened and you want to change your role.\nIf you confirm that you want to change your role, you'll be logged out from the ST.\n\nDo you really want to change your role?"
                    ), QMessageBox.Yes | QMessageBox.Cancel,
                    QMessageBox.Cancel)
                if reply == QMessageBox.Yes:
                    STSession().logout()
                elif reply == QMessageBox.Cancel:
                    # No need to switch back selected role, the Settings Dialog gets it from role registry
                    b_change_role = False

            if b_change_role:
                self.logger.info(
                    __name__,
                    "The active role has changed from '{}' to '{}'.".format(
                        self.roles.get_active_role(), selected_role))
                self.roles.set_active_role(
                    selected_role
                )  # Emits signal that refreshed the plugin for this role

        self.save_settings(db)

        QDialog.accept(self)
        self.close()

        if self._open_dlg_import_schema:
            # After Settings dialog has been closed, we could call Import Schema depending on user's answer above
            self.open_dlg_import_schema.emit(Context())
            self.logger.debug(
                __name__,
                "Settings dialog emitted a show Import Schema dialog.")

    def check_document_repository_before_saving_settings(self):
        # Check if source service is checked (active). If so, check if either status or endpoint changed. If so,
        # check if self._valid_document_repository is False. If so, we need to test the service and only allow to save
        # if such test is successful.
        res, msg = True, ''
        if self.connection_box.isChecked(
        ):  # The user wants to have the source service enabled
            initial_config = QSettings().value(
                'Asistente-LADM-COL/sources/use_service',
                DEFAULT_USE_SOURCE_SERVICE_SETTING, bool)
            initial_endpoint = QSettings().value(
                'Asistente-LADM-COL/sources/service_endpoint',
                DEFAULT_ENDPOINT_SOURCE_SERVICE)

            # Config changed or Endpoint changed?
            if initial_config != self.connection_box.isChecked(
            ) or initial_endpoint.strip() != self.txt_service_endpoint.text(
            ).strip():
                if not self._valid_document_repository:  # A test service has not been run, so we need to do it now
                    self.logger.debug(
                        __name__,
                        "The user wants to enable the source service but the 'test service' has not been run on the current URL. Testing it..."
                    )
                    res_test, msg_test = self.test_service()
                    if not res_test:
                        res = False
                        msg = QCoreApplication.translate(
                            "SettingsDialog",
                            "The source service is not valid, so it cannot be activated! Adjust such configuration before saving settings."
                        )

        return res, msg

    def source_service_endpoint_changed(self, new_text):
        # Source service endpoint was changed, so a test_service is required to make the valid variable True
        self._valid_document_repository = False

    def get_selected_role(self):
        selected_role = None
        radio_checked = None
        for i in range(self.gbx_active_role_layout.count()):
            radio = self.gbx_active_role_layout.itemAt(i).widget()
            if radio.isChecked():
                radio_checked = radio.text()
                break

        for k, v in self.roles.get_roles_info().items():
            if v == radio_checked:
                selected_role = k
                break

        return selected_role  # Role key

    def reject(self):
        self.done(0)

    def finished_slot(self, result):
        self.bar.clearWidgets()

    def save_settings(self, db):
        settings = QSettings()
        current_db_engine = self.cbo_db_engine.currentData()
        settings.setValue(
            'Asistente-LADM-COL/db/{db_source}/db_connection_engine'.format(
                db_source=self.db_source), current_db_engine)
        dict_conn = self._lst_panel[
            current_db_engine].read_connection_parameters()

        self._lst_db[current_db_engine].save_parameters_conn(
            dict_conn=dict_conn, db_source=self.db_source)

        settings.setValue(
            'Asistente-LADM-COL/models/custom_model_directories_is_checked',
            self.offline_models_radio_button.isChecked())
        if self.offline_models_radio_button.isChecked():
            settings.setValue('Asistente-LADM-COL/models/custom_models',
                              self.custom_model_directories_line_edit.text())

        self.app.settings.tolerance = self.sbx_tolerance.value()
        settings.setValue('Asistente-LADM-COL/quality/use_roads',
                          self.chk_use_roads.isChecked())

        settings.setValue(
            'Asistente-LADM-COL/models/validate_data_importing_exporting',
            self.chk_validate_data_importing_exporting.isChecked())

        endpoint_transitional_system = self.txt_service_transitional_system.text(
        ).strip()
        settings.setValue(
            'Asistente-LADM-COL/sources/service_transitional_system',
            (endpoint_transitional_system[:-1]
             if endpoint_transitional_system.endswith('/') else
             endpoint_transitional_system)
            or TransitionalSystemConfig().ST_DEFAULT_DOMAIN)

        settings.setValue('Asistente-LADM-COL/sources/use_service',
                          self.connection_box.isChecked())
        endpoint = self.txt_service_endpoint.text().strip()
        settings.setValue(
            'Asistente-LADM-COL/sources/service_endpoint',
            (endpoint[:-1] if endpoint.endswith('/') else endpoint)
            or DEFAULT_ENDPOINT_SOURCE_SERVICE)

        settings.setValue(
            'Asistente-LADM-COL/automatic_values/automatic_values_in_batch_mode',
            self.chk_automatic_values_in_batch_mode.isChecked())

        # Changes in automatic namespace, local_id or t_ili_tid configuration?
        current_namespace_enabled = settings.value(
            'Asistente-LADM-COL/automatic_values/namespace_enabled', True,
            bool)
        current_namespace_prefix = settings.value(
            'Asistente-LADM-COL/automatic_values/namespace_prefix', "")
        current_local_id_enabled = settings.value(
            'Asistente-LADM-COL/automatic_values/local_id_enabled', True, bool)
        current_t_ili_tid_enabled = settings.value(
            'Asistente-LADM-COL/automatic_values/t_ili_tid_enabled', True,
            bool)

        settings.setValue(
            'Asistente-LADM-COL/automatic_values/namespace_enabled',
            self.namespace_collapsible_group_box.isChecked())
        if self.namespace_collapsible_group_box.isChecked():
            settings.setValue(
                'Asistente-LADM-COL/automatic_values/namespace_prefix',
                self.txt_namespace.text())

        settings.setValue(
            'Asistente-LADM-COL/automatic_values/local_id_enabled',
            self.chk_local_id.isChecked())
        settings.setValue(
            'Asistente-LADM-COL/automatic_values/t_ili_tid_enabled',
            self.chk_t_ili_tid.isChecked())

        if current_namespace_enabled != self.namespace_collapsible_group_box.isChecked() or \
           current_namespace_prefix != self.txt_namespace.text() or \
           current_local_id_enabled != self.chk_local_id.isChecked() or \
           current_t_ili_tid_enabled != self.chk_t_ili_tid.isChecked():
            if db is not None:
                self.logger.info(
                    __name__,
                    "Automatic values changed in Settings dialog. All LADM-COL layers are being updated..."
                )
                self.app.core.automatic_fields_settings_changed(db)

    def restore_db_source_settings(self):
        settings = QSettings()
        default_db_engine = self.dbs_supported.id_default_db

        self.init_db_engine = settings.value(
            'Asistente-LADM-COL/db/{db_source}/db_connection_engine'.format(
                db_source=self.db_source), default_db_engine)
        index_db_engine = self.cbo_db_engine.findData(self.init_db_engine)

        if index_db_engine == -1:
            index_db_engine = self.cbo_db_engine.findData(default_db_engine)

        self.cbo_db_engine.setCurrentIndex(index_db_engine)
        self.db_engine_changed()

        # restore db settings for all panels
        for db_engine, db_factory in self._lst_db.items():
            dict_conn = db_factory.get_parameters_conn(self.db_source)
            self._lst_panel[db_engine].write_connection_parameters(dict_conn)
            self._lst_panel[db_engine].save_state()

    def restore_settings(self):
        # Restore QSettings
        settings = QSettings()

        custom_model_directories_is_checked = settings.value(
            'Asistente-LADM-COL/models/custom_model_directories_is_checked',
            DEFAULT_USE_CUSTOM_MODELS,
            type=bool)
        if custom_model_directories_is_checked:
            self.offline_models_radio_button.setChecked(True)
            self.custom_model_directories_line_edit.setText(
                settings.value('Asistente-LADM-COL/models/custom_models',
                               DEFAULT_MODELS_DIR))
            self.custom_model_directories_line_edit.setVisible(True)
            self.custom_models_dir_button.setVisible(True)
        else:
            self.online_models_radio_button.setChecked(True)
            self.custom_model_directories_line_edit.setText("")
            self.custom_model_directories_line_edit.setVisible(False)
            self.custom_models_dir_button.setVisible(False)

        self.sbx_tolerance.setValue(self.app.settings.tolerance)
        use_roads = settings.value('Asistente-LADM-COL/quality/use_roads',
                                   True, bool)
        self.chk_use_roads.setChecked(use_roads)
        self.update_images_state(use_roads)

        self.chk_automatic_values_in_batch_mode.setChecked(
            settings.value(
                'Asistente-LADM-COL/automatic_values/automatic_values_in_batch_mode',
                DEFAULT_AUTOMATIC_VALUES_IN_BATCH_MODE, bool))
        self.connection_box.setChecked(
            settings.value('Asistente-LADM-COL/sources/use_service',
                           DEFAULT_USE_SOURCE_SERVICE_SETTING, bool))
        self.namespace_collapsible_group_box.setChecked(
            settings.value(
                'Asistente-LADM-COL/automatic_values/namespace_enabled', True,
                bool))
        self.chk_local_id.setChecked(
            settings.value(
                'Asistente-LADM-COL/automatic_values/local_id_enabled', True,
                bool))
        self.chk_t_ili_tid.setChecked(
            settings.value(
                'Asistente-LADM-COL/automatic_values/t_ili_tid_enabled', True,
                bool))
        self.txt_namespace.setText(
            str(
                settings.value(
                    'Asistente-LADM-COL/automatic_values/namespace_prefix',
                    "")))

        self.chk_validate_data_importing_exporting.setChecked(
            settings.value(
                'Asistente-LADM-COL/models/validate_data_importing_exporting',
                True, bool))

        self.txt_service_transitional_system.setText(
            settings.value(
                'Asistente-LADM-COL/sources/service_transitional_system',
                TransitionalSystemConfig().ST_DEFAULT_DOMAIN))
        self.txt_service_endpoint.setText(
            settings.value('Asistente-LADM-COL/sources/service_endpoint',
                           DEFAULT_ENDPOINT_SOURCE_SERVICE))

    def db_engine_changed(self):
        if self._db is not None:
            self._db.close_connection()

        self._db = None  # Reset db connection

        for key, value in self._lst_panel.items():
            value.setVisible(False)

        current_db_engine = self.cbo_db_engine.currentData()

        self._lst_panel[current_db_engine].setVisible(True)

    def test_connection(self):
        db = self._get_db_connector_from_gui()
        test_level = EnumTestLevel.DB_SCHEMA

        if self._action_type == EnumDbActionType.SCHEMA_IMPORT:
            test_level |= EnumTestLevel.SCHEMA_IMPORT

        res, code, msg = db.test_connection(
            test_level
        )  # No need to pass required_models, we don't test that much

        if db is not None:
            db.close_connection()

        self.show_message(msg, Qgis.Info if res else Qgis.Warning)
        self.logger.info(__name__, "Test connection!")
        self.logger.debug(
            __name__,
            "Test connection ({}): {}, {}".format(test_level, res, msg))

    def test_ladm_col_structure(self):
        db = self._get_db_connector_from_gui()
        res, code, msg = db.test_connection(
            test_level=EnumTestLevel.LADM,
            required_models=self._required_models)

        if db is not None:
            db.close_connection()

        self.show_message(msg, Qgis.Info if res else Qgis.Warning)
        self.logger.info(__name__, "Test LADM structure!")
        self.logger.debug(
            __name__,
            "Test connection ({}): {}, {}".format(EnumTestLevel.LADM, res,
                                                  msg))

    def test_service(self):
        self.setEnabled(False)
        QCoreApplication.processEvents()
        res, msg = self.app.core.is_source_service_valid(
            self.txt_service_endpoint.text().strip())
        self._valid_document_repository = res  # Required to be True if the user wants to enable the source service
        self.setEnabled(True)
        self.show_message(msg['text'], msg['level'], 0)
        return res, msg

    def test_service_transitional_system(self):
        self.setEnabled(False)
        QCoreApplication.processEvents()
        res, msg = self.app.core.is_transitional_system_service_valid(
            self.txt_service_transitional_system.text().strip())
        self.setEnabled(True)
        self.show_message(msg['text'], msg['level'])

    def set_default_value_source_service(self):
        self.txt_service_endpoint.setText(DEFAULT_ENDPOINT_SOURCE_SERVICE)

    def set_default_value_transitional_system_service(self):
        self.txt_service_transitional_system.setText(
            TransitionalSystemConfig().ST_DEFAULT_DOMAIN)

    def show_message(self, message, level, duration=10):
        self.bar.clearWidgets(
        )  # Remove previous messages before showing a new one
        self.bar.pushMessage(message, level, duration)

    def show_tip(self, tip):
        self.show_message(tip, Qgis.Info,
                          0)  # Don't show counter for the tip message

    def update_images_state(self, checked):
        self.img_with_roads.setEnabled(checked)
        self.img_with_roads.setToolTip(
            QCoreApplication.translate(
                "SettingsDialog", "Missing roads will be marked as errors."
            ) if checked else '')
        self.img_without_roads.setEnabled(not checked)
        self.img_without_roads.setToolTip(
            '' if checked else QCoreApplication.translate(
                "SettingsDialog", "Missing roads will not be marked as errors."
            ))

    def show_help(self):
        show_plugin_help("settings")

    def set_action_type(self, action_type):
        self._action_type = action_type

        for key, value in self._lst_panel.items():
            value.set_action(action_type)
예제 #14
0
class QualityRuleManager(QObject, metaclass=SingletonQObject):
    def __init__(self):
        self.logger = Logger()
        self.__quality_rules_data = QualityRuleConfig.get_quality_rules_config(
        )
        self.__translated_strings = TranslatableConfigStrings(
        ).get_translatable_config_strings()
        self._quality_rule_groups = dict()
        self.__quality_rules = dict()

        self.role_registry = RoleRegistry()

        self._initialize_quality_rule_manager()

    def _initialize_quality_rule_manager(self):
        for group_k, group_v in self.__quality_rules_data.items():
            self._quality_rule_groups[group_k] = group_v[QUALITY_GROUP_NAME]

            for rule_k, rule_v in group_v[QUALITY_RULES].items():
                self.__quality_rules[rule_k] = QualityRule(rule_v)
        self.logger.info(
            __name__,
            "{} quality rules registered!".format(len(self.__quality_rules)))

    def get_quality_rule(self, rule_key):
        """
        Returns the QualityRule object corresponding to a rule code.

        :param rule_key: rule key
        :return: QualityRule
        """
        return self.__quality_rules.get(rule_key)

    def get_quality_rule_group_name(self, group_key):
        """
        Returns a quality rule group name.

        :param group_key: Group key
        :return: Group name if the group key is found. Otherwise, None.
        """
        return self._quality_rule_groups.get(group_key)

    def get_quality_rules_by_group(self, enum_group=None):
        """
        Returns all rules in a given group. If no enum_group is given,
        it returns the whole set of rules classified by group.

        :param enum_group:  EnumQualityRule.Point|Line|Polygon|Logic
        :return: dict of rules
        """
        quality_rules_group = dict()
        role_key = self.role_registry.get_active_role()
        role_quality_rules = self.role_registry.get_role_quality_rules(
            role_key)

        if enum_group:
            quality_rules_group = {
                k_rule: v_rule
                for k_rule, v_rule in self.__quality_rules.items()
                if k_rule in enum_group and k_rule in role_quality_rules
            }
        else:
            quality_rules_group[EnumQualityRule.Point] = dict()
            quality_rules_group[EnumQualityRule.Line] = dict()
            quality_rules_group[EnumQualityRule.Polygon] = dict()
            quality_rules_group[EnumQualityRule.Logic] = dict()

            for k_quality_rule, v_quality_rule in self.__quality_rules.items():
                if k_quality_rule in role_quality_rules:
                    if k_quality_rule in EnumQualityRule.Point:
                        quality_rules_group[EnumQualityRule.Point][
                            k_quality_rule] = v_quality_rule
                    elif k_quality_rule in EnumQualityRule.Line:
                        quality_rules_group[EnumQualityRule.Line][
                            k_quality_rule] = v_quality_rule
                    elif k_quality_rule in EnumQualityRule.Polygon:
                        quality_rules_group[EnumQualityRule.Polygon][
                            k_quality_rule] = v_quality_rule
                    elif k_quality_rule in EnumQualityRule.Logic:
                        quality_rules_group[EnumQualityRule.Logic][
                            k_quality_rule] = v_quality_rule

            self.logger.debug(
                __name__, "Quality Rules for role '{}': {}".format(
                    role_key,
                    ", ".join([str(rqr.value) for rqr in role_quality_rules])))

        return quality_rules_group

    def get_error_message(self, error_code):
        return self.__translated_strings.get(error_code)
class WelcomeScreenDialog(QDialog, DIALOG_UI):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.logger = Logger()
        self.help_strings = HelpStrings()

        #self.txt_help_page.setHtml(self.help_strings.DLG_WELCOME_SCREEN)
        #self.txt_help_page.anchorClicked.connect(self.save_template)

        self.finished.connect(self.finish_dialog)
        self.buttonBox.helpRequested.connect(self.show_help)

        self.gbx_layout = QVBoxLayout()
        self.roles = RoleRegistry()
        self.dict_roles = self.roles.get_roles_info()
        checked = False
        active_role = self.roles.get_active_role()

        # Initialize radio buttons
        for k,v in self.dict_roles.items():
            radio = QRadioButton(v)
            if not checked:
                if k == active_role:
                    radio.setChecked(True)
                    checked = True
                    self.show_description(self.roles.get_role_description(k), checked)  # Initialize help page

            radio.toggled.connect(partial(self.show_description, self.roles.get_role_description(k)))
            self.gbx_layout.addWidget(radio)

        self.gbx_options.setLayout(self.gbx_layout)

    def finish_dialog(self, result):
        if result == 0:
            self.roles.set_active_default_role(emit_signal=False)  # Welcome dialog should not emit role_changed signal
        else:
            self.set_checked_role_active()

        self.logger.info_msg(__name__, QCoreApplication.translate("WelcomeScreenDialog",
                                                                  "The role '{}' is now active!").format(self.roles.get_active_role_name()))

    def show_description(self, description, checked):
        if checked:
            self.txt_help_page.setHtml("<span style=\" color:#545454;\">{}</span>".format(description))

    def set_checked_role_active(self):
        radio_checked = None
        for i in range(self.gbx_layout.count()):
            radio = self.gbx_layout.itemAt(i).widget()
            if radio.isChecked():
                radio_checked = radio.text()
                break

        for k, v in self.dict_roles.items():
            if v == radio_checked:
                self.roles.set_active_role(k, emit_signal=False)  # Welcome dialog should not emit role_changed signal
                break

    def show_help(self):
        show_plugin_help()
 def refresh_mapping_for_role(self):
     for model_key in RoleRegistry().get_active_role_supported_models():
         if model_key in DB_MAPPING_CONFIG:
             self.register_db_mapping(DB_MAPPING_CONFIG[model_key])