def fill_lst_conf(self, id=None): model = QStandardItemModel() model.setColumnCount(2) self.ui.lst_laws.setModel(model) self.ui.lst_laws.setModelColumn(1) self.ui.lst_laws.selectionModel().selectionChanged.connect( self.display_graph_home) sql = "SELECT * FROM {0}.tracer_config WHERE type = {1} ORDER BY name".format( self.mdb.SCHEMA, self.cur_wq_mod) rows = self.mdb.run_query(sql, fetch=True) for i, row in enumerate(rows): for j, field in enumerate(row): new_itm = QStandardItem(str(row[j])) new_itm.setEditable(False) # new_itm.setCheckable(True) # new_itm.setCheckState(0) self.ui.lst_laws.model().setItem(i, j, new_itm) if id: for r in range(self.ui.lst_laws.model().rowCount()): if str(self.ui.lst_laws.model().item(r, 0).text()) == str(id): self.ui.lst_laws.setCurrentIndex( self.ui.lst_laws.model().item(r, 1).index()) break else: self.display_graph_home()
def fill_lst_stations(self, id=None): """ Fill stations table in function of :param id: id of station :return: """ model = QStandardItemModel() model.setColumnCount(3) model.setHorizontalHeaderLabels(['Station', 'H', 'Q']) self.ui.tab_stations.setModel(model) self.ui.tab_stations.setColumnWidth(0, 140) self.ui.tab_stations.setColumnWidth(1, 10) self.ui.tab_stations.setColumnWidth(2, 10) self.ui.tab_stations.selectionModel().selectionChanged.connect( self.station_changed) sql = "SELECT DISTINCT sta.code, not cnt_h isNull as h, not cnt_q isNull as q " \ "FROM ({0}.observations as sta LEFT JOIN (SELECT code, count(*) as cnt_h FROM {0}.observations " \ "WHERE type = 'H' GROUP BY code) as sta_h ON sta.code = sta_h.code) " \ "LEFT JOIN (SELECT code, count(*) as cnt_q FROM {0}.observations " \ "WHERE type = 'Q' GROUP BY code) as sta_q ON sta.code = sta_q.code " \ "ORDER BY sta.code".format(self.mdb.SCHEMA) rows = self.mdb.run_query(sql, fetch=True) for i, row in enumerate(rows): for j, field in enumerate(row): new_itm = QStandardItem() if j == 0: new_itm.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter) txt = str(row[j]).strip() else: new_itm.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) if row[j] is True: txt = "X" else: txt = "" new_itm.setText(txt) new_itm.setEditable(False) self.ui.tab_stations.model().setItem(i, j, new_itm) if id: for r in range(self.ui.tab_stations.model().rowCount()): if str(self.ui.tab_stations.model().item(r, 0).text()) == str( id): self.ui.tab_stations.setCurrentIndex( self.ui.tab_stations.model().item(r, 0).index()) break else: self.station_changed()
def fill_lst_conf(self, id=None): """ fill list configuration""" model = QStandardItemModel() model.setColumnCount(2) self.ui.lst_laws.setModel(model) self.ui.lst_laws.setModelColumn(1) self.ui.lst_laws.selectionModel().selectionChanged.connect( self.change_cur_law) sql = "SELECT * FROM {0}.init_conc_config WHERE type = {1} ORDER BY name".format( self.mdb.SCHEMA, self.cur_wq_mod) rows = self.mdb.run_query(sql, fetch=True) for i, row in enumerate(rows): for j, field in enumerate(row): if j != 3: new_itm = QStandardItem(str(row[j])) new_itm.setEditable(False) if j == 1: new_itm.setCheckable(True) if not row[3]: new_itm.setCheckState(0) elif row[3]: new_itm.setCheckState(2) self.ui.lst_laws.model().setItem(i, j, new_itm) self.ui.lst_laws.model().itemChanged.connect(self.sel_config_def) if id: for r in range(self.ui.lst_laws.model().rowCount()): if str(self.ui.lst_laws.model().item(r, 0).text()) == str(id): self.ui.lst_laws.setCurrentIndex( self.ui.lst_laws.model().item(r, 1).index()) break else: self.display_graph_home() self.ui.cb_bief_home.clear()
class ModelAtrributesView(QListView): """ Custom QListView implementation that displays checkable model attributes. """ def __init__(self, parent=None, dataModel=None): QListView.__init__(self, parent) self._dataModel = dataModel self._selectedDisplayMapping = OrderedDict() self._modelDisplayMapping = OrderedDict() self._attrModel = QStandardItemModel(self) def dataModel(self): """ Returns the data model instance. """ return self._dataModel def setDataModel(self, dataModel): """ Sets the data model. Should be a callable class rather than the class. instance. """ if callable(dataModel): self._dataModel = dataModel else: self._dataModel = dataModel.__class__ def modelDisplayMapping(self): """ Returns the column name and display name collection. """ return self._modelDisplayMapping def setModelDisplayMapping(self, dataMapping): """ Sets the mapping dictionary for the table object """ if dataMapping != None: self._modelDisplayMapping = dataMapping def load(self, sort=False): """ Load the model's attributes into the list view. """ if self._dataModel == None: return try: self._loadAttrs(self._dataModel.displayMapping(), sort) except AttributeError: # Ignore error if model does not contain # the displayMapping static method pass def load_mapping(self, mapping, sort=False): """ Load collection containing column name and corresponding display name. """ self._modelDisplayMapping = mapping self._loadAttrs(mapping, sort) def sort(self): """ Sorts display name in ascending order. """ self._attrModel.sort(0) def _loadAttrs(self, attrMapping, sort=False): """ Loads display mapping into the list view. Specify to sort display names in ascending order once items have been added to the model. """ self._attrModel.clear() self._attrModel.setColumnCount(2) for attrName, displayName in attrMapping.items(): # Exclude row ID in the list, other unique identifier attributes in the model can be used if attrName != "id": displayNameItem = QStandardItem(displayName) displayNameItem.setCheckable(True) attrNameItem = QStandardItem(attrName) self._attrModel.appendRow([displayNameItem, attrNameItem]) self.setModel(self._attrModel) if sort: self._attrModel.sort(0) def selectedMappings(self): """ Return a dictionary of field names and their corresponding display values. """ selectedAttrs = OrderedDict() for i in range(self._attrModel.rowCount()): displayNameItem = self._attrModel.item(i, 0) if displayNameItem.checkState() == Qt.Checked: attrNameItem = self._attrModel.item(i, 1) selectedAttrs[attrNameItem.text()] = displayNameItem.text() return selectedAttrs
class MultipleSelectTreeView(QListView): """ Custom QListView implementation that displays checkable items from a multiple select column type. """ def __init__(self, column, parent=None): """ Class constructor. :param column: Multiple select column object. :type column: MultipleSelectColumn :param parent: Parent widget for the control. :type parent: QWidget """ QListView.__init__(self, parent) # Disable editing of lookup values self.setEditTriggers(QAbstractItemView.NoEditTriggers) self.column = column self._item_model = QStandardItemModel(self) self._value_list = self.column.value_list # Stores lookup objects based on primary keys self._lookup_cache = {} self._initialize() self._association = self.column.association self._first_parent_col = self._association.first_reference_column.name self._second_parent_col = self._association.second_reference_column.name # Association model self._assoc_cls = entity_model(self._association) def reset_model(self): """ Resets the item model. """ self._item_model.clear() self._item_model.setColumnCount(2) def clear(self): """ Clears all items in the model. """ self._item_model.clear() @property def association(self): """ :return: Returns the association object corresponding to the column. :rtype: AssociationEntity """ return self._association @property def value_list(self): """ :return: Returns the ValueList object corresponding to the configured column object. :rtype: ValueList """ return self._value_list @property def item_model(self): """ :return: Returns the model corresponding to the checkable items. :rtype: QStandardItemModel """ return self._item_model def _add_item(self, id, value): """ Adds a row corresponding to id and corresponding value from a lookup table. :param id: Primary key of a lookup record. :type id: int :param value: Lookup value :type value: str """ value_item = QStandardItem(value) value_item.setCheckable(True) id_item = QStandardItem(str(id)) self._item_model.appendRow([value_item, id_item]) def _initialize(self): # Populate list with lookup items self.reset_model() # Add all lookup values in the value list table vl_cls = entity_model(self._value_list) if not vl_cls is None: vl_obj = vl_cls() res = vl_obj.queryObject().all() for r in res: self._lookup_cache[r.id] = r self._add_item(r.id, r.value) self.setModel(self._item_model) def clear_selection(self): """ Unchecks all items in the view. """ for i in range(self._item_model.rowCount()): value_item = self._item_model.item(i, 0) if value_item.checkState() == Qt.Checked: value_item.setCheckState(Qt.Unchecked) if value_item.rowCount() > 0: value_item.removeRow(0) def selection(self): """ :return: Returns a list of selected items. :rtype: list """ selection = [] for i in range(self._item_model.rowCount()): value_item = self._item_model.item(i, 0) if value_item.checkState() == Qt.Checked: id_item = self._item_model.item(i, 1) id = int(id_item.text()) # Get item from the lookup cache and append to selection if id in self._lookup_cache: lookup_rec = self._lookup_cache[id] selection.append(lookup_rec) return selection def set_selection(self, models): """ Checks items corresponding to the specified models. :param models: List containing model values in the view for selection. :type models: list """ for m in models: search_value = m.value v_items = self._item_model.findItems(search_value) # Loop through result and check items for vi in v_items: if vi.checkState() == Qt.Unchecked: vi.setCheckState(Qt.Checked)
class AbstractSTREnityListView(QListView): """ A widget for listing and selecting one or more STR entities. .. versionadded:: 1.7 """ def __init__(self, parent=None, **kwargs): super(AbstractSTREnityListView, self).__init__(parent) self._model = QStandardItemModel(self) self._model.setColumnCount(1) self.setModel(self._model) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self._model.itemChanged.connect(self._on_item_changed) self._profile = kwargs.get('profile', None) self._social_tenure = kwargs.get('social_tenure', None) # Load appropriate entities to the view if not self._profile is None: self._load_profile_entities() # Load entities in the STR definition if not self._social_tenure is None: self._select_str_entities() def _on_item_changed(self, item): # Emit signals when an item has been (de)selected. To be # implemented by subclasses. pass @property def profile(self): """ :return: Returns the current profile object in the configuration. :rtype: Profile """ return self._profile @profile.setter def profile(self, profile): """ Sets the current profile object in the configuration. :param profile: Profile object. :type profile: Profile """ self._profile = profile self._load_profile_entities() @property def social_tenure(self): """ :return: Returns the profile's social tenure entity. :rtype: SocialTenure """ return self._social_tenure @social_tenure.setter def social_tenure(self, social_tenure): """ Set the social_tenure entity. :param social_tenure: A profile's social tenure entity. :type social_tenure: SocialTenure """ self._social_tenure = social_tenure self._select_str_entities() def _select_str_entities(self): """ Select the entities defined in the STR. E.g. parties for party entity and spatial units for spatial unit entity. Default implementation does nothing, to be implemented by subclasses. """ pass def _load_profile_entities(self): # Reset view self.clear() # Populate entity items in the view for e in self._profile.user_entities(): self._add_entity(e) def _add_entity(self, entity): # Add entity item to view item = QStandardItem( GuiUtils.get_icon('table.png'), entity.short_name ) item.setCheckable(True) item.setCheckState(Qt.Unchecked) self._model.appendRow(item) def select_entities(self, entities): """ Checks STR entities in the view and emit the entity_selected signal for each item selected. :param entities: Collection of STR entities. :type entities: list """ # Clear selection self.clear_selection() for e in entities: name = e.short_name self.select_entity(name) def selected_entities(self): """ :return: Returns a list of selected entity short names. :rtype: list """ selected_items = [] for i in range(self._model.rowCount()): item = self._model.item(i) if item.checkState() == Qt.Checked: selected_items.append(item.text()) return selected_items def clear(self): """ Remove all party items in the view. """ self._model.clear() self._model.setColumnCount(1) def clear_selection(self): """ Uncheck all items in the view. """ for i in range(self._model.rowCount()): item = self._model.item(i) if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked) def select_entity(self, name): """ Selects a party entity with the given short name. :param name: Entity short name :type name: str """ items = self._model.findItems(name) if len(items) > 0: item = items[0] if item.checkState() == Qt.Unchecked: item.setCheckState(Qt.Checked) def deselect_entity(self, name): """ Deselects an entity with the given short name. :param name: Entity short name :type name: str """ items = self._model.findItems(name) if len(items) > 0: item = items[0] if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked)
class contentAuthDlg(WIDGET, BASE): ''' Content authorization dialog ''' def __init__(self, plugin): QDialog.__init__(self, plugin.iface.mainWindow()) self.setupUi(self) QgsGui.enableAutoGeometryRestore(self) # Initialize the dialog self.initGui() # Load users self.loadContent() # Load Roles self.loadRoles() # Reference to the currently selected STDM content item self.currentContent = None def initGui(self): ''' Initialize GUI properties ''' # Disable any action by the user in the roles view self.lstRoles.setEnabled(False) # Connect signals self.lstContent.activated.connect(self.onContentClicked) self.lstContent.clicked.connect(self.onContentClicked) self.lstRoles.activated.connect(self.onRoleSelected) self.lstRoles.clicked.connect(self.onRoleSelected) def loadContent(self): ''' Loads STDM content items ''' self.content = Content() # self.content=Table('content_base',Base.metadata,autoload=True,autoload_with=STDMDb.instance().engine) cntItems = self.content.queryObject().all() ''' self.content=Table('content_base',Base.metadata,autoload=True,autoload_with=STDMDb.instance().engine) session= STDMDb.instance().session cntItems=session.query(self.content) ''' cnts = [cntItem.name for cntItem in cntItems] self.contentModel = UsersRolesModel(cnts) self.lstContent.setModel(self.contentModel) def loadRoles(self, contentname=""): ''' Loads the roles in the database cluster ''' self.roleProvider = RoleProvider() sysRoles = self.roleProvider.GetAllRoles() roles = [] # Load the corresponding roles for the specified content item cnt = Content() if contentname != "": self.currentContent = self.content.queryObject().filter( Content.name == contentname).first() if self.currentContent: roles = [rl.name for rl in self.currentContent.roles] # Initialize model self.roleMappingsModel = QStandardItemModel(self) self.roleMappingsModel.setColumnCount(1) # Add role items into the standard item model for r in range(len(sysRoles)): role = sysRoles[r] if role.name != "postgres": roleItem = self._createNewRoleItem(role.name) # Check if the db role is in the approved for the current content item roleIndex = getIndex(roles, role.name) if roleIndex != -1: roleItem.setCheckState(Qt.Checked) self.roleMappingsModel.appendRow(roleItem) self.lstRoles.setModel(self.roleMappingsModel) def _createNewRoleItem(self, rolename): ''' Creates a custom role item for use in a QStandardItemModel ''' # Set icon icon = QIcon() icon.addPixmap(GuiUtils.get_icon_pixmap("roles.png"), QIcon.Normal, QIcon.Off) roleItem = QStandardItem(icon, rolename) roleItem.setCheckable(True) roleItem.setCheckState(Qt.Unchecked) return roleItem def onContentClicked(self, index): ''' Slot activated when a content item is selected to load the roles for the specified content items ''' self.lstRoles.setEnabled(True) contentName = index.data() self.loadRoles(contentName) self.privilege_provider = SinglePrivilegeProvider( contentName, current_profile()) def onRoleSelected(self, index): ''' Slot which is called when a user checks/unchecks to add/remove a role for the specified content item. ''' if self.currentContent != None: item = self.roleMappingsModel.itemFromIndex(index) rolename = item.text() self.privilege_provider.role = rolename # Get role object from role name role = Role() rl = role.queryObject().filter(Role.name == rolename).first() self.blockSignals(True) # Add role to the content item if the item is selected or remove if it was previosuly checked if item.checkState() == Qt.Checked: self.currentContent.roles.append(rl) self.privilege_provider.grant_privilege() elif item.checkState() == Qt.Unchecked: self.currentContent.roles.remove(rl) self.privilege_provider.revoke_privilege() self.currentContent.update() self.blockSignals(False)
class QVDistrictesBarris(QObject): __distBarrisCSV = r'Dades\DIST_BARRIS.csv' __zones = r'Dades\Zones.gpkg' def __init__(self): super().__init__() self.labels = [] self.registre = {} # Model self.model = QStandardItemModel() self.llegirZonesGPKG() #self.llegirDistrictesBarrisCSV() # View self.view = QTreeView() self.view.setContextMenuPolicy(Qt.ActionsContextMenu) self.actExpand = QAction("Expandeix/Contreu Tot", self) self.actExpand.setStatusTip("Expand") self.actExpand.triggered.connect(self.expand_all) self.view.addAction(self.actExpand) self.view.setModel(self.model) self.iniView() def expand_all(self): """Expandir o contraer todo el arbol, dependiendo de si detecta que esta extendido o contraido """ if self.view.isExpanded(self.model.index(0, 0, QModelIndex())): self.view.collapseAll() else: self.view.expandAll() def iniView(self): self.view.setHeaderHidden(True) for i in range(self.model.columnCount()): if i == 0: self.view.setColumnHidden(i, False) self.view.resizeColumnToContents(i) self.view.resizeColumnToContents(i) else: self.view.setColumnHidden(i, True) self.view.setEditTriggers(QTreeView.NoEditTriggers) self.expand_all() def llegirZonesGPKG(self): try: QvFuncions.setReadOnlyFile(self.__zones) pathDistrictes = self.__zones + '|layername=districtes' layerDistrictes = QgsVectorLayer(pathDistrictes, 'ogr') pathBarris = self.__zones + '|layername=barris' layerBarris = QgsVectorLayer(pathBarris, 'ogr') rowsDistrictes = layerDistrictes.getFeatures() llistaDistrictes = [] for rowD in rowsDistrictes: #print(rowD.attributes()) #zona = "" num_districte = rowD.attributes()[1] nom_districte = rowD.attributes()[2] num_barri = "" nom_barri = "" geometria = rowD.geometry().boundingBox() x_min = str(geometria.xMinimum()) y_min = str(geometria.yMinimum()) x_max = str(geometria.xMaximum()) y_max = str(geometria.yMaximum()) item = [ num_districte, nom_districte, num_barri, nom_barri, x_min, y_min, x_max, y_max ] llistaDistrictes.append(item) def ordenaPerNumDistricte(elem): return elem[0] llistaDistrictes.sort(key=ordenaPerNumDistricte) #print(llistaDistrictes) rowsBarris = layerBarris.getFeatures() llistaBarris = [] for rowB in rowsBarris: #print(rowB.attributes()) #zona = "" num_districte = rowB.attributes()[3] nom_districte = llistaDistrictes[int(num_districte) - 1][1] num_barri = rowB.attributes()[1] nom_barri = rowB.attributes()[2] geometria = rowB.geometry().boundingBox() x_min = str(geometria.xMinimum()) y_min = str(geometria.yMinimum()) x_max = str(geometria.xMaximum()) y_max = str(geometria.yMaximum()) item = [ num_districte, nom_districte, num_barri, nom_barri, x_min, y_min, x_max, y_max ] llistaBarris.append(item) def ordenaPerNumBarri(elem): return elem[2] llistaBarris.sort(key=ordenaPerNumBarri) #print(llistaBarris) self.labels = [ "ZONA", "DISTRICTE", "NOM_DISTRICTE", "BARRI", "NOM_BARRI", "X_MIN", "Y_MIN", "X_MAX", "Y_MAX" ] root = self.model.invisibleRootItem() self.model.setColumnCount(len(self.labels)) self.model.setHorizontalHeaderLabels(self.labels) #Afegir Barcelona com a arrel de l'arbre bcn_dades = [ "00", "Barcelona", "00", "Barcelona", "419710.0553820258", "4573818.80776309", "436533.35", "4591775.02" ] bcn = [QStandardItem("Barcelona")] for item in bcn_dades: bcn.append(QStandardItem(item)) root.appendRow(bcn) ultimaDistr = -1 itDist = 0 for b in llistaBarris: if ultimaDistr != int(b[0]): #Afegir següent districte dist = [QStandardItem(llistaDistrictes[itDist][1])] for i in range(0, len(llistaDistrictes[itDist])): dist.append(QStandardItem(llistaDistrictes[itDist][i])) bcn[0].appendRow(dist) itDist = itDist + 1 #Afegir següent Barri barri = [QStandardItem(b[3])] for item in b: barri.append(QStandardItem(item)) dist[0].appendRow(barri) ultimaDistr = int(b[0]) return True except: print("Error en construcció de l'arbre de zones") return False # def llegirDistrictesBarrisCSV(self): # try: # first = True # with open(self.__distBarrisCSV, newline='') as csvFile: # reader = csv.DictReader(csvFile, delimiter=';') # root = self.model.invisibleRootItem() # for row in reader: # if first: # Primer registro # self.labels = ['ZONA'] # for item in row: # self.labels.append(item) # self.model.setColumnCount(len(self.labels)) # self.model.setHorizontalHeaderLabels(self.labels) # first = False # if row['BARRI'] == '': # Registro de distrito # dist = [QStandardItem(row['NOM_DISTRICTE'])] # for item in row.values(): # dist.append(QStandardItem(item)) # root.appendRow(dist) # else: # Registro de barrio # barri = [QStandardItem(row['NOM_BARRI'])] # for item in row.values(): # barri.append(QStandardItem(item)) # dist[0].appendRow(barri) # return True # except: # print('QDistrictesBarris.llegirDistrictesBarrisCSV(): ', sys.exc_info()[0], sys.exc_info()[1]) # return False def llegirRegistre(self): try: click = self.view.currentIndex() #Controlarem si s'ha canviat d'índex o no if hasattr(self, 'ultimIndex') and self.ultimIndex == click: return self.registre self.ultimIndex = click self.registre = {} for i in range(self.model.columnCount()): index = click.sibling(click.row(), i) item = self.model.itemFromIndex(index) self.registre[self.labels[i]] = item.text() self.registre['RANG'] = QgsRectangle(float(self.registre['X_MIN']), \ float(self.registre['Y_MIN']), \ float(self.registre['X_MAX']), \ float(self.registre['Y_MAX'])) except: print('QDistrictesBarris.llegirRegistre(): ', sys.exc_info()[0], sys.exc_info()[1]) finally: return self.registre def llegirRang(self): return self.llegirRegistre()['RANG'] def esDistricte(self): return self.llegirRegistre()['BARRI'] == '' def esBarri(self): return not self.esDistricte() def llegirNom(self): if self.esDistricte(): distr = self.llegirRegistre()["NOM_DISTRICTE"] distr_d = distr + "_d" return distr_d else: barri = self.llegirRegistre()["NOM_BARRI"] if barri == "Barcelona": return barri else: barri_b = barri + "_b" return barri_b def llegirID(self): if self.esDistricte(): return self.llegirRegistre()['DISTRICTE'] return self.llegirRegistre()['BARRI']
class TemplateDocumentSelector(WIDGET, BASE): """ Dialog for selecting a document template from the saved list. """ def __init__(self, parent=None, selectMode=True, filter_data_source='', access_templates=None): QDialog.__init__(self, parent) self.setupUi(self) self.notifBar = NotificationBar(self.vlNotification) self._mode = selectMode # Filter templates by the specified table name self._filter_data_source = filter_data_source # Document templates in current profile self._profile_templates = [] self._current_profile = current_profile() # Load current profile templates self._load_current_profile_templates() self.access_templates = access_templates or [] if selectMode: self.buttonBox.setVisible(True) self.manageButtonBox.setVisible(False) currHeight = self.size().height() self.resize(200, currHeight) else: self.buttonBox.setVisible(False) self.manageButtonBox.setVisible(True) self.setWindowTitle( QApplication.translate("TemplateDocumentSelector", "Template Manager")) # Configure manage buttons btnEdit = self.manageButtonBox.button(QDialogButtonBox.Ok) btnEdit.setText( QApplication.translate("TemplateDocumentSelector", "Edit...")) btnEdit.setIcon(GuiUtils.get_icon("edit.png")) btnDelete = self.manageButtonBox.button(QDialogButtonBox.Save) btnDelete.setText( QApplication.translate("TemplateDocumentSelector", "Delete")) btnDelete.setIcon(GuiUtils.get_icon("delete.png")) # Connect signals self.buttonBox.accepted.connect(self.onAccept) btnEdit.clicked.connect(self.onEditTemplate) btnDelete.clicked.connect(self.onDeleteTemplate) # Get saved document templates then add to the model templates = documentTemplates() self._docItemModel = QStandardItemModel(parent) self._docItemModel.setColumnCount(2) # Append current profile templates to the model. for dt in self._profile_templates: if self._template_contains_filter_table( dt): # and dt.name in self.access_templates: doc_name_item = self._createDocNameItem(dt.name) file_path_item = QStandardItem(dt.path) self._docItemModel.appendRow([doc_name_item, file_path_item]) self.lstDocs.setModel(self._docItemModel) def _load_current_profile_templates(self): # Loads only those templates that refer to tables in the current # profile. if self._current_profile is None: return # Get saved document templates then add to the model templates = documentTemplates() profile_tables = self._current_profile.table_names() # Get templates for the current profile for name, path in templates.items(): doc_temp = DocumentTemplate.build_from_path(name, path) if doc_temp.data_source is None: continue # Assert data source is in the current profile if doc_temp.data_source.referenced_table_name in profile_tables or \ doc_temp.data_source.name() in user_non_profile_views(): self._add_doc_temp(doc_temp) # self._profile_templates.append(doc_temp) def _add_doc_temp(self, doc_temp): found = False for template in self._profile_templates: if template.name == doc_temp.name: found = True break if not found: self._profile_templates.append(doc_temp) def _template_contains_filter_table(self, document_template): # Returns true if the template refers to the filter data source # If no filter data source defined then always return True if document_template.data_source._dataSourceName in user_non_profile_views( ): return True if not self._filter_data_source: return True referenced_table = document_template.referenced_table_name if referenced_table == self._filter_data_source: return True return False @property def mode(self): return self._mode @property def filter_data_source(self): return self._filter_data_source def _createDocNameItem(self, docName): """ Create a template document standard item. """ # Set icon icon = QIcon() icon.addPixmap(GuiUtils.get_icon_pixmap("document.png"), QIcon.Normal, QIcon.Off) dnItem = QStandardItem(icon, docName) return dnItem def onEditTemplate(self): """ Slot raised to edit document template. """ self.notifBar.clear() if self.documentMapping() is None: self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \ "Please select a document template to edit")) return templateName, filePath = self.documentMapping() docName, ok = QInputDialog.getText(self, \ QApplication.translate("TemplateDocumentSelector", "Edit Template"), \ QApplication.translate("TemplateDocumentSelector", "Please enter the new template name below"), \ text=templateName) if ok and docName == "": self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \ "Template name cannot be empty")) return elif docName == templateName: return elif ok and docName != "": result, newTemplatePath = self._editTemplate(filePath, docName) if result: # Update view mIndices = self._selectedMappings() docNameItem = self._docItemModel.itemFromIndex(mIndices[0]) filePathItem = self._docItemModel.itemFromIndex(mIndices[1]) docNameItem.setText(docName) filePathItem.setText(newTemplatePath) self.notifBar.insertSuccessNotification(QApplication.translate("TemplateDocumentSelector", \ "'{0}' template has been successfully updated".format( docName))) else: self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \ "Error: '{0}' template could not be updated".format( templateName))) def onDeleteTemplate(self): """ Slot raised to delete document template. """ self.notifBar.clear() if self.documentMapping() == None: self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \ "Please select a document template to delete")) return templateName, filePath = self.documentMapping() result = QMessageBox.warning(self, QApplication.translate("TemplateDocumentSelector", \ "Confirm delete"), QApplication.translate("TemplateDocumentSelector", \ "Are you sure you want to delete '{0}' template?" \ "This action cannot be undone.\nClick Yes to proceed " \ "or No to cancel.".format(templateName)), QMessageBox.Yes | QMessageBox.No) if result == QMessageBox.No: return status = self._deleteDocument(filePath) if status: # Remove item from list using model index row number selectedDocNameIndices = self.lstDocs.selectionModel( ).selectedRows(0) row = selectedDocNameIndices[0].row() self._docItemModel.removeRow(row) self.notifBar.insertSuccessNotification(QApplication.translate("TemplateDocumentSelector", \ "'{0}' template has been successfully removed".format( templateName))) else: self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \ "Error: '{0}' template could not be removed".format( templateName))) def onAccept(self): """ Slot raised to close the dialog only when a selection has been made by the user. """ self.notifBar.clear() if self.documentMapping() == None: self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \ "Please select a document")) return self.accept() def _selectedMappings(self): """ Returns the model indices for the selected row. """ selectedDocNameIndices = self.lstDocs.selectionModel().selectedRows(0) selectedFilePathIndices = self.lstDocs.selectionModel().selectedRows(1) if len(selectedDocNameIndices) == 0: return None docNameIndex = selectedDocNameIndices[0] filePathIndex = selectedFilePathIndices[0] return (docNameIndex, filePathIndex) def documentMapping(self): """ Returns a tuple containing the selected document name and the corresponding file name. """ mIndices = self._selectedMappings() if mIndices == None: return None docNameItem = self._docItemModel.itemFromIndex(mIndices[0]) filePathItem = self._docItemModel.itemFromIndex(mIndices[1]) return (docNameItem.text(), filePathItem.text()) def _editTemplate(self, templatePath, newName): """ Updates the template document to use the new name. """ templateFile = QFile(templatePath) if not templateFile.open(QIODevice.ReadOnly): QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector", "Open Operation Error"), \ "{0}\n{1}".format( QApplication.translate("TemplateDocumentSelector", "Cannot read template file."), \ templateFile.errorString() )) return (False, "") templateDoc = QDomDocument() if templateDoc.setContent(templateFile): composerElement = templateDoc.documentElement() titleAttr = composerElement.attributeNode("_title") if not titleAttr.isNull(): titleAttr.setValue(newName) # Try remove file status = templateFile.remove() if not status: return (False, "") # Create new file newTemplatePath = self._composerTemplatesPath( ) + "/" + newName + ".sdt" newTemplateFile = QFile(newTemplatePath) if not newTemplateFile.open(QIODevice.WriteOnly): QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector", "Save Operation Error"), \ "{0}\n{1}".format(QApplication.translate("TemplateDocumentSelector", "Could not save template file."), \ newTemplateFile.errorString() )) return (False, "") if newTemplateFile.write(templateDoc.toByteArray()) == -1: QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector", "Save Error"), \ QApplication.translate("TemplateDocumentSelector", "Could not save template file.")) return (False, "") newTemplateFile.close() return (True, newTemplatePath) def _deleteDocument(self, templatePath): """ Delete the document template from the file system. """ docFile = QFile(templatePath) return docFile.remove() def _composerTemplatesPath(self): """ Reads the path of composer templates in the registry. """ regConfig = RegistryConfig() keyName = "ComposerTemplates" valueCollection = regConfig.read([keyName]) if len(valueCollection) == 0: return None else: return valueCollection[keyName]
class QRAVEMetaWidget(QDockWidget, Ui_QRAVEMetaWidgetBase): def __init__(self, parent=None): """Constructor.""" super(QRAVEMetaWidget, self).__init__(parent) self.setupUi(self) self.treeView.setContextMenuPolicy(Qt.CustomContextMenu) self.treeView.customContextMenuRequested.connect(self.open_menu) self.treeView.doubleClicked.connect(self.default_tree_action) self.settings = Settings() self.model = QStandardItemModel() self.treeView.setModel(self.model) self.meta = None self.menu = QMenu() # Initialize our classes self.hide() @pyqtSlot(str, str, dict, bool) def load(self, label: str, meta_type: str, meta: dict, show: bool = False): # re-initialize our model self.model.clear() self.meta = meta root_item = self.model.invisibleRootItem() self.model.setColumnCount(2) self.model.setHorizontalHeaderLabels(['Meta Name', 'Meta Value']) if meta_type == MetaType.PROJECT: self.treeView.setHeaderHidden(False) self.setWindowTitle('Project MetaData: {}'.format(label)) self.treeView.setEnabled(True) if meta is not None and len(meta.keys()) > 0: if 'project' in meta and len(meta['project'].keys()) > 0: proj_meta = QStandardItem('Project Meta') proj_meta_font = proj_meta.font() proj_meta_font.setBold(True) proj_meta.setFont(proj_meta_font) for k, v in meta['project'].items(): proj_meta.appendRow( [QStandardItem(k), QStandardItem(v)]) root_item.appendRow(proj_meta) if 'warehouse' in meta and len(meta['warehouse'].keys()) > 0: wh_meta = QStandardItem('Warehouse Meta') wh_meta_font = proj_meta.font() wh_meta_font.setBold(True) wh_meta.setFont(wh_meta_font) for k, v in meta['warehouse'].items(): wh_meta.appendRow([QStandardItem(k), QStandardItem(v)]) root_item.appendRow(wh_meta) elif meta_type == MetaType.FOLDER: self.setWindowTitle('Folder: {}'.format(label)) self.treeView.setHeaderHidden(True) self.treeView.setEnabled(False) self.model.setColumnCount(1) self.model.setHorizontalHeaderLabels(['Meta Name']) no_item = QStandardItem('Folders have no MetaData') no_item.setTextAlignment(Qt.AlignCenter) no_f = no_item.font() no_f.setItalic(True) no_item.setFont(no_f) root_item.appendRow(no_item) elif meta_type == MetaType.LAYER: self.setWindowTitle('Layer MetaData: {}'.format(label)) self.treeView.setEnabled(True) self.treeView.setHeaderHidden(False) if meta is not None and len(meta.keys()) > 0: for k, v in meta.items(): root_item.appendRow([QStandardItem(k), QStandardItem(v)]) else: self.treeView.setHeaderHidden(True) self.treeView.setEnabled(False) self.model.setColumnCount(1) self.model.setHorizontalHeaderLabels(['Meta Name']) no_item = QStandardItem('This layer has no MetaData') no_item.setTextAlignment(Qt.AlignCenter) no_f = no_item.font() no_f.setItalic(True) no_item.setFont(no_f) root_item.appendRow(no_item) elif meta_type == MetaType.NONE: self.treeView.setHeaderHidden(True) self.treeView.setEnabled(False) self.model.setColumnCount(1) self.setWindowTitle('Riverscapes MetaData: {}'.format(label)) no_item = QStandardItem('This item cannot have metadata') no_item.setTextAlignment(Qt.AlignCenter) no_f = no_item.font() no_f.setItalic(True) no_item.setFont(no_f) root_item.appendRow(no_item) return # self.tree.header().setDefaultSectionSize(180) # self._populateTree(self.tree, ) # Finally expand all levels self.treeView.expandAll() if show is True: self.show() def closeEvent(self, event): self.hide() def default_tree_action(self, index): item = self.model.itemFromIndex(index) data = item.data(Qt.UserRole) def open_menu(self, position): indexes = self.treeView.selectedIndexes() if len(indexes) < 1 or self.meta is None or len(self.meta.keys()) == 0: return # No multiselect so there is only ever one item item_name = self.model.itemFromIndex(indexes[0]) item_val = self.model.itemFromIndex( indexes[1]) if len(indexes) > 0 else None self.menu.clear() if item_val is not None: row_text = {item_name.text(): item_val.text()} self.menu.addAction('Copy Name to Clipboard', lambda: self.copy(item_name.text())) self.menu.addAction('Copy Value to Clipboard', lambda: self.copy(item_val.text())) self.menu.addAction( 'Copy Row to Clipboard (json)', lambda: self.copy( json.dumps(row_text, indent=4, sort_keys=True))) self.menu.addAction( 'Copy All to Clipboard (json)', lambda: self.copy(json.dumps(self.meta, indent=4, sort_keys=True))) self.menu.exec_(self.treeView.viewport().mapToGlobal(position)) def copy(self, data: str): cb = QGuiApplication.clipboard() cb.clear(mode=cb.Clipboard) cb.setText(data, mode=cb.Clipboard)