def test_exec_(self): engine = create_alchemy_engine() self.serializer.load() profile = self.config.profile('Rural') party_ent = profile.social_tenure.party #Map entity to SQLAlchemy class party_cls = entity_model(party_ent) party = party_cls() savings_col = party_ent.column('savings') savings_ent = savings_col.value_list #Create savings value list object savings_cls = entity_model(savings_ent) savings_obj = savings_cls() savings = [] res = savings_obj.queryObject().all() savings = [r for r in res] #Set attributes party.number = 'FK09' party.first_name = 'Jermaine' party.last_name = 'Jackson' #Append all savings options setattr(party, 'ru_check_saving_options_collection', savings) #party.save() #Hardwire result read_result = False self.assertTrue(read_result)
def _update_entities_and_models(self): """ Update the entity objects and database models for the relevant authority. """ if not self._relv_auth_entity: self._relv_auth_entity = self.curr_p.entity( self._rel_auth_entity_name) if not self._relevant_auth_lookup: self._relevant_auth_lookup = self.curr_p.entity( self._rel_auth_chk_entity_name) if not self._region_lookup: self._region_lookup = self.curr_p.entity(self._rgn_chk_entity_name) if not self._reg_div_lookup: self._reg_div_lookup = self.curr_p.entity( self._reg_div_chk_entity_name) # Check if entities exist if self._relv_auth_entity is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity'), self.tr("The relevant authority entity is missing in the " "profile.")) self.reject() elif self._relevant_auth_lookup is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity Lookup'), self.tr( "The relevant authority entity lookup is missing in the " "profile.")) self.reject() elif self._region_lookup is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity Lookup'), self.tr( "The relevant authority entity lookup is missing in the " "profile.")) self.reject() elif self._reg_div_lookup is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity Lookup'), self.tr( "The relevant authority entity lookup is missing in the " "profile.")) self.reject() # Entity models if not self._relevant_auth_type_model: self._relevant_auth_type_model = entity_model( self._relevant_auth_lookup) if not self._region_lookup_model: self._region_lookup_model = entity_model(self._region_lookup) if not self._relevant_auth_model: self._relevant_auth_model = entity_model(self._relv_auth_entity) if not self._regdiv_lookup_model: self._regdiv_lookup_model = entity_model(self._reg_div_lookup)
def update_document_types(self, document_table): # Updates the types of documents for the specified supporting doc table self.cbo_document_type.clear() if not document_table: return # Get list of supporting document entities in the current profile s_doc_entities = self._curr_profile.supporting_document_entities() selected_doc_entity = [ de for de in s_doc_entities if de.name == document_table ] if len(selected_doc_entity) == 0: return doc_type_vl = selected_doc_entity[0].document_type_entity # Query id values from the document type lookup table lk_cls = entity_model(doc_type_vl, entity_only=True) lk_obj = lk_cls() res = lk_obj.queryObject().filter().all() for r in res: self.cbo_document_type.addItem(r.value, r.id)
def __init__(self, config, formatter=None, parent=None): QWidget.__init__(self, parent) EntitySearchItem.__init__(self, formatter) self.setupUi(self) self.tbSTRViewEntity.setTabIcon(0, GuiUtils.get_icon('filter.png')) self.tbSTRViewEntity.setTabIcon(1, GuiUtils.get_icon('period_blue.png')) self.config = config self.setConfigOptions() self.curr_profile = current_profile() self.social_tenure = self.curr_profile.social_tenure self.str_model = entity_model(self.social_tenure) # Model for storing display and actual mapping values self._completer_model = None self._proxy_completer_model = None # Hook up signals self.cboFilterCol.currentIndexChanged.connect( self._on_column_index_changed) self.init_validity_dates() self.validity_from_date.dateChanged.connect(self.set_minimum_to_date) self.validity.setDisabled(True) self.init_validity_checkbox()
def __init__(self, model, entity): ''' :param model: Callable (new instances) or instance (existing instance for updating) of STDM model. ''' if callable(model): self._model = model() self._mode = SAVE else: self._model = model self._mode = UPDATE self.entity = entity self._attrMappers = [] self._attr_mapper_collection = {} self._dirtyTracker = ControlDirtyTrackerCollection() self._notifBar = None self.is_valid = False self.saved_model = None # Get document objects self.entity_model = entity_model(entity) self.entity_model_obj = self.entity_model() #Initialize notification bar if hasattr(self, "vlNotification"): self._notifBar = NotificationBar(self.vlNotification)
def add_str_type_headers(self): """ Adds headers data for QTableView columns. The headers comes from the selected entity. :param entity: The entity for which the table header is created for. :return: List of Table headers :rtype: List """ if not self.selected_party is None: self.party_1 = self.selected_party db_model = entity_model(self.party_1, True) headers = [] # Load headers if db_model is not None: # Append str type if the method # is used for str_type str_type_header = QApplication.translate('STRType', 'Social Tenure Type') share_header = QApplication.translate('STRType', 'Share ') # First (ID) column will always be hidden headers.append(str_type_header) headers.append(share_header) display_columns = entity_display_columns(self.party_1, True) for col in display_columns.values(): headers.append(col) return headers
def __init__(self): """ Initialize the STR component class. """ super(ComponentUtility, self).__init__() self.current_profile = current_profile() self.social_tenure = self.current_profile.social_tenure self.parties = self.social_tenure.parties self.spatial_units = self.social_tenure.spatial_units self.str_model = None self.str_doc_model = None if len(self.parties) > 0: self.party_1 = self.parties[0] if len(self.spatial_units) > 0: self.spatial_unit_1 = self.spatial_units[0] try: self.str_model, self.str_doc_model = entity_model( self.social_tenure, False, True ) except Exception as ex: QMessageBox.critical( iface.mainWindow(), QApplication.translate('ComponentUtility', 'Database Error'), str(ex) )
def feature_to_model(self, feature_id): """ Converts feature to db model. :param feature_id: The feature id :type feature_id: Integer :return: The model and number of columns with data. :rtype: Tuple """ ent_model = entity_model(self.entity) model_obj = ent_model() iterator = self.layer.getFeatures( QgsFeatureRequest().setFilterFid(feature_id)) feature = next(iterator) field_names = [field.name() for field in self.layer.fields()] attribute = feature.attributes() if isinstance(attribute[0], QgsField): return None, 0 mapped_data = OrderedDict(list(zip(field_names, feature.attributes()))) col_with_data = [] for col, value in mapped_data.items(): if col == 'id': continue if value is None: continue if value == NULL: continue setattr(model_obj, col, value) col_with_data.append(col) return model_obj, len(col_with_data)
def __init__(self, model=None, entity=None, parent=None): """ :param model: Callable (new instances) or instance (existing instance for updating) of STDM model. """ super().__init__(parent) if callable(model): self._model = model() self._mode = SAVE else: self._model = model self._mode = UPDATE self.entity = entity self._attrMappers = [] self._attr_mapper_collection = {} self._dirtyTracker = ControlDirtyTrackerCollection() self._notifBar = None self.is_valid = False self.saved_model = None # Get document objects self.entity_model = entity_model(entity) self.entity_model_obj = self.entity_model() # Flag to indicate whether to close the widget or dialog once model has been submitted # self.closeOnSubmit = True # Initialize notification bar if hasattr(self, "vlNotification"): self._notifBar = NotificationBar(self.vlNotification)
def add_str_type_headers(self): """ Adds headers data for QTableView columns. The headers comes from the selected entity. :param entity: The entity for which the table header is created for. :return: List of Table headers :rtype: List """ if not self.selected_party is None: self.party_1 = self.selected_party db_model = entity_model(self.party_1, True) headers = [] # Load headers if db_model is not None: # Append str type if the method # is used for str_type str_type_header = QApplication.translate( 'STRType', 'Social Tenure Type' ) share_header = QApplication.translate( 'STRType', 'Share ' ) # First (ID) column will always be hidden headers.append(str_type_header) headers.append(share_header) display_columns = entity_display_columns(self.party_1, True) for col in display_columns.values(): headers.append(col) return headers
def feature_to_model(self, feature_id): """ Converts feature to db model. :param feature_id: The feature id :type feature_id: Integer :return: The model and number of columns with data. :rtype: Tuple """ ent_model = entity_model(self.entity) model_obj = ent_model() iterator = self.layer.getFeatures( QgsFeatureRequest().setFilterFid(feature_id)) feature = next(iterator) field_names = [field.name() for field in self.layer.pendingFields()] attribute = feature.attributes() if isinstance(attribute[0], QgsField): return None, 0 mapped_data = OrderedDict(zip(field_names, feature.attributes())) col_with_data = [] for col, value in mapped_data.iteritems(): if col == 'id': continue if value is None: continue if value == NULL: continue setattr(model_obj, col, value) col_with_data.append(col) return model_obj, len(col_with_data)
def __init__(self, entity_document, document_model, parent=None): QObject.__init__(self, parent) self.containers = OrderedDict() self._canEdit = True self.document_model = document_model self.curr_profile = current_profile() self.entity_supporting_doc = entity_document.document_type_entity check_doc_type_model = entity_model(self.entity_supporting_doc) doc_type_obj = check_doc_type_model() doc_type_list = doc_type_obj.queryObject().all() self.doc_types = [(doc.id, doc.value) for doc in doc_type_list] self.doc_types = dict(self.doc_types) for id in self.doc_types.keys(): document_type_class[id] = self.document_model #Container for document references based on their unique IDs self._docRefs = [] #Set default manager for document viewing self._doc_view_manager = DocumentViewManager(self.parent_widget()) self.doc_type_mapping = OrderedDict() for id, value in self.doc_types.iteritems(): self.doc_type_mapping[id] = value
def _set_document_type_id(self): #Load document id based on the name entity = self.entity() if entity is None: return vl_cls = entity_model( entity.supporting_doc.document_type_entity, entity_only=True ) vl_obj = vl_cls() res = vl_obj.queryObject().all() for r in res: if r.value == self._dest_col: self._document_type_id = r.id break if not entity.supports_documents: msg = self.tr('The selected column does not correspond to a ' 'document type.\nHence, this translator is not ' 'applicable.') title = self.tr('Invalid Document Type') QMessageBox.critical(self, title, msg) #Close dialog self.reject()
def _entity_config_from_profile(self, table_name, short_name): """ Creates an EntityConfig object from the table name. :param table_name: Name of the database table. :type table_name: str :return: Entity configuration object. :rtype: EntityConfig """ table_display_name = format_name(short_name) entity = self.curr_profile.entity_by_name(table_name) model = entity_model(entity) if model is not None: #Entity configuration entity_cfg = EntityConfiguration() entity_cfg.Title = table_display_name entity_cfg.STRModel = model entity_cfg.data_source_name = table_name # Load filter and display columns # using only those which are of # numeric/varchar type searchable_columns = entity_searchable_columns(entity) display_columns = entity_display_columns(entity) for c in searchable_columns: if c != 'id': entity_cfg.filterColumns[c] = format_name(c) for c in display_columns: if c != 'id': entity_cfg.displayColumns[c] = format_name(c) return entity_cfg else: return None
def entity_id_to_attr(entity, attr, id): """ Converts an entity column id to another column value of the same record. :param entity: Entity :type entity: Class :param attr: Column name :type attr: String :param id: Id of the entity :type id: Integer :return: a column value if a match found :rtype: Integer or String """ doc_type_model = entity_model(entity) doc_type_obj = doc_type_model() result = doc_type_obj.queryObject().filter( doc_type_model.id == id ).first() if result is not None: attr_val = getattr( result, attr, None ) else: attr_val = id return attr_val
def certificate_postprocess(plot, plots): """ Updates the certificate details and removes the layers after generation of the certificate. """ cert_number = pg_certificate_number() user_name = stdm.data.app_dbconn.User.UserName curr_datetime = QDateTime.currentDateTime().toPyDateTime() curr_profile = current_profile() if not current_profile: return cert_entity = curr_profile.entity('Certificate') if not cert_entity: return cert_model = entity_model(cert_entity) cert_obj = cert_model() cert_obj.plot_id = plot.id cert_obj.scheme_id = plot.scheme_id cert_obj.certificate_number = cert_number cert_obj.production_date = curr_datetime cert_obj.prod_user = user_name cert_obj.save() # Remove certificate plot layer layers = QgsMapLayerRegistry.instance().mapLayersByName(CERTIFICATE_PLOT) if len(layers) > 0: QgsMapLayerRegistry.instance().removeMapLayer(layers[0])
def referencing_column_value(self, field_values): """ Gets a list of lookup objects corresponding to the values extracted from the source using the separator. :param field_values: Pair of field names and corresponding values i.e. {field1:value1, field2:value2, field3:value3...} :type field_values: dict :return: One or more object instances of lookup value objects. :rtype: list """ if len(self._input_referenced_columns) == 0: return None num_cols = len(self._input_referenced_columns) cols_iter = itertools.islice( list(self._input_referenced_columns.items()), num_cols ) # Tuple of one or two items.The format is - # (source primary enum column, enum table primary column) enum_cols_pairs = list(cols_iter) source_primary_col, enum_primary_col = enum_cols_pairs[0] delimited_source_value = field_values.get(source_primary_col, None) if not delimited_source_value: return IgnoreType() if not isinstance(delimited_source_value, str): return IgnoreType() # Get the lookup values used in the multiple select dest_col_obj = self.entity.column(enum_primary_col) if not dest_col_obj: return IgnoreType() # Get lookup entity and corresponding SQLAlchemy class lk_entity = dest_col_obj.value_list lookup_mapped_cls = entity_model(lk_entity) # Lookup objects corresponding to the values in the source string lk_objs = [] lk_vals = delimited_source_value.split(self._separator) # Get the lookup objects corresponding to the separated source values for kv in lk_vals: kv = kv.strip() if kv: # Get corresponding lookup value object based on a # case-insensitive search lookup_obj = self._db_session.query(lookup_mapped_cls).filter( func.lower(lookup_mapped_cls.value) == func.lower(kv) ).first() if lookup_obj: lk_objs.append(lookup_obj) return lk_objs
def _plot_staging_table_model(self): # Returns the SQLAlchemy class corresponding to the staging table. table_name = 'cb_staging_holder_plot' curr_profile = current_profile() staging_table_entity = curr_profile.entity_by_name(table_name) if not staging_table_entity: return None return entity_model(staging_table_entity)
def parent_entity_model(self): """ :return: Returns the database model corresponding to the parent table of the relation defined by this column. Please note that the database model will not contain relationship configurations in its attributes. :rtype: object """ entity = self.column.entity_relation.parent return entity_model(entity, entity_only=True)
def feature_STR_link(self, feature_id): STR_model = entity_model( self.current_profile.social_tenure ) model_obj = STR_model() result = model_obj.queryObject().filter( STR_model.spatial_unit_id == feature_id ).all() return result
def doc_tab_data(self): """ Sets the document types in the social tenure entity. """ doc_entity = self.social_tenure. \ supporting_doc.document_type_entity doc_type_model = entity_model(doc_entity) docs = doc_type_model() doc_type_list = docs.queryObject().all() self.doc_types = [(doc.id, doc.value) for doc in doc_type_list] self.doc_types = OrderedDict(self.doc_types)
def dbmodel_from_entity(self): """ Format model attributes from passed entity attributes :return: """ if self.entity_has_supporting_docs(): entity_object, self.doc_model = entity_model(self.entity, with_supporting_document=True) entity_object_model = entity_object() if hasattr(entity_object_model, 'documents'): if self.entity.TYPE_INFO == 'SOCIAL_TENURE': obj_doc_col = current_profile().social_tenure.supporting_doc else: obj_doc_col = self.entity.supporting_doc self._doc_manager = SourceDocumentManager( obj_doc_col, self.doc_model ) else: entity_object = entity_model(self.entity) entity_object_model = entity_object() return entity_object_model
def __init__(self, column): ColumnWidgetRegistry.__init__(self, column) self._lookups = {} #Query all lookups on initializing so as to reduce db roundtrips lookup = self._column.value_list lk_cls = entity_model(lookup, entity_only=True) lk_obj = lk_cls() res = lk_obj.queryObject().filter().all() for r in res: self._lookups[r.id] = [r.value, r.code]
def doc_tab_data(self): """ Sets the document types in the social tenure entity. """ doc_entity = self.social_tenure. \ supporting_doc.document_type_entity doc_type_model = entity_model(doc_entity) docs = doc_type_model() doc_type_list = docs.queryObject().all() self.doc_types = [(doc.id, doc.value) for doc in doc_type_list ] self.doc_types = OrderedDict(self.doc_types)
def __init__(self, config, treeview, parent=None): super(EntityNodeFormatter, self).__init__(config, treeview, parent) prefix = self.curr_profile.prefix self._str_ref = str(prefix)+"_social_tenure_relationship" self._str_title = QApplication.translate("STRFormatterBase", "Social Tenure Relationship") self._str_model, self._str_doc_model = entity_model( self.curr_profile.social_tenure, False, True ) # Cache for entity supporting document tables. # [table_name]:[list of supporting document tables] self._entity_supporting_doc_tables = {} self._str_model_disp_mapping = {} if not self._str_model is None: self._str_model_disp_mapping = entity_display_columns( self.curr_profile.social_tenure, True ) self._fk_references = [ ( e.entity_relation.child_column, e.entity_relation.parent.name, e.entity_relation.parent_column ) for e in self.curr_profile.social_tenure.columns.values() if e.TYPE_INFO == 'FOREIGN_KEY' ] self._str_num_char_cols = entity_display_columns( self.curr_profile.social_tenure ) self._current_data_source_fk_ref = self._current_data_source_foreign_key_reference() #numeric_char_cols for entities - party and sp_unit self._numeric_char_cols = entity_display_columns( self.curr_profile.entity_by_name(config.data_source_name) ) self._spatial_data_sources = profile_spatial_tables(self.curr_profile).keys()
def __init__(self, entity, column): """ Initializes entity and column property. :param entity: The entity object of the column :type entity: Object :param column: The column object :type column: Object """ #TODO disable once committed to the database self.entity = entity self.current_profile = current_profile() self.code_entity = self.current_profile.auto_generate_code self.code_model = entity_model(self.code_entity) self.code_model_obj = self.code_model() self.column = column
def save_children(self): """ Saves children models into the database by assigning the the id of the parent for foreign key column. """ if len(self.child_models) < 1: return children_obj = [] for row_entity, model in self.child_models.iteritems(): row_pos = row_entity[0] entity = row_entity[1] ent_model = entity_model(entity) entity_obj = ent_model() for col in entity.columns.values(): if col.TYPE_INFO == 'FOREIGN_KEY': if col.parent.name == self._entity.name: setattr(model, col.name, self.model().id) children_obj.append(model) entity_obj.saveMany(children_obj)
def str_type_set_data(self): """ Sets str type combobox items. :return: STR type id and value. :rtype: OrderedDict """ lookup_column_name = self.social_tenure.spatial_unit_tenure_column( self.spatial_unit).name str_lookup_obj = lookup_parent_entity( self.curr_profile, lookup_column_name ) str_types = entity_model(str_lookup_obj, True) str_type_obj = str_types() self.str_type_data = str_type_obj.queryObject().all() str_type = [(lookup.id, lookup.value) for lookup in self.str_type_data] return OrderedDict(str_type)
def set_filter(self, entity, browser): col = self.filter_col(entity) child_model = entity_model(entity) child_model_obj = child_model() col_obj = getattr(child_model, col.name) if self.model() is not None: if self.model().id is None: browser.filtered_records = [] else: browser.filtered_records = child_model_obj.queryObject().filter( col_obj == self.model().id ).all() if self.edit_model is not None: browser.filtered_records = child_model_obj.queryObject().filter( col_obj == self.edit_model.id ).all() if self.edit_model is None and self.model() is None: browser.filtered_records = []
def on_digitizing_saved(self): """ A slot raised when the save button is clicked on Digitizing Toolbar of QGIS. It saves feature models created by the digitizer and STDM form to the Database. :return: None :rtype: NoneType """ ent_model = entity_model(self.entity) entity_obj = ent_model() entity_obj.saveMany( self.feature_models.values() ) for model in self.feature_models.values(): STDMDb.instance().session.flush() for attrMapper in self.editor._attrMappers: control = attrMapper.valueHandler().control if isinstance(control, ExpressionLineEdit): value = control.on_expression_triggered(model) print attrMapper._attrName, value setattr(model, attrMapper._attrName, value) model.update() # Save child models if self.editor is not None: self.editor.save_children() # undo each feature created so that qgis # don't try to save the same feature again. # It will also clear all the models from # self.feature_models as on_feature_deleted # is raised when a feature is removed. for f_id in self.feature_models.keys(): iface.mainWindow().blockSignals(True) self.layer.deleteFeature(f_id) self.on_feature_deleted(f_id) iface.mainWindow().blockSignals(True) for i in range(len(self.feature_models)): self.layer.undoStack().undo()
def document_models(entity, link_column, link_value): """ Create supporting document models using information from the linked document table. :param entity: The entity in which the supporting document are uploaded. :type entity: Class :param link_column: Name of the column linking the source document tables to the primary entity table. :type link_column: str :param link_value: Value of the linked column which is used to retrieve the corresponding values of the supporting document primary keys. :type link_value: int :return: Instances of supporting document models corresponding to the specified record in the document linked table grouped by document type. :rtype: list """ _str_model, _doc_model = entity_model( entity, False, True ) if _doc_model is None: return [] if not hasattr(_doc_model, link_column): return [] _doc_obj = _doc_model() # get the column object for column entity id # in entity supporting_document table. entity_doc_col_obj = getattr(_doc_model, link_column) result = _doc_obj.queryObject().filter( entity_doc_col_obj == link_value ).all() doc_objs = defaultdict(list) for doc_obj in result: doc_objs[doc_obj.document_type].append(doc_obj) doc_objs = OrderedDict(doc_objs) return doc_objs
def _entity_config_from_profile(self, table_name, short_name): """ Creates an EntityConfig object from the table name. :param table_name: Name of the database table. :type table_name: str :return: Entity configuration object. :rtype: EntityConfig """ table_display_name = format_name(short_name) self.ds_entity = self.curr_profile.entity_by_name(table_name) model = entity_model(self.ds_entity) if model is not None: return EntityConfig(title=table_display_name, data_source=table_name, model=model, expression_builder=True, entity_selector=None) else: return None
def __init__(self, config, formatter=None, parent=None): QWidget.__init__(self, parent) EntitySearchItem.__init__(self, formatter) self.setupUi(self) self.config = config self.setConfigOptions() self.curr_profile = current_profile() self.social_tenure = self.curr_profile.social_tenure self.str_model = entity_model(self.social_tenure) #Model for storing display and actual mapping values self._completer_model = None self._proxy_completer_model = None #Hook up signals self.cboFilterCol.currentIndexChanged.connect( self._on_column_index_changed ) self.init_validity_dates() self.validity_from_date.dateChanged.connect( self.set_minimum_to_date ) self.validity.setDisabled(True) self.init_validity_checkbox()
def _load_entity_config(self, entity): """ Creates an EntityConfig object from entity. :param entity: The entity object :type entity: Object """ table_display_name = format_name(entity.short_name) table_name = entity.name try: model = entity_model(entity) except Exception: return None if model is not None: return EntityConfig( title=table_display_name, data_source=table_name, model=model, expression_builder=False, entity_selector=None ) else: return None
def _load_document_types(self): #Load document types in the combobox and tab widget vl_cls = entity_model( self._entity_supporting_doc.document_type_entity, entity_only=True ) vl_obj = vl_cls() res = vl_obj.queryObject().all() for r in res: #Add to combo self._cbo_doc_type.addItem(r.value, r.id) #Add to tab widget doc_type_widget = _DocumentTypeContainer(self) self._doc_tab_container.addTab(doc_type_widget, r.value) self._doc_type_widgets[r.id] = doc_type_widget #Register container self.source_document_manager.registerContainer( doc_type_widget.container, r.id )
def set_entity(self, entity): """ Sets new entity and updates the ForeignKeyMapper with a new :param entity: The entity of the ForeignKeyMapper :type entity:Object """ from stdm.ui.entity_browser import EntityBrowser self._entity = entity self._dbmodel = entity_model(entity) self._init_fk_columns() self._entitySelector = EntityBrowser( self._entity, parent=self, state=SELECT, plugin=self.plugin ) # Connect signals self._entitySelector.recordSelected.connect( self._onRecordSelectedEntityBrowser )
def update_document_types(self, document_table): #Updates the types of documents for the specified supporting doc table self.cbo_document_type.clear() if not document_table: return #Get list of supporting document entities in the current profile s_doc_entities = self._curr_profile.supporting_document_entities() selected_doc_entity = [de for de in s_doc_entities if de.name == document_table] if len(selected_doc_entity) == 0: return doc_type_vl = selected_doc_entity[0].document_type_entity #Query id values from the document type lookup table lk_cls = entity_model(doc_type_vl, entity_only=True) lk_obj = lk_cls() res = lk_obj.queryObject().filter().all() for r in res: self.cbo_document_type.addItem(r.value, r.id)
def _entity_config_from_profile(self, table_name, short_name): """ Creates an EntityConfig object from the table name. :param table_name: Name of the database table. :type table_name: str :return: Entity configuration object. :rtype: EntityConfig """ table_display_name = format_name(short_name) entity = self.curr_profile.entity_by_name(table_name) model = entity_model(entity) if model is not None: #Entity configuration entity_cfg = EntityConfiguration() entity_cfg.Title = table_display_name entity_cfg.STRModel = model entity_cfg.data_source_name = table_name for col, factory in self._get_widget_factory(entity): entity_cfg.LookupFormatters[col.name] = factory # Load filter and display columns # using only those which are of # numeric/varchar type searchable_columns = entity_searchable_columns(entity) display_columns = entity_display_columns(entity) for c in searchable_columns: if c != 'id': entity_cfg.filterColumns[c] = format_name(c) for c in display_columns: if c != 'id': entity_cfg.displayColumns[c] = format_name(c) return entity_cfg else: return None
def __init__( self, entity, model=None, parent=None, manage_documents=True, collect_model=False, parent_entity=None, exclude_columns=[], plugin = None ): """ Class constructor. :param entity: Entity object corresponding to a table object. :type entity: Entity :param model: Data object for loading data into the form widgets. If the model is set, then the editor dialog is assumed to be in edit mode. :type model: object :param parent: Parent widget that the form belongs to. :type parent: QWidget :param manage_documents: True if the dialog should provide controls for managing supporting documents. Only applicable if the entity allows for supporting documents to be attached. :type manage_documents: bool :param collect_model: If set to True only returns the filled form model without saving it to the database. :type collect_model: Boolean :param parent_entity: The parent entity of the editor :type parent_entity: Object :param exclude_columns: List of columns to be excluded if in a list. :type exclude_columns: List :return: If collect_model, returns SQLAlchemy Model """ QDialog.__init__(self, parent) self.entity_table_model = {} self.collection_suffix = self.tr('Collection') #Set minimum width self.setMinimumWidth(450) self.plugin = plugin #Flag for mandatory columns self.has_mandatory = False self.reload_form = False self._entity = entity self.edit_model = model self.column_widgets = OrderedDict() self._parent = parent self.exclude_columns = exclude_columns self.entity_tab_widget = None self._disable_collections = False self.filter_val = None self.parent_entity = parent_entity self.child_models = OrderedDict() self.entity_scroll_area = None self.entity_editor_widgets = OrderedDict() # Set notification layout bar self.vlNotification = QVBoxLayout() self.vlNotification.setObjectName('vlNotification') self._notifBar = NotificationBar(self.vlNotification) self.do_not_check_dirty = False # Set manage documents only if the entity supports documents if self._entity.supports_documents: self._manage_documents = manage_documents else: self._manage_documents = False # Setup entity model self._ent_document_model = None if self._entity.supports_documents: self.ent_model, self._ent_document_model = entity_model( self._entity, with_supporting_document=True ) else: self.ent_model = entity_model(self._entity) if not model is None: self.ent_model = model MapperMixin.__init__(self, self.ent_model, entity) self.collect_model = collect_model self.register_column_widgets() try: if isinstance(parent._parent, EntityEditorDialog): # hide collections form child editor self._disable_collections = True except AttributeError: self._parent._parent = None # Set title editor_trans = self.tr('Editor') if self._entity.label is not None: if self._entity.label != '': title_str = self._entity.label else: title_str = format_name(self._entity.short_name) else: title_str = format_name(self._entity.short_name) self.title = u'{0} {1}'.format(title_str, editor_trans) self.setWindowTitle(self.title) self._init_gui() self.adjustSize() self._get_entity_editor_widgets() if isinstance(parent._parent, EntityEditorDialog): self.parent_entity = parent.parent_entity self.set_parent_values() # make the size smaller to differentiate from parent and as it # only has few tabs. self.adjustSize() self.attribute_mappers = self._attr_mapper_collection # Exception title for editor extension exceptions self._ext_exc_msg = self.tr( 'An error has occured while executing Python code in the editor ' 'extension:' ) # Register custom editor extension if specified self._editor_ext = entity_dlg_extension(self) if not self._editor_ext is None: self._editor_ext.post_init() # Initialize CascadingFieldContext objects self._editor_ext.connect_cf_contexts()
def _entity_select_column( entity, use_inner_join=False, join_parents=False, is_primary=False, foreign_key_parents=None, omit_view_columns=None, omit_join_statement_columns=None, view_name=None ): # Check if the entity exists in the database if not pg_table_exists(entity.name): msg = u'{0} table does not exist, social tenure view will not be ' \ u'created.'.format(entity.name) LOGGER.debug(msg) raise ConfigurationException(msg) if omit_view_columns is None: omit_view_columns = [] if omit_join_statement_columns is None: omit_join_statement_columns = [] column_names = [] join_statements = [] columns = entity.columns.values() # Create foreign key parent collection if none is specified if foreign_key_parents is None: foreign_key_parents = {} str_entity = entity.profile.social_tenure if entity in str_entity.custom_attribute_entities.values(): custom_tenure = True else: custom_tenure = False i = 0 parents = [] for c in columns: if c.TYPE_INFO not in _exclude_view_column_types: normalized_entity_sname = entity.short_name.replace(' ', '_').lower() pseudo_column_name = u'{0}_{1}'.format(normalized_entity_sname, c.name) # use sudo name for custom tenure entity if custom_tenure: col_select_name = u'{0}_1.{1}'.format( entity.name, c.name ) else: col_select_name = u'{0}.{1}'.format(entity.name, c.name) # Get pseudoname to use select_column_name = u'{0} AS {1}'.format(col_select_name, pseudo_column_name) if is_primary and c.name == 'id': # add row number id instead of party.id # if multi_party is allowed. if str_entity.multi_party: # for party entity add use row number if not entity.has_geometry_column(): row_id = 'row_number() OVER () AS id' select_column_name = row_id else: # add spatial unit id as the id. col_spatial_unit_id = u'{0}.{1} AS {1}'.format( entity.name, c.name ) select_column_name = col_spatial_unit_id else: # add party id or spatial unit as id entity_id = u'{0}.{1} AS {1}'.format( entity.name, c.name ) select_column_name = entity_id # Use custom join flag use_custom_join = False if isinstance(c, ForeignKeyColumn) and join_parents: LOGGER.debug('Creating STR: Getting parent for %s column', c.name) fk_parent_entity = c.entity_relation.parent parent_table = c.entity_relation.parent.name LOGGER.debug('Parent found') # Handle renaming of parent table names to appropriate # pseudonames. if not parent_table in foreign_key_parents: foreign_key_parents[parent_table] = [] pseudo_names = foreign_key_parents.get(parent_table) # Get pseudoname to use table_pseudo_name = u'{0}_{1}'.format( parent_table, (len(pseudo_names) + 1) ) pseudo_names.append(table_pseudo_name) # Map lookup and admin unit values by default if c.TYPE_INFO == 'LOOKUP': lookup_model = entity_model(c.entity_relation.parent) lookup_model_obj = lookup_model() result = lookup_model_obj.queryObject().filter( lookup_model.code != '').filter( lookup_model.code != None).all() if len(result) == 0: select_column_name = u'{0}.value AS {1}'.format( table_pseudo_name, pseudo_column_name ) else: value = u'{0}.value'.format(table_pseudo_name) code = u'{0}.code'.format(table_pseudo_name) select_column_name = u"concat({0}, ' (', {1}, ')') AS {2}".\ format(value, code, pseudo_column_name) use_custom_join = True # Check if the column is for tenure type if c.name != 'tenure_type': use_inner_join = False elif c.TYPE_INFO == 'ADMIN_SPATIAL_UNIT': select_column_name = u'{0}.name AS {1}'.format( table_pseudo_name, pseudo_column_name) use_custom_join = True use_inner_join = False elif c.TYPE_INFO == 'FOREIGN_KEY': if c.entity_relation.parent not in str_entity.parties and \ c.entity_relation.parent not in str_entity.spatial_units: if len(c.entity_relation.display_cols) > 0: display_col_names = [] for display_col in c.entity_relation.display_cols: name = u'{0}.{1}'.format(table_pseudo_name, display_col) display_col_names.append(name) select_column_name = u"concat_ws(' '::text, {0}) AS {1}".format( ', '.join(display_col_names), pseudo_column_name ) else: if not custom_tenure: select_column_name = u'{0}.id AS {1}'.format( table_pseudo_name, pseudo_column_name ) use_custom_join = True use_inner_join = False else: QApplication.processEvents() # These are outer joins join_type = 'LEFT JOIN' # Use inner join only if parent entity is an STR entity and it is the current entity. # Other str entities should use left join. if str_entity.is_str_entity(fk_parent_entity) and \ fk_parent_entity.name in view_name: join_type = 'INNER JOIN' if use_custom_join: # exclude replace str name with custom tenure name in join. if custom_tenure: if c.name == 'social_tenure_relationship_id': i = i + 1 # pseudo_names = foreign_key_parents.get(parent_table) col_select_name = u'{0}_{1}.{2}'.format( entity.name, str(i), c.name ) # Get pseudoname to use table_pseudo_name = u'{0}_{1}'.format( entity.name, str(i) ) join_statement = u'{0} {1} {2} ON {3} = {2}.{4}'.format( join_type, entity.name, table_pseudo_name, col_select_name, c.entity_relation.parent_column ) join_statements = [join_statement] + join_statements else: join_statement = u'{0} {1} {2} ON {3} = {2}.{4}'.format( join_type, parent_table, table_pseudo_name, col_select_name, c.entity_relation.parent_column ) join_statements.append(join_statement) else: join_statement = u'{0} {1} {2} ON {3} = {2}.{4}'.format( join_type, parent_table, table_pseudo_name, col_select_name, c.entity_relation.parent_column ) join_statements.append(join_statement) else: # Assert if the column is in the list of omitted join columns # # if c.name in omit_join_statement_columns: # if 'INNER JOIN' in join_statement: # join_statements.append(join_statement) # else: # This fix needs to be tested more ... if parent_table in foreign_key_parents and 'relationship' not in entity.name: parent_table_alias = foreign_key_parents[parent_table][0] join_statement = u'{0} {1} {2} ON {3} = {2}.{4}'.format( join_type, parent_table, parent_table_alias, col_select_name, c.entity_relation.parent_column ) else: join_statement = u'{0} {1} ON {2} = {1}.{3}'.format( join_type, parent_table, col_select_name, c.entity_relation.parent_column ) parents.append(parent_table) join_statements.append(join_statement) # Assert if the column is in the list of omitted view columns if c.name not in omit_view_columns: if select_column_name: column_names.append(select_column_name) QApplication.processEvents() return column_names, join_statements
def __init__(self, plugin): QMainWindow.__init__(self, plugin.iface.mainWindow()) self.setupUi(self) self._plugin = plugin self.search_done = False # self.tbPropertyPreview.set_iface(self._plugin.iface) QTimer.singleShot( 100, lambda: self.tbPropertyPreview.set_iface(self._plugin.iface)) self.curr_profile = current_profile() self.spatial_units = self.curr_profile.social_tenure.spatial_units #Center me self.move(QDesktopWidget().availableGeometry().center() - self.frameGeometry().center()) self.sp_unit_manager = SpatialUnitManagerDockWidget( self._plugin.iface, self._plugin ) self.geom_cols = [] for spatial_unit in self.spatial_units: each_geom_col = self.sp_unit_manager.geom_columns(spatial_unit) self.geom_cols.extend(each_geom_col) # Configure notification bar self._notif_search_config = NotificationBar( self.vl_notification ) # set whether currently logged in user has # permissions to edit existing STR records self._can_edit = self._plugin.STRCntGroup.canUpdate() self._can_delete = self._plugin.STRCntGroup.canDelete() self._can_create = self._plugin.STRCntGroup.canCreate() # Variable used to store a reference to the # currently selected social tenure relationship # when displaying documents in the supporting documents tab window. # This ensures that there are no duplicates # when the same item is selected over and over again. self._strID = None self.removed_docs = None #Used to store the root hash of the currently selected node. self._curr_rootnode_hash = "" self.str_model, self.str_doc_model = entity_model( self.curr_profile.social_tenure, False, True ) self._source_doc_manager = SourceDocumentManager( self.curr_profile.social_tenure.supporting_doc, self.str_doc_model, self ) self._source_doc_manager.documentRemoved.connect( self.onSourceDocumentRemoved ) self._source_doc_manager.setEditPermissions(False) self.initGui() # if self._plugin.details_tree_view is None: # self._plugin.details_dock.init_dock() self.add_spatial_unit_layer() self.details_tree_view = DetailsTreeView(iface, self._plugin, self) # else: # self.details_tree_view = self._plugin.details_tree_view self.details_tree_view.activate_feature_details(True) self.details_tree_view.add_tree_view() self.details_tree_view.model.clear() count = pg_table_count(self.curr_profile.social_tenure.name) self.setWindowTitle( self.tr(u'{}{}'.format( self.windowTitle(), '- ' + str(count) +' rows' )) ) self.toolBox.setStyleSheet( ''' QToolBox::tab { background: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EDEDED, stop: 0.4 #EDEDED, stop: 0.5 #EDEDED, stop: 1.0 #D3D3D3 ); border-radius: 2px; border-style: outset; border-width: 2px; height: 100px; border-color: #C3C3C3; } QToolBox::tab:selected { font: italic; } ''' ) self.details_tree_view.view.setStyleSheet( ''' QTreeView:!active { selection-background-color: #72a6d9; } ''' )
def executeSearch(self): """ Base class override. Search for matching items for the specified entity and column. """ model_root_node = None prog_dialog = QProgressDialog(self) prog_dialog.setFixedWidth(380) prog_dialog.setWindowTitle( QApplication.translate( "STRViewEntityWidget", "Searching for STR..." ) ) prog_dialog.show() prog_dialog.setRange( 0, 10 ) search_term = self._searchTerm() prog_dialog.setValue(2) #Try to get the corresponding search term value from the completer model if not self._completer_model is None: reg_exp = QRegExp("^%s$"%(search_term), Qt.CaseInsensitive, QRegExp.RegExp2) self._proxy_completer_model.setFilterRegExp(reg_exp) if self._proxy_completer_model.rowCount() > 0: #Get corresponding actual value from the first matching item value_model_idx = self._proxy_completer_model.index(0, 1) source_model_idx = self._proxy_completer_model.mapToSource( value_model_idx ) prog_dialog.setValue(4) search_term = self._completer_model.data( source_model_idx, Qt.DisplayRole ) modelInstance = self.config.STRModel() modelQueryObj = modelInstance.queryObject() queryObjProperty = getattr( self.config.STRModel, self.currentFieldName() ) entity_name = modelQueryObj._primary_entity._label_name entity = self.curr_profile.entity_by_name(entity_name) prog_dialog.setValue(6) # Get property type so that the filter can # be applied according to the appropriate type propType = queryObjProperty.property.columns[0].type results = [] try: if not isinstance(propType, String): col_name = self.currentFieldName() col = entity.columns[self.currentFieldName()] if col.TYPE_INFO == 'LOOKUP': lookup_entity = lookup_parent_entity( self.curr_profile, col_name ) lkp_model = entity_model(lookup_entity) lkp_obj = lkp_model() value_obj = getattr( lkp_model, 'value' ) result = lkp_obj.queryObject().filter( func.lower(value_obj) == func.lower(search_term) ).first() if result is None: result = lkp_obj.queryObject().filter( func.lower(value_obj).like(search_term+'%') ).first() if not result is None: results = modelQueryObj.filter( queryObjProperty == result.id ).all() else: results = [] else: results = modelQueryObj.filter( func.lower(queryObjProperty) == func.lower(search_term) ).all() if self.validity.isEnabled(): valid_str_ids = self.str_validity_period_filter(results) else: valid_str_ids = None prog_dialog.setValue(7) except exc.StatementError: return model_root_node, [], search_term # if self.formatter is not None: # self.formatter.setData(results) # model_root_node = self.formatter.root(valid_str_ids) prog_dialog.setValue(10) prog_dialog.hide() return results, search_term
def value_list_updater(value_list, engine, metadata): """ Creates the value list table and adds the lookup values in the table. :param value_list: ValueList object containing lookup values. :type value_list: ValueList :param engine: SQLAlchemy engine object. :type engine: Engine :param metadata: Database container with the schema definition. :type metadata: MetaData """ entity_updater(value_list, engine, metadata) # Return if action is to delete the lookup table if value_list.action == DbItem.DROP: return # Update lookup values model = entity_model(value_list, True) if model is None: LOGGER.debug('Model for %s ValueList object could not be created.', value_list.name) return model_obj = model() # Get all the lookup values in the table db_values = model_obj.queryObject().all() # Update database values for cd in value_list.values.values(): # Search if the current code value exists in the collection matching_items = [db_obj for db_obj in db_values if db_obj.value == cd.value] model_obj = model() # If it does not exist then create if len(matching_items) == 0: # Value might be updated even if it does not exist in the database so check if cd.updated_value: value_list.update_index(cd.value) cd.value = cd.updated_value cd.updated_value = '' model_obj.code = cd.code model_obj.value = cd.value model_obj.save() else: item = matching_items[0] needs_update = False # Check if the values have changed and update accordingly if cd.updated_value: value_list.update_index(item.value) item.value = cd.updated_value cd.value = cd.updated_value cd.updated_value = '' needs_update = True if cd.updated_code: item.code = cd.updated_code cd.code = cd.updated_code cd.updated_code = '' needs_update = True if needs_update: item.update() # Refresh lookup values db_values = model_obj.queryObject().all() # Remove redundant values in the database for db_val in db_values: lookup_val = db_val.value # Check if it exists in the lookup collection code_value = value_list.code_value(lookup_val) model_obj = model() # Delete if it does not exist in the configuration collection if code_value is None: lookup_obj = model_obj.queryObject().filter( model.value == lookup_val ).one() if not lookup_obj is None: lookup_obj.delete()
def __init__(self, entity, parent=None, state=MANAGE, load_records=True, plugin=None): QDialog.__init__(self,parent) self.setupUi(self) # Add maximize buttons self.setWindowFlags( self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMaximizeButtonHint ) SupportsManageMixin.__init__(self, state) # Init document viewer setup self._view_docs_act = None viewer_title = QApplication.translate( 'EntityBrowser', 'Document Viewer' ) self.doc_viewer_title = u'{0} {1}'.format( entity.ui_display(), viewer_title ) self._doc_viewer = _EntityDocumentViewerHandler( self.doc_viewer_title, self ) self.load_records = load_records #Initialize toolbar self.plugin = plugin self.tbActions = QToolBar() self.tbActions.setObjectName('eb_actions_toolbar') self.tbActions.setIconSize(QSize(16, 16)) self.tbActions.setToolButtonStyle(Qt.ToolButtonIconOnly) self.vlActions.addWidget(self.tbActions) self._entity = entity self._dbmodel = entity_model(entity) self._state = state self._tableModel = None self._parent = parent self._data_initialized = False self._notifBar = NotificationBar(self.vlNotification) self._headers = [] self._entity_attrs = [] self._cell_formatters = {} self.filtered_records = [] self._searchable_columns = OrderedDict() self._show_docs_col = False self.child_model = OrderedDict() #ID of a record to select once records have been added to the table self._select_item = None self.current_records = 0 self.record_limit = self.get_records_limit() #get_entity_browser_record_limit() #Enable viewing of supporting documents if self.can_view_supporting_documents: self._add_view_supporting_docs_btn() # self._add_advanced_search_btn() #Connect signals self.buttonBox.accepted.connect(self.onAccept) self.tbEntity.doubleClicked[QModelIndex].connect(self.onDoubleClickView)