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)
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))
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)
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)
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)
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)
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)
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)
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
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)
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")
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
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)
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)
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()
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()
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()
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
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()
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)