class WidgetEditList(OWTextableBaseWidget): """Textable widget for modifing the lexical content of the list """ #---------------------------------------------------------------------- # Widget's metadata... name = "Edit Lexical List" description = "Edit words contained in lists (lexical fields)" icon = "icons/lexical_hunter.svg" #---------------------------------------------------------------------- # Channel definitions... inputs = [("Word segmentation", Segmentation, "inputData")] outputs = [("Segmentation with annotations", Segmentation)] #---------------------------------------------------------------------- # Layout parameters... want_main_area = True #---------------------------------------------------------------------- # Settings... settingsHandler = VersionedSettingsHandler( version=__version__.rsplit(".", 1)[0]) textFieldContent = settings.Setting(u''.encode('utf-8')) encoding = settings.Setting(u'utf-8') selectedFields = [] listTitle = "" listWord = "" titleList = settings.Setting([]) baseLocation = settings.Setting('.') def __init__(self, caller): """Widget creator.""" super().__init__() # Variable to communicate with the base widjet by calling # self.creator.vriable_name self.caller = caller # Other attributes... self.inputSeg = None self.outputSeg = None # Next two instructions are helpers from TextableUtils. Corresponding # interface elements are declared here and actually drawn below (at # their position in the UI)... self.infoBox = InfoBox(widget=self.controlArea) # Temporary dictionary so that the user can cancel changes self.tempDict = defaultDict.copy() # User interface... # CONTROL AREA # # Options box for the structure titleListBox = gui.widgetBox( widget=self.controlArea, box="Lists", orientation="horizontal", ) # SAVE AREA # (After the control one but need to be first for the savechange button) SaveBox = gui.widgetBox( widget=self.controlArea, box=None, orientation="horizontal", ) self.SaveChanges = gui.button( widget=SaveBox, master=self, label="Save changes", callback=self.saveChanges, width=130, ) self.CancelChanges = gui.button( widget=SaveBox, master=self, label="Cancel", callback=self.closeWindow, width=130, ) # END OF SAVE AREA # List of Lexical list that the user can select self.titleLabelsList = gui.listBox( widget=titleListBox, master=self, value="selectedFields", # setting (list) labels="titleList", # setting (list) tooltip= "The list of lexical list that you want to use for annotation", callback=self.updateGUI, ) self.titleLabelsList.setMinimumHeight(300) self.titleLabelsList.setMinimumWidth(150) self.titleLabelsList.setSelectionMode(1) # a box for vertical align of the button controlBox = gui.widgetBox( widget=titleListBox, box=None, orientation="vertical", ) # Actions on list self.EditList = gui.button( widget=controlBox, master=self, label="Edit", callback=self.setEditContent, width=130, autoDefault=False, ) self.ImportList = gui.button( widget=controlBox, master=self, label="Import", callback=self.importLexic, width=130, autoDefault=False, ) self.ExportList = gui.button( widget=controlBox, master=self, label="Export All", callback=self.exportAllLexics, width=130, ) self.ExportSelectedList = gui.button( widget=controlBox, master=self, label="Export Selected", callback=self.exportOneLexic, width=130, ) self.NewList = gui.button( widget=controlBox, master=self, label="New", callback=self.newLexicalField, width=130, ) self.ClearList = gui.button( widget=controlBox, master=self, label="Clear all", callback=self.clearList, width=130, ) self.RemoveSelectedList = gui.button( widget=controlBox, master=self, label="Remove Selected", callback=self.deleteSelectedList, width=130, ) # MAIN AREA (edit list) # # structure ... listEditBox = gui.widgetBox( widget=self.mainArea, box="Edit", orientation="vertical", ) listEditBox.setMinimumWidth(300) # Edit the titile of the list self.titleEdit = gui.lineEdit( widget=listEditBox, master=self, value="listTitle", label="List name", orientation="vertical", ) # Editable text Field. Each line gonna be a enter of # the lexical list selected self.ContentLabel = gui.label( widget=listEditBox, master=self, label="List content", ) self.editor = QPlainTextEdit() listEditBox.layout().addWidget(self.editor) self.editor.setMinimumHeight(300) buttonEditBox = gui.widgetBox(widget=listEditBox, box=None, orientation="horizontal") # For saving the chang on the list edit self.CommitList = gui.button( widget=buttonEditBox, master=self, label="Commit", callback=self.saveEdit, width=100, ) self.CancelList = gui.button(widget=buttonEditBox, master=self, label="Cancel list changes", callback=self.cancelListChanges, width=100) gui.rubber(self.controlArea) self.setTitleList() self.updateGUI() # Now Info box and Send button must be drawn... self.infoBox.draw() # Set the window as modal self.exec() def setEditContent(self): """Sets the lexical field informations when the user wants to edit it""" # Getting selected list title self.listTitle = list(self.titleList)[self.selectedFields[0]] # Converting words list to string self.editContent = '\n'.join(self.tempDict[self.listTitle]) # Setting editor content with words list (converted to string) self.editor.setPlainText(self.editContent) # Getting old title (to delete it later if the users wants to) self.oldTitle = self.listTitle self.updateGUI() def setTitleList(self): """Displays the lexical fields titles in the edit widget view""" self.titleList = sorted(self.tempDict.keys()) def clearList(self): """Clears the list of lexical fields""" confBox = QMessageBox( QMessageBox.Question, "Textable", "Do you really want to delete all the lexical lists?", QMessageBox.Yes | QMessageBox.No) # Getting the answer of the user result = confBox.exec_() if result == QMessageBox.Yes: # Reset textfields values self.titleEdit.setText("") self.editor.setPlainText("") # Deleting all lexical fields self.tempDict.clear() self.setTitleList() else: pass def deleteSelectedList(self): """Deletes selected lexical field""" confBox = QMessageBox(QMessageBox.Question, "Textable", "Do you really want to delete this list?", QMessageBox.Yes | QMessageBox.No) # Getting the answer of the user result = confBox.exec_() if result == QMessageBox.Yes: # Getting selected list title self.listToDelete = list(self.titleList)[self.selectedFields[0]] # Reset textfields values self.titleEdit.setText("") self.editor.setPlainText("") # Deleting selected list self.tempDict.pop(self.listToDelete, None) self.titleList = sorted(self.tempDict.keys()) else: pass def newLexicalField(self): """Sets a new entry in the lexical fields dictionnary""" newDict = "New lexical field" i = 1 while newDict in self.tempDict.keys(): newDict = "New lexical field %i" % i i += 1 self.tempDict[newDict] = "" self.setTitleList() def saveEdit(self): """Saves the modifications made by the user on the list""" # Getting textfields values self.val = self.editor.toPlainText() self.newTitle = self.titleEdit.text() # Reset textfields values self.titleEdit.setText("") self.editor.setPlainText("") wordList = self.val.split("\n") self.tempDict[self.newTitle] = wordList # Deleting old key and value if self.newTitle != self.oldTitle: del self.tempDict[self.oldTitle] self.titleList = sorted(self.tempDict.keys()) self.updateGUI() def cancelListChanges(self): # Reset textfields values self.titleEdit.setText("") self.editor.setPlainText("") self.updateGUI() def saveChanges(self): """Saves changes made by the user""" defaultDict.clear() defaultDict.update(self.tempDict) self.hide() self.caller.setTitleList() def closeWindow(self): """Cancels changes made by the user""" self.hide() def importLexic(self): """Lets the user import a lexical field from a text file""" # Opening a file browser filePath = QFileDialog.getOpenFileName(self, u'Import lexical field file', self.baseLocation, u'Text files (*)') if not filePath: return self.file = os.path.normpath(filePath) self.baseLocation = os.path.dirname(filePath) # Gets txt file name and substracts .txt extension fileName = os.path.join(self.baseLocation, self.file) # Cutting the path to get the name if platform.system() == "Windows": listLexicName = fileName.split('\\') else: listLexicName = fileName.split('/') # Getting file name lexicName = listLexicName[-1] lexicName = re.sub('\.txt$', '', lexicName) # Trying to open the files and store their content in a dictionnary # then store all of theses in a list try: fileHandle = open(fileName, encoding='utf-8') content = fileHandle.readlines() # Deleting spaces self.tempDict[lexicName] = [re.sub(r'\s', "", i) for i in content] fileHandle.close() self.setTitleList() except IOError: QMessageBox.warning(None, 'Textable', "Couldn't open file.", QMessageBox.Ok) return def exportOneLexic(self): """Lets the user export the selected list to a text file""" # Opening file browser filePath = QFileDialog.getSaveFileName( self, u'Export Selected Lexical List', self.baseLocation, ) # Setting content to save exportTitle = list(self.titleList)[self.selectedFields[0]] exportContent = self.tempDict[exportTitle] # Saving lexic content if filePath: outputFile = open( filePath, encoding='utf8', mode='w+', errors='xmlcharrefreplace', ) outputFile.write('\n'.join(exportContent)) outputFile.close() QMessageBox.information(None, 'Textable', 'Lexical file correctly exported', QMessageBox.Ok) def exportAllLexics(self): """Lets the user export all the lexics""" # Opening file browser filePath = QFileDialog.getExistingDirectory(self, u'Export Selected List', self.baseLocation) if filePath: for name in self.tempDict: exportName = name.replace(" ", "_") if platform.system() == "Windows": fullName = r"{}\{}.txt".format(filePath, exportName) else: fullName = r"{}/{}.txt".format(filePath, exportName) outputFile = open( fullName, encoding='utf8', mode='w+', errors='xmlcharrefreplace', ) outputFile.write('\n'.join(self.tempDict[name])) outputFile.close() QMessageBox.information(None, 'Textable', 'Lexical files correctly exported', QMessageBox.Ok) def inputData(self, newInput): """Process incoming data.""" pass def updateGUI(self): if self.titleEdit.text() != "": # Disabled elements self.SaveChanges.setDisabled(True) self.CancelChanges.setDisabled(True) self.EditList.setDisabled(True) self.ImportList.setDisabled(True) self.ExportList.setDisabled(True) self.ExportSelectedList.setDisabled(True) self.NewList.setDisabled(True) self.ClearList.setDisabled(True) self.RemoveSelectedList.setDisabled(True) # Enabled elements self.CommitList.setDisabled(False) self.CancelList.setDisabled(False) self.editor.setDisabled(False) self.titleEdit.setDisabled(False) if self.titleEdit.text() == "": # Enabled elements self.SaveChanges.setDisabled(False) self.CancelChanges.setDisabled(False) self.EditList.setDisabled(False) self.ImportList.setDisabled(False) self.ExportList.setDisabled(False) self.ExportSelectedList.setDisabled(False) self.NewList.setDisabled(False) self.ClearList.setDisabled(False) self.RemoveSelectedList.setDisabled(False) # Disabled elements self.CommitList.setDisabled(True) self.CancelList.setDisabled(True) self.editor.setDisabled(True) self.titleEdit.setDisabled(True) if not self.selectedFields: # Disabled elements if a list isn't selected self.RemoveSelectedList.setDisabled(True) self.ExportSelectedList.setDisabled(True) self.EditList.setDisabled(True) # The following method needs to be copied verbatim in # every Textable widget that sends a segmentation... def setCaption(self, title): if 'captionTitle' in dir(self): changed = title != self.captionTitle super().setCaption(title) if changed: self.sendButton.settingsChanged() else: super().setCaption(title)
class LeggerWidget(QDockWidget): """Legger Network widget with tree tables, cross section and sideview and legger profile selection""" # todo: # - category filter on map and tree instead of shortcut # - improve performance 'initial loop tree' closingWidget = pyqtSignal() def __init__(self, parent=None, iface=None, path_legger_db=None): """Constructor.""" super(LeggerWidget, self).__init__(parent) # store arguments self.iface = iface self.path_legger_db = path_legger_db # init parameters self.measured_model = ProfileModel() self.variant_model = ProfileModel() self.legger_model = LeggerTreeModel() self.area_model = AreaTreeModel() if not path_legger_db: messagebar_message("Database selectie", "Selecteer eerst een legger database", level=1) raise Exception("Selecteer eerst een legger database") # create session (before setup_ui) db = LeggerDatabase( {'db_path': path_legger_db}, 'spatialite' ) db.create_and_check_fields() self.session = db.get_session() # todo: request something to test connection and through error message otherwise hydro_object_count = self.session.query(HydroObject).count() if hydro_object_count == 0: messagebar_message("Database selectie", "Database bevat geen hydrovakken", level=1) raise Exception("Database bevat geen hydrovakken") # initial values self.selected_hydrovak = None self.active_begroeiings_variant = SHOW_ALL self.active_begroeiings_variant_strategy = None # setup ui self.setup_ui(self) self.legger_model.setTreeWidget(self.legger_tree_widget) self.area_model.setTreeWidget(self.startpoint_tree_widget) self.category_combo.insertItems(0, ['4', '3', '2', '1']) self.category_combo.setCurrentIndex(0) self.category_filter = 4 self.begroeiings_varianten = OrderedDict( [(SHOW_ALL, 'all'), (PRE_SELECTED, 'pre_selected'), ] + [(v.naam, v) for v in self.session.query(BegroeiingsVariant)] ) self.begroeiings_combo.insertItems( 0, self.begroeiings_varianten.keys()) self.begroeiings_variant_strategies = OrderedDict(( ('alleen dit hydrovak', 'only_this_hydrovak'), ('alle bovenstroomse hydrovakken', 'all_upstream'), )) self.begroeiings_strategy_combo.insertItems(0, self.begroeiings_variant_strategies.keys()) self.begroeiings_strategy_combo.setCurrentIndex(0) self.child_selection_strategies = OrderedDict(( ('gekozen traject tot waarde', 'selected_branch_till_value'), ('gekozen traject tot eind', 'selected_branch_till_end'), ('alleen dit hydrovak', 'selected_hydrovak'), ('bovenstrooms (met zijtakken) tot waarde ', 'upstream_till_value'), ('bovenstrooms (met zijtakken) tot eind', 'upstream_till_end'), )) self.child_selection_strategy_combo.insertItems(0, self.child_selection_strategies.keys()) self.child_selection_strategy_combo.setCurrentIndex(0) # create line layer and add to map self.layer_manager = LeggerMapManager(self.iface, self.path_legger_db) self.line_layer = self.layer_manager.get_line_layer(add_to_map=True) self.vl_tree_layer = self.layer_manager.get_virtual_tree_layer(add_to_map=True) self.vl_endpoint_layer = self.layer_manager.get_endpoint_layer(add_to_map=True) self.vl_track_layer = self.layer_manager.get_track_layer(add_to_map=True) self.vl_hover_layer = self.layer_manager.get_hover_layer(add_to_map=True) self.vl_selected_layer = self.layer_manager.get_selected_layer(add_to_map=True) self.vl_startpoint_hover_layer = self.layer_manager.get_hover_startpoint_layer(add_to_map=True) self.map_visualisation = LeggerMapVisualisation( self.iface, self.line_layer.crs()) # init network line_direct = self.layer_manager.get_line_layer(geometry_col='line') field_nr = line_direct.fieldNameIndex('direction') director = QgsLineVectorLayerDirector( line_direct, field_nr, '2', '1', '3', 3) self.network = NewNetwork( line_direct, self.line_layer, director, None, self.vl_tree_layer, self.vl_endpoint_layer ) # add listeners self.category_combo.currentIndexChanged.connect(self.category_change) self.variant_model.dataChanged.connect(self.data_changed_variant) self.legger_model.dataChanged.connect(self.data_changed_legger_tree) self.area_model.dataChanged.connect(self.data_changed_area_model) self.show_manual_input_button.clicked.connect( self.show_manual_input_window) self.next_endpoint_button.clicked.connect( self.set_next_endpoint) self.begroeiings_combo.currentIndexChanged.connect(self.onSelectBegroeiingsVariant) # self.begroeiings_strategy_combo.currentIndexChanged.connect(self.onSelectBegroeiingsVariantStrategy) # create and init startpoint (AreaTree) model def loop_over(parent, data): for child in data['children']: area = area_class(child) item = AreaTreeItem(area, parent) parent.appendChild(item) loop_over(item, child) # get startingpoints and select first sp_tree = self.network.get_start_arc_tree() root = AreaTreeItem(None, None) loop_over(root, sp_tree) self.area_model.setNewTree(root.childs) # initial, select first area first_area = root.child(0) self.area_model.setDataItemKey(first_area, 'selected', True) def category_change(self, nr): """ filters the tree and re-initialize legger tree nr: nr of selected option (hydrovak category) of combobox return: - """ self.category_filter = int(self.category_combo.currentText()) root = LeggerTreeItem(None, None) self.network.get_tree_data(root, self.category_filter) self.legger_model.setNewTree(root.childs) self.legger_model.set_column_sizes_on_view(self.legger_tree_widget) if len(root.childs) > 0: self.loop_tree(root.childs[0], initial=True) def show_manual_input_window(self): self._new_window = NewWindow( self.legger_model.selected, self.session, callback_on_save=self.update_available_profiles) self._new_window.show() def set_next_endpoint(self): """ select the next endpoint in a traject with no selected variant called by the next_endpoint_button returns: - """ sp = self.legger_model.sp if sp is None: messagebar_message('Fout', 'Selecteer eerst een startpunt (kolom sp)', level=1, # Warning duration=15) return missing_values, endpoint = self.legger_model.find_endpoint_traject_without_legger_profile(sp) if not missing_values or endpoint is None: messagebar_message('Eindpunt selectie', 'Geen traject gevonden met ontbrekende legger', duration=15) else: self.legger_model.open_till_endpoint(endpoint, close_other=True) self.legger_model.setDataItemKey(endpoint, 'ep', True) def loop_tree(self, node, depth=None, initial=False, hover=False, begroeiingsvariant=None, variant_id=None, child_strategy='selected_branch_till_value', begroeiings_strategy='pre_selected', traject_nodes=None): """ recursive loop over younger items where depth can be applied according to available profiles initial (bool): initiele loop om aantal berekende velden te bepalen child_strategy (str): options: - 'selected_branch_till_value', - 'selected_branch_till_end', - 'selected_hydrovak', - 'upstream_till_value', - 'upstream_till_end' begroeiings_strategy (str): options: - 'only_this_hydrovak' - 'all_upstream' - 'minimum' --> not implemented yet - 'maximum' --> not implemented yet :return: """ output_hydrovakken = [node] if initial: variant_id = node.hydrovak.get('selected_variant_id') depth = node.hydrovak.get('selected_depth') elif (variant_id is None and child_strategy in ['selected_branch_till_value', 'upstream_till_value'] and node.hydrovak.get('selected_variant_id')): # stop here, already value there return if initial and variant_id is None: pass elif node.hydrovak['variant_min_depth'] is None: # no variants available, so skip this one and continue downstream pass else: # get selected variant. if variant_id is None, try based on depth and begroeiingsvariant if variant_id is not None: profile_variant = self.session.query(Varianten).filter(Varianten.id == variant_id) if begroeiingsvariant is None or begroeiingsvariant == 'all' and profile_variant.count(): begroeiingsvariant = profile_variant[0].begroeiingsvariant_id else: # use given begroeiingsvariant if stategy is all_upstream otherwise use begroeiingsgraad # set on hydrovak or the default begroeiingsgraad # (correct begroeiingsvariant of first hydrovak is selected by setting variant_id) # "type(begroeiingsvariant) != str" is to filter out setting 'all' if begroeiings_strategy == 'all_upstream' and begroeiingsvariant is not None and type( begroeiingsvariant) != str: profile_variant = self.session.query(Varianten).filter( Varianten.hydro_id == node.hydrovak.get('hydro_id'), Varianten.begroeiingsvariant_id == begroeiingsvariant, Varianten.diepte < depth + precision, Varianten.diepte > depth - precision ) else: profile_variant = self.session.query(Varianten).filter( Varianten.hydro_id == node.hydrovak.get('hydro_id'), or_(Varianten.hydro.has( HydroObject.begroeiingsvariant_id == Varianten.begroeiingsvariant_id), and_(Varianten.hydro.has(HydroObject.begroeiingsvariant_id == None), Varianten.begroeiingsvariant.has(is_default=True))), Varianten.diepte < depth + precision, Varianten.diepte > depth - precision ) if profile_variant.count() > 0: if hover: # self.legger_model.setDataItemKey(node, 'sel d', depth) self.legger_model.setDataItemKey(node, 'selected_depth_tmp', depth) else: # get all info to display in legger table over_depth = node.hydrovak.get('depth') - depth if node.hydrovak.get('depth') is not None else None profilev = profile_variant.first() width = profilev.waterbreedte over_width = node.hydrovak.get('width') - width \ if node.hydrovak.get('width') is not None else None figuren = profilev.figuren score = None if len(figuren) > 0: figuur = figuren[0] over_width = "{0:.2f}".format(figuur.t_overbreedte_l + figuur.t_overbreedte_r) \ if figuur.t_overbreedte_l is not None else over_width score = "{0:.2f}".format(figuur.t_fit) over_depth = "{0:.2f}".format( figuur.t_overdiepte) if figuur.t_overdiepte is not None else over_depth else: over_depth = "{}*".format(try_round(over_depth, 2, '-')) over_width = "{}*".format(try_round(over_width, 2, '-')) verhang = try_round(profilev.verhang, 1, '-') self.legger_model.setDataItemKey(node, 'selected_depth', depth) self.legger_model.setDataItemKey(node, 'selected_width', width) self.legger_model.setDataItemKey(node, 'selected_variant_id', profilev.id) self.legger_model.setDataItemKey(node, 'selected_begroeiingsvariant_id', profilev.begroeiingsvariant_id) self.legger_model.setDataItemKey(node, 'verhang', verhang) self.legger_model.setDataItemKey(node, 'score', score) self.legger_model.setDataItemKey(node, 'over_depth', over_depth) self.legger_model.setDataItemKey(node, 'over_width', over_width) if not initial: # save selected variant selected = self.session.query(GeselecteerdeProfielen).filter( GeselecteerdeProfielen.hydro_id == node.hydrovak.get('hydro_id')).first() if selected: selected.variant = profilev else: selected = GeselecteerdeProfielen( hydro_id=node.hydrovak.get('hydro_id'), variant_id=profilev.id ) self.session.add(selected) elif not initial: # no variant which fits criteria. stop iteration here return if begroeiings_strategy == 'only_this_hydrovak': begroeiingsvariant = None elif begroeiings_strategy == 'all_upstream': # keep variant as it is pass # elif begroeiings_strategy == 'minimum': # pass # elif begroeiings_strategy == 'maximum': # pass if child_strategy == 'selected_hydrovak': loop_childs = [] elif child_strategy in ['upstream_till_value', 'upstream_till_end'] or initial: loop_childs = node.younger() else: # 'selected_branch_till_value', 'selected_branch_till_end' if traject_nodes is None or len(traject_nodes) == 0: loop_childs = [] else: child = traject_nodes.pop(0) loop_childs = [child] for young in loop_childs: hydrovakken = self.loop_tree( young, depth=depth, initial=initial, hover=hover, begroeiingsvariant=begroeiingsvariant, child_strategy=child_strategy, begroeiings_strategy=begroeiings_strategy, traject_nodes=traject_nodes, ) if hydrovakken is not None: output_hydrovakken += hydrovakken return output_hydrovakken def data_changed_legger_tree(self, index, to_index): """ changes during selection and hover of hydrovak / legger tree index (QIndex): index of changed field """ # activate draw node = self.legger_model.data(index, role=Qt.UserRole) if self.legger_model.columns[index.column()].get('field') == 'hover': ids = [feat.id() for feat in self.vl_hover_layer.getFeatures()] self.vl_hover_layer.dataProvider().deleteFeatures(ids) if node.hydrovak.get('hover'): features = [] feat = QgsFeature() feat.setGeometry(node.hydrovak.get('feature').geometry()) try: feat.setAttributes([ node.hydrovak.get('feature')['id']]) features.append(feat) self.vl_hover_layer.dataProvider().addFeatures(features) except KeyError: pass self.vl_hover_layer.commitChanges() self.vl_hover_layer.updateExtents() self.vl_hover_layer.triggerRepaint() elif self.legger_model.columns[index.column()].get('field') == 'selected': if self.legger_model.data(index, role=Qt.CheckStateRole) == Qt.Unchecked: self.save_remarks() self.selected_variant_remark.setPlainText('') self.selected_variant_remark.setDisabled(True) ids = [feat.id() for feat in self.vl_selected_layer.getFeatures()] self.vl_selected_layer.dataProvider().deleteFeatures(ids) if node.hydrovak.get('selected'): if node.hydrovak.get('tak'): self.legger_model.setDataItemKey(node.younger()[1], 'selected', Qt.Checked) else: features = [] feat = QgsFeature() feat.setGeometry(node.hydrovak.get('feature').geometry()) feat.setAttributes([ node.hydrovak.get('feature')['id']]) features.append(feat) self.vl_selected_layer.dataProvider().addFeatures(features) self.vl_selected_layer.commitChanges() self.vl_selected_layer.updateExtents() self.vl_selected_layer.triggerRepaint() if node.hydrovak.get('tak'): pass elif node.hydrovak.get('selected'): self.on_select_edit_hydrovak(self.legger_model.data(index, role=Qt.UserRole)) self.show_manual_input_button.setDisabled(False) elif (self.legger_model.selected is None or self.legger_model.data(index, role=Qt.UserRole) == self.legger_model.selected): self.variant_model.removeRows(0, len(self.variant_model.rows)) self.show_manual_input_button.setDisabled(True) elif self.legger_model.columns[index.column()].get('field') in ['ep', 'sp']: # clear current track if self.legger_model.sp is None or self.legger_model.ep is None: ids = [feat.id() for feat in self.vl_track_layer.getFeatures()] self.vl_track_layer.dataProvider().deleteFeatures(ids) self.vl_track_layer.commitChanges() self.vl_track_layer.triggerRepaint() elif node.hydrovak.get('tak'): if self.legger_model.columns[index.column()].get('field') == 'ep': self.legger_model.setDataItemKey(node.younger()[1], 'ep', Qt.Checked) if self.legger_model.columns[index.column()].get('field') == 'sp': self.legger_model.setDataItemKey(node.younger()[1], 'sp', Qt.Checked) elif self.legger_model.sp and self.legger_model.ep: features = [] def loop_rec(node): if node.hydrovak.get('tak'): node = node.older() else: feat = QgsFeature() feat.setGeometry(node.hydrovak.get('feature').geometry()) feat.setAttributes([ node.hydrovak.get('feature')['id']]) features.append(feat) if node != self.legger_model.sp: loop_rec(node.older()) loop_rec(self.legger_model.ep) self.vl_track_layer.dataProvider().addFeatures(features) self.vl_track_layer.commitChanges() self.vl_track_layer.updateExtents() self.vl_track_layer.triggerRepaint() if self.legger_model.sp is not None: self.next_endpoint_button.setDisabled(False) else: self.next_endpoint_button.setDisabled(True) def data_changed_area_model(self, index, to_index): """ changes during selection and hover of area (start point) table index (QIndex): index of changed field """ if self.area_model.columns[index.column()].get('field') == 'selected': # clear display elements if self.area_model.data(index, role=Qt.CheckStateRole) == Qt.Checked: self.variant_model.removeRows(0, len(self.variant_model.rows)) self.legger_model.set_column_value('hover', False) self.legger_model.set_column_value('selected', False) self.legger_model.set_column_value('ep', False) self.legger_model.set_column_value('sp', False) area_item = self.area_model.data(index, role=Qt.UserRole) self.network.set_tree_start_arc(area_item.area.get('arc_nr')) self.legger_model.clear() root = LeggerTreeItem(None, None) self.network.get_tree_data(root, self.category_filter) self.legger_model.setNewTree(root.childs) self.legger_model.set_column_sizes_on_view(self.legger_tree_widget) if len(root.childs) > 0: self.loop_tree(root.childs[0], initial=True) canvas = self.iface.mapCanvas() extent = self.vl_tree_layer.extent() if extent: extent.scale(1.2) canvas.setExtent(extent) elif self.area_model.columns[index.column()].get('field') == 'hover': ids = [feat.id() for feat in self.vl_startpoint_hover_layer.getFeatures()] self.vl_startpoint_hover_layer.dataProvider().deleteFeatures(ids) value = self.area_model.data(index, role=Qt.DisplayRole) if self.area_model.data(index, role=Qt.CheckStateRole) == Qt.Checked: features = [] node = self.area_model.data(index, role=Qt.UserRole) feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPoint(node.area.get('point'))) feat.setAttributes([ node.area.get('vertex_id')]) features.append(feat) self.vl_startpoint_hover_layer.dataProvider().addFeatures(features) self.vl_startpoint_hover_layer.commitChanges() self.vl_startpoint_hover_layer.updateExtents() self.vl_startpoint_hover_layer.triggerRepaint() def data_changed_variant(self, index): """ changes during selection and hover of variant table index (QIndex): index of changed field """ item = self.variant_model.rows[index.row()] if self.variant_model.columns[index.column()].name == 'active': if item.active.value: # only one selected at the time item.color.value = list(item.color.value)[:3] + [255] for row in self.variant_model.rows: if row.active.value and row != item: row.active.value = False depth = item.depth.value selected_variant_id = item.name.value traject = [] if self.legger_model.ep: traject = self.legger_model.ep.up(self.legger_model.selected) traject.reverse() if len(traject) > 0: traject.pop(0) else: messagebar_message( 'Traject nodig', 'Selecteer eerst een traject (sp en ep) voordat diepte kan worden doorgetrokken.', 1, 15) return self.loop_tree( self.legger_model.selected, depth=depth, initial=False, variant_id=selected_variant_id, begroeiingsvariant=self.get_begroeiings_variant(), child_strategy=self.get_child_selection_strategy(), begroeiings_strategy=self.get_begroeiings_strategy(), traject_nodes=traject ) self.session.commit() # trigger repaint of sideview self.sideview_widget.draw_selected_lines(self.sideview_widget._get_data()) else: item.color.value = list(item.color.value)[:3] + [20] # trigger repaint of sideview self.sideview_widget.draw_selected_lines(self.sideview_widget._get_data()) elif self.variant_model.columns[index.column()].name == 'hover': if item.hover.value: # only one selected at the time item.color.value = list(item.color.value)[:3] + [255] for row in self.variant_model.rows: if row.hover.value and row != item: row.hover.value = False depth = item.depth.value selected_variant_id = item.name.value traject = [] self.legger_model.set_column_value('selected_depth_tmp', None) if self.legger_model.ep: traject = self.legger_model.ep.up(self.legger_model.selected) traject.reverse() if len(traject) > 0: traject.pop(0) else: messagebar_message( 'Traject nodig', 'Selecteer eerst een traject (sp en ep) voordat diepte kan worden doorgetrokken.', 1, 15) return hydrovakken = self.loop_tree( self.legger_model.selected, depth=depth, initial=False, hover=True, variant_id=selected_variant_id, begroeiingsvariant=self.get_begroeiings_variant(), child_strategy=self.get_child_selection_strategy(), begroeiings_strategy=self.get_begroeiings_strategy(), traject_nodes=traject ) # set map visualisation of selected hydrovakken self.network._virtual_tree_layer.setSubsetString( '"hydro_id" in (\'{ids}\')'.format( ids='\',\''.join([str(hydrovak.hydrovak['hydro_id']) for hydrovak in hydrovakken]))) # trigger repaint of sideview self.sideview_widget.draw_selected_lines(self.sideview_widget._get_data()) else: self.legger_model.set_column_value('selected_depth_tmp', None) # reset map visualisation self.network._virtual_tree_layer.setSubsetString('') # trigger repaint of sideview self.sideview_widget.draw_selected_lines(self.sideview_widget._get_data()) def on_select_edit_hydrovak(self, item): """ set elements after selection of a hydrovak for profile selection item (LeggerTreeItem): selected hydrovak LeggerTreeItem return: - """ hydro_object = self.session.query(HydroObject).filter_by(id=item.hydrovak.get('hydro_id')).first() if hydro_object is None: self.selected_variant_remark.setPlainText('') self.selected_variant_remark.setDisabled(True) return None self.selected_hydrovak = item self.selected_hydrovak = item self.selected_hydrovak_db = hydro_object self.selected_variant_remark.setDisabled(False) self.selected_variant_remark.setPlainText(item.hydrovak.get('selected_remarks')) self.update_available_variants() def save_remarks(self): if self.selected_hydrovak: if self.selected_hydrovak_db: self.selected_hydrovak_db.opmerkingen = self.selected_variant_remark.toPlainText() self.session.add(self.selected_hydrovak_db) self.session.commit() self.legger_model.setDataItemKey( self.selected_hydrovak, 'selected_remarks', self.selected_variant_remark.toPlainText()) def update_available_variants(self): item = self.selected_hydrovak hydro_object = self.selected_hydrovak_db self.variant_model.removeRows(0, len(self.variant_model.rows)) selected_variant_id = item.hydrovak.get('selected_variant_id') var = self.session.query(Varianten) \ .join(BegroeiingsVariant) \ .outerjoin(ProfielFiguren) \ .filter(Varianten.hydro == hydro_object) \ .order_by(Varianten.diepte) if self.active_begroeiings_variant == SHOW_ALL: pass elif self.active_begroeiings_variant == PRE_SELECTED: var = var.filter(or_(Varianten.begroeiingsvariant == hydro_object.begroeiingsvariant, Varianten.id == selected_variant_id)) elif self.active_begroeiings_variant is not None: var = var.filter(or_(BegroeiingsVariant.naam == self.active_begroeiings_variant, Varianten.id == selected_variant_id)) from legger import settings verhang = 3.0 color_map = ( (1.0, settings.LOW_COLOR), (3.0, settings.OK_COLOR), (4.0, settings.HIGH_COLOR), ) profs = [] for profile in var.all(): active = selected_variant_id == profile.id over_width = None over_depth = None if profile.figuren: over_width = profile.figuren[0].t_overbreedte_l + profile.figuren[0].t_overbreedte_r over_depth = profile.figuren[0].t_overdiepte else: if profile.hydro.kenmerken and profile.hydro.kenmerken[0].diepte is not None and profile.diepte is not None: over_depth = profile.hydro.kenmerken[0].diepte - profile.diepte if profile.hydro.kenmerken and profile.hydro.kenmerken[0].breedte is not None and profile.waterbreedte is not None: over_width = profile.hydro.kenmerken[0].breedte - profile.waterbreedte profs.append({ 'name': profile.id, 'active': active, # digits differ far after the 'depth': profile.diepte, 'begroeiingsvariant': profile.begroeiingsvariant.naam, 'score': profile.figuren[0].t_fit if profile.figuren else None, 'over_depth': over_depth if over_depth is not None else None, 'over_width': over_width if over_depth is not None else None, 'over_width_color': [255, 0, 0] if over_width < 0 else [255, 255, 255], 'verhang': profile.verhang, 'color': interpolated_color(value=profile.verhang, color_map=color_map, alpha=(255 if active else 80)), 'points': [ (-0.5 * profile.waterbreedte, hydro_object.streefpeil), (-0.5 * profile.bodembreedte, hydro_object.streefpeil - profile.diepte), (0.5 * profile.bodembreedte, hydro_object.streefpeil - profile.diepte), (0.5 * profile.waterbreedte, hydro_object.streefpeil), ] }) self.variant_model.insertRows(profs) def update_available_profiles(self, item, variant): """ used for updating ranges after adding a profile manually """ # update variant table self.on_select_edit_hydrovak(item) diepte = float(variant.diepte) if item.hydrovak.get('variant_max_depth') is None or diepte > item.hydrovak.get('variant_max_depth'): self.legger_model.setDataItemKey(item, 'variant_max_depth', diepte) if item.hydrovak.get('variant_min_depth') is None or diepte < item.hydrovak.get('variant_min_depth'): self.legger_model.setDataItemKey(item, 'variant_min_depth', diepte) def onSelectBegroeiingsVariant(self): self.active_begroeiings_variant = self.begroeiings_combo.currentText() self.update_available_variants() def get_begroeiings_variant(self): return self.begroeiings_varianten[self.begroeiings_combo.currentText()] def get_begroeiings_strategy(self): return self.begroeiings_variant_strategies[self.begroeiings_strategy_combo.currentText()] def get_child_selection_strategy(self): return self.child_selection_strategies[self.child_selection_strategy_combo.currentText()] def closeEvent(self, event): """ close event for widget, including removal of layers and disconnection of listeners event: close event return: None """ self.save_remarks() if self.vl_tree_layer in QgsMapLayerRegistry.instance().mapLayers().values(): QgsMapLayerRegistry.instance().removeMapLayer(self.vl_tree_layer) if self.line_layer in QgsMapLayerRegistry.instance().mapLayers().values(): QgsMapLayerRegistry.instance().removeMapLayer(self.line_layer) if self.vl_endpoint_layer in QgsMapLayerRegistry.instance().mapLayers().values(): QgsMapLayerRegistry.instance().removeMapLayer(self.vl_endpoint_layer) if self.vl_track_layer in QgsMapLayerRegistry.instance().mapLayers().values(): QgsMapLayerRegistry.instance().removeMapLayer(self.vl_track_layer) if self.vl_hover_layer in QgsMapLayerRegistry.instance().mapLayers().values(): QgsMapLayerRegistry.instance().removeMapLayer(self.vl_hover_layer) if self.vl_selected_layer in QgsMapLayerRegistry.instance().mapLayers().values(): QgsMapLayerRegistry.instance().removeMapLayer(self.vl_selected_layer) if self.vl_startpoint_hover_layer in QgsMapLayerRegistry.instance().mapLayers().values(): QgsMapLayerRegistry.instance().removeMapLayer(self.vl_startpoint_hover_layer) self.category_combo.currentIndexChanged.disconnect(self.category_change) self.show_manual_input_button.clicked.disconnect(self.show_manual_input_window) self.next_endpoint_button.clicked.disconnect(self.set_next_endpoint) self.variant_model.dataChanged.disconnect(self.data_changed_variant) self.legger_model.dataChanged.disconnect(self.data_changed_legger_tree) self.area_model.dataChanged.disconnect(self.data_changed_area_model) self.begroeiings_combo.currentIndexChanged.disconnect(self.onSelectBegroeiingsVariant) self.legger_model.setTreeWidget(None) self.closingWidget.emit() event.accept() def setup_ui(self, dock_widget): """ initiate main Qt building blocks of interface :param dock_widget: QDockWidget instance """ dock_widget.setObjectName("dock_widget") dock_widget.setAttribute(Qt.WA_DeleteOnClose) self.dock_widget_content = QWidget(self) self.dock_widget_content.setObjectName("dockWidgetContent") self.main_vlayout = QVBoxLayout(self) self.dock_widget_content.setLayout(self.main_vlayout) # add button to add objects to graphs self.button_bar_hlayout = QHBoxLayout(self) self.show_manual_input_button = QPushButton(self) self.button_bar_hlayout.addWidget(self.show_manual_input_button) self.show_manual_input_button.setDisabled(True) self.button_bar_hlayout.addWidget(QLabel("filter t/m categorie:")) self.category_combo = QComboBox(self) self.button_bar_hlayout.addWidget(self.category_combo) self.next_endpoint_button = QPushButton(self) self.button_bar_hlayout.addWidget(self.next_endpoint_button) self.next_endpoint_button.setDisabled(True) self.child_selection_strategy_combo = QComboBox(self) self.button_bar_hlayout.addWidget(QLabel("doortrekken tot:")) self.button_bar_hlayout.addWidget(self.child_selection_strategy_combo) spacer_item = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.button_bar_hlayout.addItem(spacer_item) # self.button_bar_hlayout.addItem(QLabel("doortrekken tot:")) # self.button_bar_hlayout.addItem(self.begroeiings_strategy_combo) self.main_vlayout.addLayout(self.button_bar_hlayout) # add tabWidget for graphWidgets self.contentLayout = QHBoxLayout(self) self.tree_table_tab = QTabWidget(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.tree_table_tab.sizePolicy().hasHeightForWidth()) self.tree_table_tab.setSizePolicy(sizePolicy) self.tree_table_tab.setMinimumSize(QSize(850, 0)) self.contentLayout.addWidget(self.tree_table_tab) # startpointTree self.startpoint_tree_widget = StartpointTreeWidget(self, self.area_model) # sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) # sizePolicy.setHorizontalStretch(0) # sizePolicy.setVerticalStretch(0) # sizePolicy.setHeightForWidth( # self.legger_tree_widget.sizePolicy().hasHeightForWidth()) # self.legger_tree_widget.setSizePolicy(sizePolicy) # self.legger_tree_widget.setMinimumSize(QSize(750, 0)) self.tree_table_tab.addTab(self.startpoint_tree_widget, 'startpunten') # LeggerTree self.legger_tree_widget = LeggerTreeWidget(self, self.legger_model) # sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) # sizePolicy.setHorizontalStretch(0) # sizePolicy.setVerticalStretch(0) # sizePolicy.setHeightForWidth( # self.legger_tree_widget.sizePolicy().hasHeightForWidth()) # self.legger_tree_widget.setSizePolicy(sizePolicy) # self.legger_tree_widget.setMinimumSize(QSize(750, 0)) self.tree_table_tab.addTab(self.legger_tree_widget, 'hydrovakken') # graphs self.graph_vlayout = QVBoxLayout(self) # Graph self.plot_widget = LeggerPlotWidget( self, session=self.session, legger_model=self.legger_model, variant_model=self.variant_model) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.plot_widget.sizePolicy().hasHeightForWidth()) self.plot_widget.setSizePolicy(sizePolicy) self.plot_widget.setMinimumSize(QSize(250, 150)) self.graph_vlayout.addWidget(self.plot_widget, 2) # Sideview Graph self.sideview_widget = LeggerSideViewPlotWidget( self, session=self.session, legger_model=self.legger_model) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.sideview_widget.sizePolicy().hasHeightForWidth()) self.sideview_widget.setSizePolicy(sizePolicy) self.sideview_widget.setMinimumSize(QSize(250, 150)) self.graph_vlayout.addWidget(self.sideview_widget) self.contentLayout.addLayout(self.graph_vlayout, 2) self.rightVstack = QVBoxLayout(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self.begroeiings_combo = QComboBox(self) self.begroeiings_strategy_combo = QComboBox(self) self.groupBox_begroeiings = QGroupBox(self) self.groupBox_begroeiings.setTitle("begroeiingsfilter en voor welk deel") vbox_strat = QVBoxLayout() vbox_strat.addWidget(self.begroeiings_combo) vbox_strat.addWidget(self.begroeiings_strategy_combo) self.groupBox_begroeiings.setLayout(vbox_strat) self.rightVstack.addWidget(self.groupBox_begroeiings) # variantentable self.plot_item_table = VariantenTable(self, variant_model=self.variant_model) self.plot_item_table.setMinimumWidth(380) self.rightVstack.addWidget(self.plot_item_table) self.selected_variant_remark = QPlainTextEdit(self) self.selected_variant_remark.setFixedHeight(100) self.selected_variant_remark.setDisabled(True) self.rightVstack.addWidget(self.selected_variant_remark) self.contentLayout.addLayout(self.rightVstack, 0) self.main_vlayout.addLayout(self.contentLayout) # add dockwidget dock_widget.setWidget(self.dock_widget_content) self.retranslate_ui(dock_widget) QMetaObject.connectSlotsByName(dock_widget) def retranslate_ui(self, dock_widget): pass dock_widget.setWindowTitle(_translate( "DockWidget", "Legger", None)) self.show_manual_input_button.setText(_translate( "DockWidget", "Voeg profiel toe", None)) self.next_endpoint_button.setText(_translate( "DockWidget", "Volgend eindpunt", None))