def set_completer_object(dialog, table_object):
    """ Set autocomplete of widget @table_object + "_id"
        getting id's from selected @table_object
    """

    widget = qt_tools.getWidget(dialog, table_object + "_id")
    if not widget:
        return

    # Set SQL
    field_object_id = "id"
    if table_object == "element":
        field_object_id = table_object + "_id"
    sql = (f"SELECT DISTINCT({field_object_id})" f" FROM {table_object}")
    rows = global_vars.controller.get_rows(sql)
    if rows is None:
        return

    for i in range(0, len(rows)):
        aux = rows[i]
        rows[i] = str(aux[0])

    # Set completer and model: add autocomplete in the widget
    completer = QCompleter()
    completer.setCaseSensitivity(Qt.CaseInsensitive)
    widget.setCompleter(completer)
    model = QStringListModel()
    model.setStringList(rows)
    completer.setModel(model)
Exemplo n.º 2
0
    def setupCompleter(self):
        # set up string list for completer

        TOMsMessageLog.logMessage("In setupCompleter:", level=Qgis.Info)
        lookupStringSet = set()
        # https://gis.stackexchange.com/questions/155805/qstringlist-error-in-plugin-of-qgis-2-10

        self.GazetteerLayer = QgsProject.instance().mapLayersByName("StreetGazetteerRecords")[0]

        for row in self.GazetteerLayer.getFeatures():
            streetName = row.attribute("Descriptor_")
            locality = row.attribute("Locality")
            nameString = streetName
            if locality:
                nameString = nameString + ", " + locality

            if nameString:
                TOMsMessageLog.logMessage("In setupCompleter: nameString: " + nameString, level=Qgis.Info)
                lookupStringSet.add(nameString)
                # self.gazetteerStringList.append((nameString))

        completer = QCompleter()
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setFilterMode(Qt.MatchContains)
        self.searchTextbox.setCompleter(completer)
        model = QStringListModel()
        completer.setModel(model)
        model.setStringList(self.gazetteerStringList)
        model.setStringList(sorted(lookupStringSet))
Exemplo n.º 3
0
 def setCompleter(self, values, wgt):
     completer = QCompleter(self)
     completerModel = QStringListModel(self)
     wgt.setCompleter(completer)
     completer.setModel(completerModel)
     completer.setCaseSensitivity(False)
     completerModel.setStringList(values)
 def update_models_completer(self):
     completer = QCompleter(self.ilicache.model, self.ili_models_line_edit)
     completer.setCaseSensitivity(Qt.CaseInsensitive)
     completer.setFilterMode(Qt.MatchContains)
     self.delegate = ModelCompleterDelegate()
     completer.popup().setItemDelegate(self.delegate)
     self.ili_models_line_edit.setCompleter(completer)
     self.multiple_models_dialog.models_line_edit.setCompleter(completer)
Exemplo n.º 5
0
    def __init__(self, parent, title):
        QWizardPage.__init__(self, parent)
        self.workflow_wizard = parent

        self.setupUi(self)
        self.setTitle(title)

        self.workflow_wizard = parent
        self.is_complete = True

        self.model_list_view.setModel(self.workflow_wizard.import_models_model)
        self.model_list_view.clicked.connect(
            self.workflow_wizard.import_models_model.check)
        self.model_list_view.space_pressed.connect(
            self.workflow_wizard.import_models_model.check)
        self.model_list_view.model().modelReset.connect(
            self._update_models_dependent_info)

        self.crs = QgsCoordinateReferenceSystem()
        self.ili2db_options = Ili2dbOptionsDialog(self)
        self.ili2db_options_button.clicked.connect(self.ili2db_options.open)
        self.ili2db_options.finished.connect(self._fill_toml_file_info_label)

        self.crsSelector.crsChanged.connect(self._crs_changed)

        self.ilimetaconfigcache = IliDataCache(
            self.workflow_wizard.import_schema_configuration.base_configuration
        )
        self.metaconfig_delegate = MetaConfigCompleterDelegate()
        self.metaconfig = configparser.ConfigParser()
        self.current_models = None
        self.current_metaconfig_id = None
        self.ili_metaconfig_line_edit.setPlaceholderText(
            self.tr("[Search metaconfig / topping from UsabILIty Hub]"))
        self.ili_metaconfig_line_edit.setEnabled(False)
        completer = QCompleter(self.ilimetaconfigcache.model,
                               self.ili_metaconfig_line_edit)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setFilterMode(Qt.MatchContains)
        completer.popup().setItemDelegate(self.metaconfig_delegate)
        self.ili_metaconfig_line_edit.setCompleter(completer)
        self.ili_metaconfig_line_edit.textChanged.emit(
            self.ili_metaconfig_line_edit.text())
        self.ili_metaconfig_line_edit.textChanged.connect(
            self._complete_metaconfig_completer)
        self.ili_metaconfig_line_edit.punched.connect(
            self._complete_metaconfig_completer)
        self.ili_metaconfig_line_edit.textChanged.connect(
            self._on_metaconfig_completer_activated)
        self.workflow_wizard.ilireferencedatacache.model_refreshed.connect(
            self._update_linked_models)
Exemplo n.º 6
0
def set_completer_lineedit(qlineedit, list_items):
    """ Set a completer into a QLineEdit
    :param qlineedit: Object where to set the completer (QLineEdit)
    :param list_items: List of items to set into the completer (List)["item1","item2","..."]
    """

    completer = QCompleter()
    completer.setCaseSensitivity(Qt.CaseInsensitive)
    completer.setMaxVisibleItems(10)
    completer.setCompletionMode(0)
    completer.setFilterMode(Qt.MatchContains)
    completer.popup().setStyleSheet("color: black;")
    qlineedit.setCompleter(completer)
    model = QStringListModel()
    model.setStringList(list_items)
    completer.setModel(model)
Exemplo n.º 7
0
    def _update_completer(self, values):
        # Get the items in a tuple and put them in a list

        # Store display and actual values in a
        # model for easier mapping and
        # retrieval when carrying out searches

        model_attr_mapping = []

        # Check if there are formaters specified
        # for the current field name
        for mv in values:
            f_model_values = []

            m_val = mv[0]

            if m_val is not None:
                col_label = self.currentFieldName()
                if col_label in self.config.LookupFormatters:
                    formatter = self.config.LookupFormatters[col_label]
                    if formatter.column.TYPE_INFO == 'LOOKUP':
                        m_val = formatter.code_value(m_val)[0]
                    else:
                        m_val = formatter.format_column_value(m_val)
            f_model_values.extend([m_val, m_val])

            model_attr_mapping.append(f_model_values)

        self._completer_model = BaseSTDMTableModel(model_attr_mapping,
                                                   ["", ""], self)

        # We will use the QSortFilterProxyModel for filtering purposes
        self._proxy_completer_model = QSortFilterProxyModel()
        self._proxy_completer_model.setDynamicSortFilter(True)
        self._proxy_completer_model.setSourceModel(self._completer_model)
        self._proxy_completer_model.setSortCaseSensitivity(Qt.CaseInsensitive)
        self._proxy_completer_model.setFilterKeyColumn(0)

        # Configure completer
        mod_completer = QCompleter(self._completer_model, self)
        mod_completer.setCaseSensitivity(Qt.CaseInsensitive)
        mod_completer.setCompletionMode(QCompleter.PopupCompletion)
        mod_completer.setCompletionColumn(0)
        mod_completer.setCompletionRole(Qt.DisplayRole)

        self.txtFilterPattern.setCompleter(mod_completer)
Exemplo n.º 8
0
def set_completer_rows(widget, rows):
    """ Set a completer into a widget
    :param widget: Object where to set the completer (QLineEdit)
    :param rows: rows to set into the completer (List)["item1","item2","..."]
    """

    if rows is None:
        return

    list_values = []
    for row in rows:
        list_values.append(str(row[0]))

    # Set completer and model: add autocomplete in the widget
    completer = QCompleter()
    completer.setCaseSensitivity(Qt.CaseInsensitive)
    widget.setCompleter(completer)
    model = QStringListModel()
    model.setStringList(list_values)
    completer.setModel(model)
def set_completer_feature_id(widget, geom_type, viewname):
    """ Set autocomplete of widget 'feature_id'
        getting id's from selected @viewname
    """

    if geom_type == '':
        return

    # Adding auto-completion to a QLineEdit
    completer = QCompleter()
    completer.setCaseSensitivity(Qt.CaseInsensitive)
    widget.setCompleter(completer)
    model = QStringListModel()

    sql = (f"SELECT {geom_type}_id" f" FROM {viewname}")
    row = global_vars.controller.get_rows(sql)
    if row:
        for i in range(0, len(row)):
            aux = row[i]
            row[i] = str(aux[0])

        model.setStringList(row)
        completer.setModel(model)
def set_completer_widget(tablename, widget, field_id):
    """ Set autocomplete of widget @table_object + "_id"
        getting id's from selected @table_object
    """

    if not widget:
        return

    # Set SQL
    sql = (f"SELECT DISTINCT({field_id})"
           f" FROM {tablename}"
           f" ORDER BY {field_id}")
    row = global_vars.controller.get_rows(sql)
    for i in range(0, len(row)):
        aux = row[i]
        row[i] = str(aux[0])

    # Set completer and model: add autocomplete in the widget
    completer = QCompleter()
    completer.setCaseSensitivity(Qt.CaseInsensitive)
    widget.setCompleter(completer)
    model = QStringListModel()
    model.setStringList(row)
    completer.setModel(model)
Exemplo n.º 11
0
class DeletionReason(QDialog, FORM_CLASS):
    def __init__(self, selected_number, parent=None):
        super(DeletionReason, self).__init__(parent)
        self.setupUi(self)
        self.setWindowModality(Qt.ApplicationModal)
        self.db = db
        # initiate label
        self.lb_reason.setText(
            "Number of outlines that will be deleted: {}".format(
                selected_number))
        # initiate le_deletion_reason
        self.le_reason.setMaxLength(250)
        self.le_reason.setPlaceholderText("Reason for Deletion")
        self.completer_box()

    def completer_box(self):
        """Box automatic completion"""
        reasons = self.db._execute(bulk_load_select.deletion_description_value)
        reason_list = [row[0] for row in reasons.fetchall()]
        # Fill the search box
        self.completer = QCompleter(reason_list)
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.le_reason.setCompleter(self.completer)
Exemplo n.º 12
0
class TmParentAction(object):
    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class constructor """

        # Initialize instance attributes
        self.tree_manage_version = "1.0"
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.settings = settings
        self.controller = controller
        self.plugin_dir = plugin_dir
        self.dao = self.controller.dao
        self.schema_name = self.controller.schema_name
        self.project_type = None
        self.file_gsw = None
        self.gsw_settings = None
        self.lazy_widget = None

    def set_controller(self, controller):
        """ Set controller class """

        self.controller = controller
        self.schema_name = self.controller.schema_name

    def get_plugin_version(self):
        """ Get plugin version from metadata.txt file """

        # Check if metadata file exists
        metadata_file = os.path.join(self.plugin_dir, 'metadata.txt')
        if not os.path.exists(metadata_file):
            message = "Metadata file not found" + metadata_file
            self.controller.show_warning(message, parameter=metadata_file)
            return None

        metadata = configparser.ConfigParser()
        metadata.read(metadata_file)
        plugin_version = metadata.get('general', 'version')
        if plugin_version is None:
            message = "Plugin version not found"
            self.controller.show_warning(message)

        return plugin_version

    def load_settings(self, dialog=None):
        """ Load QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        try:
            screens = ctypes.windll.user32
            screen_x = screens.GetSystemMetrics(78)
            screen_y = screens.GetSystemMetrics(79)
            x = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_x")
            y = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_y")
            width = self.controller.plugin_settings_value(
                dialog.objectName() + "_width", dialog.property('width'))
            height = self.controller.plugin_settings_value(
                dialog.objectName() + "_height", dialog.property('height'))

            if int(x) < 0 or int(y) < 0:
                dialog.resize(int(width), int(height))
            else:
                if int(x) > screen_x:
                    x = int(screen_x) - int(width)
                if int(y) > screen_y:
                    y = int(screen_y)
                dialog.setGeometry(int(x), int(y), int(width), int(height))
        except:
            pass

    def save_settings(self, dialog=None):
        """ Save QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_width", dialog.width())
        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_height", dialog.height())
        self.controller.plugin_settings_set_value(dialog.objectName() + "_x",
                                                  dialog.pos().x() + 8)
        self.controller.plugin_settings_set_value(dialog.objectName() + "_y",
                                                  dialog.pos().y() + 31)

    def open_dialog(self,
                    dlg=None,
                    dlg_name=None,
                    info=True,
                    maximize_button=True,
                    stay_on_top=True):
        """ Open dialog """

        # Check database connection before opening dialog
        if not self.controller.check_db_connection():
            return

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg

        # Manage i18n of the dialog
        if dlg_name:
            self.controller.manage_translation(dlg_name, dlg)

        # Manage stay on top, maximize/minimize button and information button
        # if info is True maximize flag will be ignored
        # To enable maximize button you must set info to False
        flags = Qt.WindowCloseButtonHint
        if info:
            flags |= Qt.WindowSystemMenuHint | Qt.WindowContextHelpButtonHint
        else:
            if maximize_button:
                flags |= Qt.WindowMinMaxButtonsHint

        if stay_on_top:
            flags |= Qt.WindowStaysOnTopHint

        dlg.setWindowFlags(flags)

        # Open dialog
        if issubclass(type(dlg), GwDialog):
            dlg.open()
        elif issubclass(type(dlg), GwMainWindow):
            dlg.show()
        else:
            dlg.show()

    def close_dialog(self, dlg=None):
        """ Close dialog """

        try:
            self.save_settings(dlg)
            dlg.close()
            map_tool = self.canvas.mapTool()
            # If selected map tool is from the plugin, set 'Pan' as current one
            if map_tool.toolName() == '':
                self.iface.actionPan().trigger()
        except AttributeError:
            pass

    def hide_colums(self, widget, comuns_to_hide):
        for i in range(0, len(comuns_to_hide)):
            widget.hideColumn(comuns_to_hide[i])

    def set_icon(self, widget, icon):
        """ Set @icon to selected @widget """

        # Get icons folder
        icons_folder = os.path.join(self.plugin_dir, 'icons')
        icon_path = os.path.join(icons_folder, str(icon) + ".png")
        if os.path.exists(icon_path):
            widget.setIcon(QIcon(icon_path))
        else:
            self.controller.log_info("File not found", parameter=icon_path)

    def check_expression(self, expr_filter, log_info=False):
        """ Check if expression filter @expr_filter is valid """

        if log_info:
            self.controller.log_info(expr_filter)
        expr = QgsExpression(expr_filter)
        if expr.hasParserError():
            message = "Expression Error"
            self.controller.log_warning(message, parameter=expr_filter)
            return False, expr

        return True, expr

    def set_table_columns(self, dialog, widget, table_name, project_type=None):
        """ Configuration of tables. Set visibility and width of columns """

        widget = utils_giswater.getWidget(dialog, widget)
        if not widget:
            return

        # Set width and alias of visible columns
        columns_to_delete = []
        sql = (f"SELECT columnindex, width, alias, status"
               f" FROM config_form_tableview"
               f" WHERE tablename = '{table_name}'")
        if project_type is not None:
            sql += f" AND project_type = '{project_type}' "
        sql += " ORDER BY column_index"

        rows = self.controller.get_rows(sql, log_info=False)
        if not rows:
            return

        for row in rows:
            if not row['status']:
                columns_to_delete.append(row['columnindex'] - 1)
            else:
                width = row['width']
                if width is not None:
                    widget.setColumnWidth(row['columnindex'] - 1, width)
                widget.model().setHeaderData(row['columnindex'] - 1,
                                             Qt.Horizontal, row['alias'])

        widget.model().select()

        # Delete columns
        for column in columns_to_delete:
            widget.hideColumn(column)

    def set_completer_object(self, tablename, widget, field_search):
        """ Set autocomplete of widget @table_object + "_id"
            getting id's from selected @table_object
        """

        if not widget:
            return

        # Set SQL
        sql = (f"SELECT DISTINCT({field_search})"
               f" FROM {tablename}"
               f" ORDER BY {field_search}")
        rows = self.controller.get_rows(sql)
        if rows is None:
            return

        for i in range(0, len(rows)):
            aux = rows[i]
            rows[i] = aux[0]

        # Set completer and model: add autocomplete in the widget
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(0)
        widget.setCompleter(self.completer)
        model = QStringListModel()
        model.setStringList(rows)
        self.completer.setModel(model)

    def refresh_map_canvas(self, restore_cursor=False):
        """ Refresh all layers present in map canvas """

        self.canvas.refreshAllLayers()
        for layer_refresh in self.canvas.layers():
            layer_refresh.triggerRepaint()

        if restore_cursor:
            self.set_cursor_restore()

    def set_cursor_restore(self):
        """ Restore to previous cursors """
        QApplication.restoreOverrideCursor()

    def get_cursor_multiple_selection(self):
        """ Set cursor for multiple selection """

        path_folder = os.path.join(os.path.dirname(__file__), os.pardir)
        path_cursor = os.path.join(path_folder, 'icons', '201.png')
        if os.path.exists(path_cursor):
            cursor = QCursor(QPixmap(path_cursor))
        else:
            cursor = QCursor(Qt.ArrowCursor)

        return cursor

    def fill_table(self,
                   qtable,
                   table_name,
                   set_edit_triggers=QTableView.NoEditTriggers,
                   expr_filter=None):
        """ Fill table @widget filtering query by @workcat_id
            Set a model with selected filter.
            Attach that model to selected table
            @setEditStrategy:
             0: OnFieldChange
             1: OnRowChange
             2: OnManualSubmit
        """

        expr = None
        if expr_filter:
            # Check expression
            (is_valid,
             expr) = self.check_expression(expr_filter)  # @UnusedVariable
            if not is_valid:
                return expr

        # Set a model with selected filter expression
        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set model
        model = QSqlTableModel()
        model.setTable(table_name)
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.setSort(0, 0)
        model.select()

        # When change some field we need to refresh Qtableview and filter by psector_id
        qtable.setEditTriggers(set_edit_triggers)

        # Check for errors
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())
        # Attach model to table view
        if expr:
            qtable.setModel(model)
            qtable.model().setFilter(expr_filter)
        else:
            qtable.setModel(model)

        return expr

    def get_feature_by_id(self, layer, id, field_id):

        features = layer.getFeatures()
        for feature in features:
            if feature[field_id] == id:
                return feature

        return False

    def put_combobox(self, qtable, rows, combo_values, field, combo_pos,
                     col_update):
        """ Set one column of a QtableView as QComboBox with values from database.
        :param qtable: QTableView to fill
        :param rows: List of items to set QComboBox (["..", "..."])
        :param combo_values: List of items to populate QComboBox (["..", "..."])
        :param field: Field to set QComboBox (String)
        :param combo_pos: Position of the column where we want to put the QComboBox (integer)
        :param col_update: Column to update into QTableView.Model() (integer)
        :return:
        """
        self.controller.log_info(str())
        for x, row in enumerate(rows):
            combo = QComboBox()
            combo.setSizeAdjustPolicy(2)
            # Populate QComboBox
            utils_giswater.set_item_data(combo, combo_values, 1)
            # Set QCombobox to wanted item
            utils_giswater.set_combo_itemData(combo, str(row[field]), 0)
            # Get index and put QComboBox into QTableView at index position
            idx = qtable.model().index(x, combo_pos)
            qtable.setIndexWidget(idx, combo)
            combo.currentIndexChanged.connect(
                partial(self.update_real_field, qtable, combo, x, combo_pos,
                        col_update))

    def update_real_field(self, qtable, combo, pos_x, combo_pos, col_update):
        """ Update values from QComboBox to QTableView
        :param qtable: QTableView Where update values
         :param combo: QComboBox from which we will take the value
        :param pos_x: Position of the row where we want to update value (integer)
        :param combo_pos: Position of the column where we want to put the QComboBox (integer)
        :param col_update: Column to update into QTableView.Model() (integer)
        :return:
        """

        elem = combo.itemData(combo.currentIndex())
        i = qtable.model().index(pos_x, combo_pos)
        qtable.model().setData(i, elem[0])
        i = qtable.model().index(pos_x, col_update)
        qtable.model().setData(i, elem[0])

    def create_body(self, form='', feature='', filter_fields='', extras=None):
        """ Create and return parameters as body to functions"""

        client = f'$${{"client":{{"device":4, "infoType":1, "lang":"ES"}}, '
        form = '"form":{' + form + '}, '
        feature = '"feature":{' + feature + '}, '
        filter_fields = '"filterFields":{' + filter_fields + '}'
        page_info = '"pageInfo":{}'
        data = '"data":{' + filter_fields + ', ' + page_info
        if extras is not None:
            data += ', ' + extras
        data += f'}}}}$$'
        body = "" + client + form + feature + data

        return body

    def set_dates_from_to(self, widget_from, widget_to, table_name, field_from,
                          field_to):

        sql = ("SELECT MIN(LEAST(" + field_from + ", " + field_to + ")),"
               " MAX(GREATEST(" + field_from + ", " + field_to + "))"
               " FROM " + table_name + "")
        row = self.controller.get_row(sql, log_sql=False)
        current_date = QDate.currentDate()
        if row:
            if row[0]:
                widget_from.setDate(row[0])
            else:
                widget_from.setDate(current_date)
            if row[1]:
                widget_to.setDate(row[1])
            else:
                widget_to.setDate(current_date)

    def remove_selection(self):
        """ Remove selected features of all layers """

        for layer in self.canvas.layers():
            if type(layer) is QgsVectorLayer:
                layer.removeSelection()
        self.canvas.refresh()

        for a in self.iface.attributesToolBar().actions():
            if a.objectName() == 'mActionDeselectAll':
                a.trigger()
                break
Exemplo n.º 13
0
class MapTilerGeocoderToolbar:
    def __init__(self, iface):
        # TODO: We are going to let the user set this up in a future iteration
        self.iface = iface
        self.proj = QgsProject.instance()
        self.toolbar = self.iface.addToolBar(u'MapTiler')
        self.toolbar.setObjectName(u'MapTiler')

        # init QCompleter
        self.completer = QCompleter([])
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setMaxVisibleItems(30)
        self.completer.setModelSorting(QCompleter.UnsortedModel)
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.completer.activated[QModelIndex].connect(self.on_result_clicked)

        # init LineEdit of searchword
        self.search_line_edit = QLineEdit()
        self.search_line_edit.setPlaceholderText('MapTiler Geocoding API')
        self.search_line_edit.setMaximumWidth(300)
        self.search_line_edit.setClearButtonEnabled(True)
        self.search_line_edit.setCompleter(self.completer)
        self.search_line_edit.textEdited.connect(self.on_searchword_edited)
        self.search_line_edit.returnPressed.connect(
            self.on_searchword_returned)
        self.toolbar.addWidget(self.search_line_edit)

        # LineEdit edited event
    def on_searchword_edited(self):
        model = self.completer.model()
        model.setStringList([])
        self.completer.complete()

    # LineEdit returned event
    def on_searchword_returned(self):
        searchword = self.search_line_edit.text()
        geojson_dict = self._fetch_geocoding_api(searchword)

        # always dict is Non when apikey invalid
        if geojson_dict is None:
            return

        self.result_features = geojson_dict['features']

        result_list = []
        for feature in self.result_features:
            result_list.append('%s:%s' %
                               (feature['text'], feature['place_name']))

        model = self.completer.model()
        model.setStringList(result_list)
        self.completer.complete()

    def _fetch_geocoding_api(self, searchword):
        # get a center point of MapCanvas
        center = self.iface.mapCanvas().center()
        center_as_qgspoint = QgsPoint(center.x(), center.y())

        # transform the center point to EPSG:4326
        target_crs = QgsCoordinateReferenceSystem('EPSG:4326')
        transform = QgsCoordinateTransform(self.proj.crs(), target_crs,
                                           self.proj)
        center_as_qgspoint.transform(transform)
        center_lonlat = [center_as_qgspoint.x(), center_as_qgspoint.y()]

        # start Geocoding
        locale = 'en'
        global_locale = QSettings().value('locale/globalLocale')
        if global_locale:
            locale = global_locale[0:2]
        else:
            user_locale = QSettings().value('locale/userLocale')
            if user_locale:
                locale = user_locale[0:2]

        geocoder = MapTilerGeocoder(locale)
        geojson_dict = geocoder.geocoding(searchword, center_lonlat)
        return geojson_dict

    def on_result_clicked(self, result_index):
        # add selected feature to Project
        selected_feature = self.result_features[result_index.row()]

        extent_rect = QgsRectangle()
        current_crs = QgsCoordinateReferenceSystem()

        bbox = selected_feature.get("bbox")
        geometry_type = selected_feature.get("geometry", {}).get("type")

        if bbox:
            extent_rect = QgsRectangle(bbox[0], bbox[1], bbox[2], bbox[3])
            current_crs = QgsCoordinateReferenceSystem("EPSG:4326")
        elif geometry_type == "GeometryCollection":
            geometries = selected_feature.get("geometries")
            if geometries is None:
                print("invalid GeoJSON")
                return
            tmp_geojson = {"type": "Feature", "geometry": geometries[0]}
            geojson_str = json.dumps(tmp_geojson)
            vlayer = QgsVectorLayer(geojson_str, 'tmp', 'ogr')
            extent_rect = vlayer.extent()
            current_crs = vlayer.sourceCrs()
        else:
            geojson_str = json.dumps(selected_feature)
            vlayer = QgsVectorLayer(geojson_str, 'tmp', 'ogr')
            extent_rect = vlayer.extent()
            current_crs = vlayer.sourceCrs()

        extent_leftbottom = QgsPoint(extent_rect.xMinimum(),
                                     extent_rect.yMinimum())
        extent_righttop = QgsPoint(extent_rect.xMaximum(),
                                   extent_rect.yMaximum())

        # transform 2points to project CRS
        target_crs = self.proj.crs()
        transform = QgsCoordinateTransform(current_crs, target_crs, self.proj)
        extent_leftbottom.transform(transform)
        extent_righttop.transform(transform)

        # make rectangle same to new extent by transformed 2points
        extent_rect = QgsRectangle(extent_leftbottom.x(),
                                   extent_leftbottom.y(), extent_righttop.x(),
                                   extent_righttop.y())

        self.iface.mapCanvas().zoomToFeatureExtent(extent_rect)
    def __init__(self, parent, title):
        QWizardPage.__init__(self, parent)
        self.workflow_wizard = parent

        self.setupUi(self)
        self.setTitle(title)

        self.workflow_wizard = parent
        self.is_complete = True
        self.basket_handling = False

        self.workflow_wizard.ilireferencedatacache.file_download_succeeded.connect(
            lambda dataset_id, path: self._on_referencedata_received(path)
        )
        self.workflow_wizard.ilireferencedatacache.file_download_failed.connect(
            self._on_referencedata_failed
        )
        self.ilireferencedata_delegate = MetaConfigCompleterDelegate()
        self.ilireferencedata_line_edit.setPlaceholderText(
            self.tr("[Search referenced data files from UsabILIty Hub]")
        )
        self.ilireferencedata_line_edit.setEnabled(False)
        completer = QCompleter(
            self.workflow_wizard.ilireferencedatacache.model,
            self.ilireferencedata_line_edit,
        )
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setFilterMode(Qt.MatchContains)
        completer.popup().setItemDelegate(self.ilireferencedata_delegate)
        self.ilireferencedata_line_edit.setCompleter(completer)
        self.ilireferencedata_line_edit.textChanged.emit(
            self.ilireferencedata_line_edit.text()
        )
        self.ilireferencedata_line_edit.textChanged.connect(
            self._complete_referencedata_completer
        )
        self.ilireferencedata_line_edit.punched.connect(
            self._complete_referencedata_completer
        )

        self.add_button.clicked.connect(self._add_row)
        self.remove_button.clicked.connect(self._remove_selected_rows)

        self.add_button.setEnabled(False)
        self.ilireferencedata_line_edit.textChanged.connect(
            lambda: self.add_button.setEnabled(self._valid_referencedata())
        )
        self.remove_button.setEnabled(self._valid_selection())
        self.file_table_view.clicked.connect(
            lambda: self.remove_button.setEnabled(self._valid_selection())
        )

        self.add_button.setIcon(QgsApplication.getThemeIcon("/symbologyAdd.svg"))
        self.remove_button.setIcon(QgsApplication.getThemeIcon("/symbologyRemove.svg"))

        self.workflow_wizard.import_data_file_model.sourceModel().setHorizontalHeaderLabels(
            [self.tr("Import File"), self.tr("Catalogue"), self.tr("Dataset")]
        )
        self.file_table_view.setModel(self.workflow_wizard.import_data_file_model)
        self.file_table_view.horizontalHeader().setSectionResizeMode(
            gui_utils.SourceModel.Columns.SOURCE, QHeaderView.Stretch
        )
        self.file_table_view.horizontalHeader().setSectionResizeMode(
            gui_utils.SourceModel.Columns.IS_CATALOGUE, QHeaderView.ResizeToContents
        )
        self.file_table_view.horizontalHeader().setSectionResizeMode(
            gui_utils.SourceModel.Columns.DATASET, QHeaderView.ResizeToContents
        )

        self.file_table_view.verticalHeader().setSectionsMovable(True)
        self.file_table_view.verticalHeader().setDragEnabled(True)
        self.file_table_view.verticalHeader().setDragDropMode(QHeaderView.InternalMove)
        self.file_table_view.resizeColumnsToContents()
        self.workflow_wizard.import_data_file_model.dataChanged.connect(
            self._update_delegates
        )

        self.db_connector = None

        self.datasetmanager_dlg = None
        self.datasetmanager_button.setCheckable(True)
        self.datasetmanager_button.clicked.connect(self._show_datasetmanager_dialog)
        self.datasetmanager_button.setIcon(
            QIcon(
                os.path.join(
                    os.path.dirname(__file__),
                    "../../images/QgisModelBaker-datasetmanager-icon.svg",
                )
            )
        )
 def update_models_completer(self):
     completer = QCompleter(self.ilicache.model, self.input_line_edit)
     completer.setCaseSensitivity(Qt.CaseInsensitive)
     completer.setFilterMode(Qt.MatchContains)
     completer.popup().setItemDelegate(self.model_delegate)
     self.input_line_edit.setCompleter(completer)
class ReplaceFeatureMapTool(ParentMapTool):
    """ Button 44: User select one feature. Execute SQL function: 'gw_fct_feature_replace' """
    def __init__(self, iface, settings, action, index_action):
        """ Class constructor """

        super(ReplaceFeatureMapTool, self).__init__(iface, settings, action,
                                                    index_action)
        self.current_date = QDate.currentDate().toString('yyyy-MM-dd')
        self.project_type = None
        self.geom_type = None
        self.geom_view = None
        self.cat_table = None
        self.feature_type_ws = None
        self.feature_type_ud = None

    def manage_dates(self, date_value):
        """ Manage dates """

        date_result = None
        try:
            date_result = str(date_value)
            date_result = date_result.replace("-", "/")
            date_result = datetime.strptime(date_result, '%Y/%m/%d')
        except Exception as e:
            self.controller.log_warning(str(e))
        finally:
            return date_result

    def init_replace_feature_form(self, feature):

        # Create the dialog and signals
        self.dlg_replace = FeatureReplace()
        self.load_settings(self.dlg_replace)

        sql = "SELECT id FROM cat_work ORDER BY id"
        rows = self.controller.get_rows(sql)
        if rows:
            utils_giswater.fillComboBox(self.dlg_replace,
                                        self.dlg_replace.workcat_id_end, rows)
            utils_giswater.set_autocompleter(self.dlg_replace.workcat_id_end)

        row = self.controller.get_config('edit_workcat_vdefault')
        if row:
            edit_workcat_vdefault = self.dlg_replace.workcat_id_end.findText(
                row[0])
            self.dlg_replace.workcat_id_end.setCurrentIndex(
                edit_workcat_vdefault)

        row = self.controller.get_config('edit_enddate_vdefault')
        if row:
            self.enddate_aux = self.manage_dates(row[0]).date()
        else:
            work_id = utils_giswater.getWidgetText(
                self.dlg_replace, self.dlg_replace.workcat_id_end)
            sql = (f"SELECT builtdate FROM cat_work "
                   f"WHERE id = '{work_id}'")
            row = self.controller.get_row(sql)
            current_date = self.manage_dates(self.current_date)
            if row and row[0]:
                builtdate = self.manage_dates(row[0])
                if builtdate != 'null' and builtdate:
                    self.enddate_aux = builtdate.date()
                else:
                    self.enddate_aux = current_date.date()
            else:
                self.enddate_aux = current_date.date()

        self.dlg_replace.enddate.setDate(self.enddate_aux)

        # Get feature type from current feature
        feature_type = None
        if self.project_type == 'ws':
            feature_type = feature.attribute(self.feature_type_ws)
        elif self.project_type == 'ud':
            feature_type = feature.attribute(self.feature_type_ud)
            if self.geom_type in ('node', 'connec'):
                sql = f"SELECT DISTINCT(id) FROM {self.cat_table} ORDER BY id"
                rows = self.controller.get_rows(sql)
                utils_giswater.fillComboBox(self.dlg_replace,
                                            "featurecat_id",
                                            rows,
                                            allow_nulls=False)
            elif self.geom_type in ('gully'):
                sql = f"SELECT DISTINCT(id) FROM cat_grate ORDER BY id"
                rows = self.controller.get_rows(sql)
                utils_giswater.fillComboBox(self.dlg_replace,
                                            "featurecat_id",
                                            rows,
                                            allow_nulls=False)

        self.dlg_replace.feature_type.setText(feature_type)
        self.dlg_replace.feature_type_new.currentIndexChanged.connect(
            self.edit_change_elem_type_get_value)
        self.dlg_replace.btn_catalog.clicked.connect(partial(
            self.open_catalog))
        self.dlg_replace.workcat_id_end.currentIndexChanged.connect(
            self.update_date)

        # Fill 1st combo boxes-new system node type
        sql = (
            f"SELECT DISTINCT(id) FROM cat_feature WHERE lower(feature_type) = '{self.geom_type}' "
            f"AND active is True "
            f"ORDER BY id")
        rows = self.controller.get_rows(sql)
        utils_giswater.fillComboBox(self.dlg_replace, "feature_type_new", rows)

        self.dlg_replace.btn_new_workcat.clicked.connect(
            partial(self.new_workcat))
        self.dlg_replace.btn_accept.clicked.connect(
            partial(self.get_values, self.dlg_replace))
        self.dlg_replace.btn_cancel.clicked.connect(
            partial(self.close_dialog, self.dlg_replace))
        self.dlg_replace.rejected.connect(self.cancel_map_tool)
        # Open dialog
        self.open_dialog(self.dlg_replace, maximize_button=False)

    def open_catalog(self):

        # Get feature_type
        feature_type = utils_giswater.getWidgetText(
            self.dlg_replace, self.dlg_replace.feature_type_new)

        if feature_type is 'null':
            msg = "New feature type is null. Please, select a valid value."
            self.controller.show_info_box(msg, "Info")
            return

        sql = f"SELECT lower(feature_type) FROM cat_feature WHERE id = '{feature_type}'"
        row = self.controller.get_row(sql)

        self.catalog = ApiCatalog(self.iface, self.settings, self.controller,
                                  self.plugin_dir)
        self.catalog.api_catalog(self.dlg_replace, 'featurecat_id', row[0],
                                 feature_type)

    def update_date(self):

        row = self.controller.get_config('edit_enddate_vdefault')
        if row:
            self.enddate_aux = self.manage_dates(row[0]).date()
        else:
            work_id = utils_giswater.getWidgetText(
                self.dlg_replace, self.dlg_replace.workcat_id_end)
            sql = (f"SELECT builtdate FROM cat_work "
                   f"WHERE id = '{work_id}'")
            row = self.controller.get_row(sql)
            current_date = self.manage_dates(self.current_date)
            if row and row[0]:
                builtdate = self.manage_dates(row[0])
                if builtdate != 'null' and builtdate:
                    self.enddate_aux = builtdate.date()
                else:
                    self.enddate_aux = current_date.date()
            else:
                self.enddate_aux = current_date.date()

        self.dlg_replace.enddate.setDate(self.enddate_aux)

    def new_workcat(self):

        self.dlg_new_workcat = InfoWorkcatUi()
        self.load_settings(self.dlg_new_workcat)
        utils_giswater.setCalendarDate(self.dlg_new_workcat,
                                       self.dlg_new_workcat.builtdate, None,
                                       True)

        table_object = "cat_work"
        self.set_completer_object(table_object,
                                  self.dlg_new_workcat.cat_work_id, 'id')

        # Set signals
        self.dlg_new_workcat.btn_accept.clicked.connect(
            partial(self.manage_new_workcat_accept, table_object))
        self.dlg_new_workcat.btn_cancel.clicked.connect(
            partial(self.close_dialog, self.dlg_new_workcat))

        # Open dialog
        self.open_dialog(self.dlg_new_workcat, dlg_name='info_workcat')

    def manage_new_workcat_accept(self, table_object):
        """ Insert table 'cat_work'. Add cat_work """

        # Get values from dialog
        values = ""
        fields = ""
        cat_work_id = utils_giswater.getWidgetText(
            self.dlg_new_workcat, self.dlg_new_workcat.cat_work_id)
        if cat_work_id != "null":
            fields += 'id, '
            values += ("'" + str(cat_work_id) + "', ")
        descript = utils_giswater.getWidgetText(self.dlg_new_workcat,
                                                "descript")
        if descript != "null":
            fields += 'descript, '
            values += ("'" + str(descript) + "', ")
        link = utils_giswater.getWidgetText(self.dlg_new_workcat, "link")
        if link != "null":
            fields += 'link, '
            values += ("'" + str(link) + "', ")
        workid_key_1 = utils_giswater.getWidgetText(self.dlg_new_workcat,
                                                    "workid_key_1")
        if workid_key_1 != "null":
            fields += 'workid_key1, '
            values += ("'" + str(workid_key_1) + "', ")
        workid_key_2 = utils_giswater.getWidgetText(self.dlg_new_workcat,
                                                    "workid_key_2")
        if workid_key_2 != "null":
            fields += 'workid_key2, '
            values += ("'" + str(workid_key_2) + "', ")
        builtdate = self.dlg_new_workcat.builtdate.dateTime().toString(
            'yyyy-MM-dd')
        if builtdate != "null":
            fields += 'builtdate, '
            values += ("'" + str(builtdate) + "', ")

        if values != "":
            fields = fields[:-2]
            values = values[:-2]
            if cat_work_id == 'null':
                msg = "Work_id field is empty"
                self.controller.show_info_box(msg, "Warning")
            else:
                # Check if this element already exists
                sql = (f"SELECT DISTINCT(id) "
                       f"FROM {table_object} "
                       f"WHERE id = '{cat_work_id}'")
                row = self.controller.get_row(sql, log_info=False)
                if row is None:
                    sql = f"INSERT INTO cat_work ({fields}) VALUES ({values})"
                    self.controller.execute_sql(sql, log_sql=True)

                    sql = "SELECT id FROM cat_work ORDER BY id"
                    rows = self.controller.get_rows(sql)
                    if rows:
                        utils_giswater.fillComboBox(
                            self.dlg_replace, self.dlg_replace.workcat_id_end,
                            rows)
                        current_index = self.dlg_replace.workcat_id_end.findText(
                            str(cat_work_id))
                        self.dlg_replace.workcat_id_end.setCurrentIndex(
                            current_index)

                    self.close_dialog(self.dlg_new_workcat)
                else:
                    msg = "This Workcat is already exist"
                    self.controller.show_info_box(msg, "Warning")

    def set_completer_object(self, tablename, widget, field_id):
        """ Set autocomplete of widget @table_object + "_id"
            getting id's from selected @table_object
        """

        if not widget:
            return

        sql = (f"SELECT DISTINCT({field_id}) "
               f"FROM {tablename} "
               f"ORDER BY {field_id}")
        rows = self.controller.get_rows(sql)
        if rows is None:
            return

        for i in range(0, len(rows)):
            aux = rows[i]
            rows[i] = str(aux[0])

        # Set completer and model: add autocomplete in the widget
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()
        model.setStringList(rows)
        self.completer.setModel(model)

    def get_values(self, dialog):

        self.workcat_id_end_aux = utils_giswater.getWidgetText(
            dialog, dialog.workcat_id_end)
        self.enddate_aux = dialog.enddate.date().toString('yyyy-MM-dd')

        # Check null values
        if self.workcat_id_end_aux in (None, 'null'):
            message = "Mandatory field is missing. Please, set a value"
            self.controller.show_warning(message, parameter='Workcat_id')
            return

        feature_type_new = utils_giswater.getWidgetText(
            dialog, dialog.feature_type_new)
        featurecat_id = utils_giswater.getWidgetText(dialog,
                                                     dialog.featurecat_id)

        # Ask question before executing
        message = "Are you sure you want to replace selected feature with a new one?"
        answer = self.controller.ask_question(message, "Replace feature")
        if answer:

            # Get function input parameters
            feature = f'"type":"{self.geom_type}"'
            extras = f'"old_feature_id":"{self.feature_id}"'
            extras += f', "workcat_id_end":"{self.workcat_id_end_aux}"'
            extras += f', "enddate":"{self.enddate_aux}"'
            extras += f', "keep_elements":"{utils_giswater.isChecked(dialog, "keep_elements")}"'
            body = self.create_body(feature=feature, extras=extras)

            # Execute SQL function and show result to the user
            function_name = "gw_fct_feature_replace"
            sql = f"SELECT {function_name}({body})::text"
            row = self.controller.get_row(sql, log_sql=True)
            if not row:
                message = "Error replacing feature"
                self.controller.show_warning(message)
                self.deactivate()
                self.set_action_pan()
                self.close_dialog(dialog, set_action_pan=False)
                return

            complet_result = [
                json.loads(row[0], object_pairs_hook=OrderedDict)
            ]
            message = "Feature replaced successfully"
            self.controller.show_info(message)

            # Force user to manage with state = 1 features
            current_user = self.controller.get_project_user()
            sql = (f"DELETE FROM selector_state "
                   f"WHERE state_id = 1 AND cur_user = '******';"
                   f"\nINSERT INTO selector_state (state_id, cur_user) "
                   f"VALUES (1, '{current_user}');")
            self.controller.execute_sql(sql)

            if feature_type_new != "null" and featurecat_id != "null":
                # Get id of new generated feature
                sql = (f"SELECT {self.geom_type}_id "
                       f"FROM {self.geom_view} "
                       f"ORDER BY {self.geom_type}_id::int4 DESC LIMIT 1")
                row = self.controller.get_row(sql)
                if row:
                    if self.geom_type == 'connec':
                        field_cat_id = "connecat_id"
                    else:
                        field_cat_id = self.geom_type + "cat_id"
                    if self.geom_type != 'gully':
                        sql = (f"UPDATE {self.geom_view} "
                               f"SET {field_cat_id} = '{featurecat_id}' "
                               f"WHERE {self.geom_type}_id = '{row[0]}'")
                    self.controller.execute_sql(sql, log_sql=True)
                    if self.project_type == 'ud':
                        sql = (
                            f"UPDATE {self.geom_view} "
                            f"SET {self.geom_type}_type = '{feature_type_new}' "
                            f"WHERE {self.geom_type}_id = '{row[0]}'")
                        self.controller.execute_sql(sql, log_sql=True)

                message = "Values has been updated"
                self.controller.show_info(message)

            # Fill tab 'Info log'
            if complet_result and complet_result[0]['status'] == "Accepted":
                self.populate_info_text(self.dlg_replace,
                                        complet_result[0]['body']['data'])

            # Refresh canvas
            self.refresh_map_canvas()
            self.controller.set_layer_index('v_edit_arc')
            self.controller.set_layer_index('v_edit_connec')
            self.controller.set_layer_index('v_edit_gully')
            self.controller.set_layer_index('v_edit_node')
            self.refresh_legend()

            # Deactivate map tool
            self.deactivate()
            self.set_action_pan()

            # Disable ok button at the end of process
            self.dlg_replace.btn_accept.setEnabled(False)

    """ QgsMapTools inherited event functions """

    def keyPressEvent(self, event):

        if event.key() == Qt.Key_Escape:
            self.cancel_map_tool()
            return

    def canvasMoveEvent(self, event):

        # Hide marker and clicked point
        self.vertex_marker.hide()
        event_point = self.snapper_manager.get_event_point(event)

        # Snapping layers 'v_edit_'
        result = self.snapper_manager.snap_to_background_layers(event_point)
        if self.snapper_manager.result_is_valid():
            layer = self.snapper_manager.get_snapped_layer(result)
            tablename = self.controller.get_layer_source_table_name(layer)
            if tablename and 'v_edit' in tablename:
                self.snapper_manager.add_marker(result, self.vertex_marker)

    def canvasReleaseEvent(self, event):

        if event.button() == Qt.RightButton:
            self.cancel_map_tool()
            return

        event_point = self.snapper_manager.get_event_point(event)

        # Snapping
        result = self.snapper_manager.snap_to_background_layers(event_point)
        if not self.snapper_manager.result_is_valid():
            return

        # Get snapped feature
        snapped_feat = self.snapper_manager.get_snapped_feature(result)
        if snapped_feat:
            layer = self.snapper_manager.get_snapped_layer(result)
            tablename = self.controller.get_layer_source_table_name(layer)

            if tablename and 'v_edit' in tablename:
                if tablename == 'v_edit_node':
                    self.geom_type = 'node'
                elif tablename == 'v_edit_connec':
                    self.geom_type = 'connec'
                elif tablename == 'v_edit_gully':
                    self.geom_type = 'gully'

                self.geom_view = tablename
                self.cat_table = 'cat_' + self.geom_type
                self.feature_type_ws = self.geom_type + 'type_id'
                self.feature_type_ud = self.geom_type + '_type'
                self.feature_id = snapped_feat.attribute(self.geom_type +
                                                         '_id')
                self.init_replace_feature_form(snapped_feat)

    def activate(self):

        # Set active and current layer
        self.layer_node = self.controller.get_layer_by_tablename("v_edit_node")
        self.iface.setActiveLayer(self.layer_node)
        self.current_layer = self.layer_node

        # Check button
        self.action().setChecked(True)

        # Set main snapping layers
        self.snapper_manager.set_snapping_layers()

        # Store user snapping configuration
        self.snapper_manager.store_snapping_options()

        # Disable snapping
        self.snapper_manager.enable_snapping()

        # Set snapping to 'node', 'connec' and 'gully'
        self.snapper_manager.snap_to_node()
        self.snapper_manager.snap_to_connec_gully()

        self.snapper_manager.set_snapping_mode()

        # Change cursor
        self.canvas.setCursor(self.cursor)

        self.project_type = self.controller.get_project_type()

        # Show help message when action is activated
        if self.show_help:
            message = "Select the feature by clicking on it and it will be replaced"
            self.controller.show_info(message)

    def deactivate(self):

        ParentMapTool.deactivate(self)

    def edit_change_elem_type_get_value(self, index):
        """ Just select item to 'real' combo 'featurecat_id' (that is hidden) """

        if index == -1:
            return

        # Get selected value from 2nd combobox
        feature_type_new = utils_giswater.getWidgetText(
            self.dlg_replace, "feature_type_new")

        # When value is selected, enabled 3rd combo box
        if feature_type_new == 'null':
            return

        if self.project_type == 'ws':
            # Fill 3rd combo_box-catalog_id
            utils_giswater.setWidgetEnabled(self.dlg_replace,
                                            self.dlg_replace.featurecat_id,
                                            True)
            sql = (f"SELECT DISTINCT(id) "
                   f"FROM {self.cat_table} "
                   f"WHERE {self.feature_type_ws} = '{feature_type_new}'")
            rows = self.controller.get_rows(sql)
            utils_giswater.fillComboBox(self.dlg_replace,
                                        self.dlg_replace.featurecat_id, rows)
Exemplo n.º 17
0
class ParentManage(ParentAction, object):

    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class to keep common functions of classes
        'ManageDocument', 'ManageElement' and 'ManageVisit' of toolbar 'edit' """

        super(ParentManage, self).__init__(iface, settings, controller, plugin_dir)

        self.x = ""
        self.y = ""
        self.canvas = self.iface.mapCanvas()
        self.plan_om = None
        self.previous_map_tool = None
        self.autocommit = True
        self.lazy_widget = None
        self.workcat_id_end = None
        self.xyCoordinates_conected = False
        self.remove_ids = True
        self.snapper_manager = None


    def reset_lists(self):
        """ Reset list of selected records """

        self.ids = []
        self.list_ids = {}
        self.list_ids['arc'] = []
        self.list_ids['node'] = []
        self.list_ids['connec'] = []
        self.list_ids['gully'] = []
        self.list_ids['element'] = []


    def reset_layers(self):
        """ Reset list of layers """

        self.layers = {}
        self.layers['arc'] = []
        self.layers['node'] = []
        self.layers['connec'] = []
        self.layers['gully'] = []
        self.layers['element'] = []


    def reset_model(self, dialog, table_object, geom_type):
        """ Reset model of the widget """ 

        table_relation = table_object + "_x_" + geom_type
        widget_name = "tbl_" + table_relation
        widget = utils_giswater.getWidget(dialog, widget_name)
        if widget:              
            widget.setModel(None)


    def remove_selection(self, remove_groups=True):
        """ Remove all previous selections """

        layer = self.controller.get_layer_by_tablename("v_edit_arc")
        if layer:
            layer.removeSelection()
        layer = self.controller.get_layer_by_tablename("v_edit_node")
        if layer:
            layer.removeSelection()
        layer = self.controller.get_layer_by_tablename("v_edit_connec")
        if layer:
            layer.removeSelection()
        layer = self.controller.get_layer_by_tablename("v_edit_element")
        if layer:
            layer.removeSelection()
            
        if self.project_type == 'ud':
            layer = self.controller.get_layer_by_tablename("v_edit_gully")
            if layer:
                layer.removeSelection()

        try:
            if remove_groups:
                for layer in self.layers['arc']:
                    layer.removeSelection()
                for layer in self.layers['node']:
                    layer.removeSelection()
                for layer in self.layers['connec']:
                    layer.removeSelection()
                for layer in self.layers['gully']:
                    layer.removeSelection()
                for layer in self.layers['element']:
                    layer.removeSelection()
        except:
            pass

        self.canvas.refresh()
    
    
    def reset_widgets(self, dialog, table_object):
        """ Clear contents of input widgets """
        
        if table_object == "doc":
            utils_giswater.setWidgetText(dialog, "doc_type", "")
            utils_giswater.setWidgetText(dialog, "observ", "")
            utils_giswater.setWidgetText(dialog, "path", "")
        elif table_object == "element":
            utils_giswater.setWidgetText(dialog, "elementcat_id", "")
            utils_giswater.setWidgetText(dialog, "state", "")
            utils_giswater.setWidgetText(dialog, "expl_id","")
            utils_giswater.setWidgetText(dialog, "ownercat_id", "")
            utils_giswater.setWidgetText(dialog, "location_type", "")
            utils_giswater.setWidgetText(dialog, "buildercat_id", "")
            utils_giswater.setWidgetText(dialog, "workcat_id", "")
            utils_giswater.setWidgetText(dialog, "workcat_id_end", "")
            utils_giswater.setWidgetText(dialog, "comment", "")
            utils_giswater.setWidgetText(dialog, "observ", "")
            utils_giswater.setWidgetText(dialog, "path", "")
            utils_giswater.setWidgetText(dialog, "rotation", "")
            utils_giswater.setWidgetText(dialog, "verified", "")
            utils_giswater.setWidgetText(dialog, dialog.num_elements, "")
                    
    
    def fill_widgets(self, dialog, table_object, row):
        """ Fill input widgets with data int he @row """
        
        if table_object == "doc":
            
            utils_giswater.setWidgetText(dialog, "doc_type", row["doc_type"])
            utils_giswater.setWidgetText(dialog, "observ",  row["observ"])
            utils_giswater.setWidgetText(dialog, "path",  row["path"])
             
        elif table_object == "element":
                    
            state = ""  
            if row['state']:          
                sql = (f"SELECT name FROM value_state"
                       f" WHERE id = '{row['state']}'")
                row_aux = self.controller.get_row(sql, commit=self.autocommit)
                if row_aux:
                    state = row_aux[0]
    
            expl_id = ""
            if row['expl_id']:
                sql = (f"SELECT name FROM exploitation"
                       f" WHERE expl_id = '{row['expl_id']}'")
                row_aux = self.controller.get_row(sql, commit=self.autocommit)
                if row_aux:
                    expl_id = row_aux[0]

            utils_giswater.setWidgetText(dialog, "code", row['code'])
            sql = (f"SELECT elementtype_id FROM cat_element"
                   f" WHERE id = '{row['elementcat_id']}'")
            row_type = self.controller.get_row(sql)
            if row_type:
                utils_giswater.setWidgetText(dialog, "element_type", row_type[0])

            utils_giswater.setWidgetText(dialog, "elementcat_id", row['elementcat_id'])
            utils_giswater.setWidgetText(dialog, "num_elements", row['num_elements'])
            utils_giswater.setWidgetText(dialog, "state", state)
            utils_giswater.setWidgetText(dialog, "expl_id", expl_id)
            utils_giswater.setWidgetText(dialog, "ownercat_id", row['ownercat_id'])
            utils_giswater.setWidgetText(dialog, "location_type", row['location_type'])
            utils_giswater.setWidgetText(dialog, "buildercat_id", row['buildercat_id'])
            utils_giswater.setWidgetText(dialog, "builtdate", row['builtdate'])
            utils_giswater.setWidgetText(dialog, "workcat_id", row['workcat_id'])
            utils_giswater.setWidgetText(dialog, "workcat_id_end", row['workcat_id_end'])
            utils_giswater.setWidgetText(dialog, "comment", row['comment'])
            utils_giswater.setWidgetText(dialog, "observ", row['observ'])
            utils_giswater.setWidgetText(dialog, "link", row['link'])
            utils_giswater.setWidgetText(dialog, "verified", row['verified'])
            utils_giswater.setWidgetText(dialog, "rotation", row['rotation'])
            if str(row['undelete']) == 'True':
                dialog.undelete.setChecked(True)
            
              
    def get_records_geom_type(self, dialog, table_object, geom_type):
        """ Get records of @geom_type associated to selected @table_object """
        
        object_id = utils_giswater.getWidgetText(dialog, table_object + "_id")
        table_relation = table_object + "_x_" + geom_type
        widget_name = "tbl_" + table_relation           
        
        exists = self.controller.check_table(table_relation)
        if not exists:
            self.controller.log_info(f"Not found: {table_relation}")
            return
              
        sql = (f"SELECT {geom_type}_id "
               f"FROM {table_relation} "
               f"WHERE {table_object}_id = '{object_id}'")
        rows = self.controller.get_rows(sql, commit=True, log_info=False)
        if rows:
            for row in rows:
                self.list_ids[geom_type].append(str(row[0]))
                self.ids.append(str(row[0]))

            expr_filter = self.get_expr_filter(geom_type)
            self.set_table_model(dialog, widget_name, geom_type, expr_filter)
    
    
    def exist_object(self, dialog, table_object):
        """ Check if selected object (document or element) already exists """
        
        # Reset list of selected records
        self.reset_lists()
        
        field_object_id = "id"
        if table_object == "element":
            field_object_id = table_object + "_id"           
        object_id = utils_giswater.getWidgetText(dialog, table_object + "_id")

        # Check if we already have data with selected object_id
        sql = (f"SELECT * "
               f" FROM {table_object}"
               f" WHERE {field_object_id} = '{object_id}'")
        row = self.controller.get_row(sql, log_info=False)

        # If object_id not found: Clear data
        if not row:    
            self.reset_widgets(dialog, table_object)
            if table_object == 'element':
                self.set_combo(dialog, 'state', 'value_state', 'state_vdefault', field_name='name')
                self.set_combo(dialog, 'expl_id', 'exploitation', 'exploitation_vdefault', field_id='expl_id',field_name='name')
                self.set_calendars(dialog, 'builtdate', 'config_param_user', 'value', 'builtdate_vdefault')
                self.set_combo(dialog, 'workcat_id', 'cat_work', 'workcat_vdefault', field_id='id', field_name='id')
            if hasattr(self, 'single_tool_mode'):
                # some tools can work differently if standalone or integrated in
                # another tool
                if self.single_tool_mode:
                    self.remove_selection(True)
            else:
                self.remove_selection(True)
            self.reset_model(dialog, table_object, "arc")
            self.reset_model(dialog, table_object, "node")
            self.reset_model(dialog, table_object, "connec")
            self.reset_model(dialog, table_object, "element")
            if self.project_type == 'ud':
                self.reset_model(dialog, table_object, "gully")

            return

        # Fill input widgets with data of the @row
        self.fill_widgets(dialog, table_object, row)

        # Check related 'arcs'
        self.get_records_geom_type(dialog, table_object, "arc")
        
        # Check related 'nodes'
        self.get_records_geom_type(dialog, table_object, "node")
        
        # Check related 'connecs'
        self.get_records_geom_type(dialog, table_object, "connec")

        # Check related 'elements'
        self.get_records_geom_type(dialog, table_object, "element")

        # Check related 'gullys'
        if self.project_type == 'ud':        
            self.get_records_geom_type(dialog, table_object, "gully")


    def populate_combo(self, dialog, widget, table_name, field_name="id"):
        """ Executes query and fill combo box """

        sql = (f"SELECT {field_name}"
               f" FROM {table_name}"
               f" ORDER BY {field_name}")
        rows = self.controller.get_rows(sql, commit=self.autocommit)
        utils_giswater.fillComboBox(dialog, widget, rows)
        if rows:
            utils_giswater.setCurrentIndex(dialog, widget, 0)


    def set_combo(self, dialog, widget, table_name, parameter, field_id='id', field_name='id'):
        """ Executes query and set combo box """
        
        sql = (f"SELECT t1.{field_name} FROM {table_name} as t1"
               f" INNER JOIN config_param_user as t2 ON t1.{field_id}::text = t2.value::text"
               f" WHERE parameter = '{parameter}' AND cur_user = current_user")
        row = self.controller.get_row(sql)
        if row:
            utils_giswater.setWidgetText(dialog, widget, row[0])


    def set_calendars(self, dialog, widget, table_name, value, parameter):
        """ Executes query and set QDateEdit """
        
        sql = (f"SELECT {value} FROM {table_name}"
               f" WHERE parameter = '{parameter}' AND cur_user = current_user")
        row = self.controller.get_row(sql)
        if row:
            date = QDate.fromString(row[0], 'yyyy-MM-dd')
        else:
            date = QDate.currentDate()
        utils_giswater.setCalendarDate(dialog, widget, date)


    def add_point(self):
        """ Create the appropriate map tool and connect to the corresponding signal """

        active_layer = self.iface.activeLayer()
        if active_layer is None:
            active_layer = self.controller.get_layer_by_tablename('version')
            self.iface.setActiveLayer(active_layer)

        # Vertex marker
        self.vertex_marker = QgsVertexMarker(self.canvas)
        self.vertex_marker.setColor(QColor(255, 100, 255))
        self.vertex_marker.setIconSize(15)
        self.vertex_marker.setIconType(QgsVertexMarker.ICON_CROSS)
        self.vertex_marker.setPenWidth(3)

        # Snapper
        if self.snapper_manager is None:
            self.snapper_manager = SnappingConfigManager(self.iface)
            self.snapper = self.snapper_manager.get_snapper()
            if self.snapper_manager.controller is None:
                self.snapper_manager.set_controller(self.controller)

        self.emit_point = QgsMapToolEmitPoint(self.canvas)
        self.previous_map_tool = self.canvas.mapTool()
        self.canvas.setMapTool(self.emit_point)
        self.canvas.xyCoordinates.connect(self.mouse_move)
        self.xyCoordinates_conected = True
        self.emit_point.canvasClicked.connect(partial(self.get_xy))


    def mouse_move(self, point):

        # Hide marker and get coordinates
        self.snapped_point = None
        self.vertex_marker.hide()
        event_point = self.snapper_manager.get_event_point(point=point)

        # Snapping
        result = self.snapper_manager.snap_to_background_layers(event_point)
        if self.snapper_manager.result_is_valid():
            self.snapper_manager.add_marker(result, self.vertex_marker)
        else:
            self.vertex_marker.hide()


    def get_xy(self, point):
        """ Get coordinates of selected point """

        if self.snapped_point:
            self.x = self.snapped_point.x()
            self.y = self.snapped_point.y()
        else:
            self.x = point.x()
            self.y = point.y()

        message = "Geometry has been added!"
        self.controller.show_info(message)
        self.emit_point.canvasClicked.disconnect()
        self.canvas.xyCoordinates.disconnect()
        self.xyCoordinates_conected = False
        self.iface.mapCanvas().refreshAllLayers()
        self.vertex_marker.hide()


    def get_values_from_form(self, dialog):

        self.enddate = utils_giswater.getCalendarDate(dialog, "enddate")
        self.workcat_id_end = utils_giswater.getWidgetText(dialog, "workcat_id_end")
        self.description = utils_giswater.getWidgetText(dialog, "descript")


    def tab_feature_changed(self, dialog, table_object):
        """ Set geom_type and layer depending selected tab
            @table_object = ['doc' | 'element' | 'cat_work']
        """

        self.get_values_from_form(dialog)
        tab_position = dialog.tab_feature.currentIndex()
        if tab_position == 0:
            self.geom_type = "arc"   
        elif tab_position == 1:
            self.geom_type = "node"
        elif tab_position == 2:
            self.geom_type = "connec"
        elif tab_position == 3:
            self.geom_type = "element"
        elif tab_position == 4:
            self.geom_type = "gully"

        self.hide_generic_layers()                  
        widget_name = f"tbl_{table_object}_x_{self.geom_type}"
        viewname = f"v_edit_{self.geom_type}"
        self.widget = utils_giswater.getWidget(dialog, widget_name)
            
        # Adding auto-completion to a QLineEdit
        self.set_completer_feature_id(dialog.feature_id, self.geom_type, viewname)
        
        self.iface.actionPan().trigger()    
        

    def set_completer_object(self, dialog, table_object):
        """ Set autocomplete of widget @table_object + "_id" 
            getting id's from selected @table_object 
        """
                     
        widget = utils_giswater.getWidget(dialog, table_object + "_id")
        if not widget:
            return
        
        # Set SQL
        field_object_id = "id"
        if table_object == "element":
            field_object_id = table_object + "_id"
        sql = (f"SELECT DISTINCT({field_object_id})"
               f" FROM {table_object}")
        rows = self.controller.get_rows(sql, commit=self.autocommit)
        if rows is None:
            return

        for i in range(0, len(rows)):
            aux = rows[i]
            rows[i] = str(aux[0])

        # Set completer and model: add autocomplete in the widget
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()
        model.setStringList(rows)
        self.completer.setModel(model)
        
        
    def set_completer_widget(self, tablename, widget, field_id):
        """ Set autocomplete of widget @table_object + "_id"
            getting id's from selected @table_object
        """

        if not widget:
            return

        # Set SQL
        sql = (f"SELECT DISTINCT({field_id})"
               f" FROM {tablename}"
               f" ORDER BY {field_id}")
        row = self.controller.get_rows(sql, commit=True)
        for i in range(0, len(row)):
            aux = row[i]
            row[i] = str(aux[0])

        # Set completer and model: add autocomplete in the widget
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()
        model.setStringList(row)
        self.completer.setModel(model)
                

    def set_completer_feature_id(self, widget, geom_type, viewname):
        """ Set autocomplete of widget 'feature_id' 
            getting id's from selected @viewname 
        """
             
        # Adding auto-completion to a QLineEdit
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()

        sql = (f"SELECT {geom_type}_id"
               f" FROM {viewname}")
        row = self.controller.get_rows(sql, commit=self.autocommit)
        if row:
            for i in range(0, len(row)):
                aux = row[i]
                row[i] = str(aux[0])

            model.setStringList(row)
            self.completer.setModel(model)


    def get_expr_filter(self, geom_type):
        """ Set an expression filter with the contents of the list.
            Set a model with selected filter. Attach that model to selected table 
        """

        list_ids = self.list_ids[geom_type]
        field_id = geom_type + "_id"
        if len(list_ids) == 0:
            return None

        # Set expression filter with features in the list        
        expr_filter = field_id + " IN ("
        for i in range(len(list_ids)):
            expr_filter += f"'{list_ids[i]}', "
        expr_filter = expr_filter[:-2] + ")"

        # Check expression
        (is_valid, expr) = self.check_expression(expr_filter)
        if not is_valid:
            return None

        # Select features of layers applying @expr
        self.select_features_by_ids(geom_type, expr)
        
        return expr_filter


    def reload_table(self, dialog, table_object, geom_type, expr_filter):
        """ Reload @widget with contents of @tablename applying selected @expr_filter """

        if type(table_object) is str:
            widget_name = f"tbl_{table_object}_x_{geom_type}"
            widget = utils_giswater.getWidget(dialog, widget_name)

            if not widget:
                message = "Widget not found"
                self.controller.log_info(message, parameter=widget_name)
                return None

        elif type(table_object) is QTableView:
            widget = table_object
        else:
            message = "Table_object is not a table name or QTableView"
            self.controller.log_info(message)
            return None

        expr = self.set_table_model(dialog, widget, geom_type, expr_filter)
        return expr


    def set_table_model(self, dialog, table_object, geom_type, expr_filter):
        """ Sets a TableModel to @widget_name attached to
            @table_name and filter @expr_filter 
        """

        expr = None
        if expr_filter:
            # Check expression
            (is_valid, expr) = self.check_expression(expr_filter)    #@UnusedVariable
            if not is_valid:
                return expr

        # Set a model with selected filter expression
        table_name = "v_edit_" + geom_type
        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set the model
        model = QSqlTableModel()
        model.setTable(table_name)
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.select()
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())
            return expr

        # Attach model to selected widget
        if type(table_object) is str:
            widget = utils_giswater.getWidget(dialog, table_object)
            if not widget:
                message = "Widget not found"
                self.controller.log_info(message, parameter=table_object)
                return expr
        elif type(table_object) is QTableView:
            widget = table_object
        else:
            message = "Table_object is not a table name or QTableView"
            self.controller.log_info(message)
            return expr

        if expr_filter:
            widget.setModel(model)
            widget.model().setFilter(expr_filter)
            widget.model().select()
        else:
            widget.setModel(None)

        return expr


    def apply_lazy_init(self, widget):
        """Apply the init function related to the model. It's necessary
        a lazy init because model is changed everytime is loaded."""

        if self.lazy_widget is None:
            return
        if widget != self.lazy_widget:
            return
        self.lazy_init_function(self.lazy_widget)


    def lazy_configuration(self, widget, init_function):
        """set the init_function where all necessary events are set.
        This is necessary to allow a lazy setup of the events because set_table_events
        can create a table with a None model loosing any event connection."""

        # TODO: create a dictionary with key:widged.objectName value:initFuction
        # to allow multiple lazy initialization
        self.lazy_widget = widget
        self.lazy_init_function = init_function


    def select_features_by_ids(self, geom_type, expr):
        """ Select features of layers of group @geom_type applying @expr """

        # Build a list of feature id's and select them
        for layer in self.layers[geom_type]:
            if expr is None:
                layer.removeSelection()  
            else:                
                it = layer.getFeatures(QgsFeatureRequest(expr))
                id_list = [i.id() for i in it]
                if len(id_list) > 0:
                    layer.selectByIds(id_list)   
                else:
                    layer.removeSelection()             
        
             
    def delete_records(self, dialog, table_object, query=False):
        """ Delete selected elements of the table """

        self.disconnect_signal_selection_changed()

        if type(table_object) is str:
            widget_name = f"tbl_{table_object}_x_{self.geom_type}"
            widget = utils_giswater.getWidget(dialog, widget_name)
            if not widget:
                message = "Widget not found"
                self.controller.show_warning(message, parameter=widget_name)
                return
        elif type(table_object) is QTableView:
            widget = table_object
        else:
            message = "Table_object is not a table name or QTableView"
            self.controller.log_info(message)
            return

        # Control when QTableView is void or has no model
        try:
            # Get selected rows
            selected_list = widget.selectionModel().selectedRows()
        except AttributeError as e:
            selected_list = []


        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_info_box(message)
            return

        if query:
            full_list = widget.model()
            for x in range(0, full_list.rowCount()):
                self.ids.append(widget.model().record(x).value(f"{self.geom_type}_id"))
        else:
            self.ids = self.list_ids[self.geom_type]

        field_id = self.geom_type + "_id"
        
        del_id = []
        inf_text = ""
        list_id = ""
        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_feature = widget.model().record(row).value(field_id)
            inf_text += f"{id_feature}, "
            list_id += f"'{id_feature}', "
            del_id.append(id_feature)
        inf_text = inf_text[:-2]
        list_id = list_id[:-2]
        message = "Are you sure you want to delete these records?"
        title = "Delete records"
        answer = self.controller.ask_question(message, title, inf_text)
        if answer:
            for el in del_id:
                self.ids.remove(el)
        else:
            return

        expr_filter = None
        expr = None
        if len(self.ids) > 0:

            # Set expression filter with features in the list
            expr_filter = f'"{field_id}" IN ('
            for i in range(len(self.ids)):
                expr_filter += f"'{self.ids[i]}', "
            expr_filter = expr_filter[:-2] + ")"

            # Check expression
            (is_valid, expr) = self.check_expression(expr_filter) #@UnusedVariable
            if not is_valid:
                return

        # Update model of the widget with selected expr_filter
        if query:
            self.delete_feature_at_plan(dialog, self.geom_type, list_id)
            self.reload_qtable(dialog, self.geom_type, self.plan_om)
        else:
            self.reload_table(dialog, table_object, self.geom_type, expr_filter)
            self.apply_lazy_init(table_object)

        # Select features with previous filter
        # Build a list of feature id's and select them
        self.select_features_by_ids(self.geom_type, expr)

        if query:
            self.remove_selection()
        # Update list
        self.list_ids[self.geom_type] = self.ids
        self.enable_feature_type(dialog)
        self.connect_signal_selection_changed(dialog, table_object)


    def manage_close(self, dialog, table_object, cur_active_layer=None):
        """ Close dialog and disconnect snapping """

        if cur_active_layer:
            self.iface.setActiveLayer(cur_active_layer)
        if hasattr(self, 'single_tool_mode'):
            # some tools can work differently if standalone or integrated in
            # another tool
            if self.single_tool_mode:
                self.remove_selection(True)
        else:
            self.remove_selection(True)
        self.reset_model(dialog, table_object, "arc")
        self.reset_model(dialog, table_object, "node")
        self.reset_model(dialog, table_object, "connec")
        self.reset_model(dialog, table_object, "element")
        if self.project_type == 'ud':
            self.reset_model(dialog, table_object, "gully")
        self.close_dialog(dialog)
        self.hide_generic_layers()
        self.disconnect_snapping()   
        self.disconnect_signal_selection_changed()


    def selection_init(self, dialog, table_object, query=False):
        """ Set canvas map tool to an instance of class 'MultipleSelection' """

        multiple_selection = MultipleSelection(self.iface, self.controller, self.layers[self.geom_type], 
            parent_manage=self, table_object=table_object, dialog=dialog)
        self.disconnect_signal_selection_changed()
        self.previous_map_tool = self.canvas.mapTool()        
        self.canvas.setMapTool(multiple_selection)              
        self.connect_signal_selection_changed(dialog, table_object, query)
        cursor = self.get_cursor_multiple_selection()
        self.canvas.setCursor(cursor)


    def selection_changed(self, dialog, table_object, geom_type, query=False):
        """ Slot function for signal 'canvas.selectionChanged' """
        self.disconnect_signal_selection_changed()
        field_id = geom_type + "_id"

        if self.remove_ids:
            self.ids = []

        # Iterate over all layers of the group
        for layer in self.layers[self.geom_type]:
            if layer.selectedFeatureCount() > 0:
                # Get selected features of the layer
                features = layer.selectedFeatures()
                for feature in features:
                    # Append 'feature_id' into the list
                    selected_id = feature.attribute(field_id)
                    if selected_id not in self.ids:
                        self.ids.append(selected_id)

        if geom_type == 'arc':
            self.list_ids['arc'] = self.ids
        elif geom_type == 'node':
            self.list_ids['node'] = self.ids
        elif geom_type == 'connec':
            self.list_ids['connec'] = self.ids
        elif geom_type == 'gully':
            self.list_ids['gully'] = self.ids
        elif geom_type == 'element':
            self.list_ids['element'] = self.ids

        expr_filter = None
        if len(self.ids) > 0:
            # Set 'expr_filter' with features that are in the list
            expr_filter = f'"{field_id}" IN ('
            for i in range(len(self.ids)):
                expr_filter += f"'{self.ids[i]}', "
            expr_filter = expr_filter[:-2] + ")"

            # Check expression
            (is_valid, expr) = self.check_expression(expr_filter)   #@UnusedVariable
            if not is_valid:
                return                                           
                          
            self.select_features_by_ids(geom_type, expr)
                        
        # Reload contents of table 'tbl_@table_object_x_@geom_type'
        if query:
            self.insert_feature_to_plan(dialog, self.geom_type)
            if self.plan_om == 'plan':
                self.remove_selection()
            self.reload_qtable(dialog, geom_type, self.plan_om)
        else:
            self.reload_table(dialog, table_object, self.geom_type, expr_filter)
            self.apply_lazy_init(table_object)

        # Remove selection in generic 'v_edit' layers
        if self.plan_om == 'plan':
            self.remove_selection(False)
        self.enable_feature_type(dialog)
        self.connect_signal_selection_changed(dialog, table_object)


    def delete_feature_at_plan(self, dialog, geom_type, list_id):
        """ Delete features_id to table plan_@geom_type_x_psector"""

        value = utils_giswater.getWidgetText(dialog, dialog.psector_id)
        sql = (f"DELETE FROM {self.plan_om}_psector_x_{geom_type} "
               f"WHERE {geom_type}_id IN ({list_id}) AND psector_id = '{value}'")
        self.controller.execute_sql(sql)


    def enable_feature_type(self, dialog):

        feature_type = dialog.findChild(QComboBox, 'feature_type')
        table = dialog.findChild(QTableView, 'tbl_relation')
        if feature_type is not None and table is not None:
            if len(self.ids) > 0:
                feature_type.setEnabled(False)
            else:
                feature_type.setEnabled(True)


    def insert_feature(self, dialog, table_object, query=False, remove_ids=True):
        """ Select feature with entered id. Set a model with selected filter.
            Attach that model to selected table
        """

        self.disconnect_signal_selection_changed()

        # Clear list of ids
        if remove_ids:
            self.ids = []
        field_id = self.geom_type + "_id"

        feature_id = utils_giswater.getWidgetText(dialog, "feature_id")
        if feature_id == 'null':
            message = "You need to enter a feature id"
            self.controller.show_info_box(message)
            return

        # Iterate over all layers of the group
        for layer in self.layers[self.geom_type]:
            if layer.selectedFeatureCount() > 0:
                # Get selected features of the layer
                features = layer.selectedFeatures()
                for feature in features:
                    # Append 'feature_id' into the list
                    selected_id = feature.attribute(field_id)
                    if selected_id not in self.ids:
                        self.ids.append(selected_id)
            if feature_id not in self.ids:
                # If feature id doesn't exist in list -> add
                self.ids.append(str(feature_id))

        # Set expression filter with features in the list
        expr_filter = f'"{field_id}" IN ('
        for i in range(len(self.ids)):
            expr_filter += f"'{self.ids[i]}', "
        expr_filter = expr_filter[:-2] + ")"

        # Check expression
        (is_valid, expr) = self.check_expression(expr_filter)
        if not is_valid:
            return

        # Select features with previous filter
        # Build a list of feature id's and select them
        for layer in self.layers[self.geom_type]:
            it = layer.getFeatures(QgsFeatureRequest(expr))
            id_list = [i.id() for i in it]
            if len(id_list) > 0:
                layer.selectByIds(id_list)

        # Reload contents of table 'tbl_???_x_@geom_type'
        if query:
            self.insert_feature_to_plan(dialog, self.geom_type)
            self.remove_selection()
        else:
            self.reload_table(dialog, table_object, self.geom_type, expr_filter)
            self.apply_lazy_init(table_object)            

        # Update list
        self.list_ids[self.geom_type] = self.ids
        self.enable_feature_type(dialog)
        self.connect_signal_selection_changed(dialog, table_object)


    def insert_feature_to_plan(self, dialog, geom_type):
        """ Insert features_id to table plan_@geom_type_x_psector """

        value = utils_giswater.getWidgetText(dialog, dialog.psector_id)
        for i in range(len(self.ids)):
            sql = (f"SELECT {geom_type}_id "
                   f"FROM {self.plan_om}_psector_x_{geom_type} "
                   f"WHERE {geom_type}_id = '{self.ids[i]}' AND psector_id = '{value}'")
            row = self.controller.get_row(sql)
            if not row:
                sql = (f"INSERT INTO {self.plan_om}_psector_x_{geom_type}"
                       f"({geom_type}_id, psector_id) VALUES('{self.ids[i]}', '{value}')")
                self.controller.execute_sql(sql)
            self.reload_qtable(dialog, geom_type, self.plan_om)


    def reload_qtable(self, dialog, geom_type, plan_om):
        """ Reload QtableView """
        
        value = utils_giswater.getWidgetText(dialog, dialog.psector_id)
        expr = f"psector_id = '{value}'"
        qtable = utils_giswater.getWidget(dialog, f'tbl_psector_x_{geom_type}')
        self.fill_table_by_expr(qtable, f"{plan_om}_psector_x_{geom_type}", expr)
        self.set_table_columns(dialog, qtable, f"{plan_om}_psector_x_{geom_type}")
        self.refresh_map_canvas()


    def fill_table_by_expr(self, qtable, table_name, expr):
        """
        :param qtable: QTableView to show
        :param expr: expression to set model
        """
        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name
            
        model = QSqlTableModel()
        model.setTable(table_name)
        model.setFilter(expr)
        model.setEditStrategy(QSqlTableModel.OnFieldChange)
        qtable.setEditTriggers(QTableView.DoubleClicked)
        model.select()
        qtable.setModel(model)
        qtable.show()

        # Check for errors
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())

    def disconnect_snapping(self):
        """ Select 'Pan' as current map tool and disconnect snapping """

        try:
            self.iface.actionPan().trigger()
            self.canvas.xyCoordinates.disconnect()
            if self.emit_point:       
                self.emit_point.canvasClicked.disconnect()
        except:
            pass


    def fill_table_object(self, widget, table_name, expr_filter=None):
        """ Set a model with selected filter. Attach that model to selected table """

        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set model
        model = QSqlTableModel()
        model.setTable(table_name)
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.sort(0, 1)
        if expr_filter:
            model.setFilter(expr_filter)            
        model.select()

        # Check for errors
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())

        # Attach model to table view
        widget.setModel(model)


    def filter_by_id(self, dialog, widget_table, widget_txt, table_object, field_object_id='id'):

        field_object_id = "id"
        if table_object == "element":
            field_object_id = table_object + "_id"
        object_id = utils_giswater.getWidgetText(dialog, widget_txt)
        if object_id != 'null':
            expr = f"{field_object_id}::text ILIKE '%{object_id}%'"
            # Refresh model with selected filter
            widget_table.model().setFilter(expr)
            widget_table.model().select()
        else:
            self.fill_table_object(widget_table, self.schema_name + "." + table_object)


    def delete_selected_object(self, widget, table_object):
        """ Delete selected objects of the table (by object_id) """

        # Get selected rows
        selected_list = widget.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return

        inf_text = ""
        list_id = ""
        field_object_id = "id"

        if table_object == "element":
            field_object_id = table_object + "_id"
        elif "v_ui_om_visitman_x_" in table_object:
            field_object_id = "visit_id"

        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_ = widget.model().record(row).value(str(field_object_id))
            inf_text += f"{id_}, "
            list_id += f"'{id_}', "
        inf_text = inf_text[:-2]
        list_id = list_id[:-2]
        message = "Are you sure you want to delete these records?"
        title = "Delete records"
        answer = self.controller.ask_question(message, title, inf_text)
        if answer:
            sql = (f"DELETE FROM {table_object} "
                   f"WHERE {field_object_id} IN ({list_id})")
            self.controller.execute_sql(sql, commit=self.autocommit)
            widget.model().select()

    
    def open_selected_object(self, dialog, widget, table_object):
        """ Open object form with selected record of the table """

        selected_list = widget.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return

        row = selected_list[0].row()

        # Get object_id from selected row
        field_object_id = "id"
        widget_id = table_object + "_id"
        if table_object == "element":
            field_object_id = table_object + "_id"
        if table_object == "v_ui_om_visit":
            widget_id = "visit_id"
        elif "v_ui_om_visitman_x_" in table_object:
            field_object_id = "visit_id"
        selected_object_id = widget.model().record(row).value(field_object_id)

        # Close this dialog and open selected object
        dialog.close()

        if table_object == "doc":
            self.manage_document()
            utils_giswater.setWidgetText(self.dlg_add_doc, widget_id, selected_object_id)
        elif table_object == "element":
            self.manage_element(new_element_id=False)
            utils_giswater.setWidgetText(self.dlg_add_element, widget_id, selected_object_id)
        elif table_object == "v_ui_om_visit":
            self.manage_visit(visit_id=selected_object_id)
        elif "v_ui_om_visitman_x_" in table_object:
            self.manage_visit(visit_id=selected_object_id)


    def set_selectionbehavior(self, dialog):
        
        # Get objects of type: QTableView
        widget_list = dialog.findChildren(QTableView)
        for widget in widget_list:
            widget.setSelectionBehavior(QAbstractItemView.SelectRows) 
        
        
    def hide_generic_layers(self, visible=False):       
        """ Hide generic layers """
        
        layer = self.controller.get_layer_by_tablename("v_edit_arc")
        if layer:
            self.controller.set_layer_visible(layer)
        layer = self.controller.get_layer_by_tablename("v_edit_node")
        if layer:
            self.controller.set_layer_visible(layer)
        layer = self.controller.get_layer_by_tablename("v_edit_connec")
        if layer:
            self.controller.set_layer_visible(layer)
        layer = self.controller.get_layer_by_tablename("v_edit_element")
        if layer:
            self.controller.set_layer_visible(layer)
            
        if self.project_type == 'ud':
            layer = self.controller.get_layer_by_tablename("v_edit_gully")
            if layer:
                self.controller.set_layer_visible(layer)
        
    
    def connect_signal_selection_changed(self, dialog, table_object, query=False):
        """ Connect signal selectionChanged """
        
        try:
            self.canvas.selectionChanged.connect(partial(self.selection_changed, dialog,  table_object, self.geom_type, query))
        except Exception:    
            pass
    
    
    def disconnect_signal_selection_changed(self):
        """ Disconnect signal selectionChanged """
        
        try:
            self.canvas.selectionChanged.disconnect()  
            self.iface.actionPan().trigger()
        except Exception:   
            pass
        

    def fill_widget_with_fields(self, dialog, data_object, field_names):
        """Fill the Widget with value get from data_object limited to 
        the list of field_names."""
        
        for field_name in field_names:
            value = getattr(data_object, field_name)
            if not hasattr(dialog, field_name):
                continue

            widget = getattr(dialog, field_name)
            if type(widget) == QDateEdit:
                widget.setDate(value if value else QDate.currentDate())
            elif type(widget) == QDateTimeEdit:
                widget.setDateTime(value if value else QDateTime.currentDateTime())


            if type(widget) in [QLineEdit, QTextEdit]:
                if value:
                    widget.setText(value)
                else:
                    widget.clear()
            if type(widget) in [QComboBox]:
                if not value:
                    widget.setCurrentIndex(0)
                    continue
                # look the value in item text
                index = widget.findText(str(value))
                if index >= 0:
                    widget.setCurrentIndex(index)
                    continue
                # look the value in itemData
                index = widget.findData(value)
                if index >= 0:
                    widget.setCurrentIndex(index)
                    continue


    def set_model_to_table(self, widget, table_name, expr_filter):
        """ Set a model with selected filter.
        Attach that model to selected table """

        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set model
        model = QSqlTableModel();
        model.setTable(table_name)
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.setFilter(expr_filter)
        model.select()

        # Check for errors
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())

        # Attach model to table view
        if widget:
            widget.setModel(model)
        else:
            self.controller.log_info("set_model_to_table: widget not found")
Exemplo n.º 18
0
class QCercadorAdreca(QObject):
    sHanTrobatCoordenades = pyqtSignal(int, 'QString')  # atencion

    def __init__(self, lineEditCarrer, lineEditNumero, origen='SQLITE'):
        super().__init__()

        # self.pare= pare

        self.origen = origen
        self.leCarrer = lineEditCarrer
        self.leNumero = lineEditNumero
        self.connectarLineEdits()
        self.carrerActivat = False

        self.dictCarrers = {}
        self.dictNumeros = collections.defaultdict(dict)

        # self.db.setConnectOptions("QSQLITE_OPEN_READONLY")
        self.numClick=0
        self.db = QvApp().dbGeo

        if self.db is None:  # not self.db.open(): # En caso de que no se abra
            QMessageBox.critical(None, "Error al abrir la base de datos.\n\n"
                                 "Click para cancelar y salir.", QMessageBox.Cancel)

        self.query = QSqlQuery(self.db)  # Intancia del Query
        self.txto = ''
        self.calle_con_acentos = ''
        self.habilitaLeNum()

        self.iniAdreca()

        if self.llegirAdreces():
            # si se ha podido leer las direciones... creando el diccionario...
            self.prepararCompleterCarrer()

    def habilitaLeNum(self):
        self.carrerActivat = False
        return  # De moment no es desactivarà mai
        # Hauria de funcionar només amb la primera condició, però per raons que escapen al meu coneixement, no anava :()
        self.leNumero.setEnabled(
            self.calle_con_acentos != '' or self.txto != '')

    def cercadorAdrecaFi(self):
        if self.db.isOpen():
            self.db.close()

    def prepararCompleterCarrer(self):
        # creo instancia de completer que relaciona diccionario de calles con lineEdit
        # self.completerCarrer = QCompleter(self.dictCarrers, self.leCarrer)
        self.completerCarrer = CompleterAdreces(
            self.dictCarrers, self.leCarrer)
        # Determino funcionamiento del completer
        self.completerCarrer.setFilterMode(QtCore.Qt.MatchContains)
        self.completerCarrer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        # Funcion que se ejecutará cuando
        self.completerCarrer.activated.connect(self.activatCarrer)
        # Asigno el completer al lineEdit
        self.leCarrer.setCompleter(self.completerCarrer)

    def prepararCompleterNumero(self):
        self.dictNumerosFiltre = self.dictNumeros[self.codiCarrer]
        self.completerNumero = QCompleter(
            self.dictNumerosFiltre, self.leNumero)
        self.completerNumero.activated.connect(self.activatNumero)
        self.completerNumero.setFilterMode(QtCore.Qt.MatchStartsWith)
        self.completerNumero.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.leNumero.setCompleter(self.completerNumero)
        # self.leNumero.setValidator(ValidadorNums(self.dictNumeros[self.codiCarrer],self))

    def iniAdreca(self):
        self.iniAdrecaCarrer()
        self.iniAdrecaNumero()

    def iniAdrecaCarrer(self):
        self.nomCarrer = ''
        self.codiCarrer = ''

    def iniAdrecaNumero(self):
        self.numeroCarrer = ''
        self.coordAdreca = None
        self.infoAdreca = None

    def connectarLineEdits(self):
        self.leCarrer.textChanged.connect(self.esborrarNumero)
        self.leCarrer.editingFinished.connect(self.trobatCarrer)
        # CUARENTENA
        # self.leCarrer.mouseDoubleClickEvent = self.clear_leNumero_leCarrer
        self.leCarrer.mouseDoubleClickEvent = self.SeleccPalabraOTodoEnFrase
        self.leCarrer.setAlignment(Qt.AlignLeft)

        self.leNumero.editingFinished.connect(self.trobatNumero)
        # self.leNumero.returnPressed.connect(self.trobatNumero)

    def SeleccPalabraOTodoEnFrase(self, event):
        """
          Funcion conectada al dobleclick.
          Si se dobleclica 1 vez---> selecciona la palabra (lo que hay entre dos blancos)
          Se se dobleclica 2 veces---> selecciona toda la frase 
        """
        self.carrerActivat=False
        #  self.numClick en def __init__ se inicializa a 0
        if self.numClick == 1:  # segundo doble click => seleccionar toda la frase
            self.leCarrer.selectAll()
            self.numClick =-1
        else:      # primer doble click selecciona la palabra
            # Limite de la palabra por la izquierda (blanco o inicio por izquierda)
            self.ii = self.leCarrer.cursorPosition() - 1
            while self.ii >=0 and self.leCarrer.text()[self.ii] != ' ': 
                self.ii -= 1 ;   self.inicio= self.ii

            # Limite de la palabra por la derecha (blanco o fin por derecha)
            self.ii= self.leCarrer.cursorPosition() - 1 
            while self.ii < len(self.leCarrer.text()) and self.leCarrer.text()[self.ii] != ' ': 
                self.ii += 1 ;   self.fin= self.ii                

            # selecciona palabra en frase por posicion
            self.leCarrer.setSelection(self.inicio+1,self.fin-self.inicio-1)
            
        self.numClick += 1  
    # CUARENTENA
    # def clear_leNumero_leCarrer(self, carrer):
    #     self.carrerActivat = False
    #     self.leNumero.clear()
    #     self.leCarrer.clear()

    # Venimos del completer, un click en desplegable ....
    def activatCarrer(self, carrer):
        self.carrerActivat = True
        # print(carrer)

        carrer=carrer.replace('(var) ','')
        # if chr(29) in carrer:
        #     carrer=carrer.split(chr(29))[0]
        nn = carrer.find(chr(30))
        if nn == -1:
            ss = carrer
        else:
            ss = carrer[0:nn-1]
        # ss=ss.replace('(var) ','')

        self.calle_con_acentos = ss.rstrip()

        self.leCarrer.setAlignment(Qt.AlignLeft)
        self.leCarrer.setText(self.calle_con_acentos)

        # self.leCarrer.setText(carrer)
        self.iniAdreca()
        if carrer in self.dictCarrers:
            self.nomCarrer = carrer
            self.codiCarrer = self.dictCarrers[self.nomCarrer]

            try:
                index = 0
                # self.query = QSqlQuery() # Intancia del Query
                # self.query.exec_("select codi, num_lletra_post, etrs89_coord_x, etrs89_coord_y, num_oficial  from Numeros where codi = '" + self.codiCarrer +"'")

                self.query.exec_(
                    "select codi,case num_lletra_post when '0' then ' ' else num_lletra_post end,  etrs89_coord_x, etrs89_coord_y, num_oficial  from Numeros   where codi = '" + self.codiCarrer + "'")
                # self.query.exec_("select codi,case num_lletra_post when '0' then ' ' else num_lletra_post end,  etrs89_coord_x, etrs89_coord_y, case num_oficial when '0' then ' ' else num_oficial end  from Numeros   where codi = '" + self.codiCarrer +"'")

                while self.query.next():
                    row = collections.OrderedDict()
                    row['NUM_LLETRA_POST'] = self.query.value(
                        1)  # Numero y Letra
                    row['ETRS89_COORD_X'] = self.query.value(2)  # coor x
                    row['ETRS89_COORD_Y'] = self.query.value(3)  # coor y
                    row['NUM_OFICIAL'] = self.query.value(4)  # numero oficial

                    self.dictNumeros[self.codiCarrer][self.query.value(
                        1)] = row
                    index += 1

                self.query.finish()
                # self.db.close()

                self.prepararCompleterNumero()
                self.focusANumero()

            except Exception as e:
                print(str(e))
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Warning)

                msg.setText(str(sys.exc_info()[1]))
                # msg.setInformativeText("OK para salir del programa \nCANCEL para seguir en el programa")
                msg.setWindowTitle("qVista ERROR")
                msg.setStandardButtons(QMessageBox.Close)
                retval = msg.exec_()  # No fem res amb el valor de retorn (???)

                print('QCercadorAdreca.iniAdreca(): ',
                      sys.exc_info()[0], sys.exc_info()[1])
                return False
            else:
                pass

        else:
            info = "ERROR >> [1]"
            self.sHanTrobatCoordenades.emit(1, info)  # adreça vacia
        self.habilitaLeNum()
        # self.prepararCompleterNumero()
        # self.focusANumero()

    def trobatCarrer(self):
        if self.leCarrer.text() == '':
            self.leNumero.setCompleter(None)
            return
        if not self.carrerActivat:
            # print(self.leCarrer.text())
            # així obtenim el carrer on estàvem encara que no l'haguem seleccionat explícitament
            self.txto = self.completerCarrer.popup().currentIndex().data()
            if self.txto is None:
                self.txto = self.completerCarrer.currentCompletion()
            if self.txto == '':
                return
            # self.txto=self.txto.split(chr(29))[0]

            nn = self.txto.find(chr(30))
            self.txto=self.txto.replace('(var) ','')
            if nn == -1:
                ss = self.txto
            else:
                ss = self.txto[0:nn-1]
            # ss=ss.replace('(var) ','')

            # ss= self.txto[0:nn-1]
            self.calle_con_acentos = ss.rstrip()

            self.leCarrer.setAlignment(Qt.AlignLeft)
            self.leCarrer.setText(self.calle_con_acentos)

            self.iniAdreca()
            if self.txto != self.nomCarrer:
                # self.iniAdreca()
                if self.txto in self.dictCarrers:
                    self.nomCarrer = self.txto
                    self.codiCarrer = self.dictCarrers[self.nomCarrer]
                    self.focusANumero()

                    try:
                        index = 0
                        # self.query = QSqlQuery() # Intancia del Query
                        # self.query.exec_("select codi, num_lletra_post, etrs89_coord_x, etrs89_coord_y, num_oficial  from Numeros where codi = '" + self.codiCarrer +"'")
                        self.query.exec_(
                            "select codi,case num_lletra_post when '0' then ' ' else num_lletra_post end,  etrs89_coord_x, etrs89_coord_y, num_oficial  from Numeros   where codi = '" + self.codiCarrer + "'")

                        while self.query.next():
                            row = collections.OrderedDict()
                            row['NUM_LLETRA_POST'] = self.query.value(
                                1)  # Numero y Letra
                            row['ETRS89_COORD_X'] = self.query.value(
                                2)  # coor x
                            row['ETRS89_COORD_Y'] = self.query.value(
                                3)  # coor y
                            row['NUM_OFICIAL'] = self.query.value(
                                4)  # numero oficial

                            self.dictNumeros[self.codiCarrer][self.query.value(
                                1)] = row
                            index += 1

                        self.query.finish()
                        # self.db.close()
                        self.prepararCompleterNumero()
                        self.focusANumero()

                    except Exception as e:
                        print(str(e))
                        msg = QMessageBox()
                        msg.setIcon(QMessageBox.Warning)

                        msg.setText(str(sys.exc_info()[1]))
                        # msg.setInformativeText("OK para salir del programa \nCANCEL para seguir en el programa")
                        msg.setWindowTitle("qVista ERROR")
                        msg.setStandardButtons(QMessageBox.Close)
                        retval = msg.exec_()  # No fem res amb el valor de retorn (???)

                        print('QCercadorAdreca.iniAdreca(): ',
                              sys.exc_info()[0], sys.exc_info()[1])
                        return False

                else:
                    info = "ERROR >> [2]"
                    # direccion no está en diccicionario
                    self.sHanTrobatCoordenades.emit(2, info)
                    self.iniAdreca()
            else:
                info = "ERROR >> [3]"
                self.sHanTrobatCoordenades.emit(3, info)  # nunca
        else:
            info = "ERROR >> [4]"
            self.sHanTrobatCoordenades.emit(4, info)  # adreça vac
        self.habilitaLeNum()

    def llegirAdreces(self):
        if self.origen == 'SQLITE':
            ok = self.llegirAdrecesSQlite()
        else:
            ok = False
        return ok

    def llegirAdrecesSQlite(self):
        try:
            index = 0
            # self.query = QSqlQuery() # Intancia del Query
            self.query.exec_(
                "select codi , nom_oficial , variants  from Carrers")

            while self.query.next():
                codi_carrer = self.query.value(0)  # Codigo calle
                nombre = self.query.value(1)  # numero oficial
                variants = self.query.value(2).lower()  # Variants del nom
                nombre_sin_acentos = self.remove_accents(nombre)
                if nombre == nombre_sin_acentos:
                    # clave= nombre + "  (" + codi_carrer + ")"
                    clave = nombre + \
                        "  (" + codi_carrer + \
                        ")                                                  " + \
                        chr(30)
                else:
                    clave = nombre + "  (" + codi_carrer + ")                                                  "+chr(
                        30)+"                                                         " + nombre_sin_acentos
                    # asignacion al diccionario
                variants.replace(',', 50*' ')
                clave += chr(29)+50*' '+variants
                self.dictCarrers[clave] = codi_carrer

                index += 1

            self.query.finish()
            # self.db.close()
            return True
        except Exception as e:
            print(str(e))
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Warning)

            msg.setText(str(sys.exc_info()[1]))
            # msg.setInformativeText("OK para salir del programa \nCANCEL para seguir en el programa")
            msg.setWindowTitle("qVista ERROR")
            msg.setStandardButtons(QMessageBox.Close)
            retval = msg.exec_()  # No fem res amb el valor de retorn (???)

            print('QCercadorAdreca.llegirAdrecesSQlite(): ',
                  sys.exc_info()[0], sys.exc_info()[1])
            return False

    # Normalización caracteres quitando acentos

    def remove_accents(self, input_str):
        nfkd_form = unicodedata.normalize('NFKD', input_str)
        only_ascii = nfkd_form.encode('ASCII', 'ignore')
        return only_ascii.decode("utf8")

    def activatNumero(self, txt):
        self.leNumero.setText(txt)
        self.iniAdrecaNumero()
        # if self.leCarrer.text() in self.dictCarrers:
        # self.txto = self.completerCarrer.currentCompletion()
        self.txto = self.completerCarrer.popup().currentIndex().data()
        if self.txto is None:
            self.txto = self.completerCarrer.currentCompletion()
        self.txto=self.txto.replace('(var) ','')
        if self.txto in self.dictCarrers:
            if txt in self.dictNumerosFiltre:
                self.numeroCarrer = txt
                self.infoAdreca = self.dictNumerosFiltre[self.numeroCarrer]
                self.coordAdreca = QgsPointXY(float(self.infoAdreca['ETRS89_COORD_X']),
                                              float(self.infoAdreca['ETRS89_COORD_Y']))

                self.NumeroOficial = self.infoAdreca['NUM_OFICIAL']
                self.leNumero.setText(self.NumeroOficial)
                self.leNumero.clearFocus()

                info = "[0]"
                self.sHanTrobatCoordenades.emit(0, info)
                if self.leNumero.text() == ' ':
                    self.leNumero.clear()

        else:
            info = "ERROR >> [5]"
            self.sHanTrobatCoordenades.emit(5, info)  # numero

    def trobatNumero(self):
        # Si no hi ha carrer, eliminem el completer del número
        if self.leCarrer.text() == '':
            self.leNumero.setCompleter(None)
        if self.leNumero.text() == '':
            return
        # self.txto = self.completerCarrer.currentCompletion()
        try:
            # if self.leCarrer.text() in self.dictCarrers:
            self.txto = self.completerCarrer.popup().currentIndex().data()
            if self.txto is None:
                self.txto = self.completerCarrer.currentCompletion()
            self.txto=self.txto.replace('(var) ','')
            if self.txto in self.dictCarrers:

                if self.leNumero.text() != '':
                    txt = self.completerNumero.popup().currentIndex().data()
                    if txt is None:
                        txt = self.completerNumero.currentCompletion()
                    # txt = self.completerNumero.currentCompletion()
                    self.leNumero.setText(txt)
                else:
                    txt = ' '

                if txt != '':  # and txt != self.numeroCarrer:
                    self.iniAdrecaNumero()
                    if self.nomCarrer != '':
                        if txt in self.dictNumerosFiltre:
                            self.numeroCarrer = txt
                            self.infoAdreca = self.dictNumerosFiltre[self.numeroCarrer]
                            self.coordAdreca = QgsPointXY(float(self.infoAdreca['ETRS89_COORD_X']),
                                                          float(self.infoAdreca['ETRS89_COORD_Y']))
                            self.NumeroOficial = self.infoAdreca['NUM_OFICIAL']
                            self.leNumero.clearFocus()
                            self.leNumero.setText(self.NumeroOficial)
                            info = "[0]"
                            self.sHanTrobatCoordenades.emit(0, info)
                            if self.leNumero.text() == ' ':
                                self.leNumero.clear()

                        else:
                            info = "ERROR >> [6]"
                            # numero no está en diccicionario
                            self.sHanTrobatCoordenades.emit(6, info)
                    else:
                        info = "ERROR >> [7]"
                        self.sHanTrobatCoordenades.emit(
                            7, info)  # adreça vacia  nunca
                else:
                    info = "ERROR >> [8]"
                    self.sHanTrobatCoordenades.emit(
                        8, info)  # numero en blanco
            else:
                self.leNumero.clear()
                info = "ERROR >> [9]"
                self.sHanTrobatCoordenades.emit(9, info)  # numero en blanco
        except:
            return
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Warning)
            info_rsc = 'ERROR: ' + str(sys.exc_info()[0])
            msg.setText(info_rsc)
            # msg.setInformativeText("OK para salir del programa \nCANCEL para seguir en el programa")
            msg.setWindowTitle("qVista >> QVCercadorAdreca>> trobatNumero")

            msg.setStandardButtons(QMessageBox.Close)
            retval = msg.exec_()  # No fem res amb el valor de retorn (???)

    def focusANumero(self):
        self.leNumero.setFocus()

    def esborrarNumero(self):
        # self.carrerActivat = False
        self.calle_con_acentos = ''
        self.leNumero.clear()
class TmParentManage(TmParentAction, object):
    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class to keep common functions of classes
        'ManageDocument', 'ManageElement' and 'ManageVisit' of toolbar 'edit' """

        super(TmParentManage, self).__init__(iface, settings, controller,
                                             plugin_dir)
        self.x = ""
        self.y = ""
        self.canvas = self.iface.mapCanvas()
        self.plan_om = None
        self.previous_map_tool = None
        self.autocommit = True
        self.lazy_widget = None
        self.workcat_id_end = None

    def reset_lists(self):
        """ Reset list of selected records """

        self.ids = []
        self.list_ids = {}
        self.list_ids['node'] = []

    def reset_layers(self):
        """ Reset list of layers """

        self.layers = {}
        self.layers['node'] = []
        self.visible_layers = []

    def remove_selection(self):
        """ Remove all previous selections """

        try:
            for layer in self.layers['node']:
                if layer in self.visible_layers:
                    self.controller.set_layer_visible(layer, False)
            for layer in self.layers['node']:
                if layer in self.visible_layers:
                    self.controller.set_layer_visible(layer, True)
                    layer.removeSelection()
        except:
            pass

        self.canvas.refresh()
        self.canvas.setMapTool(self.previous_map_tool)

    def add_point(self):
        """ Create the appropriate map tool and connect to the corresponding signal """

        self.emit_point = QgsMapToolEmitPoint(self.canvas)
        self.previous_map_tool = self.canvas.mapTool()
        self.canvas.setMapTool(self.emit_point)
        self.emit_point.canvasClicked.connect(partial(self.get_xy))

    def get_xy(self, point):
        """ Get coordinates of selected point """

        self.x = point.x()
        self.y = point.y()
        message = "Geometry has been added!"
        self.controller.show_info(message)
        self.emit_point.canvasClicked.disconnect()

    def set_completer_feature_id(self, widget, geom_type, viewname):
        """ Set autocomplete of widget 'feature_id'. Getting id's from selected @viewname """

        # Adding auto-completion to a QLineEdit
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()

        sql = (f"SELECT {geom_type}_id" f" FROM {viewname}")
        row = self.controller.get_rows(sql, commit=self.autocommit)
        if row:
            for i in range(0, len(row)):
                aux = row[i]
                row[i] = str(aux[0])

            model.setStringList(row)
            self.completer.setModel(model)

    def set_table_model(self, qtable, geom_type, expr_filter):
        """ Sets a TableModel to @widget_name attached to @table_name and filter @expr_filter """

        expr = None
        if expr_filter:
            # Check expression
            (is_valid,
             expr) = self.check_expression(expr_filter)  # @UnusedVariable
            if not is_valid:
                return expr

        # Set a model with selected filter expression
        table_name = "v_edit_" + geom_type
        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set the model
        model = QSqlTableModel()
        model.setTable(table_name)
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.select()
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())
            return expr

        # Attach model to selected widget
        if type(qtable) is QTableView:
            widget = qtable
        else:
            message = "Table_object is not a table name or QTableView"
            self.controller.log_info(message)
            return expr

        if expr_filter:
            widget.setModel(model)
            widget.model().setFilter(expr_filter)
            widget.model().select()
        else:
            widget.setModel(None)

        return expr

    def apply_lazy_init(self, widget):
        """ Apply the init function related to the model. It's necessary
        a lazy init because model is changed everytime is loaded """

        if self.lazy_widget is None:
            return
        if widget != self.lazy_widget:
            return
        self.lazy_init_function(self.lazy_widget)

    def lazy_configuration(self, widget, init_function):
        """ set the init_function where all necessary events are set.
        This is necessary to allow a lazy setup of the events because set_table_events
        can create a table with a None model loosing any event connection """

        # TODO: create a dictionary with key:widged.objectName value:initFuction
        # to allow multiple lazy initialization
        self.lazy_widget = widget
        self.lazy_init_function = init_function

    def select_features_by_ids(self, geom_type, expr):
        """ Select features of layers of group @geom_type applying @expr """

        # Build a list of feature id's and select them
        for layer in self.layers[geom_type]:
            if expr is None:
                layer.removeSelection()
            else:
                it = layer.getFeatures(QgsFeatureRequest(expr))
                id_list = [i.id() for i in it]
                if len(id_list) > 0:
                    layer.selectByIds(id_list)
                else:
                    layer.removeSelection()

    def delete_records(self, dialog, table_object):
        """ Delete selected elements of the table """

        self.disconnect_signal_selection_changed()

        if type(table_object) is str:
            widget_name = f"tbl_{table_object}_x_{self.geom_type}"
            widget = utils_giswater.getWidget(dialog, widget_name)
            if not widget:
                message = "Widget not found"
                self.controller.show_warning(message, parameter=widget_name)
                return
        elif type(table_object) is QTableView:
            widget = table_object
        else:
            message = "Table_object is not a table name or QTableView"
            self.controller.log_info(message)
            return

        # Get selected rows
        selected_list = widget.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_info_box(message)
            return

        self.ids = self.list_ids[self.geom_type]
        field_id = self.geom_type + "_id"

        del_id = []
        inf_text = ""

        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_feature = widget.model().record(row).value(field_id)
            inf_text += f"{id_feature}, "

            del_id.append(id_feature)
        inf_text = inf_text[:-2]

        message = "Are you sure you want to delete these records?"
        title = "Delete records"
        answer = self.controller.ask_question(message, title, inf_text)
        if answer:
            for el in del_id:
                self.ids.remove(el)
        else:
            return

        expr_filter = None
        expr = None
        if len(self.ids) > 0:

            # Set expression filter with features in the list
            expr_filter = f'"{field_id}" IN ('
            for i in range(len(self.ids)):
                expr_filter += f"'{self.ids[i]}', "
            expr_filter = expr_filter[:-2] + ")"

            # Check expression
            (is_valid,
             expr) = self.check_expression(expr_filter)  # @UnusedVariable
            if not is_valid:
                return

        # Update model of the widget with selected expr_filter
        self.reload_table(table_object, self.geom_type, expr_filter)
        self.apply_lazy_init(table_object)

        # Select features with previous filter
        # Build a list of feature id's and select them
        self.select_features_by_ids(self.geom_type, expr)

        # Update list
        self.list_ids[self.geom_type] = self.ids

        self.connect_signal_selection_changed(table_object)

    def selection_init(self, table_object):
        """ Set canvas map tool to an instance of class 'MultipleSelection' """

        current_visible_layers = self.get_visible_layers()
        for layer in current_visible_layers:
            if layer not in self.visible_layers:
                self.visible_layers.append(layer)
        self.controller.log_info(str(self.visible_layers))
        multiple_selection = TmMultipleSelection(self.iface,
                                                 self.controller,
                                                 self.layers[self.geom_type],
                                                 parent_manage=self,
                                                 table_object=table_object)
        self.disconnect_signal_selection_changed()
        self.previous_map_tool = self.canvas.mapTool()
        self.canvas.setMapTool(multiple_selection)
        self.connect_signal_selection_changed(table_object)
        cursor = self.get_cursor_multiple_selection()
        self.canvas.setCursor(cursor)

    def selection_changed(self, qtable, geom_type):
        """ Slot function for signal 'canvas.selectionChanged' """

        self.disconnect_signal_selection_changed()

        field_id = geom_type + "_id"
        self.ids = []

        # Iterate over all layers of the group
        for layer in self.layers[self.geom_type]:
            if layer.selectedFeatureCount(
            ) > 0 and self.controller.is_layer_visible(layer):
                # Get selected features of the layer
                features = layer.selectedFeatures()
                for feature in features:
                    # Append 'feature_id' into the list
                    selected_id = feature.attribute(field_id)
                    if selected_id not in self.ids:
                        self.ids.append(selected_id)

        if geom_type == 'node':
            self.list_ids['node'] = self.ids

        expr_filter = None
        if len(self.ids) > 0:
            # Set 'expr_filter' with features that are in the list
            expr_filter = f'"{field_id}" IN ('
            for i in range(len(self.ids)):
                expr_filter += f"'{self.ids[i]}', "
            expr_filter = expr_filter[:-2] + ")"

            # Check expression
            (is_valid,
             expr) = self.check_expression(expr_filter)  # @UnusedVariable
            if not is_valid:
                return

            self.select_features_by_ids(geom_type, expr)

        # Reload contents of table 'tbl_@table_object_x_@geom_type'
        self.reload_table(qtable, self.geom_type, expr_filter)
        self.apply_lazy_init(qtable)
        # Remove selection in generic 'v_edit' layers
        #self.remove_selection(False)

        self.connect_signal_selection_changed(qtable)

    def insert_feature(self, widget, table_object):
        """ Select feature with entered id. Set a model with selected filter.
        Attach that model to selected table
        """

        self.disconnect_signal_selection_changed()

        # Clear list of ids
        self.ids = []
        field_id = self.geom_type + "_id"

        feature_id = widget.text()
        if feature_id == 'null':
            message = "You need to enter a feature id"
            self.controller.show_info_box(message)
            return

        # Iterate over all layers of the group
        for layer in self.layers[self.geom_type]:
            if layer.selectedFeatureCount() > 0:
                # Get selected features of the layer
                features = layer.selectedFeatures()
                for feature in features:
                    # Append 'feature_id' into the list
                    selected_id = feature.attribute(field_id)
                    self.ids.append(selected_id)
            if feature_id not in self.ids:
                # If feature id doesn't exist in list -> add
                self.ids.append(str(feature_id))

        # Set expression filter with features in the list
        expr_filter = f'"{field_id}" IN ('
        for i in range(len(self.ids)):
            expr_filter += f"'{self.ids[i]}', "
        expr_filter = expr_filter[:-2] + ")"

        # Check expression
        (is_valid, expr) = self.check_expression(expr_filter)
        if not is_valid:
            return

        # Select features with previous filter
        # Build a list of feature id's and select them
        for layer in self.layers[self.geom_type]:
            it = layer.getFeatures(QgsFeatureRequest(expr))
            id_list = [i.id() for i in it]
            if len(id_list) > 0:
                layer.selectByIds(id_list)

        # Reload contents of table 'tbl_???_x_@geom_type'
        self.reload_table(table_object, self.geom_type, expr_filter)
        self.apply_lazy_init(table_object)

        # Update list
        self.list_ids[self.geom_type] = self.ids

        self.connect_signal_selection_changed(table_object)

    def disconnect_snapping(self):
        """ Select 'Pan' as current map tool and disconnect snapping """

        try:
            self.iface.actionPan().trigger()
            self.canvas.xyCoordinates.disconnect()
            if self.emit_point:
                self.emit_point.canvasClicked.disconnect()
        except:
            pass

    def connect_signal_selection_changed(self, table_object):
        """ Connect signal selectionChanged """

        try:
            self.canvas.selectionChanged.connect(
                partial(self.selection_changed, table_object, self.geom_type))
        except Exception:
            pass

    def disconnect_signal_selection_changed(self):
        """ Disconnect signal selectionChanged """

        try:
            self.canvas.selectionChanged.disconnect()
        except Exception:
            pass

    def fill_widget_with_fields(self, dialog, data_object, field_names):
        """ Fill the Widget with value get from data_object limited to the list of field_names. """

        for field_name in field_names:
            value = getattr(data_object, field_name)
            if not hasattr(dialog, field_name):
                continue

            widget = getattr(dialog, field_name)
            if type(widget) in [QDateEdit, QDateTimeEdit]:
                widget.setDateTime(value if value else QDate.currentDate())
            if type(widget) in [QLineEdit, QTextEdit]:
                if value:
                    widget.setText(value)
                else:
                    widget.clear()
            if type(widget) in [QComboBox]:
                if not value:
                    widget.setCurrentIndex(0)
                    continue
                # look the value in item text
                index = widget.findText(str(value))
                if index >= 0:
                    widget.setCurrentIndex(index)
                    continue
                # look the value in itemData
                index = widget.findData(value)
                if index >= 0:
                    widget.setCurrentIndex(index)
                    continue

    def reload_table(self, qtable, geom_type, expr_filter):
        """ Reload @widget with contents of @tablename applying selected @expr_filter """

        if type(qtable) is QTableView:
            widget = qtable
        else:
            message = "Table_object is not a table name or QTableView"
            self.controller.log_info(message)
            return None

        expr = self.set_table_model(widget, geom_type, expr_filter)
        return expr

    def get_visible_layers(self, return_as_list=True):
        """ Return list or string as {...} with all visible layer in TOC """

        visible_layer = []
        layers = self.controller.get_layers()
        if return_as_list:
            for layer in layers:
                if self.controller.is_layer_visible(layer):
                    visible_layer.append(layer)
            return visible_layer

        for layer in layers:
            if self.controller.is_layer_visible(layer):
                visible_layer += f'"{layer.name()}", '
        visible_layer = visible_layer[:-2] + "}"

        return visible_layer
Exemplo n.º 20
0
class ParentAction(object):
    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class constructor """

        # Initialize instance attributes
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.settings = settings
        self.controller = controller
        self.plugin_dir = plugin_dir
        self.dao = self.controller.dao
        self.schema_name = self.controller.schema_name
        self.project_type = None
        self.plugin_version = self.get_plugin_version()
        self.add_layer = AddLayer(iface, settings, controller, plugin_dir)

    def set_controller(self, controller):
        """ Set controller class """

        self.controller = controller
        self.schema_name = self.controller.schema_name

    def open_web_browser(self, dialog, widget=None):
        """ Display url using the default browser """

        if widget is not None:
            url = utils_giswater.getWidgetText(dialog, widget)
            if url == 'null':
                url = 'http://www.giswater.org'
        else:
            url = 'http://www.giswater.org'

        webbrowser.open(url)

    def get_plugin_version(self):
        """ Get plugin version from metadata.txt file """

        # Check if metadata file exists
        metadata_file = os.path.join(self.plugin_dir, 'metadata.txt')
        if not os.path.exists(metadata_file):
            message = "Metadata file not found"
            self.controller.show_warning(message, parameter=metadata_file)
            return None

        metadata = configparser.ConfigParser()
        metadata.read(metadata_file)
        plugin_version = metadata.get('general', 'version')
        if plugin_version is None:
            message = "Plugin version not found"
            self.controller.show_warning(message)

        return plugin_version

    def get_file_dialog(self, dialog, widget):
        """ Get file dialog """

        # Check if selected file exists. Set default value if necessary
        file_path = utils_giswater.getWidgetText(dialog, widget)
        if file_path is None or file_path == 'null' or not os.path.exists(
                str(file_path)):
            folder_path = self.plugin_dir
        else:
            folder_path = os.path.dirname(file_path)

        # Open dialog to select file
        os.chdir(folder_path)
        file_dialog = QFileDialog()
        file_dialog.setFileMode(QFileDialog.AnyFile)
        message = "Select file"
        folder_path, filter_ = file_dialog.getOpenFileName(
            parent=None, caption=self.controller.tr(message))
        if folder_path:
            utils_giswater.setWidgetText(dialog, widget, str(folder_path))

    def get_folder_dialog(self, dialog, widget):
        """ Get folder dialog """

        # Check if selected folder exists. Set default value if necessary
        folder_path = utils_giswater.getWidgetText(dialog, widget)
        if folder_path is None or folder_path == 'null' or not os.path.exists(
                folder_path):
            folder_path = os.path.expanduser("~")

        # Open dialog to select folder
        os.chdir(folder_path)
        file_dialog = QFileDialog()
        file_dialog.setFileMode(QFileDialog.Directory)
        message = "Select folder"
        folder_path = file_dialog.getExistingDirectory(
            parent=None,
            caption=self.controller.tr(message),
            directory=folder_path)
        if folder_path:
            utils_giswater.setWidgetText(dialog, widget, str(folder_path))

    def load_settings(self, dialog=None):
        """ Load QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        try:
            x = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_x")
            y = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_y")
            width = self.controller.plugin_settings_value(
                dialog.objectName() + "_width", dialog.property('width'))
            height = self.controller.plugin_settings_value(
                dialog.objectName() + "_height", dialog.property('height'))

            if int(x) < 0 or int(y) < 0:
                dialog.resize(int(width), int(height))
            else:
                screens = ctypes.windll.user32
                screen_x = screens.GetSystemMetrics(78)
                screen_y = screens.GetSystemMetrics(79)
                if int(x) > screen_x:
                    x = int(screen_x) - int(width)
                if int(y) > screen_y:
                    y = int(screen_y)
                dialog.setGeometry(int(x), int(y), int(width), int(height))
        except:
            pass

    def save_settings(self, dialog=None):
        """ Save QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_width", dialog.property('width'))
        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_height", dialog.property('height'))
        self.controller.plugin_settings_set_value(dialog.objectName() + "_x",
                                                  dialog.pos().x() + 8)
        self.controller.plugin_settings_set_value(dialog.objectName() + "_y",
                                                  dialog.pos().y() + 31)

    def open_dialog(self,
                    dlg=None,
                    dlg_name=None,
                    info=True,
                    maximize_button=True,
                    stay_on_top=True):
        """ Open dialog """

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg

        # Manage i18n of the dialog
        if dlg_name:
            self.controller.manage_translation(dlg_name, dlg)

        # Manage stay on top, maximize/minimize button and information button
        # if info is True maximize flag will be ignored
        # To enable maximize button you must set info to False
        flags = Qt.WindowCloseButtonHint
        if info:
            flags |= Qt.WindowSystemMenuHint | Qt.WindowContextHelpButtonHint
        else:
            if maximize_button:
                flags |= Qt.WindowMinMaxButtonsHint

        if stay_on_top:
            flags |= Qt.WindowStaysOnTopHint

        dlg.setWindowFlags(flags)

        # Open dialog
        if issubclass(type(dlg), GwDialog):
            dlg.open()
        elif issubclass(type(dlg), GwMainWindow):
            dlg.show()
        else:
            print(f"WARNING: dialog type {type(dlg)} is not handled!")
            dlg.show()

    def close_dialog(self, dlg=None):
        """ Close dialog """

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg
        try:
            self.save_settings(dlg)
            dlg.close()
            map_tool = self.canvas.mapTool()
            # If selected map tool is from the plugin, set 'Pan' as current one
            if map_tool.toolName() == '':
                self.iface.actionPan().trigger()
        except AttributeError:
            pass
        except Exception as e:
            print(type(e).__name__)

    def multi_row_selector(self,
                           dialog,
                           tableleft,
                           tableright,
                           field_id_left,
                           field_id_right,
                           name='name',
                           hide_left=[
                               0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
                               27, 28, 29, 30
                           ],
                           hide_right=[1, 2, 3],
                           aql=""):
        """
        :param dialog:
        :param tableleft: Table to consult and load on the left side
        :param tableright: Table to consult and load on the right side
        :param field_id_left: ID field of the left table
        :param field_id_right: ID field of the right table
        :param name: field name (used in add_lot.py)
        :param hide_left: Columns to hide from the left table
        :param hide_right: Columns to hide from the right table
        :param aql: (add query left) Query added to the left side (used in basic.py def basic_exploitation_selector())
        :return:
        """
        # fill QTableView all_rows
        tbl_all_rows = dialog.findChild(QTableView, "all_rows")
        tbl_all_rows.setSelectionBehavior(QAbstractItemView.SelectRows)
        schema_name = self.schema_name.replace('"', '')
        query_left = f"SELECT * FROM {schema_name}.{tableleft} WHERE {name} NOT IN "
        query_left += f"(SELECT {tableleft}.{name} FROM {schema_name}.{tableleft}"
        query_left += f" RIGHT JOIN {schema_name}.{tableright} ON {tableleft}.{field_id_left} = {tableright}.{field_id_right}"
        query_left += f" WHERE cur_user = current_user)"
        query_left += f" AND  {field_id_left} > -1"
        query_left += aql

        self.fill_table_by_query(tbl_all_rows, query_left)
        self.hide_colums(tbl_all_rows, hide_left)
        tbl_all_rows.setColumnWidth(1, 200)

        # fill QTableView selected_rows
        tbl_selected_rows = dialog.findChild(QTableView, "selected_rows")
        tbl_selected_rows.setSelectionBehavior(QAbstractItemView.SelectRows)

        query_right = f"SELECT {tableleft}.{name}, cur_user, {tableleft}.{field_id_left}, {tableright}.{field_id_right}"
        query_right += f" FROM {schema_name}.{tableleft}"
        query_right += f" JOIN {schema_name}.{tableright} ON {tableleft}.{field_id_left} = {tableright}.{field_id_right}"

        query_right += " WHERE cur_user = current_user"

        self.fill_table_by_query(tbl_selected_rows, query_right)
        self.hide_colums(tbl_selected_rows, hide_right)
        tbl_selected_rows.setColumnWidth(0, 200)
        # Button select
        dialog.btn_select.clicked.connect(
            partial(self.multi_rows_selector, tbl_all_rows, tbl_selected_rows,
                    field_id_left, tableright, field_id_right, query_left,
                    query_right, field_id_right))

        # Button unselect
        query_delete = f"DELETE FROM {schema_name}.{tableright}"
        query_delete += f" WHERE current_user = cur_user AND {tableright}.{field_id_right}="
        dialog.btn_unselect.clicked.connect(
            partial(self.unselector, tbl_all_rows, tbl_selected_rows,
                    query_delete, query_left, query_right, field_id_right))

        # QLineEdit
        dialog.txt_name.textChanged.connect(
            partial(self.query_like_widget_text, dialog, dialog.txt_name,
                    tbl_all_rows, tableleft, tableright, field_id_right,
                    field_id_left, name))

        # Order control
        tbl_all_rows.horizontalHeader().sectionClicked.connect(
            partial(self.order_by_column, tbl_all_rows, query_left))
        tbl_selected_rows.horizontalHeader().sectionClicked.connect(
            partial(self.order_by_column, tbl_selected_rows, query_right))

    def order_by_column(self, qtable, query, idx):
        """
        :param qtable: QTableView widget
        :param query: Query for populate QsqlQueryModel
        :param idx: The index of the clicked column
        :return:
        """
        oder_by = {0: "ASC", 1: "DESC"}
        sort_order = qtable.horizontalHeader().sortIndicatorOrder()
        col_to_sort = qtable.model().headerData(idx, Qt.Horizontal)
        query += f" ORDER BY {col_to_sort} {oder_by[sort_order]}"
        self.fill_table_by_query(qtable, query)
        self.refresh_map_canvas()

    def hide_colums(self, widget, comuns_to_hide):
        for i in range(0, len(comuns_to_hide)):
            widget.hideColumn(comuns_to_hide[i])

    def unselector(self, qtable_left, qtable_right, query_delete, query_left,
                   query_right, field_id_right):

        selected_list = qtable_right.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return
        expl_id = []
        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_ = str(qtable_right.model().record(row).value(field_id_right))
            expl_id.append(id_)
        for i in range(0, len(expl_id)):
            self.controller.execute_sql(query_delete + str(expl_id[i]))

        # Refresh
        oder_by = {0: "ASC", 1: "DESC"}
        sort_order = qtable_left.horizontalHeader().sortIndicatorOrder()
        idx = qtable_left.horizontalHeader().sortIndicatorSection()
        col_to_sort = qtable_left.model().headerData(idx, Qt.Horizontal)
        query_left += f" ORDER BY {col_to_sort} {oder_by[sort_order]}"
        self.fill_table_by_query(qtable_left, query_left)

        sort_order = qtable_right.horizontalHeader().sortIndicatorOrder()
        idx = qtable_right.horizontalHeader().sortIndicatorSection()
        col_to_sort = qtable_right.model().headerData(idx, Qt.Horizontal)
        query_right += f" ORDER BY {col_to_sort} {oder_by[sort_order]}"
        self.fill_table_by_query(qtable_right, query_right)
        self.refresh_map_canvas()

    def multi_rows_selector(self, qtable_left, qtable_right, id_ori,
                            tablename_des, id_des, query_left, query_right,
                            field_id):
        """
            :param qtable_left: QTableView origin
            :param qtable_right: QTableView destini
            :param id_ori: Refers to the id of the source table
            :param tablename_des: table destini
            :param id_des: Refers to the id of the target table, on which the query will be made
            :param query_right:
            :param query_left:
            :param field_id:
        """

        selected_list = qtable_left.selectionModel().selectedRows()

        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return
        expl_id = []
        curuser_list = []
        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_ = qtable_left.model().record(row).value(id_ori)
            expl_id.append(id_)
            curuser = qtable_left.model().record(row).value("cur_user")
            curuser_list.append(curuser)
        for i in range(0, len(expl_id)):
            # Check if expl_id already exists in expl_selector
            sql = (
                f"SELECT DISTINCT({id_des}, cur_user)"
                f" FROM {tablename_des}"
                f" WHERE {id_des} = '{expl_id[i]}' AND cur_user = current_user"
            )
            row = self.controller.get_row(sql)

            if row:
                # if exist - show warning
                message = "Id already selected"
                self.controller.show_info_box(message,
                                              "Info",
                                              parameter=str(expl_id[i]))
            else:
                sql = (f"INSERT INTO {tablename_des} ({field_id}, cur_user) "
                       f" VALUES ({expl_id[i]}, current_user)")
                self.controller.execute_sql(sql)

        # Refresh
        oder_by = {0: "ASC", 1: "DESC"}
        sort_order = qtable_left.horizontalHeader().sortIndicatorOrder()
        idx = qtable_left.horizontalHeader().sortIndicatorSection()
        col_to_sort = qtable_left.model().headerData(idx, Qt.Horizontal)
        query_left += f" ORDER BY {col_to_sort} {oder_by[sort_order]}"
        self.fill_table_by_query(qtable_right, query_right)

        sort_order = qtable_right.horizontalHeader().sortIndicatorOrder()
        idx = qtable_right.horizontalHeader().sortIndicatorSection()
        col_to_sort = qtable_right.model().headerData(idx, Qt.Horizontal)
        query_right += f" ORDER BY {col_to_sort} {oder_by[sort_order]}"
        self.fill_table_by_query(qtable_left, query_left)
        self.refresh_map_canvas()

    def fill_table_psector(self,
                           widget,
                           table_name,
                           set_edit_strategy=QSqlTableModel.OnManualSubmit):
        """ Set a model with selected @table_name. Attach that model to selected table """

        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set model
        self.model = QSqlTableModel()
        self.model.setTable(table_name)
        self.model.setEditStrategy(set_edit_strategy)
        self.model.setSort(0, 0)
        self.model.select()

        # Check for errors
        if self.model.lastError().isValid():
            self.controller.show_warning(self.model.lastError().text())

        # Attach model to table view
        widget.setModel(self.model)

    def fill_table(self,
                   widget,
                   table_name,
                   set_edit_strategy=QSqlTableModel.OnManualSubmit,
                   expr_filter=None):
        """ Set a model with selected filter.
        Attach that model to selected table """

        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set model
        self.model = QSqlTableModel()
        self.model.setTable(table_name)
        self.model.setEditStrategy(set_edit_strategy)
        self.model.setSort(0, 0)
        self.model.select()

        # Check for errors
        if self.model.lastError().isValid():
            self.controller.show_warning(self.model.lastError().text())

        # Attach model to table view
        widget.setModel(self.model)
        if expr_filter:
            widget.model().setFilter(expr_filter)

    def fill_table_by_query(self, qtable, query):
        """
        :param qtable: QTableView to show
        :param query: query to set model
        """

        model = QSqlQueryModel()
        model.setQuery(query)
        qtable.setModel(model)
        qtable.show()

        # Check for errors
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())

    def query_like_widget_text(self,
                               dialog,
                               text_line,
                               qtable,
                               tableleft,
                               tableright,
                               field_id_r,
                               field_id_l,
                               name='name'):
        """ Fill the QTableView by filtering through the QLineEdit"""

        query = utils_giswater.getWidgetText(dialog,
                                             text_line,
                                             return_string_null=False).lower()
        sql = (
            f"SELECT * FROM {tableleft} WHERE {name} NOT IN "
            f"(SELECT {tableleft}.{name} FROM {tableleft}"
            f" RIGHT JOIN {tableright}"
            f" ON {tableleft}.{field_id_l} = {tableright}.{field_id_r}"
            f" WHERE cur_user = current_user) AND LOWER({name}::text) LIKE '%{query}%'"
        )
        self.fill_table_by_query(qtable, sql)

    def set_icon(self, widget, icon):
        """ Set @icon to selected @widget """

        # Get icons folder
        icons_folder = os.path.join(self.plugin_dir, 'icons')
        icon_path = os.path.join(icons_folder, str(icon) + ".png")
        if os.path.exists(icon_path):
            widget.setIcon(QIcon(icon_path))
        else:
            self.controller.log_info("File not found", parameter=icon_path)

    def check_expression(self, expr_filter, log_info=False):
        """ Check if expression filter @expr_filter is valid """

        if log_info:
            self.controller.log_info(expr_filter)
        expr = QgsExpression(expr_filter)
        if expr.hasParserError():
            message = "Expression Error"
            self.controller.log_warning(message, parameter=expr_filter)
            return False, expr

        return True, expr

    def refresh_map_canvas(self, restore_cursor=False):
        """ Refresh all layers present in map canvas """

        self.canvas.refreshAllLayers()
        for layer_refresh in self.canvas.layers():
            layer_refresh.triggerRepaint()

        if restore_cursor:
            self.set_cursor_restore()

    def set_cursor_wait(self):
        """ Change cursor to 'WaitCursor' """
        QApplication.setOverrideCursor(Qt.WaitCursor)

    def set_cursor_restore(self):
        """ Restore to previous cursors """
        QApplication.restoreOverrideCursor()

    def get_cursor_multiple_selection(self):
        """ Set cursor for multiple selection """

        path_folder = os.path.join(os.path.dirname(__file__), os.pardir)
        path_cursor = os.path.join(path_folder, 'icons', '201.png')
        if os.path.exists(path_cursor):
            cursor = QCursor(QPixmap(path_cursor))
        else:
            cursor = QCursor(Qt.ArrowCursor)

        return cursor

    def set_table_columns(self,
                          dialog,
                          widget,
                          table_name,
                          sort_order=0,
                          isQStandardItemModel=False):
        """ Configuration of tables. Set visibility and width of columns """

        widget = utils_giswater.getWidget(dialog, widget)
        if not widget:
            return

        # Set width and alias of visible columns
        columns_to_delete = []
        sql = (f"SELECT column_index, width, alias, status"
               f" FROM config_client_forms"
               f" WHERE table_id = '{table_name}'"
               f" ORDER BY column_index")
        rows = self.controller.get_rows(sql, commit=True, log_info=False)
        if not rows:
            return

        for row in rows:
            if not row['status']:
                columns_to_delete.append(row['column_index'] - 1)
            else:
                width = row['width']
                if width is None:
                    width = 100
                widget.setColumnWidth(row['column_index'] - 1, width)
                widget.model().setHeaderData(row['column_index'] - 1,
                                             Qt.Horizontal, row['alias'])

        # Set order
        if isQStandardItemModel:
            widget.model().sort(sort_order, Qt.AscendingOrder)
        else:
            widget.model().setSort(sort_order, Qt.AscendingOrder)
            widget.model().select()
        # Delete columns
        for column in columns_to_delete:
            widget.hideColumn(column)

        return widget

    def connect_signal_selection_changed(self, option):
        """ Connect signal selectionChanged """

        try:
            if option == "mincut_connec":
                self.canvas.selectionChanged.connect(
                    partial(self.snapping_selection_connec))
            elif option == "mincut_hydro":
                self.canvas.selectionChanged.connect(
                    partial(self.snapping_selection_hydro))
        except Exception:
            pass

    def disconnect_signal_selection_changed(self):
        """ Disconnect signal selectionChanged """

        try:
            self.canvas.selectionChanged.disconnect()
        except Exception:
            pass
        finally:
            self.iface.actionPan().trigger()

    def set_label_current_psector(self, dialog):

        sql = (
            "SELECT t1.name FROM plan_psector AS t1 "
            " INNER JOIN config_param_user AS t2 ON t1.psector_id::text = t2.value "
            " WHERE t2.parameter='psector_vdefault' AND cur_user = current_user"
        )
        row = self.controller.get_row(sql)
        if not row:
            return
        utils_giswater.setWidgetText(dialog, 'lbl_vdefault_psector', row[0])

    def multi_rows_delete(self, widget, table_name, column_id):
        """ Delete selected elements of the table
        :param QTableView widget: origin
        :param table_name: table origin
        :param column_id: Refers to the id of the source table
        """

        # Get selected rows
        selected_list = widget.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return

        inf_text = ""
        list_id = ""
        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_ = widget.model().record(row).value(str(column_id))
            inf_text += f"{id_}, "
            list_id += f"'{id_}', "
        inf_text = inf_text[:-2]
        list_id = list_id[:-2]
        message = "Are you sure you want to delete these records?"
        title = "Delete records"
        answer = self.controller.ask_question(message, title, inf_text)
        if answer:
            sql = f"DELETE FROM {table_name}"
            sql += f" WHERE {column_id} IN ({list_id})"
            self.controller.execute_sql(sql)
            widget.model().select()

    def select_features_by_expr(self, layer, expr):
        """ Select features of @layer applying @expr """

        if not layer:
            return

        if expr is None:
            layer.removeSelection()
        else:
            it = layer.getFeatures(QgsFeatureRequest(expr))
            # Build a list of feature id's from the previous result and select them
            id_list = [i.id() for i in it]
            if len(id_list) > 0:
                layer.selectByIds(id_list)
            else:
                layer.removeSelection()

    def hide_void_groupbox(self, dialog):
        """ Hide empty grupbox """

        grbox_list = dialog.findChildren(QGroupBox)
        for grbox in grbox_list:
            widget_list = grbox.findChildren(QWidget)
            if len(widget_list) == 0:
                grbox.setVisible(False)

    def zoom_to_selected_features(self, layer, geom_type=None, zoom=None):
        """ Zoom to selected features of the @layer with @geom_type """

        if not layer:
            return

        self.iface.setActiveLayer(layer)
        self.iface.actionZoomToSelected().trigger()

        if geom_type:

            # Set scale = scale_zoom
            if geom_type in ('node', 'connec', 'gully'):
                scale = self.scale_zoom

            # Set scale = max(current_scale, scale_zoom)
            elif geom_type == 'arc':
                scale = self.iface.mapCanvas().scale()
                if int(scale) < int(self.scale_zoom):
                    scale = self.scale_zoom
            else:
                scale = 5000

            if zoom is not None:
                scale = zoom

            self.iface.mapCanvas().zoomScale(float(scale))

    def set_completer(self, tablename, widget, field_search, color='black'):
        """ Set autocomplete of widget @table_object + "_id"
            getting id's from selected @table_object
        """

        if not widget:
            return

        # Set SQL
        sql = (f"SELECT DISTINCT({field_search})"
               f" FROM {tablename}"
               f" ORDER BY {field_search}")
        row = self.controller.get_rows(sql, commit=True)

        for i in range(0, len(row)):
            aux = row[i]
            row[i] = str(aux[0])

        # Set completer and model: add autocomplete in the widget
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(0)
        self.completer.popup().setStyleSheet("color: " + color + ";")
        widget.setCompleter(self.completer)

        model = QStringListModel()
        model.setStringList(row)
        self.completer.setModel(model)

    def get_max_rectangle_from_coords(self, list_coord):
        """ Returns the minimum rectangle(x1, y1, x2, y2) of a series of coordinates
        :type list_coord: list of coors in format ['x1 y1', 'x2 y2',....,'x99 y99']
        """

        coords = list_coord.group(1)
        polygon = coords.split(',')
        x, y = polygon[0].split(' ')
        min_x = x  # start with something much higher than expected min
        min_y = y
        max_x = x  # start with something much lower than expected max
        max_y = y
        for i in range(0, len(polygon)):
            x, y = polygon[i].split(' ')
            if x < min_x:
                min_x = x
            if x > max_x:
                max_x = x
            if y < min_y:
                min_y = y
            if y > max_y:
                max_y = y

        return max_x, max_y, min_x, min_y

    def zoom_to_rectangle(self, x1, y1, x2, y2, margin=5):

        rect = QgsRectangle(
            float(x1) - margin,
            float(y1) - margin,
            float(x2) + margin,
            float(y2) + margin)
        self.canvas.setExtent(rect)
        self.canvas.refresh()

    def create_action(self,
                      action_name,
                      action_group,
                      icon_num=None,
                      text=None):
        """ Creates a new action with selected parameters """

        icon = None
        icon_folder = self.plugin_dir + '/icons/'
        icon_path = icon_folder + icon_num + '.png'
        if os.path.exists(icon_path):
            icon = QIcon(icon_path)

        if icon is None:
            action = QAction(text, action_group)
        else:
            action = QAction(icon, text, action_group)
        action.setObjectName(action_name)

        return action

    def set_wait_cursor(self):
        QApplication.instance().setOverrideCursor(Qt.WaitCursor)

    def set_arrow_cursor(self):
        QApplication.instance().setOverrideCursor(Qt.ArrowCursor)

    def delete_layer_from_toc(self, layer_name):
        """ Delete layer from toc if exist """

        layer = None
        for lyr in list(QgsProject.instance().mapLayers().values()):
            if lyr.name() == layer_name:
                layer = lyr
                break
        if layer is not None:
            QgsProject.instance().removeMapLayer(layer)
            self.delete_layer_from_toc(layer_name)

    def create_body(self, form='', feature='', filter_fields='', extras=None):
        """ Create and return parameters as body to functions"""

        client = '"client":{"device":9, "infoType":100, "lang":"ES"}, '
        form = f'"form":{{{form}}}, '
        feature = f'"feature":{{{feature}}}, '
        filter_fields = f'"filterFields":{{{filter_fields}}}'
        page_info = '"pageInfo":{}'
        data = f'"data":{{{filter_fields}, {page_info}'
        if extras is not None:
            data += ', ' + extras
        data += '}'
        body = "" + client + form + feature + data

        return body

    def set_layers_visible(self, layers):
        for layer in layers:
            lyr = self.controller.get_layer_by_tablename(layer)
            if lyr:
                self.controller.set_layer_visible(lyr)

    def add_temp_layer(self,
                       dialog,
                       data,
                       function_name,
                       force_tab=True,
                       reset_text=True,
                       tab_idx=1,
                       del_old_layers=True):
        if del_old_layers:
            self.delete_layer_from_toc(function_name)
        srid = self.controller.plugin_settings_value('srid')
        for k, v in list(data.items()):
            if str(k) == 'setVisibleLayers':
                self.set_layers_visible(v)
            elif str(k) == "info":
                self.populate_info_text(dialog, data, force_tab, reset_text,
                                        tab_idx)
            else:
                counter = len(data[k]['values'])
                if counter > 0:
                    counter = len(data[k]['values'])
                    geometry_type = data[k]['geometryType']
                    v_layer = QgsVectorLayer(
                        f"{geometry_type}?crs=epsg:{srid}", function_name,
                        'memory')
                    self.populate_vlayer(v_layer, data, k, counter)
                    if 'qmlPath' in data[k]:
                        qml_path = data[k]['qmlPath']
                        self.load_qml(v_layer, qml_path)

    def populate_info_text(self,
                           dialog,
                           data,
                           force_tab=True,
                           reset_text=True,
                           tab_idx=1):

        change_tab = False
        text = utils_giswater.getWidgetText(dialog,
                                            dialog.txt_infolog,
                                            return_string_null=False)

        if reset_text:
            text = ""
        for item in data['info']['values']:
            if 'message' in item:
                if item['message'] is not None:
                    text += str(item['message']) + "\n"
                    if force_tab:
                        change_tab = True
                else:
                    text += "\n"

        utils_giswater.setWidgetText(dialog, 'txt_infolog', text + "\n")
        qtabwidget = dialog.findChild(QTabWidget, 'mainTab')
        if change_tab and qtabwidget is not None:
            qtabwidget.setCurrentIndex(tab_idx)

        return change_tab

    def populate_vlayer(self, virtual_layer, data, layer_type, counter):

        prov = virtual_layer.dataProvider()

        # Enter editing mode
        virtual_layer.startEditing()
        if counter > 0:
            for key, value in list(data[layer_type]['values'][0].items()):
                # add columns
                if str(key) != 'the_geom':
                    prov.addAttributes([QgsField(str(key), QVariant.String)])

        # Add features
        for item in data[layer_type]['values']:
            attributes = []
            fet = QgsFeature()

            for k, v in list(item.items()):
                if str(k) != 'the_geom':
                    attributes.append(v)
                if str(k) in 'the_geom':
                    sql = f"SELECT St_AsText('{v}')"
                    row = self.controller.get_row(sql, log_sql=False)
                    geometry = QgsGeometry.fromWkt(str(row[0]))
                    fet.setGeometry(geometry)
            fet.setAttributes(attributes)
            prov.addFeatures([fet])

        # Commit changes
        virtual_layer.commitChanges()
        QgsProject.instance().addMapLayer(virtual_layer, False)
        root = QgsProject.instance().layerTreeRoot()
        my_group = root.findGroup('GW Functions results')
        if my_group is None:
            my_group = root.insertGroup(0, 'GW Functions results')

        my_group.insertLayer(0, virtual_layer)

    def get_composers_list(self):

        layour_manager = QgsProject.instance().layoutManager().layouts()
        active_composers = [layout for layout in layour_manager]
        return active_composers

    def get_composer_index(self, name):

        index = 0
        composers = self.get_composers_list()
        for comp_view in composers:
            composer_name = comp_view.name()
            if composer_name == name:
                break
            index += 1

        return index

    def get_all_actions(self):

        self.controller.log_info(str("TEST"))
        actions_list = self.iface.mainWindow().findChildren(QAction)
        for action in actions_list:
            self.controller.log_info(str(action.objectName()))
            action.triggered.connect(partial(self.show_action_name, action))

    def show_action_name(self, action):
        self.controller.log_info(str(action.objectName()))

    def set_restriction(self, dialog, widget_to_ignore, restriction):
        """
        Set all widget enabled(False) or readOnly(True) except those on the tuple
        :param dialog:
        :param widget_to_ignore: tuple = ('widgetname1', 'widgetname2', 'widgetname3', ...)
        :param restriction: roles that do not have access. tuple = ('role1', 'role1', 'role1', ...)
        :return:
        """

        role = self.controller.get_restriction()
        if role in restriction:
            widget_list = dialog.findChildren(QWidget)
            for widget in widget_list:
                if widget.objectName() in widget_to_ignore:
                    continue
                # Set editable/readonly
                if type(widget) in (QLineEdit, QDoubleSpinBox, QTextEdit):
                    widget.setReadOnly(True)
                    widget.setStyleSheet(
                        "QWidget {background: rgb(242, 242, 242);color: rgb(100, 100, 100)}"
                    )
                elif type(widget) in (QComboBox, QCheckBox, QTableView,
                                      QPushButton):
                    widget.setEnabled(False)

    def set_dates_from_to(self, widget_from, widget_to, table_name, field_from,
                          field_to):

        sql = (f"SELECT MIN(LEAST({field_from}, {field_to})),"
               f" MAX(GREATEST({field_from}, {field_to}))"
               f" FROM {table_name}")
        row = self.controller.get_row(sql, log_sql=False)
        current_date = QDate.currentDate()
        if row:
            if row[0]:
                widget_from.setDate(row[0])
            else:
                widget_from.setDate(current_date)
            if row[1]:
                widget_to.setDate(row[1])
            else:
                widget_to.setDate(current_date)

    def get_values_from_catalog(self, table_name, typevalue, order_by='id'):

        sql = (f"SELECT id, idval"
               f" FROM {table_name}"
               f" WHERE typevalue = '{typevalue}'"
               f" ORDER BY {order_by}")
        rows = self.controller.get_rows(sql, commit=True)
        return rows

    def integer_validator(self, value, widget, btn_accept):
        """ Check if the value is an integer or not.
            This function is called in def set_datatype_validator(self, value, widget, btn)
            widget = getattr(self, f"{widget.property('datatype')}_validator")( value, widget, btn)
        """
        if value is None or bool(re.search("^\d*$", value)):
            widget.setStyleSheet(
                "QLineEdit{background:rgb(255, 255, 255); color:rgb(0, 0, 0)}")
            btn_accept.setEnabled(True)
        else:
            widget.setStyleSheet("border: 1px solid red")
            btn_accept.setEnabled(False)

    def double_validator(self, value, widget, btn_accept):
        """ Check if the value is double or not.
            This function is called in def set_datatype_validator(self, value, widget, btn)
            widget = getattr(self, f"{widget.property('datatype')}_validator")( value, widget, btn)
        """
        if value is None or bool(re.search("^\d*$", value)) or bool(
                re.search("^\d+\.\d+$", value)):
            widget.setStyleSheet(
                "QLineEdit{background:rgb(255, 255, 255); color:rgb(0, 0, 0)}")
            btn_accept.setEnabled(True)
        else:
            widget.setStyleSheet("border: 1px solid red")
            btn_accept.setEnabled(False)

    def load_qml(self, layer, qml_path):
        """ Apply QML style located in @qml_path in @layer """

        if layer is None:
            return False

        if not os.path.exists(qml_path):
            self.controller.log_warning("File not found", parameter=qml_path)
            return False

        if not qml_path.endswith(".qml"):
            self.controller.log_warning("File extension not valid",
                                        parameter=qml_path)
            return False

        layer.loadNamedStyle(qml_path)
        layer.triggerRepaint()

        return True

    def open_file_path(self, filter_="All (*.*)"):
        """ Open QFileDialog """
        msg = self.controller.tr("Select DXF file")
        path, filter_ = QFileDialog.getOpenFileName(None, msg, "", filter_)

        return path, filter_

    def show_exceptions_msg(self, title, msg=""):
        cat_exception = {
            'KeyError': 'Key on returned json from ddbb is missed.'
        }
        self.dlg_info = BasicInfo()
        self.dlg_info.btn_accept.setVisible(False)
        self.dlg_info.btn_close.clicked.connect(
            partial(self.close_dialog, self.dlg_info))
        self.dlg_info.setWindowTitle(title)
        utils_giswater.setWidgetText(self.dlg_info, self.dlg_info.txt_info,
                                     msg)
        self.open_dialog(self.dlg_info)
Exemplo n.º 21
0
 def update_models_completer(self):
     completer = QCompleter(self.ilicache.model_names)
     completer.setCaseSensitivity(Qt.CaseInsensitive)
     self.ili_models_line_edit.setCompleter(completer)
     self.multiple_models_dialog.models_line_edit.setCompleter(completer)
Exemplo n.º 22
0
class geopunt4QgisAdresDialog(QDialog):
    def __init__(self, iface):
        QDialog.__init__(self, None)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.iface = iface

        # initialize locale
        locale = QSettings().value("locale/userLocale", "nl")
        if not locale: locale == 'nl'
        else: locale = locale[0:2]
        localePath = os.path.join(os.path.dirname(__file__), 'i18n',
                                  'geopunt4qgis_{}.qm'.format(locale))
        if os.path.exists(localePath):
            self.translator = QTranslator()
            self.translator.load(localePath)
            QCoreApplication.installTranslator(self.translator)

        self._initGui()

    def _initGui(self):
        """setup the user interface"""
        self.ui = Ui_geopunt4Qgis()
        self.ui.setupUi(self)

        #get settings
        self.s = QSettings()
        self.loadSettings()

        #setup geometryHelper object
        self.gh = geometryHelper(self.iface)

        #create graphicsLayer
        self.graphicsLayer = []

        self.firstShow = True

        self.completer = QCompleter(self)
        self.completerModel = QStringListModel(self)
        self.ui.gemeenteBox.setCompleter(self.completer)
        self.completer.setModel(self.completerModel)
        self.completer.setCaseSensitivity(False)

        #setup a message bar
        self.bar = QgsMessageBar()
        self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.ui.verticalLayout.addWidget(self.bar)

        self.ui.buttonBox.addButton(QPushButton("Sluiten"),
                                    QDialogButtonBox.RejectRole)
        for btn in self.ui.buttonBox.buttons():
            btn.setAutoDefault(0)

        #event handlers
        if self.adresSearchOnEnter:
            self.ui.zoekText.returnPressed.connect(self.onZoekActivated)
        else:
            self.ui.zoekText.textEdited.connect(self.onZoekActivated)
        self.ui.gemeenteBox.currentIndexChanged.connect(self.onZoekActivated)
        self.ui.resultLijst.itemDoubleClicked.connect(self.onItemActivated)
        self.ui.resultLijst.itemClicked.connect(self.onItemClick)
        self.ui.ZoomKnop.clicked.connect(self.onZoomKnopClick)
        self.ui.Add2mapKnop.clicked.connect(self.onAdd2mapKnopClick)
        self.ui.buttonBox.helpRequested.connect(self.openHelp)
        self.finished.connect(self.clean)

    def loadSettings(self):
        self.saveToFile = int(self.s.value("geopunt4qgis/adresSavetoFile", 1))
        layerName = self.s.value("geopunt4qgis/adreslayerText", "")
        if layerName:
            self.layerName = layerName
        self.adresSearchOnEnter = int(
            self.s.value("geopunt4qgis/adresSearchOnEnter", 0))
        self.timeout = int(self.s.value("geopunt4qgis/timeout", 15))
        if settings().proxyUrl:
            self.proxy = settings().proxyUrl
        else:
            self.proxy = ""
        self.startDir = self.s.value("geopunt4qgis/startDir",
                                     os.path.expanduser("~"))
        self.gp = Adres(self.timeout, self.proxy)

    # overwrite
    def show(self):
        QDialog.show(self)
        self.setWindowModality(0)
        arUrl = "http://loc.api.geopunt.be/"
        inet = internet_on(proxyUrl=self.proxy,
                           timeout=self.timeout,
                           testSite=arUrl)

        if not inet:
            msg = "Kan geen verbing maken met de site van Geopunt: {} \nMogelijke is deze site niet bereikbaar, dan zal deze tool ook niet werken.\nProbeer later opnieuw. Indien dit probleem zich blijft voordoen contacteer informatie Vlaanderen.".format(
                arUrl)
            QMessageBox.warning(self.iface.mainWindow(),
                                "Waarschuwing: kan geen verbinding maken", msg)
            self.bar.pushMessage(QCoreApplication.translate(
                "geopunt4QgisPoidialog", "Waarschuwing"),
                                 msg,
                                 level=Qgis.Warning,
                                 duration=3)
            return

        if self.firstShow:
            self.am = basisregisters.adresMatch(self.timeout, self.proxy)
            gemeenteNamen = [n["Naam"] for n in self.am.gemeenten()]

            self.ui.gemeenteBox.addItems(gemeenteNamen)
            self.completerModel.setStringList(gemeenteNamen)
            self.ui.gemeenteBox.setEditText(
                QCoreApplication.translate("geopunt4QgisAdresDialog",
                                           "gemeente"))
            self.ui.gemeenteBox.setStyleSheet('QComboBox {color: #808080}')
            self.ui.gemeenteBox.setFocus()
            self.firstShow = False

    def openHelp(self):
        webbrowser.open_new_tab(
            "http://www.geopunt.be/voor-experts/geopunt-plug-ins/functionaliteiten/zoek-een-adres"
        )

    def onZoekActivated(self):
        self._clearGraphicsLayer()
        self.bar.clearWidgets()

        gemeente = self.ui.gemeenteBox.currentText()
        if gemeente != QCoreApplication.translate("geopunt4QgisAdresDialog",
                                                  "gemeente"):
            self.ui.gemeenteBox.setStyleSheet('QComboBox {color: #000000}')

            txt = self.ui.zoekText.text() + ", " + gemeente

            suggesties = self.gp.fetchSuggestion(txt, 25)

            self.ui.resultLijst.clear()
            if type(suggesties) is list and len(suggesties) != 0:
                self.ui.resultLijst.addItems(suggesties)
                if len(suggesties) == 1:
                    self.ui.resultLijst.setCurrentRow(0)

    def onItemActivated(self, item):
        txt = item.text()
        self._zoomLoc(txt)

    def onItemClick(self, item):
        txt = item.text()
        streetNr = txt.split(",")[:-1]
        self.ui.zoekText.setText(",".join(streetNr))

    def onZoomKnopClick(self):
        item = self.ui.resultLijst.currentItem()
        if item:
            self._zoomLoc(item.text())

    def onAdd2mapKnopClick(self):
        item = self.ui.resultLijst.currentItem()
        if item:
            self._addToMap(item.text())

    def _clearGraphicsLayer(self):
        for graphic in self.graphicsLayer:
            self.iface.mapCanvas().scene().removeItem(graphic)
        self.graphicsLayer = []

    def _zoomLoc(self, txt):
        self._clearGraphicsLayer()
        locations = self.gp.fetchLocation(txt)
        if type(locations) is list and len(locations):
            loc = locations[0]

            LowerLeftX = loc['BoundingBox']['LowerLeft']['X_Lambert72']
            LowerLeftY = loc['BoundingBox']['LowerLeft']['Y_Lambert72']
            UpperRightX = loc['BoundingBox']['UpperRight']['X_Lambert72']
            UpperRightY = loc['BoundingBox']['UpperRight']['Y_Lambert72']

            self.gh.zoomtoRec(QgsPointXY(LowerLeftX, LowerLeftY),
                              QgsPointXY(UpperRightX, UpperRightY), 31370)

            xlb, ylb = loc["Location"]["X_Lambert72"], loc["Location"][
                "Y_Lambert72"]
            x, y = self.gh.prjPtToMapCrs(QgsPointXY(xlb, ylb), 31370)

            m = QgsVertexMarker(self.iface.mapCanvas())
            self.graphicsLayer.append(m)
            m.setCenter(QgsPointXY(x, y))
            m.setColor(QColor(255, 255, 0))
            m.setIconSize(1)
            m.setIconType(QgsVertexMarker.ICON_BOX)
            m.setPenWidth(9)

        elif type(locations) is str:
            self.bar.pushMessage(QCoreApplication.translate(
                "geopunt4QgisAdresDialog", "Waarschuwing"),
                                 locations,
                                 level=Qgis.Warning,
                                 duration=3)
        else:
            self.bar.pushMessage("Error",
                                 QCoreApplication.translate(
                                     "geopunt4QgisAdresDialog",
                                     "onbekende fout"),
                                 level=Qgis.Critical,
                                 duration=3)

    def _addToMap(self, txt):
        if not self.layernameValid(): return
        locations = self.gp.fetchLocation(txt)
        if type(locations) is list and len(locations):
            loc = locations[0]
            x, y = loc["Location"]["X_Lambert72"], loc["Location"][
                "Y_Lambert72"]
            adres = loc["FormattedAddress"]
            LocationType = loc["LocationType"]

            pt = self.gh.prjPtToMapCrs(QgsPointXY(x, y), 31370)

            self.gh.save_adres_point(pt,
                                     adres,
                                     typeAddress=LocationType,
                                     layername=self.layerName,
                                     saveToFile=self.saveToFile,
                                     sender=self,
                                     startFolder=os.path.join(
                                         self.startDir, self.layerName))

    def layernameValid(self):
        if not hasattr(self, 'layerName'):
            layerName, accept = QInputDialog.getText(
                None,
                QCoreApplication.translate("geopunt4Qgis", 'Laag toevoegen'),
                QCoreApplication.translate("geopunt4Qgis",
                                           'Geef een naam voor de laag op:'))
            if accept == False:
                return False
            else:
                self.layerName = layerName
        return True

    def clean(self):
        self.bar.clearWidgets()
        self.ui.resultLijst.clear()
        self.ui.zoekText.setText("")
        self.ui.gemeenteBox.setEditText(
            QCoreApplication.translate("geopunt4QgisAdresDialog", "gemeente"))
        self.ui.gemeenteBox.setStyleSheet('QComboBox {color: #808080}')
        self._clearGraphicsLayer()
Exemplo n.º 23
0
class Go2Epa(ApiParent):
    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class to control toolbar 'go2epa' """

        ApiParent.__init__(self, iface, settings, controller, plugin_dir)

        self.g2epa_opt = Go2EpaOptions(iface, settings, controller, plugin_dir)
        self.iterations = 0

    def set_project_type(self, project_type):
        self.project_type = project_type

    def go2epa(self):
        """ Button 23: Open form to set INP, RPT and project """

        # Show form in docker?
        self.controller.init_docker('qgis_form_docker')

        # Create dialog
        self.dlg_go2epa = Go2EpaUI()
        self.load_settings(self.dlg_go2epa)
        self.load_user_values()
        if self.project_type in 'ws':
            self.dlg_go2epa.chk_export_subcatch.setVisible(False)

        # Set signals
        self.set_signals()

        if self.project_type == 'ws':
            self.dlg_go2epa.btn_hs_ds.setText("Dscenario Selector")
            tableleft = "cat_dscenario"
            tableright = "selector_inp_demand"
            field_id_left = "dscenario_id"
            field_id_right = "dscenario_id"
            self.dlg_go2epa.btn_hs_ds.clicked.connect(
                partial(self.sector_selection,
                        tableleft,
                        tableright,
                        field_id_left,
                        field_id_right,
                        aql=""))

        elif self.project_type == 'ud':
            self.dlg_go2epa.btn_hs_ds.setText("Hydrology selector")
            self.dlg_go2epa.btn_hs_ds.clicked.connect(
                self.ud_hydrology_selector)

        # Check OS and enable/disable checkbox execute EPA software
        if sys.platform != "win32":
            utils_giswater.setChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_exec, False)
            self.dlg_go2epa.chk_exec.setEnabled(False)
            self.dlg_go2epa.chk_exec.setText(
                'Execute EPA software (Runs only on Windows)')

        self.set_completer_result(self.dlg_go2epa.txt_result_name,
                                  'v_ui_rpt_cat_result', 'result_id')

        if self.controller.dlg_docker:
            self.controller.manage_translation('go2epa', self.dlg_go2epa)
            self.controller.dock_dialog(self.dlg_go2epa)
            self.dlg_go2epa.btn_cancel.clicked.disconnect()
            self.dlg_go2epa.btn_cancel.clicked.connect(
                self.controller.close_docker)
        else:
            self.open_dialog(self.dlg_go2epa, dlg_name='go2epa')

    def set_signals(self):

        self.dlg_go2epa.txt_result_name.textChanged.connect(
            partial(self.check_result_id))
        self.dlg_go2epa.btn_file_inp.clicked.connect(
            self.go2epa_select_file_inp)
        self.dlg_go2epa.btn_file_rpt.clicked.connect(
            self.go2epa_select_file_rpt)
        self.dlg_go2epa.btn_accept.clicked.connect(self.go2epa_accept)
        self.dlg_go2epa.btn_cancel.clicked.connect(
            partial(self.close_dialog, self.dlg_go2epa))
        self.dlg_go2epa.rejected.connect(
            partial(self.close_dialog, self.dlg_go2epa))
        self.dlg_go2epa.btn_options.clicked.connect(self.epa_options)

    def check_inp_chk(self, file_inp):

        if file_inp is None:
            msg = "Select valid INP file"
            self.controller.show_warning(msg, parameter=str(file_inp))
            return False

    def check_rpt(self):

        file_inp = utils_giswater.getWidgetText(self.dlg_go2epa,
                                                self.dlg_go2epa.txt_file_inp)
        file_rpt = utils_giswater.getWidgetText(self.dlg_go2epa,
                                                self.dlg_go2epa.txt_file_rpt)

        # Control execute epa software
        if utils_giswater.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_exec):
            if self.check_inp_chk(file_inp) is False:
                return False

            if file_rpt is None:
                msg = "Select valid RPT file"
                self.controller.show_warning(msg, parameter=str(file_rpt))
                return False

            if not utils_giswater.isChecked(self.dlg_go2epa,
                                            self.dlg_go2epa.chk_export):
                if not os.path.exists(file_inp):
                    msg = "File INP not found"
                    self.controller.show_warning(msg, parameter=str(file_rpt))
                    return False

    def check_fields(self):

        file_inp = utils_giswater.getWidgetText(self.dlg_go2epa,
                                                self.dlg_go2epa.txt_file_inp)
        file_rpt = utils_giswater.getWidgetText(self.dlg_go2epa,
                                                self.dlg_go2epa.txt_file_rpt)
        result_name = utils_giswater.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_result_name, False, False)

        # Check if at least one process is selected
        export_checked = utils_giswater.isChecked(self.dlg_go2epa,
                                                  self.dlg_go2epa.chk_export)
        exec_checked = utils_giswater.isChecked(self.dlg_go2epa,
                                                self.dlg_go2epa.chk_exec)
        import_result_checked = utils_giswater.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_import_result)

        if not export_checked and not exec_checked and not import_result_checked:
            msg = "You need to select at least one process"
            self.controller.show_info_box(msg, title="Go2Epa")
            return False

        # Control export INP
        if utils_giswater.isChecked(self.dlg_go2epa,
                                    self.dlg_go2epa.chk_export):
            if self.check_inp_chk(file_inp) is False:
                return False

        # Control execute epa software
        if self.check_rpt() is False:
            return False

        # Control import result
        if utils_giswater.isChecked(self.dlg_go2epa,
                                    self.dlg_go2epa.chk_import_result):
            if file_rpt is None:
                msg = "Select valid RPT file"
                self.controller.show_warning(msg, parameter=str(file_rpt))
                return False
            if not utils_giswater.isChecked(self.dlg_go2epa,
                                            self.dlg_go2epa.chk_exec):
                if not os.path.exists(file_rpt):
                    msg = "File RPT not found"
                    self.controller.show_warning(msg, parameter=str(file_rpt))
                    return False
            else:
                if self.check_rpt() is False:
                    return False

        # Control result name
        if result_name == '':
            self.dlg_go2epa.txt_result_name.setStyleSheet(
                "border: 1px solid red")
            msg = "This parameter is mandatory. Please, set a value"
            self.controller.show_details(msg, title="Rpt fail", inf_text=None)
            return False

        sql = (f"SELECT result_id FROM rpt_cat_result "
               f"WHERE result_id = '{result_name}' LIMIT 1")
        row = self.controller.get_row(sql)
        if row:
            msg = "Result name already exists, do you want overwrite?"
            answer = self.controller.ask_question(msg, title="Alert")
            if not answer:
                return False

        return True

    def load_user_values(self):
        """ Load QGIS settings related with file_manager """

        cur_user = self.controller.get_current_user()

        self.dlg_go2epa.txt_result_name.setMaxLength(16)
        self.result_name = self.controller.plugin_settings_value(
            'go2epa_RESULT_NAME' + cur_user)
        self.dlg_go2epa.txt_result_name.setText(self.result_name)
        self.file_inp = self.controller.plugin_settings_value(
            'go2epa_FILE_INP' + cur_user)
        self.dlg_go2epa.txt_file_inp.setText(self.file_inp)
        self.file_rpt = self.controller.plugin_settings_value(
            'go2epa_FILE_RPT' + cur_user)
        self.dlg_go2epa.txt_file_rpt.setText(self.file_rpt)

        value = self.controller.plugin_settings_value(
            'go2epa_chk_NETWORK_GEOM' + cur_user)
        if str(value) == 'true':
            utils_giswater.setChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_only_check, True)
        value = self.controller.plugin_settings_value('go2epa_chk_INP' +
                                                      cur_user)
        if str(value) == 'true':
            utils_giswater.setChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_export, True)
        value = self.controller.plugin_settings_value('go2epa_chk_UD' +
                                                      cur_user)
        if str(value) == 'true':
            utils_giswater.setChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_export_subcatch,
                                      True)
        value = self.controller.plugin_settings_value('go2epa_chk_EPA' +
                                                      cur_user)
        if str(value) == 'true':
            utils_giswater.setChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_exec, True)
        value = self.controller.plugin_settings_value('go2epa_chk_RPT' +
                                                      cur_user)
        if str(value) == 'true':
            utils_giswater.setChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_import_result, True)

    def save_user_values(self):
        """ Save QGIS settings related with file_manager """

        cur_user = self.controller.get_current_user()
        self.controller.plugin_settings_set_value(
            'go2epa_RESULT_NAME' + cur_user,
            utils_giswater.getWidgetText(self.dlg_go2epa,
                                         'txt_result_name',
                                         return_string_null=False))
        self.controller.plugin_settings_set_value(
            'go2epa_FILE_INP' + cur_user,
            utils_giswater.getWidgetText(self.dlg_go2epa,
                                         'txt_file_inp',
                                         return_string_null=False))
        self.controller.plugin_settings_set_value(
            'go2epa_FILE_RPT' + cur_user,
            utils_giswater.getWidgetText(self.dlg_go2epa,
                                         'txt_file_rpt',
                                         return_string_null=False))
        self.controller.plugin_settings_set_value(
            'go2epa_chk_NETWORK_GEOM' + cur_user,
            utils_giswater.isChecked(self.dlg_go2epa,
                                     self.dlg_go2epa.chk_only_check))
        self.controller.plugin_settings_set_value(
            'go2epa_chk_INP' + cur_user,
            utils_giswater.isChecked(self.dlg_go2epa,
                                     self.dlg_go2epa.chk_export))
        self.controller.plugin_settings_set_value(
            'go2epa_chk_UD' + cur_user,
            utils_giswater.isChecked(self.dlg_go2epa,
                                     self.dlg_go2epa.chk_export_subcatch))
        self.controller.plugin_settings_set_value(
            'go2epa_chk_EPA' + cur_user,
            utils_giswater.isChecked(self.dlg_go2epa,
                                     self.dlg_go2epa.chk_exec))
        self.controller.plugin_settings_set_value(
            'go2epa_chk_RPT' + cur_user,
            utils_giswater.isChecked(self.dlg_go2epa,
                                     self.dlg_go2epa.chk_import_result))

    def sector_selection(self,
                         tableleft,
                         tableright,
                         field_id_left,
                         field_id_right,
                         aql=""):
        """ Load the tables in the selection form """

        dlg_psector_sel = Multirow_selector('dscenario')
        self.load_settings(dlg_psector_sel)
        dlg_psector_sel.btn_ok.clicked.connect(dlg_psector_sel.close)

        if tableleft == 'cat_dscenario':
            dlg_psector_sel.setWindowTitle(" Dscenario selector")
            utils_giswater.setWidgetText(
                dlg_psector_sel, dlg_psector_sel.lbl_filter,
                self.controller.tr('Filter by: Dscenario name',
                                   context_name='labels'))
            utils_giswater.setWidgetText(
                dlg_psector_sel, dlg_psector_sel.lbl_unselected,
                self.controller.tr('Unselected dscenarios',
                                   context_name='labels'))
            utils_giswater.setWidgetText(
                dlg_psector_sel, dlg_psector_sel.lbl_selected,
                self.controller.tr('Selected dscenarios',
                                   context_name='labels'))

        self.multi_row_selector(dlg_psector_sel,
                                tableleft,
                                tableright,
                                field_id_left,
                                field_id_right,
                                aql=aql)

        self.open_dialog(dlg_psector_sel)

    def epa_options(self):
        """ Open dialog api_epa_options.ui.ui """

        self.g2epa_opt.go2epa_options()
        return

    def ud_hydrology_selector(self):
        """ Dialog hydrology_selector.ui """

        self.dlg_hydrology_selector = HydrologySelector()
        self.load_settings(self.dlg_hydrology_selector)

        self.dlg_hydrology_selector.btn_accept.clicked.connect(
            self.save_hydrology)
        self.dlg_hydrology_selector.hydrology.currentIndexChanged.connect(
            self.update_labels)
        self.dlg_hydrology_selector.txt_name.textChanged.connect(
            partial(self.filter_cbx_by_text, "cat_hydrology",
                    self.dlg_hydrology_selector.txt_name,
                    self.dlg_hydrology_selector.hydrology))

        sql = "SELECT DISTINCT(name), hydrology_id FROM cat_hydrology ORDER BY name"
        rows = self.controller.get_rows(sql)
        if not rows:
            message = "Any data found in table"
            self.controller.show_warning(message, parameter='cat_hydrology')
            return False

        utils_giswater.set_item_data(self.dlg_hydrology_selector.hydrology,
                                     rows)

        sql = (
            "SELECT DISTINCT(t1.name) FROM cat_hydrology AS t1 "
            "INNER JOIN selector_inp_hydrology AS t2 ON t1.hydrology_id = t2.hydrology_id "
            "WHERE t2.cur_user = current_user")
        row = self.controller.get_row(sql)
        if row:
            utils_giswater.setWidgetText(self.dlg_hydrology_selector,
                                         self.dlg_hydrology_selector.hydrology,
                                         row[0])
        else:
            utils_giswater.setWidgetText(self.dlg_hydrology_selector,
                                         self.dlg_hydrology_selector.hydrology,
                                         0)

        self.update_labels()
        self.open_dialog(self.dlg_hydrology_selector)

    def save_hydrology(self):

        hydrology_id = utils_giswater.get_item_data(
            self.dlg_hydrology_selector, self.dlg_hydrology_selector.hydrology,
            1)
        sql = ("SELECT cur_user FROM selector_inp_hydrology "
               "WHERE cur_user = current_user")
        row = self.controller.get_row(sql)
        if row:
            sql = (f"UPDATE selector_inp_hydrology "
                   f"SET hydrology_id = {hydrology_id} "
                   f"WHERE cur_user = current_user")
        else:
            sql = (
                f"INSERT INTO selector_inp_hydrology (hydrology_id, cur_user) "
                f"VALUES('{hydrology_id}', current_user)")
        self.controller.execute_sql(sql)

        message = "Values has been update"
        self.controller.show_info(message)
        self.close_dialog(self.dlg_hydrology_selector)

    def update_labels(self):
        """ Show text in labels from SELECT """

        sql = (
            f"SELECT infiltration, text FROM cat_hydrology"
            f" WHERE name = '{self.dlg_hydrology_selector.hydrology.currentText()}'"
        )
        row = self.controller.get_row(sql)
        if row is not None:
            utils_giswater.setText(self.dlg_hydrology_selector,
                                   self.dlg_hydrology_selector.infiltration,
                                   row[0])
            utils_giswater.setText(self.dlg_hydrology_selector,
                                   self.dlg_hydrology_selector.descript,
                                   row[1])

    def filter_cbx_by_text(self, tablename, widgettxt, widgetcbx):

        sql = (f"SELECT DISTINCT(name), hydrology_id FROM {tablename}"
               f" WHERE name LIKE '%{widgettxt.text()}%'"
               f" ORDER BY name ")
        rows = self.controller.get_rows(sql)
        if not rows:
            message = "Check the table 'cat_hydrology' "
            self.controller.show_warning(message)
            return False
        utils_giswater.set_item_data(widgetcbx, rows)
        self.update_labels()

    def go2epa_select_file_inp(self):
        """ Select INP file """

        self.file_inp = utils_giswater.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_file_inp)
        # Set default value if necessary
        if self.file_inp is None or self.file_inp == '':
            self.file_inp = self.plugin_dir

        # Get directory of that file
        folder_path = os.path.dirname(self.file_inp)
        if not os.path.exists(folder_path):
            folder_path = os.path.dirname(__file__)
        os.chdir(folder_path)
        message = self.controller.tr("Select INP file")
        widget_is_checked = utils_giswater.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_export)
        if widget_is_checked:
            self.file_inp, filter_ = QFileDialog.getSaveFileName(
                None, message, "", '*.inp')
        else:
            self.file_inp, filter_ = QFileDialog.getOpenFileName(
                None, message, "", '*.inp')
        utils_giswater.setWidgetText(self.dlg_go2epa,
                                     self.dlg_go2epa.txt_file_inp,
                                     self.file_inp)

    def go2epa_select_file_rpt(self):
        """ Select RPT file """

        # Set default value if necessary
        if self.file_rpt is None or self.file_rpt == '':
            self.file_rpt = self.plugin_dir

        # Get directory of that file
        folder_path = os.path.dirname(self.file_rpt)
        if not os.path.exists(folder_path):
            folder_path = os.path.dirname(__file__)
        os.chdir(folder_path)
        message = self.controller.tr("Select RPT file")
        widget_is_checked = utils_giswater.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_export)
        if widget_is_checked:
            self.file_rpt, filter_ = QFileDialog.getSaveFileName(
                None, message, "", '*.rpt')
        else:
            self.file_rpt, filter_ = QFileDialog.getOpenFileName(
                None, message, "", '*.rpt')
        utils_giswater.setWidgetText(self.dlg_go2epa,
                                     self.dlg_go2epa.txt_file_rpt,
                                     self.file_rpt)

    def go2epa_accept(self):
        """ Save INP, RPT and result name into GSW file """

        # Save user values
        self.save_user_values()

        self.dlg_go2epa.txt_infolog.clear()
        self.dlg_go2epa.txt_file_rpt.setStyleSheet(None)
        status = self.check_fields()
        if status is False:
            return

        # Get widgets values
        self.result_name = utils_giswater.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_result_name, False, False)
        self.net_geom = utils_giswater.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_only_check)
        self.export_inp = utils_giswater.isChecked(self.dlg_go2epa,
                                                   self.dlg_go2epa.chk_export)
        self.export_subcatch = utils_giswater.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_export_subcatch)
        self.file_inp = utils_giswater.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_file_inp)
        self.exec_epa = utils_giswater.isChecked(self.dlg_go2epa,
                                                 self.dlg_go2epa.chk_exec)
        self.file_rpt = utils_giswater.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_file_rpt)
        self.import_result = utils_giswater.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_import_result)

        # Check for sector selector
        if self.export_inp:
            sql = "SELECT sector_id FROM selector_sector LIMIT 1"
            row = self.controller.get_row(sql)
            if row is None:
                msg = "You need to select some sector"
                self.controller.show_info_box(msg)
                return

        # Set background task 'Go2Epa'
        description = f"Go2Epa"
        self.task_go2epa = TaskGo2Epa(description, self.controller, self)
        QgsApplication.taskManager().addTask(self.task_go2epa)
        QgsApplication.taskManager().triggerTask(self.task_go2epa)

    def set_completer_result(self, widget, viewname, field_name):
        """ Set autocomplete of widget 'feature_id'
            getting id's from selected @viewname
        """

        result_name = utils_giswater.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_result_name)

        # Adding auto-completion to a QLineEdit
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()

        sql = f"SELECT {field_name} FROM {viewname}"
        rows = self.controller.get_rows(sql)

        if rows:
            for i in range(0, len(rows)):
                aux = rows[i]
                rows[i] = str(aux[0])

            model.setStringList(rows)
            self.completer.setModel(model)
            if result_name in rows:
                self.dlg_go2epa.chk_only_check.setEnabled(True)

    def check_result_id(self):
        """ Check if selected @result_id already exists """

        result_id = utils_giswater.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_result_name)
        sql = (f"SELECT result_id FROM v_ui_rpt_cat_result"
               f" WHERE result_id = '{result_id}'")
        row = self.controller.get_row(sql, log_info=False)
        if not row:
            self.dlg_go2epa.chk_only_check.setChecked(False)
            self.dlg_go2epa.chk_only_check.setEnabled(False)
        else:
            self.dlg_go2epa.chk_only_check.setEnabled(True)

    def check_data(self):
        """ Check data executing function 'gw_fct_pg2epa' """

        sql = f"SELECT gw_fct_pg2epa('{self.project_name}', 'True');"
        row = self.controller.get_row(sql)
        if not row:
            return False

        if row[0] > 0:
            message = ("It is not possible to execute the epa model."
                       "There are errors on your project. Review it!")
            sql_details = (
                f"SELECT table_id, column_id, error_message"
                f" FROM audit_check_data"
                f" WHERE fid = 114 AND result_id = '{self.project_name}'")
            inf_text = "For more details execute query:\n" + sql_details
            title = "Execute epa model"
            self.controller.show_info_box(message,
                                          title,
                                          inf_text,
                                          parameter=row[0])
            self.csv_audit_check_data("audit_check_data",
                                      "audit_check_data_log.csv")
            return False

        else:
            message = "Data is ok. You can try to generate the INP file"
            title = "Execute epa model"
            self.controller.show_info_box(message, title)
            return True

    def csv_audit_check_data(self, tablename, filename):

        # Get columns name in order of the table
        rows = self.controller.get_columns_list(tablename)
        if not rows:
            message = "Table not found"
            self.controller.show_warning(message, parameter=tablename)
            return

        columns = []
        for i in range(0, len(rows)):
            column_name = rows[i]
            columns.append(str(column_name[0]))
        sql = (f"SELECT table_id, column_id, error_message"
               f" FROM {tablename}"
               f" WHERE fid = 114 AND result_id = '{self.project_name}'")
        rows = self.controller.get_rows(sql)
        if not rows:
            message = "No records found with selected 'result_id'"
            self.controller.show_warning(message, parameter=self.project_name)
            return

        all_rows = []
        all_rows.append(columns)
        for i in rows:
            all_rows.append(i)
        path = self.controller.get_log_folder() + filename
        try:
            with open(path, "w") as output:
                writer = csv.writer(output, lineterminator='\n')
                writer.writerows(all_rows)
            message = "File created successfully"
            self.controller.show_info(message, parameter=path)
        except IOError:
            message = "File cannot be created. Check if it is already opened"
            self.controller.show_warning(message, parameter=path)

    def save_file_parameters(self):
        """ Save INP, RPT and result name into GSW file """

        self.gsw_settings.setValue('FILE_INP', self.file_inp)
        self.gsw_settings.setValue('FILE_RPT', self.file_rpt)
        self.gsw_settings.setValue('RESULT_NAME', self.result_name)

    def go2epa_result_selector(self):
        """ Button 29: Epa result selector """

        # Create the dialog and signals
        self.dlg_go2epa_result = Go2EpaSelectorUi()
        self.load_settings(self.dlg_go2epa_result)
        if self.project_type == 'ud':
            utils_giswater.remove_tab_by_tabName(
                self.dlg_go2epa_result.tabWidget, "tab_time")
        if self.project_type == 'ws':
            utils_giswater.remove_tab_by_tabName(
                self.dlg_go2epa_result.tabWidget, "tab_datetime")
        self.dlg_go2epa_result.btn_accept.clicked.connect(
            self.result_selector_accept)
        self.dlg_go2epa_result.btn_cancel.clicked.connect(
            partial(self.close_dialog, self.dlg_go2epa_result))
        self.dlg_go2epa_result.rejected.connect(
            partial(self.close_dialog, self.dlg_go2epa_result))

        # Set values from widgets of type QComboBox
        sql = ("SELECT DISTINCT(result_id), result_id "
               "FROM v_ui_rpt_cat_result ORDER BY result_id")
        rows = self.controller.get_rows(sql)
        utils_giswater.set_item_data(
            self.dlg_go2epa_result.rpt_selector_result_id, rows)
        rows = self.controller.get_rows(sql, add_empty_row=True)
        utils_giswater.set_item_data(
            self.dlg_go2epa_result.rpt_selector_compare_id, rows)

        if self.project_type == 'ws':

            sql = ("SELECT DISTINCT time, time FROM rpt_arc "
                   "WHERE result_id ILIKE '%%' ORDER BY time")
            rows = self.controller.get_rows(sql, add_empty_row=True)
            utils_giswater.set_item_data(
                self.dlg_go2epa_result.cmb_time_to_show, rows)
            utils_giswater.set_item_data(
                self.dlg_go2epa_result.cmb_time_to_compare, rows)

            self.dlg_go2epa_result.rpt_selector_result_id.currentIndexChanged.connect(
                partial(self.populate_time,
                        self.dlg_go2epa_result.rpt_selector_result_id,
                        self.dlg_go2epa_result.cmb_time_to_show))
            self.dlg_go2epa_result.rpt_selector_compare_id.currentIndexChanged.connect(
                partial(self.populate_time,
                        self.dlg_go2epa_result.rpt_selector_compare_id,
                        self.dlg_go2epa_result.cmb_time_to_compare))

        elif self.project_type == 'ud':

            # Populate GroupBox Selector date
            result_id = utils_giswater.get_item_data(
                self.dlg_go2epa_result,
                self.dlg_go2epa_result.rpt_selector_result_id, 0)
            sql = (f"SELECT DISTINCT(resultdate), resultdate FROM rpt_arc "
                   f"WHERE result_id = '{result_id}' "
                   f"ORDER BY resultdate")
            rows = self.controller.get_rows(sql)
            if rows is not None:
                utils_giswater.set_item_data(
                    self.dlg_go2epa_result.cmb_sel_date, rows)
                selector_date = utils_giswater.get_item_data(
                    self.dlg_go2epa_result,
                    self.dlg_go2epa_result.cmb_sel_date, 0)
                sql = (f"SELECT DISTINCT(resulttime), resulttime FROM rpt_arc "
                       f"WHERE result_id = '{result_id}' "
                       f"AND resultdate = '{selector_date}' "
                       f"ORDER BY resulttime")
                rows = self.controller.get_rows(sql, add_empty_row=True)
                utils_giswater.set_item_data(
                    self.dlg_go2epa_result.cmb_sel_time, rows)

            self.dlg_go2epa_result.rpt_selector_result_id.currentIndexChanged.connect(
                partial(self.populate_date_time,
                        self.dlg_go2epa_result.cmb_sel_date))

            self.dlg_go2epa_result.cmb_sel_date.currentIndexChanged.connect(
                partial(self.populate_time,
                        self.dlg_go2epa_result.rpt_selector_result_id,
                        self.dlg_go2epa_result.cmb_sel_time))

            # Populate GroupBox Selector compare
            result_id_to_comp = utils_giswater.get_item_data(
                self.dlg_go2epa_result,
                self.dlg_go2epa_result.rpt_selector_result_id, 0)
            sql = (f"SELECT DISTINCT(resultdate), resultdate FROM rpt_arc "
                   f"WHERE result_id = '{result_id_to_comp}' "
                   f"ORDER BY resultdate ")
            rows = self.controller.get_rows(sql)
            if rows is not None:
                utils_giswater.set_item_data(
                    self.dlg_go2epa_result.cmb_com_date, rows)
                selector_cmp_date = utils_giswater.get_item_data(
                    self.dlg_go2epa_result,
                    self.dlg_go2epa_result.cmb_com_date, 0)
                sql = (f"SELECT DISTINCT(resulttime), resulttime FROM rpt_arc "
                       f"WHERE result_id = '{result_id_to_comp}' "
                       f"AND resultdate = '{selector_cmp_date}' "
                       f"ORDER BY resulttime")
                rows = self.controller.get_rows(sql, add_empty_row=True)
                utils_giswater.set_item_data(
                    self.dlg_go2epa_result.cmb_com_time, rows)

            self.dlg_go2epa_result.rpt_selector_compare_id.currentIndexChanged.connect(
                partial(self.populate_date_time,
                        self.dlg_go2epa_result.cmb_com_date))
            self.dlg_go2epa_result.cmb_com_date.currentIndexChanged.connect(
                partial(self.populate_time,
                        self.dlg_go2epa_result.rpt_selector_compare_id,
                        self.dlg_go2epa_result.cmb_com_time))

        # Get current data from tables 'rpt_selector_result' and 'rpt_selector_compare'
        sql = "SELECT result_id FROM selector_rpt_main"
        row = self.controller.get_row(sql)
        if row:
            utils_giswater.set_combo_itemData(
                self.dlg_go2epa_result.rpt_selector_result_id,
                row["result_id"], 0)
        sql = "SELECT result_id FROM selector_rpt_compare"
        row = self.controller.get_row(sql)
        if row:
            utils_giswater.set_combo_itemData(
                self.dlg_go2epa_result.rpt_selector_compare_id,
                row["result_id"], 0)

        # Open the dialog
        self.open_dialog(self.dlg_go2epa_result, dlg_name='go2epa_selector')

    def populate_date_time(self, combo_date):

        result_id = utils_giswater.get_item_data(
            self.dlg_go2epa_result,
            self.dlg_go2epa_result.rpt_selector_result_id, 0)
        sql = (f"SELECT DISTINCT(resultdate), resultdate FROM rpt_arc "
               f"WHERE result_id = '{result_id}' "
               f"ORDER BY resultdate")
        rows = self.controller.get_rows(sql)
        utils_giswater.set_item_data(combo_date, rows)

    def populate_time(self, combo_result, combo_time):
        """ Populate combo times """

        result_id = utils_giswater.get_item_data(self.dlg_go2epa_result,
                                                 combo_result)
        if self.project_type == 'ws':
            field = "time"
        else:
            field = "resulttime"

        sql = (f"SELECT DISTINCT {field}, {field} "
               f"FROM rpt_arc "
               f"WHERE result_id ILIKE '{result_id}' "
               f"ORDER BY {field};")

        rows = self.controller.get_rows(sql, add_empty_row=True)
        utils_giswater.set_item_data(combo_time, rows)

    def result_selector_accept(self):
        """ Update current values to the table """

        # Set project user
        user = self.controller.get_project_user()

        # Delete previous values
        sql = (
            f"DELETE FROM selector_rpt_main WHERE cur_user = '******';\n"
            f"DELETE FROM selector_rpt_compare WHERE cur_user = '******';\n")
        sql += (
            f"DELETE FROM selector_rpt_main_tstep WHERE cur_user = '******';\n"
            f"DELETE FROM selector_rpt_compare_tstep WHERE cur_user = '******';\n"
        )
        self.controller.execute_sql(sql)

        # Get new values from widgets of type QComboBox
        rpt_selector_result_id = utils_giswater.get_item_data(
            self.dlg_go2epa_result,
            self.dlg_go2epa_result.rpt_selector_result_id)
        rpt_selector_compare_id = utils_giswater.get_item_data(
            self.dlg_go2epa_result,
            self.dlg_go2epa_result.rpt_selector_compare_id)

        if rpt_selector_result_id not in (None, -1, ''):
            sql = (f"INSERT INTO selector_rpt_main (result_id, cur_user)"
                   f" VALUES ('{rpt_selector_result_id}', '{user}');\n")
            self.controller.execute_sql(sql)

        if rpt_selector_compare_id not in (None, -1, ''):
            sql = (f"INSERT INTO selector_rpt_compare (result_id, cur_user)"
                   f" VALUES ('{rpt_selector_compare_id}', '{user}');\n")
            self.controller.execute_sql(sql)

        if self.project_type == 'ws':
            time_to_show = utils_giswater.get_item_data(
                self.dlg_go2epa_result,
                self.dlg_go2epa_result.cmb_time_to_show)
            time_to_compare = utils_giswater.get_item_data(
                self.dlg_go2epa_result,
                self.dlg_go2epa_result.cmb_time_to_compare)
            if time_to_show not in (None, -1, ''):
                sql = (
                    f"INSERT INTO selector_rpt_main_tstep (timestep, cur_user)"
                    f" VALUES ('{time_to_show}', '{user}');\n")
                self.controller.execute_sql(sql)
            if time_to_compare not in (None, -1, ''):
                sql = (
                    f"INSERT INTO selector_rpt_compare_tstep (timestep, cur_user)"
                    f" VALUES ('{time_to_compare}', '{user}');\n")
                self.controller.execute_sql(sql)

        elif self.project_type == 'ud':
            date_to_show = utils_giswater.get_item_data(
                self.dlg_go2epa_result, self.dlg_go2epa_result.cmb_sel_date)
            time_to_show = utils_giswater.get_item_data(
                self.dlg_go2epa_result, self.dlg_go2epa_result.cmb_sel_time)
            date_to_compare = utils_giswater.get_item_data(
                self.dlg_go2epa_result, self.dlg_go2epa_result.cmb_com_date)
            time_to_compare = utils_giswater.get_item_data(
                self.dlg_go2epa_result, self.dlg_go2epa_result.cmb_com_time)
            if date_to_show not in (None, -1, ''):
                sql = (
                    f"INSERT INTO selector_rpt_main_tstep (resultdate, resulttime, cur_user)"
                    f" VALUES ('{date_to_show}', '{time_to_show}', '{user}');\n"
                )
                self.controller.execute_sql(sql)
            if date_to_compare not in (None, -1, ''):
                sql = (
                    f"INSERT INTO selector_rpt_compare_tstep (resultdate, resulttime, cur_user)"
                    f" VALUES ('{date_to_compare}', '{time_to_compare}', '{user}');\n"
                )
                self.controller.execute_sql(sql)

        # Show message to user
        message = "Values has been updated"
        self.controller.show_info(message)
        self.close_dialog(self.dlg_go2epa_result)

    def go2epa_options_get_data(self, tablename, dialog):
        """ Get data from selected table """

        sql = f"SELECT * FROM {tablename}"
        row = self.controller.get_row(sql)
        if not row:
            message = "Any data found in table"
            self.controller.show_warning(message, parameter=tablename)
            return None

        # Iterate over all columns and populate its corresponding widget
        columns = []
        for i in range(0, len(row)):
            column_name = self.dao.get_column_name(i)
            widget = dialog.findChild(QWidget, column_name)
            widget_type = utils_giswater.getWidgetType(dialog, widget)
            if row[column_name] is not None:
                if widget_type is QCheckBox:
                    utils_giswater.setChecked(dialog, widget, row[column_name])
                elif widget_type is QComboBox:
                    utils_giswater.set_combo_itemData(widget, row[column_name],
                                                      0)
                elif widget_type is QDateEdit:
                    dateaux = row[column_name].replace('/', '-')
                    date = QDate.fromString(dateaux, 'dd-MM-yyyy')
                    utils_giswater.setCalendarDate(dialog, widget, date)
                elif widget_type is QTimeEdit:
                    timeparts = str(row[column_name]).split(':')
                    if len(timeparts) < 3:
                        timeparts.append("0")
                    days = int(timeparts[0]) / 24
                    hours = int(timeparts[0]) % 24
                    minuts = int(timeparts[1])
                    seconds = int(timeparts[2])
                    time = QTime(hours, minuts, seconds)
                    utils_giswater.setTimeEdit(dialog, widget, time)
                    utils_giswater.setText(dialog, column_name + "_day", days)
                else:
                    utils_giswater.setWidgetText(dialog, widget,
                                                 str(row[column_name]))

            columns.append(column_name)

        return columns

    def go2epa_result_manager(self):
        """ Button 25: Epa result manager """

        # Create the dialog
        self.dlg_manager = EpaManager()
        self.load_settings(self.dlg_manager)

        # Manage widgets
        reg_exp = QRegExp("^[A-Za-z0-9_]{1,16}$")
        self.dlg_manager.txt_result_id.setValidator(QRegExpValidator(reg_exp))

        # Fill combo box and table view
        self.fill_combo_result_id()
        self.dlg_manager.tbl_rpt_cat_result.setSelectionBehavior(
            QAbstractItemView.SelectRows)
        self.fill_table(self.dlg_manager.tbl_rpt_cat_result,
                        'v_ui_rpt_cat_result')
        self.set_table_columns(self.dlg_manager,
                               self.dlg_manager.tbl_rpt_cat_result,
                               'v_ui_rpt_cat_result')

        # Set signals
        self.dlg_manager.btn_delete.clicked.connect(
            partial(self.multi_rows_delete,
                    self.dlg_manager.tbl_rpt_cat_result, 'rpt_cat_result',
                    'result_id'))
        self.dlg_manager.btn_close.clicked.connect(
            partial(self.close_dialog, self.dlg_manager))
        self.dlg_manager.rejected.connect(
            partial(self.close_dialog, self.dlg_manager))
        self.dlg_manager.txt_result_id.editTextChanged.connect(
            self.filter_by_result_id)

        # Open form
        self.open_dialog(self.dlg_manager, dlg_name='go2epa_manager')

    def fill_combo_result_id(self):

        sql = "SELECT result_id FROM v_ui_rpt_cat_result ORDER BY result_id"
        rows = self.controller.get_rows(sql)
        utils_giswater.fillComboBox(self.dlg_manager,
                                    self.dlg_manager.txt_result_id, rows)

    def filter_by_result_id(self):

        table = self.dlg_manager.tbl_rpt_cat_result
        widget_txt = self.dlg_manager.txt_result_id
        tablename = 'v_ui_rpt_cat_result'
        result_id = utils_giswater.getWidgetText(self.dlg_manager, widget_txt)
        if result_id != 'null':
            expr = f" result_id ILIKE '%{result_id}%'"
            # Refresh model with selected filter
            table.model().setFilter(expr)
            table.model().select()
        else:
            self.fill_table(table, tablename)

    def update_sql(self):
        usql = UpdateSQL(self.iface, self.settings, self.controller,
                         self.plugin_dir)
        usql.init_sql()
Exemplo n.º 24
0
class GwGo2Epa:
    def __init__(self):
        """ Class to control toolbar 'go2epa' """

        self.g2epa_opt = GwGo2EpaOptions()
        self.iterations = 0
        self.controller = global_vars.controller
        self.project_type = self.controller.get_project_type()
        self.plugin_dir = global_vars.plugin_dir

    def go2epa(self):
        """ Button 23: Open form to set INP, RPT and project """

        # Show form in docker?
        self.controller.init_docker('qgis_form_docker')

        # Create dialog
        self.dlg_go2epa = Go2EpaUI()
        load_settings(self.dlg_go2epa)
        self.load_user_values()
        if self.project_type in 'ws':
            self.dlg_go2epa.chk_export_subcatch.setVisible(False)

        # Set signals
        self.set_signals()

        if self.project_type == 'ws':
            self.dlg_go2epa.btn_hs_ds.setText("Dscenario Selector")
            tableleft = "cat_dscenario"
            tableright = "selector_inp_demand"
            field_id_left = "dscenario_id"
            field_id_right = "dscenario_id"
            self.dlg_go2epa.btn_hs_ds.clicked.connect(
                partial(self.sector_selection,
                        tableleft,
                        tableright,
                        field_id_left,
                        field_id_right,
                        aql=""))

        elif self.project_type == 'ud':
            self.dlg_go2epa.btn_hs_ds.setText("Hydrology selector")
            self.dlg_go2epa.btn_hs_ds.clicked.connect(
                self.ud_hydrology_selector)

        # Check OS and enable/disable checkbox execute EPA software
        if sys.platform != "win32":
            qt_tools.setChecked(self.dlg_go2epa, self.dlg_go2epa.chk_exec,
                                False)
            self.dlg_go2epa.chk_exec.setEnabled(False)
            self.dlg_go2epa.chk_exec.setText(
                'Execute EPA software (Runs only on Windows)')

        self.set_completer_result(self.dlg_go2epa.txt_result_name,
                                  'v_ui_rpt_cat_result', 'result_id')

        if self.controller.dlg_docker:
            self.controller.manage_translation('go2epa', self.dlg_go2epa)
            self.controller.dock_dialog(self.dlg_go2epa)
            self.dlg_go2epa.btn_cancel.clicked.disconnect()
            self.dlg_go2epa.btn_cancel.clicked.connect(
                self.controller.close_docker)
        else:
            open_dialog(self.dlg_go2epa, dlg_name='go2epa')

    def set_signals(self):

        self.dlg_go2epa.txt_result_name.textChanged.connect(
            partial(self.check_result_id))
        self.dlg_go2epa.btn_file_inp.clicked.connect(
            self.go2epa_select_file_inp)
        self.dlg_go2epa.btn_file_rpt.clicked.connect(
            self.go2epa_select_file_rpt)
        self.dlg_go2epa.btn_accept.clicked.connect(self.go2epa_accept)
        self.dlg_go2epa.btn_cancel.clicked.connect(
            partial(close_dialog, self.dlg_go2epa))
        self.dlg_go2epa.rejected.connect(partial(close_dialog,
                                                 self.dlg_go2epa))
        self.dlg_go2epa.btn_options.clicked.connect(self.epa_options)

    def check_inp_chk(self, file_inp):

        if file_inp is None:
            msg = "Select valid INP file"
            self.controller.show_warning(msg, parameter=str(file_inp))
            return False

    def check_rpt(self):

        file_inp = qt_tools.getWidgetText(self.dlg_go2epa,
                                          self.dlg_go2epa.txt_file_inp)
        file_rpt = qt_tools.getWidgetText(self.dlg_go2epa,
                                          self.dlg_go2epa.txt_file_rpt)

        # Control execute epa software
        if qt_tools.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_exec):
            if self.check_inp_chk(file_inp) is False:
                return False

            if file_rpt is None:
                msg = "Select valid RPT file"
                self.controller.show_warning(msg, parameter=str(file_rpt))
                return False

            if not qt_tools.isChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_export):
                if not os.path.exists(file_inp):
                    msg = "File INP not found"
                    self.controller.show_warning(msg, parameter=str(file_rpt))
                    return False

    def check_fields(self):

        file_inp = qt_tools.getWidgetText(self.dlg_go2epa,
                                          self.dlg_go2epa.txt_file_inp)
        file_rpt = qt_tools.getWidgetText(self.dlg_go2epa,
                                          self.dlg_go2epa.txt_file_rpt)
        result_name = qt_tools.getWidgetText(self.dlg_go2epa,
                                             self.dlg_go2epa.txt_result_name,
                                             False, False)

        # Control export INP
        if qt_tools.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_export):
            if self.check_inp_chk(file_inp) is False:
                return False

        # Control execute epa software
        if self.check_rpt() is False:
            return False

        # Control import result
        if qt_tools.isChecked(self.dlg_go2epa,
                              self.dlg_go2epa.chk_import_result):
            if file_rpt is None:
                msg = "Select valid RPT file"
                self.controller.show_warning(msg, parameter=str(file_rpt))
                return False
            if not qt_tools.isChecked(self.dlg_go2epa,
                                      self.dlg_go2epa.chk_exec):
                if not os.path.exists(file_rpt):
                    msg = "File RPT not found"
                    self.controller.show_warning(msg, parameter=str(file_rpt))
                    return False
            else:
                if self.check_rpt() is False:
                    return False

        # Control result name
        if result_name == '':
            self.dlg_go2epa.txt_result_name.setStyleSheet(
                "border: 1px solid red")
            msg = "This parameter is mandatory. Please, set a value"
            self.controller.show_details(msg, title="Rpt fail", inf_text=None)
            return False

        sql = (f"SELECT result_id FROM rpt_cat_result "
               f"WHERE result_id = '{result_name}' LIMIT 1")
        row = self.controller.get_row(sql)
        if row:
            msg = "Result name already exists, do you want overwrite?"
            answer = self.controller.ask_question(msg, title="Alert")
            if not answer:
                return False

        return True

    def load_user_values(self):
        """ Load QGIS settings related with file_manager """

        self.dlg_go2epa.txt_result_name.setMaxLength(16)
        self.result_name = get_parser_value('go2epa', 'go2epa_RESULT_NAME')
        self.dlg_go2epa.txt_result_name.setText(self.result_name)
        self.file_inp = get_parser_value('go2epa', 'go2epa_FILE_INP')
        self.dlg_go2epa.txt_file_inp.setText(self.file_inp)
        self.file_rpt = get_parser_value('go2epa', 'go2epa_FILE_RPT')
        self.dlg_go2epa.txt_file_rpt.setText(self.file_rpt)

        value = get_parser_value('go2epa', 'go2epa_chk_NETWORK_GEOM')
        qt_tools.setChecked(self.dlg_go2epa, self.dlg_go2epa.chk_only_check,
                            value)
        value = get_parser_value('go2epa', 'go2epa_chk_INP')
        qt_tools.setChecked(self.dlg_go2epa, self.dlg_go2epa.chk_export, value)
        value = get_parser_value('go2epa', 'go2epa_chk_UD')
        qt_tools.setChecked(self.dlg_go2epa,
                            self.dlg_go2epa.chk_export_subcatch, value)
        value = get_parser_value('go2epa', 'go2epa_chk_EPA')
        qt_tools.setChecked(self.dlg_go2epa, self.dlg_go2epa.chk_exec, value)
        value = get_parser_value('go2epa', 'go2epa_chk_RPT')
        qt_tools.setChecked(self.dlg_go2epa, self.dlg_go2epa.chk_import_result,
                            value)

    def save_user_values(self):
        """ Save QGIS settings related with file_manager """

        set_parser_value(
            'go2epa', 'go2epa_RESULT_NAME',
            f"{qt_tools.getWidgetText(self.dlg_go2epa, 'txt_result_name', return_string_null=False)}"
        )
        set_parser_value(
            'go2epa', 'go2epa_FILE_INP',
            f"{qt_tools.getWidgetText(self.dlg_go2epa, 'txt_file_inp', return_string_null=False)}"
        )
        set_parser_value(
            'go2epa', 'go2epa_FILE_RPT',
            f"{qt_tools.getWidgetText(self.dlg_go2epa, 'txt_file_rpt', return_string_null=False)}"
        )
        set_parser_value(
            'go2epa', 'go2epa_chk_NETWORK_GEOM',
            f"{qt_tools.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_only_check)}"
        )
        set_parser_value(
            'go2epa', 'go2epa_chk_INP',
            f"{qt_tools.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_export)}"
        )
        set_parser_value(
            'go2epa', 'go2epa_chk_UD',
            f"{qt_tools.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_export_subcatch)}"
        )
        set_parser_value(
            'go2epa', 'go2epa_chk_EPA',
            f"{qt_tools.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_exec)}")
        set_parser_value(
            'go2epa', 'go2epa_chk_RPT',
            f"{qt_tools.isChecked(self.dlg_go2epa, self.dlg_go2epa.chk_import_result)}"
        )

    def sector_selection(self,
                         tableleft,
                         tableright,
                         field_id_left,
                         field_id_right,
                         aql=""):
        """ Load the tables in the selection form """

        dlg_psector_sel = Multirow_selector('dscenario')
        load_settings(dlg_psector_sel)
        dlg_psector_sel.btn_ok.clicked.connect(dlg_psector_sel.close)

        if tableleft == 'cat_dscenario':
            dlg_psector_sel.setWindowTitle(" Dscenario selector")
            qt_tools.setWidgetText(
                dlg_psector_sel, dlg_psector_sel.lbl_filter,
                self.controller.tr('Filter by: Dscenario name',
                                   context_name='labels'))
            qt_tools.setWidgetText(
                dlg_psector_sel, dlg_psector_sel.lbl_unselected,
                self.controller.tr('Unselected dscenarios',
                                   context_name='labels'))
            qt_tools.setWidgetText(
                dlg_psector_sel, dlg_psector_sel.lbl_selected,
                self.controller.tr('Selected dscenarios',
                                   context_name='labels'))

        multi_row_selector(dlg_psector_sel,
                           tableleft,
                           tableright,
                           field_id_left,
                           field_id_right,
                           aql=aql)

        open_dialog(dlg_psector_sel)

    def epa_options(self):
        """ Open dialog api_epa_options.ui.ui """

        self.g2epa_opt.go2epa_options()
        return

    def ud_hydrology_selector(self):
        """ Dialog hydrology_selector.ui """

        self.dlg_hydrology_selector = HydrologySelector()
        load_settings(self.dlg_hydrology_selector)

        self.dlg_hydrology_selector.btn_accept.clicked.connect(
            self.save_hydrology)
        self.dlg_hydrology_selector.hydrology.currentIndexChanged.connect(
            self.update_labels)
        self.dlg_hydrology_selector.txt_name.textChanged.connect(
            partial(self.filter_cbx_by_text, "cat_hydrology",
                    self.dlg_hydrology_selector.txt_name,
                    self.dlg_hydrology_selector.hydrology))

        sql = "SELECT DISTINCT(name), hydrology_id FROM cat_hydrology ORDER BY name"
        rows = self.controller.get_rows(sql)
        if not rows:
            message = "Any data found in table"
            self.controller.show_warning(message, parameter='cat_hydrology')
            return False

        qt_tools.set_item_data(self.dlg_hydrology_selector.hydrology, rows)

        sql = (
            "SELECT DISTINCT(t1.name) FROM cat_hydrology AS t1 "
            "INNER JOIN selector_inp_hydrology AS t2 ON t1.hydrology_id = t2.hydrology_id "
            "WHERE t2.cur_user = current_user")
        row = self.controller.get_row(sql)
        if row:
            qt_tools.setWidgetText(self.dlg_hydrology_selector,
                                   self.dlg_hydrology_selector.hydrology,
                                   row[0])
        else:
            qt_tools.setWidgetText(self.dlg_hydrology_selector,
                                   self.dlg_hydrology_selector.hydrology, 0)

        self.update_labels()
        open_dialog(self.dlg_hydrology_selector)

    def save_hydrology(self):

        hydrology_id = qt_tools.get_item_data(
            self.dlg_hydrology_selector, self.dlg_hydrology_selector.hydrology,
            1)
        sql = ("SELECT cur_user FROM selector_inp_hydrology "
               "WHERE cur_user = current_user")
        row = self.controller.get_row(sql)
        if row:
            sql = (f"UPDATE selector_inp_hydrology "
                   f"SET hydrology_id = {hydrology_id} "
                   f"WHERE cur_user = current_user")
        else:
            sql = (
                f"INSERT INTO selector_inp_hydrology (hydrology_id, cur_user) "
                f"VALUES('{hydrology_id}', current_user)")
        self.controller.execute_sql(sql)

        message = "Values has been update"
        self.controller.show_info(message)
        close_dialog(self.dlg_hydrology_selector)

    def update_labels(self):
        """ Show text in labels from SELECT """

        sql = (
            f"SELECT infiltration, text FROM cat_hydrology"
            f" WHERE name = '{self.dlg_hydrology_selector.hydrology.currentText()}'"
        )
        row = self.controller.get_row(sql)
        if row is not None:
            qt_tools.setText(self.dlg_hydrology_selector,
                             self.dlg_hydrology_selector.infiltration, row[0])
            qt_tools.setText(self.dlg_hydrology_selector,
                             self.dlg_hydrology_selector.descript, row[1])

    def filter_cbx_by_text(self, tablename, widgettxt, widgetcbx):

        sql = (f"SELECT DISTINCT(name), hydrology_id FROM {tablename}"
               f" WHERE name LIKE '%{widgettxt.text()}%'"
               f" ORDER BY name ")
        rows = self.controller.get_rows(sql)
        if not rows:
            message = "Check the table 'cat_hydrology' "
            self.controller.show_warning(message)
            return False
        qt_tools.set_item_data(widgetcbx, rows)
        self.update_labels()

    def go2epa_select_file_inp(self):
        """ Select INP file """

        self.file_inp = qt_tools.getWidgetText(self.dlg_go2epa,
                                               self.dlg_go2epa.txt_file_inp)
        # Set default value if necessary
        if self.file_inp is None or self.file_inp == '':
            self.file_inp = global_vars.plugin_dir

        # Get directory of that file
        folder_path = os.path.dirname(self.file_inp)
        if not os.path.exists(folder_path):
            folder_path = os.path.dirname(__file__)
        os.chdir(folder_path)
        message = self.controller.tr("Select INP file")
        self.file_inp, filter_ = QFileDialog.getSaveFileName(
            None, message, "", '*.inp')
        qt_tools.setWidgetText(self.dlg_go2epa, self.dlg_go2epa.txt_file_inp,
                               self.file_inp)

    def go2epa_select_file_rpt(self):
        """ Select RPT file """

        # Set default value if necessary
        if self.file_rpt is None or self.file_rpt == '':
            self.file_rpt = global_vars.plugin_dir

        # Get directory of that file
        folder_path = os.path.dirname(self.file_rpt)
        if not os.path.exists(folder_path):
            folder_path = os.path.dirname(__file__)
        os.chdir(folder_path)
        message = self.controller.tr("Select RPT file")
        self.file_rpt, filter_ = QFileDialog.getSaveFileName(
            None, message, "", '*.rpt')
        qt_tools.setWidgetText(self.dlg_go2epa, self.dlg_go2epa.txt_file_rpt,
                               self.file_rpt)

    def go2epa_accept(self):
        """ Save INP, RPT and result name into GSW file """

        # Save user values
        self.save_user_values()

        self.dlg_go2epa.txt_infolog.clear()
        self.dlg_go2epa.txt_file_rpt.setStyleSheet(None)
        status = self.check_fields()
        if status is False:
            return

        # Get widgets values
        self.result_name = qt_tools.getWidgetText(
            self.dlg_go2epa, self.dlg_go2epa.txt_result_name, False, False)
        self.net_geom = qt_tools.isChecked(self.dlg_go2epa,
                                           self.dlg_go2epa.chk_only_check)
        self.export_inp = qt_tools.isChecked(self.dlg_go2epa,
                                             self.dlg_go2epa.chk_export)
        self.export_subcatch = qt_tools.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_export_subcatch)
        self.file_inp = qt_tools.getWidgetText(self.dlg_go2epa,
                                               self.dlg_go2epa.txt_file_inp)
        self.exec_epa = qt_tools.isChecked(self.dlg_go2epa,
                                           self.dlg_go2epa.chk_exec)
        self.file_rpt = qt_tools.getWidgetText(self.dlg_go2epa,
                                               self.dlg_go2epa.txt_file_rpt)
        self.import_result = qt_tools.isChecked(
            self.dlg_go2epa, self.dlg_go2epa.chk_import_result)

        # Check for sector selector
        if self.export_inp:
            sql = "SELECT sector_id FROM selector_sector LIMIT 1"
            row = self.controller.get_row(sql)
            if row is None:
                msg = "You need to select some sector"
                self.controller.show_info_box(msg)
                return

        # Set background task 'Go2Epa'
        description = f"Go2Epa"
        self.task_go2epa = GwGo2EpaTask(description, self)
        QgsApplication.taskManager().addTask(self.task_go2epa)
        QgsApplication.taskManager().triggerTask(self.task_go2epa)

    def set_completer_result(self, widget, viewname, field_name):
        """ Set autocomplete of widget 'feature_id'
            getting id's from selected @viewname
        """

        result_name = qt_tools.getWidgetText(self.dlg_go2epa,
                                             self.dlg_go2epa.txt_result_name)

        # Adding auto-completion to a QLineEdit
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()

        sql = f"SELECT {field_name} FROM {viewname}"
        rows = self.controller.get_rows(sql)

        if rows:
            for i in range(0, len(rows)):
                aux = rows[i]
                rows[i] = str(aux[0])

            model.setStringList(rows)
            self.completer.setModel(model)
            if result_name in rows:
                self.dlg_go2epa.chk_only_check.setEnabled(True)

    def check_result_id(self):
        """ Check if selected @result_id already exists """

        result_id = qt_tools.getWidgetText(self.dlg_go2epa,
                                           self.dlg_go2epa.txt_result_name)
        sql = (f"SELECT result_id FROM v_ui_rpt_cat_result"
               f" WHERE result_id = '{result_id}'")
        row = self.controller.get_row(sql, log_info=False)
        if not row:
            self.dlg_go2epa.chk_only_check.setChecked(False)
            self.dlg_go2epa.chk_only_check.setEnabled(False)
        else:
            self.dlg_go2epa.chk_only_check.setEnabled(True)

    def go2epa_options_get_data(self, tablename, dialog):
        """ Get data from selected table """

        sql = f"SELECT * FROM {tablename}"
        row = self.controller.get_row(sql)
        if not row:
            message = "Any data found in table"
            self.controller.show_warning(message, parameter=tablename)
            return None

        # Iterate over all columns and populate its corresponding widget
        columns = []
        for i in range(0, len(row)):
            column_name = self.controller.dao.get_column_name(i)
            widget = dialog.findChild(QWidget, column_name)
            widget_type = qt_tools.getWidgetType(dialog, widget)
            if row[column_name] is not None:
                if widget_type is QCheckBox:
                    qt_tools.setChecked(dialog, widget, row[column_name])
                elif widget_type is QComboBox:
                    qt_tools.set_combo_itemData(widget, row[column_name], 0)
                elif widget_type is QDateEdit:
                    dateaux = row[column_name].replace('/', '-')
                    date = QDate.fromString(dateaux, 'dd-MM-yyyy')
                    qt_tools.setCalendarDate(dialog, widget, date)
                elif widget_type is QTimeEdit:
                    timeparts = str(row[column_name]).split(':')
                    if len(timeparts) < 3:
                        timeparts.append("0")
                    days = int(timeparts[0]) / 24
                    hours = int(timeparts[0]) % 24
                    minuts = int(timeparts[1])
                    seconds = int(timeparts[2])
                    time = QTime(hours, minuts, seconds)
                    qt_tools.setTimeEdit(dialog, widget, time)
                    qt_tools.setText(dialog, column_name + "_day", days)
                else:
                    qt_tools.setWidgetText(dialog, widget,
                                           str(row[column_name]))

            columns.append(column_name)

        return columns

    def update_sql(self):
        usql = GwAdmin()
        usql.init_sql()
Exemplo n.º 25
0
class TmParentAction(object):
    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class constructor """

        # Initialize instance attributes
        self.tree_manage_version = "1.0"
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.settings = settings
        self.controller = controller
        self.plugin_dir = plugin_dir
        self.dao = self.controller.dao
        self.schema_name = self.controller.schema_name
        self.project_type = None
        self.file_gsw = None
        self.gsw_settings = None
        self.lazy_widget = None

    def set_controller(self, controller):
        """ Set controller class """

        self.controller = controller
        self.schema_name = self.controller.schema_name

    def get_plugin_version(self):
        """ Get plugin version from metadata.txt file """

        # Check if metadata file exists
        metadata_file = os.path.join(self.plugin_dir, 'metadata.txt')
        if not os.path.exists(metadata_file):
            message = "Metadata file not found" + metadata_file
            self.controller.show_warning(message, parameter=metadata_file)
            return None

        metadata = configparser.ConfigParser()
        metadata.read(metadata_file)
        plugin_version = metadata.get('general', 'version')
        if plugin_version is None:
            message = "Plugin version not found"
            self.controller.show_warning(message)

        return plugin_version

    def load_settings(self, dialog=None):
        """ Load QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        try:
            screens = ctypes.windll.user32
            screen_x = screens.GetSystemMetrics(78)
            screen_y = screens.GetSystemMetrics(79)
            x = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_x")
            y = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_y")
            width = self.controller.plugin_settings_value(
                dialog.objectName() + "_width", dialog.property('width'))
            height = self.controller.plugin_settings_value(
                dialog.objectName() + "_height", dialog.property('height'))

            if int(x) < 0 or int(y) < 0:
                dialog.resize(int(width), int(height))
            else:
                if int(x) > screen_x:
                    x = int(screen_x) - int(width)
                if int(y) > screen_y:
                    y = int(screen_y)
                dialog.setGeometry(int(x), int(y), int(width), int(height))
        except:
            pass

    def save_settings(self, dialog=None):
        """ Save QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_width", dialog.width())
        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_height", dialog.height())
        self.controller.plugin_settings_set_value(dialog.objectName() + "_x",
                                                  dialog.pos().x() + 8)
        self.controller.plugin_settings_set_value(dialog.objectName() + "_y",
                                                  dialog.pos().y() + 31)

    def open_dialog(self,
                    dlg=None,
                    dlg_name=None,
                    info=True,
                    maximize_button=True,
                    stay_on_top=True):
        """ Open dialog """

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg

        # Manage i18n of the dialog
        if dlg_name:
            self.controller.manage_translation(dlg_name, dlg)

        # Manage stay on top, maximize/minimize button and information button
        # if info is True maximize flag will be ignored
        # To enable maximize button you must set info to False
        flags = Qt.WindowCloseButtonHint
        if info:
            flags |= Qt.WindowSystemMenuHint | Qt.WindowContextHelpButtonHint
        else:
            if maximize_button:
                flags |= Qt.WindowMinMaxButtonsHint

        if stay_on_top:
            flags |= Qt.WindowStaysOnTopHint

        dlg.setWindowFlags(flags)

        # Open dialog
        if issubclass(type(dlg), GwDialog):
            dlg.open()
        elif issubclass(type(dlg), GwMainWindow):
            dlg.show()
        else:
            print(f"WARNING: dialog type {type(dlg)} is not handled!")
            dlg.show()

    def close_dialog(self, dlg=None):
        """ Close dialog """

        try:
            self.save_settings(dlg)
            dlg.close()
            map_tool = self.canvas.mapTool()
            # If selected map tool is from the plugin, set 'Pan' as current one
            if map_tool.toolName() == '':
                self.iface.actionPan().trigger()
        except AttributeError:
            pass

    def hide_colums(self, widget, comuns_to_hide):
        for i in range(0, len(comuns_to_hide)):
            widget.hideColumn(comuns_to_hide[i])

    def set_icon(self, widget, icon):
        """ Set @icon to selected @widget """

        # Get icons folder
        icons_folder = os.path.join(self.plugin_dir, 'icons')
        icon_path = os.path.join(icons_folder, str(icon) + ".png")
        if os.path.exists(icon_path):
            widget.setIcon(QIcon(icon_path))
        else:
            self.controller.log_info("File not found", parameter=icon_path)

    def check_expression(self, expr_filter, log_info=False):
        """ Check if expression filter @expr_filter is valid """

        if log_info:
            self.controller.log_info(expr_filter)
        expr = QgsExpression(expr_filter)
        if expr.hasParserError():
            message = "Expression Error"
            self.controller.log_warning(message, parameter=expr_filter)
            return False, expr

        return True, expr

    def set_table_columns(self, dialog, widget, table_name, project_type=None):
        """ Configuration of tables. Set visibility and width of columns """

        widget = utils_giswater.getWidget(dialog, widget)
        if not widget:
            return

        # Set width and alias of visible columns
        columns_to_delete = []
        sql = (f"SELECT column_index, width, alias, status"
               f" FROM config_client_forms"
               f" WHERE table_id = '{table_name}'")
        if project_type is not None:
            sql += f" AND project_type = '{project_type}' "
        sql += " ORDER BY column_index"

        rows = self.controller.get_rows(sql, log_info=False)
        if not rows:
            return

        for row in rows:
            if not row['status']:
                columns_to_delete.append(row['column_index'] - 1)
            else:
                width = row['width']
                if width is not None:
                    widget.setColumnWidth(row['column_index'] - 1, width)
                widget.model().setHeaderData(row['column_index'] - 1,
                                             Qt.Horizontal, row['alias'])

        widget.model().select()

        # Delete columns
        for column in columns_to_delete:
            widget.hideColumn(column)

    def set_completer_object(self, tablename, widget, field_search):
        """ Set autocomplete of widget @table_object + "_id"
            getting id's from selected @table_object
        """

        if not widget:
            return

        # Set SQL
        sql = (f"SELECT DISTINCT({field_search})"
               f" FROM {tablename}"
               f" ORDER BY {field_search}")
        rows = self.controller.get_rows(sql)
        if rows is None:
            return

        for i in range(0, len(rows)):
            aux = rows[i]
            rows[i] = aux[0]

        # Set completer and model: add autocomplete in the widget
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(0)
        widget.setCompleter(self.completer)
        model = QStringListModel()
        model.setStringList(rows)
        self.completer.setModel(model)

    def refresh_map_canvas(self, restore_cursor=False):
        """ Refresh all layers present in map canvas """

        self.canvas.refreshAllLayers()
        for layer_refresh in self.canvas.layers():
            layer_refresh.triggerRepaint()

        if restore_cursor:
            self.set_cursor_restore()

    def set_cursor_restore(self):
        """ Restore to previous cursors """
        QApplication.restoreOverrideCursor()

    def get_cursor_multiple_selection(self):
        """ Set cursor for multiple selection """

        path_folder = os.path.join(os.path.dirname(__file__), os.pardir)
        path_cursor = os.path.join(path_folder, 'icons', '201.png')
        if os.path.exists(path_cursor):
            cursor = QCursor(QPixmap(path_cursor))
        else:
            cursor = QCursor(Qt.ArrowCursor)

        return cursor

    def fill_table(self,
                   qtable,
                   table_name,
                   set_edit_triggers=QTableView.NoEditTriggers,
                   expr_filter=None):
        """ Fill table @widget filtering query by @workcat_id
            Set a model with selected filter.
            Attach that model to selected table
            @setEditStrategy:
             0: OnFieldChange
             1: OnRowChange
             2: OnManualSubmit
        """

        expr = None
        if expr_filter:
            # Check expression
            (is_valid,
             expr) = self.check_expression(expr_filter)  # @UnusedVariable
            if not is_valid:
                return expr

        # Set a model with selected filter expression
        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name

        # Set model
        model = QSqlTableModel()
        model.setTable(table_name)
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.setSort(0, 0)
        model.select()

        # When change some field we need to refresh Qtableview and filter by psector_id
        qtable.setEditTriggers(set_edit_triggers)

        # Check for errors
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())
        # Attach model to table view
        if expr:
            qtable.setModel(model)
            qtable.model().setFilter(expr_filter)
        else:
            qtable.setModel(model)

        return expr

    def get_feature_by_id(self, layer, id, field_id):

        features = layer.getFeatures()
        for feature in features:
            if feature[field_id] == id:
                return feature

        return False
Exemplo n.º 26
0
class EditDialog(QDialog, FORM_CLASS):
    """ Dialog to edit building outlines"""

    edit_geometry_saved = pyqtSignal(list)
    delete_outline_saved = pyqtSignal(list, str)

    def __init__(self, parent_frame, parent=None):
        super(EditDialog, self).__init__(parent)
        self.setupUi(self)
        self.setWindowModality(Qt.NonModal)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        self.parent_frame = parent_frame
        self.layer_registry = self.parent_frame.layer_registry
        self.db = self.parent_frame.db

        self.parent_frame_name = self.parent_frame.__class__.__name__
        if self.parent_frame_name == "BulkLoadFrame":
            self.editing_layer = self.parent_frame.bulk_load_layer
            self.current_dataset = self.parent_frame.current_dataset
            # Update qa layers
            self.edit_geometry_saved.connect(self.liqa_on_edit_geometry_saved)
            self.delete_outline_saved.connect(self.liqa_on_delete_outline_saved)
        elif self.parent_frame_name == "AlterRelationships":
            self.editing_layer = self.parent_frame.lyr_bulk_load
            self.current_dataset = self.parent_frame.current_dataset
        elif self.parent_frame_name == "ProductionFrame":
            self.editing_layer = self.parent_frame.building_layer
            self.current_dataset = None

        self.init_dialog()

        # Bulk loadings & editing fields
        self.added_geoms = OrderedDict()
        self.geom = None
        self.ids = []
        self.geoms = {}
        self.bulk_load_outline_id = None
        self.split_geoms = {}

        # processing class instances
        self.change_instance = None

        # initiate le_deletion_reason
        self.le_deletion_reason.setMaxLength(250)
        self.le_deletion_reason.setPlaceholderText("Reason for Deletion")
        self.completer_box()

        self.cmb_status.currentIndexChanged.connect(self.enable_le_deletion_reason)
        self.rejected.connect(self.close_dialog)

    def init_dialog(self):
        """Constructor """
        self.layout_status.hide()
        self.layout_capture_method.hide()
        self.layout_lifecycle_stage.hide()
        self.layout_general_info.hide()
        self.layout_end_lifespan.hide()
        self.cmb_status.setDisabled(1)
        self.le_deletion_reason.setDisabled(1)
        self.cmb_capture_method.setDisabled(1)
        self.cmb_lifecycle_stage.setDisabled(1)
        self.cmb_capture_source.setDisabled(1)
        self.cmb_ta.setDisabled(1)
        self.cmb_town.setDisabled(1)
        self.cmb_suburb.setDisabled(1)
        self.btn_edit_save.setDisabled(1)
        self.btn_edit_reset.setDisabled(1)
        self.btn_end_lifespan.setDisabled(1)

    def add_outline(self):
        """When the user selects to add a new outline"""
        self.setWindowTitle("Add Outline")
        self.added_geoms = OrderedDict()
        self.geom = None
        iface.actionCancelEdits().trigger()
        # reset toolbar
        for action in iface.building_toolbar.actions():
            if action.text() not in ["Pan Map", "Add Outline", "Edit Geometry", "Edit Attributes"]:
                iface.building_toolbar.removeAction(action)
            if action.text() == "Add Outline":
                action.setDisabled(True)
            else:
                action.setEnabled(True)
        # set change instance to added class
        try:
            self.btn_edit_save.clicked.disconnect()
        except TypeError:
            pass
        try:
            self.btn_edit_reset.clicked.disconnect()
        except TypeError:
            pass

        if self.parent_frame_name == "BulkLoadFrame" or self.parent_frame_name == "AlterRelationships":
            self.change_instance = bulk_load_changes.AddBulkLoad(self)
            self.layout_status.hide()
            self.layout_capture_method.show()
            self.layout_lifecycle_stage.hide()
            self.layout_general_info.show()
            self.layout_end_lifespan.hide()
        elif self.parent_frame_name == "ProductionFrame":
            self.change_instance = production_changes.AddProduction(self)
            self.layout_status.hide()
            self.layout_capture_method.show()
            self.layout_lifecycle_stage.show()
            self.layout_general_info.show()
            self.layout_end_lifespan.hide()

        # connect signals and slots
        self.btn_edit_save.clicked.connect(partial(self.change_instance.edit_save_clicked, True))
        self.btn_edit_reset.clicked.connect(self.change_instance.edit_reset_clicked)
        self.editing_layer.featureAdded.connect(self.change_instance.creator_feature_added)
        self.editing_layer.featureDeleted.connect(self.change_instance.creator_feature_deleted)
        self.editing_layer.geometryChanged.connect(self.change_instance.creator_geometry_changed)

    def edit_attribute(self):
        """When the user selects to edit a building attribute"""
        self.setWindowTitle("Edit Attribute")
        self.ids = []
        self.building_outline_id = None
        iface.actionCancelEdits().trigger()
        # reset toolbar
        for action in iface.building_toolbar.actions():
            if action.text() not in ["Pan Map", "Add Outline", "Edit Geometry", "Edit Attributes"]:
                iface.building_toolbar.removeAction(action)
            if action.text() in ["Edit Attributes"]:
                action.setDisabled(True)
            else:
                action.setEnabled(True)
        try:
            self.btn_edit_save.clicked.disconnect()
        except TypeError:
            pass
        try:
            self.btn_edit_reset.clicked.disconnect()
        except TypeError:
            pass

        if self.parent_frame_name == "BulkLoadFrame" or self.parent_frame_name == "AlterRelationships":
            self.change_instance = bulk_load_changes.EditAttribute(self)
            self.layout_status.show()
            self.layout_capture_method.show()
            self.layout_lifecycle_stage.hide()
            self.layout_general_info.show()
            self.layout_end_lifespan.hide()
        elif self.parent_frame_name == "ProductionFrame":
            self.change_instance = production_changes.EditAttribute(self)
            self.layout_status.hide()
            self.layout_capture_method.show()
            self.layout_lifecycle_stage.show()
            self.layout_general_info.show()
            self.layout_end_lifespan.show()

            try:
                self.btn_end_lifespan.clicked.disconnect()
            except Exception:
                pass
            self.btn_end_lifespan.clicked.connect(partial(self.change_instance.end_lifespan, True))

        # set up signals and slots
        self.btn_edit_save.clicked.connect(partial(self.change_instance.edit_save_clicked, True))
        self.btn_edit_reset.clicked.connect(self.change_instance.edit_reset_clicked)
        self.editing_layer.selectionChanged.connect(self.change_instance.selection_changed)

    def edit_geometry(self):
        """"When the user selects to edit a building geometry"""
        self.setWindowTitle("Edit Geometry")
        self.geoms = {}
        iface.actionCancelEdits().trigger()
        # reset toolbar
        for action in iface.building_toolbar.actions():
            if action.text() not in ["Pan Map", "Add Outline", "Edit Geometry", "Edit Attributes"]:
                iface.building_toolbar.removeAction(action)
            if action.text() == "Edit Geometry":
                action.setDisabled(True)
            else:
                action.setEnabled(True)
        try:
            self.btn_edit_save.clicked.disconnect()
        except TypeError:
            pass
        try:
            self.btn_edit_reset.clicked.disconnect()
        except TypeError:
            pass

        if self.parent_frame_name == "BulkLoadFrame" or self.parent_frame_name == "AlterRelationships":
            self.change_instance = bulk_load_changes.EditGeometry(self)
            self.layout_status.hide()
            self.layout_capture_method.show()
            self.layout_lifecycle_stage.hide()
            self.layout_general_info.hide()
            self.layout_end_lifespan.hide()
        elif self.parent_frame_name == "ProductionFrame":
            self.change_instance = production_changes.EditGeometry(self)
            self.layout_status.hide()
            self.layout_capture_method.show()
            self.layout_lifecycle_stage.hide()
            self.layout_general_info.hide()
            self.layout_end_lifespan.hide()

        # set up signals and slots
        self.btn_edit_save.clicked.connect(partial(self.change_instance.edit_save_clicked, True))
        self.btn_edit_reset.clicked.connect(self.change_instance.edit_reset_clicked)
        self.editing_layer.geometryChanged.connect(self.change_instance.geometry_changed)
        self.editing_layer.featureAdded.connect(self.change_instance.creator_feature_added)

    def close_dialog(self):
        """When 'x' is clicked"""
        self.change_instance = None
        self.added_geoms = OrderedDict()
        self.geom = None
        self.ids = []
        self.building_outline_id = None
        self.geoms = {}
        self.split_geoms = {}
        self.added_building_ids = []

        self.parent_frame.edit_cancel_clicked()
        for action in iface.building_toolbar.actions():
            if action.text() not in ["Pan Map", "Add Outline", "Edit Geometry", "Edit Attributes"]:
                iface.building_toolbar.removeAction(action)
            else:
                action.setEnabled(True)

    def get_change_instance(self):
        """Return change instance"""
        return self.change_instance

    def completer_box(self):
        """Box automatic completion"""
        reasons = self.db.execute_return(bulk_load_select.deletion_description_value)
        reason_list = [row[0] for row in reasons.fetchall()]
        # Fill the search box
        self.completer = QCompleter(reason_list)
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.le_deletion_reason.setCompleter(self.completer)

    @pyqtSlot()
    def enable_le_deletion_reason(self):
        """When the user opts to delete an outline"""
        if self.cmb_status.currentText() == "Deleted During QA":
            self.le_deletion_reason.setEnabled(1)
            self.le_deletion_reason.setFocus()
            self.le_deletion_reason.selectAll()
        else:
            self.le_deletion_reason.setDisabled(1)
            self.le_deletion_reason.clear()

    @pyqtSlot(list)
    def liqa_on_edit_geometry_saved(self, ids):
        """Update LIQA when geometry edited"""
        for qa_lyr in self.find_qa_layer():
            if not self.bulk_load_id_field_exists(qa_lyr):
                continue
            bulk_load_ids = self.get_bulk_load_ids(qa_lyr)
            for feat_id in ids:
                if feat_id in list(bulk_load_ids.values()):
                    qa_feat_id = list(bulk_load_ids.keys())[list(bulk_load_ids.values()).index(feat_id)]
                    self.update_qa_layer_attribute(qa_lyr, qa_feat_id, "Fixed", "Geometry edited")

    @pyqtSlot(list, str)
    def liqa_on_delete_outline_saved(self, ids, del_reason):
        """Update LIQA when feature deleted"""
        for qa_lyr in self.find_qa_layer():
            if not self.bulk_load_id_field_exists(qa_lyr):
                continue
            bulk_load_ids = self.get_bulk_load_ids(qa_lyr)
            for feat_id in ids:
                if feat_id in list(bulk_load_ids.values()):
                    qa_feat_id = list(bulk_load_ids.keys())[list(bulk_load_ids.values()).index(feat_id)]
                    self.update_qa_layer_attribute(qa_lyr, qa_feat_id, "Fixed", "Deleted- {}".format(del_reason))

    def bulk_load_id_field_exists(self, qa_layer):
        field_names = [field.name() for field in qa_layer.fields()]
        if "bulk_load_" in field_names:
            return True
        return False

    def find_qa_layer(self):
        """find qa layer"""
        for layer in QgsProject.instance().mapLayers().values():
            if layer.name().startswith("qa_"):
                yield layer

    def get_bulk_load_ids(self, qa_layer):
        """return bulk load ids"""
        bulk_load_ids = {}
        for feat in qa_layer.getFeatures():
            bulk_load_ids[feat.id()] = feat["bulk_load_"]
        return bulk_load_ids

    def update_qa_layer_attribute(self, qa_lyr, qa_id, error_status, comment):
        """update qa layer attributes"""
        qa_lyr.startEditing()
        qa_lyr.changeAttributeValue(qa_id, 1, error_status, True)
        qa_lyr.changeAttributeValue(qa_id, 2, comment, True)
        qa_lyr.commitChanges()
Exemplo n.º 27
0
class GwGo2EpaButton(GwAction):
    """ Button 23: Go2epa """
    def __init__(self, icon_path, action_name, text, toolbar, action_group):

        super().__init__(icon_path, action_name, text, toolbar, action_group)
        self.project_type = global_vars.project_type
        self.epa_options_list = []

    def clicked_event(self):

        self._open_go2epa()

    def check_result_id(self):
        """ Check if selected @result_id already exists """

        self.dlg_go2epa.txt_result_name.setStyleSheet(None)

    # region private functions

    def _open_go2epa(self):

        self._go2epa()

    def _go2epa(self):
        """ Button 23: Open form to set INP, RPT and project """

        # Show form in docker?
        tools_gw.init_docker('qgis_form_docker')

        # Create dialog
        self.dlg_go2epa = GwGo2EpaUI()
        tools_gw.load_settings(self.dlg_go2epa)
        self._load_user_values()
        if self.project_type in 'ws':
            self.dlg_go2epa.chk_export_subcatch.setVisible(False)

        # Set signals
        self._set_signals()
        self.dlg_go2epa.btn_cancel.setEnabled(False)

        # Disable tab log
        tools_gw.disable_tab_log(self.dlg_go2epa)

        # Set shortcut keys
        self.dlg_go2epa.key_escape.connect(partial(tools_gw.close_docker))

        self.dlg_go2epa.btn_hs_ds.clicked.connect(
            partial(self._sector_selection))

        # Check OS and enable/disable checkbox execute EPA software
        if sys.platform != "win32":
            tools_qt.set_checked(self.dlg_go2epa, self.dlg_go2epa.chk_exec,
                                 False)
            self.dlg_go2epa.chk_exec.setEnabled(False)
            self.dlg_go2epa.chk_exec.setText(
                'Execute EPA software (Runs only on Windows)')

        self._set_completer_result(self.dlg_go2epa.txt_result_name,
                                   'v_ui_rpt_cat_result', 'result_id')
        self.check_result_id()
        if global_vars.session_vars['dialog_docker']:
            tools_qt.manage_translation('go2epa', self.dlg_go2epa)
            tools_gw.docker_dialog(self.dlg_go2epa)
            self.dlg_go2epa.btn_close.clicked.disconnect()
            self.dlg_go2epa.btn_close.clicked.connect(
                partial(tools_gw.close_docker, option_name='position'))
        else:
            tools_gw.open_dialog(self.dlg_go2epa, dlg_name='go2epa')

    def _set_signals(self):

        self.dlg_go2epa.btn_cancel.clicked.connect(self._cancel_task)
        self.dlg_go2epa.txt_result_name.textChanged.connect(
            partial(self.check_result_id))
        self.dlg_go2epa.btn_file_inp.clicked.connect(
            self._go2epa_select_file_inp)
        self.dlg_go2epa.btn_file_rpt.clicked.connect(
            self._go2epa_select_file_rpt)
        self.dlg_go2epa.btn_accept.clicked.connect(self._go2epa_accept)
        self.dlg_go2epa.btn_close.clicked.connect(
            partial(tools_gw.close_dialog, self.dlg_go2epa))
        self.dlg_go2epa.rejected.connect(
            partial(tools_gw.close_dialog, self.dlg_go2epa))
        self.dlg_go2epa.btn_options.clicked.connect(self._go2epa_options)
        self.dlg_go2epa.mainTab.currentChanged.connect(
            partial(self._manage_btn_accept))

    def _manage_btn_accept(self, index):
        """
        Disable btn_accept when on tab info log and/or if go2epa_task is active
            :param index: tab index (passed by signal)
        """

        if index == 1:
            self.dlg_go2epa.btn_accept.setEnabled(False)
        else:
            # Disable if task is active, enabled otherwise
            if hasattr(self, 'go2epa_task') and self.go2epa_task is not None:
                try:
                    if self.go2epa_task.isActive():
                        self.dlg_go2epa.btn_accept.setEnabled(False)
                        return
                except RuntimeError:
                    pass
            self.dlg_go2epa.btn_accept.setEnabled(True)

    def _check_inp_chk(self, file_inp):

        if file_inp is None:
            msg = "Select valid INP file"
            tools_qgis.show_warning(msg, parameter=str(file_inp))
            return False

        return True

    def _check_rpt(self):

        file_inp = tools_qt.get_text(self.dlg_go2epa,
                                     self.dlg_go2epa.txt_file_inp)
        file_rpt = tools_qt.get_text(self.dlg_go2epa,
                                     self.dlg_go2epa.txt_file_rpt)

        # Control execute epa software
        if tools_qt.is_checked(self.dlg_go2epa, self.dlg_go2epa.chk_exec):
            if not self._check_inp_chk(file_inp):
                return False

            if file_rpt is None:
                msg = "Select valid RPT file"
                tools_qgis.show_warning(msg, parameter=str(file_rpt))
                return False

            if not tools_qt.is_checked(self.dlg_go2epa,
                                       self.dlg_go2epa.chk_export):
                if not os.path.exists(file_inp):
                    msg = "File INP not found"
                    tools_qgis.show_warning(msg, parameter=str(file_inp))
                    return False

        return True

    def _check_fields(self):

        file_inp = tools_qt.get_text(self.dlg_go2epa,
                                     self.dlg_go2epa.txt_file_inp)
        file_rpt = tools_qt.get_text(self.dlg_go2epa,
                                     self.dlg_go2epa.txt_file_rpt)
        result_name = tools_qt.get_text(self.dlg_go2epa,
                                        self.dlg_go2epa.txt_result_name, False,
                                        False)

        # Check if at least one process is selected
        export_checked = tools_qt.is_checked(self.dlg_go2epa,
                                             self.dlg_go2epa.chk_export)
        exec_checked = tools_qt.is_checked(self.dlg_go2epa,
                                           self.dlg_go2epa.chk_exec)
        import_result_checked = tools_qt.is_checked(
            self.dlg_go2epa, self.dlg_go2epa.chk_import_result)

        if not export_checked and not exec_checked and not import_result_checked:
            msg = "You need to select at least one process"
            tools_qt.show_info_box(msg, title="Go2Epa")
            return False

        # Control export INP
        if export_checked:
            if not self._check_inp_chk(file_inp):
                return False

        # Control execute epa software
        if not self._check_rpt():
            return False

        # Control import result
        if import_result_checked:
            if file_rpt is None:
                msg = "Select valid RPT file"
                tools_qgis.show_warning(msg, parameter=str(file_rpt))
                return False
            if not tools_qt.is_checked(self.dlg_go2epa,
                                       self.dlg_go2epa.chk_exec):
                if not os.path.exists(file_rpt):
                    msg = "File RPT not found"
                    tools_qgis.show_warning(msg, parameter=str(file_rpt))
                    return False
            else:
                if not self._check_rpt():
                    return False

        # Control result name
        if result_name == '':
            self.dlg_go2epa.txt_result_name.setStyleSheet(
                "border: 1px solid red")
            msg = "This parameter is mandatory. Please, set a value"
            tools_qt.show_details(msg, title="Rpt fail", inf_text=None)
            return False

        self.dlg_go2epa.txt_result_name.setStyleSheet(None)

        sql = (f"SELECT result_id FROM rpt_cat_result "
               f"WHERE result_id = '{result_name}' LIMIT 1")
        row = tools_db.get_row(sql)
        if import_result_checked and not export_checked and not exec_checked:
            if not row:
                msg = "Result name not found. It's not possible to import RPT file into database"
                tools_qt.show_info_box(msg, "Import RPT file")
                return False
        else:
            if row:
                msg = "Result name already exists, do you want overwrite?"
                answer = tools_qt.show_question(msg, title="Alert")
                if not answer:
                    return False

        return True

    def _load_user_values(self):
        """ Load QGIS settings related with file_manager """

        self.dlg_go2epa.txt_result_name.setMaxLength(16)
        self.result_name = tools_gw.get_config_parser('btn_go2epa',
                                                      'go2epa_RESULT_NAME',
                                                      "user", "session")
        self.dlg_go2epa.txt_result_name.setText(self.result_name)
        self.file_inp = tools_gw.get_config_parser('btn_go2epa',
                                                   'go2epa_FILE_INP', "user",
                                                   "session")
        self.dlg_go2epa.txt_file_inp.setText(self.file_inp)
        self.file_rpt = tools_gw.get_config_parser('btn_go2epa',
                                                   'go2epa_FILE_RPT', "user",
                                                   "session")
        self.dlg_go2epa.txt_file_rpt.setText(self.file_rpt)

        value = tools_gw.get_config_parser('btn_go2epa', 'go2epa_chk_INP',
                                           "user", "session")
        tools_qt.set_checked(self.dlg_go2epa, self.dlg_go2epa.chk_export,
                             value)
        value = tools_gw.get_config_parser('btn_go2epa', 'go2epa_chk_UD',
                                           "user", "session")
        tools_qt.set_checked(self.dlg_go2epa,
                             self.dlg_go2epa.chk_export_subcatch, value)
        value = tools_gw.get_config_parser('btn_go2epa', 'go2epa_chk_EPA',
                                           "user", "session")
        tools_qt.set_checked(self.dlg_go2epa, self.dlg_go2epa.chk_exec, value)
        value = tools_gw.get_config_parser('btn_go2epa', 'go2epa_chk_RPT',
                                           "user", "session")
        tools_qt.set_checked(self.dlg_go2epa,
                             self.dlg_go2epa.chk_import_result, value)

    def _save_user_values(self):
        """ Save QGIS settings related with file_manager """

        txt_result_name = f"{tools_qt.get_text(self.dlg_go2epa, 'txt_result_name', return_string_null=False)}"
        tools_gw.set_config_parser('btn_go2epa', 'go2epa_RESULT_NAME',
                                   f"{txt_result_name}")
        txt_file_inp = f"{tools_qt.get_text(self.dlg_go2epa, 'txt_file_inp', return_string_null=False)}"
        tools_gw.set_config_parser('btn_go2epa', 'go2epa_FILE_INP',
                                   f"{txt_file_inp}")
        txt_file_rpt = f"{tools_qt.get_text(self.dlg_go2epa, 'txt_file_rpt', return_string_null=False)}"
        tools_gw.set_config_parser('btn_go2epa', 'go2epa_FILE_RPT',
                                   f"{txt_file_rpt}")
        chk_export = f"{tools_qt.is_checked(self.dlg_go2epa, self.dlg_go2epa.chk_export)}"
        tools_gw.set_config_parser('btn_go2epa', 'go2epa_chk_INP',
                                   f"{chk_export}")
        chk_export_subcatch = f"{tools_qt.is_checked(self.dlg_go2epa, self.dlg_go2epa.chk_export_subcatch)}"
        tools_gw.set_config_parser('btn_go2epa', 'go2epa_chk_UD',
                                   f"{chk_export_subcatch}")
        chk_exec = f"{tools_qt.is_checked(self.dlg_go2epa, self.dlg_go2epa.chk_exec)}"
        tools_gw.set_config_parser('btn_go2epa', 'go2epa_chk_EPA',
                                   f"{chk_exec}")
        chk_import_result = f"{tools_qt.is_checked(self.dlg_go2epa, self.dlg_go2epa.chk_import_result)}"
        tools_gw.set_config_parser('btn_go2epa', 'go2epa_chk_RPT',
                                   f"{chk_import_result}")

    def _sector_selection(self):
        """ Load the tables in the selection form """

        # Get class Selector from selector.py
        go2epa_selector = GwSelector()

        # Create the dialog
        dlg_selector = GwSelectorUi()
        tools_gw.load_settings(dlg_selector)

        # Create the common signals
        go2epa_selector.get_selector(dlg_selector,
                                     '"selector_basic"',
                                     current_tab='tab_dscenario')
        tools_gw.save_current_tab(dlg_selector, dlg_selector.main_tab, 'basic')

        # Open form
        if global_vars.session_vars['dialog_docker']:
            # Set signals when have docker form
            dlg_selector.btn_close.clicked.connect(
                partial(tools_gw.docker_dialog, self.dlg_go2epa))
            dlg_selector.btn_close.clicked.connect(
                partial(self._manage_form_settings, 'restore'))
            # Save widgets settings from go2epa form
            self._manage_form_settings('save')
            # Open form
            tools_gw.docker_dialog(dlg_selector)
        else:
            # Set signals when have not docker form
            dlg_selector.btn_close.clicked.connect(
                partial(tools_gw.close_dialog, dlg_selector))
            # Open form
            tools_gw.open_dialog(dlg_selector)

    def _manage_form_settings(self, action):

        if action == 'save':
            # Get widgets form values
            self.txt_result_name = tools_qt.get_text(
                self.dlg_go2epa, self.dlg_go2epa.txt_result_name)
            self.chk_export = self.dlg_go2epa.chk_export.isChecked()
            self.chk_export_subcatch = self.dlg_go2epa.chk_export_subcatch.isChecked(
            )
            self.txt_file_inp = tools_qt.get_text(self.dlg_go2epa,
                                                  self.dlg_go2epa.txt_file_inp)
            self.chk_exec = self.dlg_go2epa.chk_exec.isChecked()
            self.txt_file_rpt = tools_qt.get_text(self.dlg_go2epa,
                                                  self.dlg_go2epa.txt_file_rpt)
            self.chk_import_result = self.dlg_go2epa.chk_import_result.isChecked(
            )
        elif action == 'restore':
            # Set widgets form values
            if self.txt_result_name is not 'null':
                tools_qt.set_widget_text(self.dlg_go2epa,
                                         self.dlg_go2epa.txt_result_name,
                                         self.txt_result_name)
            if self.chk_export is not 'null':
                tools_qt.set_widget_text(self.dlg_go2epa,
                                         self.dlg_go2epa.chk_export,
                                         self.chk_export)
            if self.chk_export_subcatch is not 'null':
                tools_qt.set_widget_text(self.dlg_go2epa,
                                         self.dlg_go2epa.chk_export_subcatch,
                                         self.chk_export_subcatch)
            if self.txt_file_inp is not 'null':
                tools_qt.set_widget_text(self.dlg_go2epa,
                                         self.dlg_go2epa.txt_file_inp,
                                         self.txt_file_inp)
            if self.chk_exec is not 'null':
                tools_qt.set_widget_text(self.dlg_go2epa,
                                         self.dlg_go2epa.chk_exec,
                                         self.chk_exec)
            if self.txt_file_rpt is not 'null':
                tools_qt.set_widget_text(self.dlg_go2epa,
                                         self.dlg_go2epa.txt_file_rpt,
                                         self.txt_file_rpt)
            if self.chk_import_result is not 'null':
                tools_qt.set_widget_text(self.dlg_go2epa,
                                         self.dlg_go2epa.chk_import_result,
                                         self.chk_import_result)

    def _go2epa_select_file_inp(self):
        """ Select INP file """

        self.file_inp = tools_qt.get_text(self.dlg_go2epa,
                                          self.dlg_go2epa.txt_file_inp)
        # Set default value if necessary
        if self.file_inp is None or self.file_inp == '':
            self.file_inp = global_vars.plugin_dir

        # Get directory of that file
        folder_path = os.path.dirname(self.file_inp)
        if not os.path.exists(folder_path):
            folder_path = os.path.dirname(__file__)
        os.chdir(folder_path)
        message = tools_qt.tr("Select INP file")
        widget_is_checked = tools_qt.is_checked(self.dlg_go2epa,
                                                self.dlg_go2epa.chk_export)
        if widget_is_checked:
            self.file_inp, filter_ = QFileDialog.getSaveFileName(
                None, message, "", '*.inp')
        else:
            self.file_inp, filter_ = QFileDialog.getOpenFileName(
                None, message, "", '*.inp')
        tools_qt.set_widget_text(self.dlg_go2epa, self.dlg_go2epa.txt_file_inp,
                                 self.file_inp)

    def _go2epa_select_file_rpt(self):
        """ Select RPT file """

        # Set default value if necessary
        if self.file_rpt is None or self.file_rpt == '':
            self.file_rpt = global_vars.plugin_dir

        # Get directory of that file
        folder_path = os.path.dirname(self.file_rpt)
        if not os.path.exists(folder_path):
            folder_path = os.path.dirname(__file__)
        os.chdir(folder_path)
        message = tools_qt.tr("Select RPT file")
        widget_is_checked = tools_qt.is_checked(self.dlg_go2epa,
                                                self.dlg_go2epa.chk_export)
        if widget_is_checked:
            self.file_rpt, filter_ = QFileDialog.getSaveFileName(
                None, message, "", '*.rpt')
        else:
            self.file_rpt, filter_ = QFileDialog.getOpenFileName(
                None, message, "", '*.rpt')
        tools_qt.set_widget_text(self.dlg_go2epa, self.dlg_go2epa.txt_file_rpt,
                                 self.file_rpt)

    def _go2epa_accept(self):
        """ Save INP, RPT and result name"""

        # Manage if task is already running
        if hasattr(self, 'go2epa_task') and self.go2epa_task is not None:
            try:
                if self.go2epa_task.isActive():
                    message = "Go2Epa task is already active!"
                    tools_qgis.show_warning(message)
                    return
            except RuntimeError:
                pass

        # Save user values
        self._save_user_values()

        self.dlg_go2epa.txt_infolog.clear()
        self.dlg_go2epa.txt_file_rpt.setStyleSheet(None)
        status = self._check_fields()
        if status is False:
            return

        # Get widgets values
        self.result_name = tools_qt.get_text(self.dlg_go2epa,
                                             self.dlg_go2epa.txt_result_name,
                                             False, False)
        self.export_inp = tools_qt.is_checked(self.dlg_go2epa,
                                              self.dlg_go2epa.chk_export)
        self.export_subcatch = tools_qt.is_checked(
            self.dlg_go2epa, self.dlg_go2epa.chk_export_subcatch)
        self.file_inp = tools_qt.get_text(self.dlg_go2epa,
                                          self.dlg_go2epa.txt_file_inp)
        self.exec_epa = tools_qt.is_checked(self.dlg_go2epa,
                                            self.dlg_go2epa.chk_exec)
        self.file_rpt = tools_qt.get_text(self.dlg_go2epa,
                                          self.dlg_go2epa.txt_file_rpt)
        self.import_result = tools_qt.is_checked(
            self.dlg_go2epa, self.dlg_go2epa.chk_import_result)

        # Check for sector selector
        if self.export_inp:
            sql = "SELECT sector_id FROM selector_sector WHERE sector_id > 0 LIMIT 1"
            row = tools_db.get_row(sql)
            if row is None:
                msg = "You need to select some sector"
                tools_qt.show_info_box(msg)
                return

        self.dlg_go2epa.btn_accept.setEnabled(False)
        self.dlg_go2epa.btn_cancel.setEnabled(True)

        # Set background task 'Go2Epa'
        description = f"Go2Epa"
        self.go2epa_task = GwEpaFileManager(description, self)
        QgsApplication.taskManager().addTask(self.go2epa_task)
        QgsApplication.taskManager().triggerTask(self.go2epa_task)

    def _cancel_task(self):

        if hasattr(self, 'go2epa_task'):
            self.go2epa_task.cancel()

    def _set_completer_result(self, widget, viewname, field_name):
        """ Set autocomplete of widget 'feature_id'
            getting id's from selected @viewname
        """

        # Adding auto-completion to a QLineEdit
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        widget.setCompleter(self.completer)
        model = QStringListModel()

        sql = f"SELECT {field_name} FROM {viewname}"
        rows = tools_db.get_rows(sql)

        if rows:
            for i in range(0, len(rows)):
                aux = rows[i]
                rows[i] = str(aux[0])

            model.setStringList(rows)
            self.completer.setModel(model)

    def _go2epa_options(self):
        """ Button 23: Open form to set INP, RPT and project """

        # Clear list
        self.epa_options_list = []

        # Create dialog
        self.dlg_go2epa_options = GwGo2EpaOptionsUi()
        tools_gw.load_settings(self.dlg_go2epa_options)

        form = '"formName":"epaoptions"'
        body = tools_gw.create_body(form=form)
        json_result = tools_gw.execute_procedure('gw_fct_getconfig', body)
        if not json_result or json_result['status'] == 'Failed':
            return False

        tools_gw.build_dialog_options(self.dlg_go2epa_options,
                                      json_result['body']['form']['formTabs'],
                                      0, self.epa_options_list)
        grbox_list = self.dlg_go2epa_options.findChildren(QGroupBox)
        for grbox in grbox_list:
            widget_list = grbox.findChildren(QWidget)
            if len(widget_list) == 0:
                grbox.setVisible(False)
            else:
                layout_list = grbox.findChildren(QGridLayout)
                for lyt in layout_list:
                    spacer = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                         QSizePolicy.Expanding)
                    lyt.addItem(spacer)

        # Event on change from combo parent
        self._get_event_combo_parent(json_result)
        self.dlg_go2epa_options.btn_accept.clicked.connect(
            partial(self._update_values, self.epa_options_list))
        self.dlg_go2epa_options.btn_cancel.clicked.connect(
            partial(tools_gw.close_dialog, self.dlg_go2epa_options))
        self.dlg_go2epa_options.rejected.connect(
            partial(tools_gw.close_dialog, self.dlg_go2epa_options))

        tools_gw.open_dialog(self.dlg_go2epa_options,
                             dlg_name='go2epa_options')

    def _update_values(self, _json):

        my_json = json.dumps(_json)
        form = '"formName":"epaoptions"'
        extras = f'"fields":{my_json}'
        body = tools_gw.create_body(form=form, extras=extras)
        json_result = tools_gw.execute_procedure('gw_fct_setconfig', body)
        if not json_result or json_result['status'] == 'Failed':
            return False

        tools_gw.manage_current_selections_docker(json_result)

        message = "Values has been updated"
        tools_qgis.show_info(message)
        # Close dialog
        tools_gw.close_dialog(self.dlg_go2epa_options)

    def _get_event_combo_parent(self, complet_result):

        for field in complet_result['body']['form']['formTabs'][0]["fields"]:
            if field['isparent']:
                widget = self.dlg_go2epa_options.findChild(
                    QComboBox, field['widgetname'])
                if widget:
                    widget.currentIndexChanged.connect(
                        partial(self._fill_child, self.dlg_go2epa_options,
                                widget))

    def _fill_child(self, dialog, widget):

        combo_parent = widget.objectName()
        combo_id = tools_qt.get_combo_value(dialog, widget)
        # TODO cambiar por gw_fct_getchilds then unified with tools_gw.get_child if posible
        json_result = tools_gw.execute_procedure(
            'gw_fct_getcombochilds',
            f"'epaoptions', '', '', '{combo_parent}', '{combo_id}', ''")
        if not json_result or json_result['status'] == 'Failed':
            return False

        for combo_child in json_result['fields']:
            if combo_child is not None:
                tools_gw.manage_combo_child(dialog, widget, combo_child)