def __init__(self, ms): """ constructor """ super(MSTableModel, self).__init__(None) self.ms = ms self.valid_codes = self.ms.taxonomy.codes self.headers = [ get_ui_string("widget.mod.tableheader.zone"), get_ui_string("widget.mod.tableheader.path"), get_ui_string("widget.mod.tableheader.value"), get_ui_string("widget.mod.tableheader.weight"),] self.modifiers = [] self.row_count = 0 # total row count for zone, stat in self.ms.assignments(): # get all modifier in the tree for node, idx, modifier in stat.get_modifiers(10): # each modifier has several values that will be listed in # different rows in the table # start_count / end_count are start/end row index for the table start_count = self.row_count self.row_count += len(modifier.keys()) end_count = self.row_count # build the string containing path to the node parent = node parent_str = [] for i in range(node.level): parent_str.append(str(parent.value)) # move up to next parent parent = parent.parent # reverse to put root at the beginning parent_str.reverse() self.modifiers.append((zone.name, "/".join(parent_str), start_count, end_count, idx, modifier, node))
def deleteMSBranch(self, node): """ delete selected node and children from mapping scheme tree """ self.ui.statusbar.showMessage( get_ui_string("app.status.ms.processing")) self.project.ms.delete_branch(node) self.visualizeMappingScheme(self.project.ms) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.modified"))
def loadProj(self): """ open file dialog to load an existing application """ self.getOpenFileName(self, get_ui_string("app.window.msg.project.open"), get_ui_string("app.extension.db"), self.openProjectFile) self.ui.statusbar.showMessage(get_ui_string("app.status.project.loaded"))
def closeProject(self): """ close opened project and update UI elements accordingly """ # adjust UI in application window self.tab_result.closeAll() # this call must happen first. # otherwise, it locks temporary GIS files self.ui.mainTabs.setTabEnabled(self.TAB_DATA, False) self.ui.mainTabs.setTabEnabled(self.TAB_MS, False) self.ui.mainTabs.setTabEnabled(self.TAB_MOD, False) self.ui.mainTabs.setTabEnabled(self.TAB_RESULT, False) self.showTab(self.TAB_DATA) # disable menu/menu items self.ui.actionSave.setEnabled(False) self.ui.actionSave_as.setEnabled(False) self.ui.actionMapping_Schemes.setEnabled(False) self.ui.actionResult.setEnabled(False) self.ui.actionProcessing_Options.setEnabled(False) if getattr(self, 'project', None) is not None: # save existing project is needed if self.project.require_save: ans = QMessageBox.question(self, get_ui_string("app.window.msg.project.not_saved"), get_ui_string("app.window.msg.project.save_or_not"), buttons=QMessageBox.Yes|QMessageBox.No, defaultButton=QMessageBox.Yes) if ans == QMessageBox.Yes: self.saveProj() # adjust UI in tabs self.tab_datainput.closeProject() self.tab_ms.clearMappingScheme() self.tab_mod.closeMappingScheme() self.project.clean_up() del self.project self.project = None
def setProcessingOptions(self): if self.project is None: return # set options to be those defined in project self.proc_options.resetOptions() for attribute in dir(self.proc_options): try: proc_attribute = self.project.operator_options['proc.%s'%attribute] setattr(self.proc_options, attribute, proc_attribute) except: # for empty project, this is the first time proc.options is set # just use default from proc_option dialogbox pass if self.proc_options.exec_() == QDialog.Accepted: for attribute in dir(self.proc_options): self.project.operator_options['proc.%s'%attribute] = getattr(self.proc_options, attribute) # alert user answer = QMessageBox.question(self, get_ui_string("app.confirm.title"), get_ui_string("app.confirm.build.exposure"), buttons = QMessageBox.No | QMessageBox.Yes, defaultButton=QMessageBox.No) if answer == QMessageBox.No: return self.buildExposure()
def appendMSBranch(self, node, branch): """ append a branch (from library) to a node in a mapping scheme tree """ self.ui.statusbar.showMessage( get_ui_string("app.status.ms.processing")) self.project.ms.append_branch(node, branch) self.visualizeMappingScheme(self.project.ms) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.modified"))
def createEmptyMS(self): """ build an empty mapping scheme tree for user to manipulate manually """ self.ui.statusbar.showMessage(get_ui_string("app.status.ms.processing")) # invoke asynchronously invoke_async(get_ui_string("app.status.processing"), self.project.create_empty_ms) self.visualizeMappingScheme(self.project.ms) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.created"))
def exportResults(self, export_format, export_path): """ export mapping scheme leaves as CSV """ self.ui.statusbar.showMessage(get_ui_string("app.status.exposure.exported")) # invoke asynchronously self.project.set_export(export_format, export_path) invoke_async(get_ui_string("app.status.processing"), self.project.export_data) self.ui.statusbar.showMessage(get_ui_string("app.status.exposure.exported"))
def setProcessingOptions(self): if self.project is None: return # set options to be those defined in project self.proc_options.resetOptions() for attribute in dir(self.proc_options): try: proc_attribute = self.project.operator_options['proc.%s' % attribute] setattr(self.proc_options, attribute, proc_attribute) except: # for empty project, this is the first time proc.options is set # just use default from proc_option dialogbox pass if self.proc_options.exec_() == QDialog.Accepted: for attribute in dir(self.proc_options): self.project.operator_options['proc.%s' % attribute] = getattr( self.proc_options, attribute) # alert user answer = QMessageBox.question( self, get_ui_string("app.confirm.title"), get_ui_string("app.confirm.build.exposure"), buttons=QMessageBox.No | QMessageBox.Yes, defaultButton=QMessageBox.No) if answer == QMessageBox.No: return self.buildExposure()
def loadMS(self, path): self.ui.statusbar.showMessage( get_ui_string("app.status.ms.processing")) # invoke asynchronously invoke_async(get_ui_string("app.status.processing"), self.project.load_ms, path) self.visualizeMappingScheme(self.project.ms) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.created"))
def loadProj(self): """ open file dialog to load an existing application """ self.getOpenFileName(self, get_ui_string("app.window.msg.project.open"), get_ui_string("app.extension.db"), self.openProjectFile) self.ui.statusbar.showMessage( get_ui_string("app.status.project.loaded"))
def exportMS(self, path, format): """ export mapping scheme leaves as CSV """ self.ui.statusbar.showMessage( get_ui_string("app.status.ms.processing")) # invoke asynchronously invoke_async(get_ui_string("app.status.processing"), self.project.export_ms, path, format) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.exported"))
def createEmptyMS(self): """ build an empty mapping scheme tree for user to manipulate manually """ self.ui.statusbar.showMessage( get_ui_string("app.status.ms.processing")) # invoke asynchronously invoke_async(get_ui_string("app.status.processing"), self.project.create_empty_ms) self.visualizeMappingScheme(self.project.ms) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.created"))
def exportResults(self, export_format, export_path): """ export mapping scheme leaves as CSV """ self.ui.statusbar.showMessage( get_ui_string("app.status.exposure.exported")) # invoke asynchronously self.project.set_export(export_format, export_path) invoke_async(get_ui_string("app.status.processing"), self.project.export_data) self.ui.statusbar.showMessage( get_ui_string("app.status.exposure.exported"))
def buildMappingScheme(self): """ build mapping scheme with given data """ self.ui.statusbar.showMessage(get_ui_string("app.status.ms.processing")) # invoke asynchronously try: invoke_async(get_ui_string("app.status.processing"), self.project.build_ms) except SIDDException as err: # different error message used in this case raise SIDDUIException(get_ui_string('project.error.sampling', str(err))) self.visualizeMappingScheme(self.project.ms) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.created"))
def saveProjAs(self): if self.project is None: return filename = QFileDialog.getSaveFileName( self, get_ui_string("app.window.msg.project.create"), get_app_dir(), get_ui_string("app.extension.db")) # no need to check for file overwrite, because QFileDialog return always confirmed overwrite if not filename.isNull(): filename = str(filename) self.project.set_project_path(filename) self.project.sync(SyncModes.Write) self.saveLastOpenDir(filename[0:filename.rfind("/")]) self.ui.statusbar.showMessage( get_ui_string("app.status.project.saved"))
def saveProjAs(self): if self.project is None: return filename = QFileDialog.getSaveFileName(self, get_ui_string("app.window.msg.project.create"), get_app_dir(), get_ui_string("app.extension.db")) # no need to check for file overwrite, because QFileDialog return always confirmed overwrite if not filename.isNull(): filename = str(filename) self.project.set_project_path(filename) self.project.sync(SyncModes.Write) self.saveLastOpenDir(filename[0:filename.rfind("/")]) self.ui.statusbar.showMessage(get_ui_string("app.status.project.saved"))
def showVerificationResults(self): """ show the result of data verification """ NO_KEY = ":/imgs/icons/no.png" YES_KEY = ":/imgs/icons/yes.png" project = self.project # if project is None or project.fp_type == FootprintTypes.None: self.ui.img_lb_verify_fp.setPixmap(QPixmap(NO_KEY)) else: self.ui.img_lb_verify_fp.setPixmap(QPixmap(YES_KEY)) if project is None or project.survey_type == SurveyTypes.None: self.ui.img_lb_verify_svy.setPixmap(QPixmap(NO_KEY)) else: self.ui.img_lb_verify_svy.setPixmap(QPixmap(YES_KEY)) if project is None or project.zone_type == ZonesTypes.None: self.ui.img_lb_verify_zones.setPixmap(QPixmap(NO_KEY)) else: self.ui.img_lb_verify_zones.setPixmap(QPixmap(YES_KEY)) if project is None or project.popgrid_type == PopGridTypes.None: self.ui.img_lb_verify_pop.setPixmap(QPixmap(NO_KEY)) else: self.ui.img_lb_verify_pop.setPixmap(QPixmap(YES_KEY)) if project is None or project.output_type == OutputTypes.Grid: self.ui.img_lb_verify_agg_grid.setPixmap(QPixmap(YES_KEY)) self.ui.img_lb_verify_agg_zone.setPixmap(QPixmap(NO_KEY)) else: self.ui.img_lb_verify_agg_zone.setPixmap(QPixmap(YES_KEY)) self.ui.img_lb_verify_agg_grid.setPixmap(QPixmap(NO_KEY)) if project is None: self.ui.txt_verify_text.setText('') elif project.status == ProjectStatus.ReadyForExposure: self.ui.txt_verify_text.setText(get_ui_string('widget.input.verify.sucess')) elif project.status == ProjectStatus.ReadyForMS: self.ui.txt_verify_text.setText(get_ui_string('widget.input.verify.datarequired')) # append error messages for err in project.errors: errMsg = get_ui_string('project.error.%s' % str(err)) if errMsg == '': errMsg = get_ui_string('widget.input.verify.unknownerror') self.ui.txt_verify_text.append('-%s' % errMsg) else: #project.status == ProjectStatus.NotVerified: self.ui.txt_verify_text.setText(get_ui_string('widget.input.verify.noaction'))
def buildMappingScheme(self): """ build mapping scheme with given data """ self.ui.statusbar.showMessage( get_ui_string("app.status.ms.processing")) # invoke asynchronously try: invoke_async(get_ui_string("app.status.processing"), self.project.build_ms) except SIDDException as err: # different error message used in this case raise SIDDUIException( get_ui_string('project.error.sampling', str(err))) self.visualizeMappingScheme(self.project.ms) self.ui.statusbar.showMessage(get_ui_string("app.status.ms.created"))
def __init__(self, values, weights, parser, valid_codes, is_editable=[True, True]): """ constructor """ super(MSLevelTableModel, self).__init__() # table header self.headers = [ get_ui_string('dlg.msbranch.edit.tableheader.value'), get_ui_string('dlg.msbranch.edit.tableheader.weight'), 'Value', 'Weight (%)' ] self.parser=parser self.valid_codes=valid_codes self.values, self.weights = self.do_sort(values, weights) self.is_editable = is_editable self.editable_indices = {}
def __init__(self, values, weights, parser, valid_codes, is_editable=[True, True]): """ constructor """ super(MSLevelTableModel, self).__init__() # table header self.headers = [ get_ui_string("dlg.msbranch.edit.tableheader.value"), get_ui_string("dlg.msbranch.edit.tableheader.weight"), "Value", "Weight (%)", ] self.parser = parser self.valid_codes = valid_codes self.values, self.weights = self.do_sort(values, weights) self.is_editable = is_editable self.editable_indices = {}
def editModifier(self): """ edit selected modifier """ mod = self.getSelectedModifier() # make sure there is mod selected if mod is None: logUICall.log(get_ui_string("widget.ms.warning.node.required"), logUICall.WARNING) return # show edit dialog box for selected modifier self.dlgEditMod.setNode(self.ms, mod) ans = self.dlgEditMod.exec_() # accepted means apply change if ans == QDialog.Accepted: # NOTE: dlgEditMod already should have performed all the checks on # values/weights pair, we can safely assume that data is clean # to be used #[zone_name, bldg_type, startIdx, endIdx, modidx, modifier, node] = mod if self.dlgEditMod.node is not None: modifier = StatisticModifier(self.dlgEditMod.modifier_name) for value, weight in map(None, self.dlgEditMod.values, self.dlgEditMod.weights): modifier.values[value] = weight self.dlgEditMod.node.set_modifier(self.dlgEditMod.modidx, modifier) self.app.visualizeMappingScheme(self.ms)
def createWizard(self): try: # should not update preview while using wizard self.setVisible(False) self.previewInput = False wizard = WidgetDataWizard(self, Project(self.app_config, self.taxonomy)) if wizard.exec_() == QDialog.Accepted: # setProject makes call to GIS component that requires visibility self.setVisible(True) self.previewInput = True self.setProject(wizard.project) self.ui.statusbar.showMessage( get_ui_string("app.status.project.created")) # else # do nothing? except: pass finally: # return to normal window # these calls are reached # 1. in case any exception occurs, # 2. wizard finished or cancelled self.setVisible(True) self.previewInput = True
def verifyData(self, item): """ callback at each table value update. two checks - value is integer - range is valid with new value """ item_val = item.data(Qt.DisplayRole) if item_val == QVariant('None'): return int_val = item_val.toInt() row, col = item.row(), item.column() if int_val[1]: # is integer # set value self.range_values[col][row] = int_val[0] # allow set range only if is valid range_is_valid = False try: range_is_valid = self.is_range_valid() except SIDDRangeGroupException as err: # error means not valid self.ui.lb_notes.setText(err.message) except Exception as err: # error means not valid self.ui.lb_notes.setText(err.message) self.ui.buttons.button(QDialogButtonBox.Ok).setEnabled(range_is_valid) else: # not integer # restore logUICall.log(get_ui_string('dlg.attr.value.error'), logUICall.WARNING) self.ui.table_ranges.setItem(row, col, QTableWidgetItem('%s'%self.range_values[col][row]))
def createBlank(self): """ create a new project """ # create new project file project = Project(self.app_config, self.taxonomy) # open project and sync UI self.setProject(project, skipVerify=True) self.ui.statusbar.showMessage(get_ui_string("app.status.project.created"))
def mapEditTheme(self): """ event handler for btn_edit - identify item on map """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) # build layer render property Dialog for selected layer dlg_render = QDialog() dlg_render.setWindowTitle(get_ui_string('widget.result.renderer.settings')) dlg_render.setModal(True) dlg_render.setFixedSize(530, 370) dlg_render.renderer = QgsRendererV2PropertiesDialog(self.map_layers[cur_layer_idx], self.style, True) dlg_render.renderer.setParent(dlg_render) dlg_render.renderer.setGeometry(QRect(10, 10, 510, 325)) dlg_render.buttonBox = QDialogButtonBox(dlg_render) dlg_render.buttonBox.setGeometry(QRect(10, 335, 510, 25)) dlg_render.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) dlg_render.buttonBox.accepted.connect(dlg_render.accept) dlg_render.buttonBox.accepted.connect(dlg_render.renderer.onOK) dlg_render.buttonBox.rejected.connect(dlg_render.reject) dlg_render.setVisible(True) # get user input and update renderer answer = dlg_render.exec_() if answer == QDialog.Accepted: self.map_layer_renderer[cur_layer_idx] = None self.map_layer_renderer[cur_layer_idx] = self.map_layers[cur_layer_idx].rendererV2().clone() self.canvas.refresh() dlg_render.destroy() del dlg_render except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING)
def wrapper(*args, **kw): self.main_window.setEnabled(False) try: logUICall.log('function call %s from module %s' % (f.__name__, f.__module__), logUICall.DEBUG) return f(*args, **kw) except SIDDUIException as uie: logUICall.log(uie, logUICall.WARNING) self.main_window.ui.statusbar.showMessage(get_ui_string('app.error.ui')) except SIDDException as se: logUICall.log(se, logUICall.WARNING) self.main_window.ui.statusbar.showMessage(get_ui_string('app.error.model')) except Exception as e: logUICall.log(e, logUICall.ERROR) self.main_window.ui.statusbar.showMessage(get_ui_string('app.error.unexpected')) finally: self.main_window.setEnabled(True)
def setModelData(self, editor, model, index): existing_values = index.model().values code = self.valid_codes[str(editor.currentText())] if self.allow_repeats: model.setData(index, QVariant(code), Qt.EditRole) else: try: existing_values.index(code) # check to see if it is the same one if index.data().toString() != code: # not the same one, show warning QMessageBox.warning(None, get_ui_string("app.warning.title"), get_ui_string("dlg.msbranch.error.attribute.exists", (code))) except: # code not in existing values list model.setData(index, QVariant(code), Qt.EditRole)
def createBlank(self): """ create a new project """ # create new project file project = Project(self.app_config, self.taxonomy) # open project and sync UI self.setProject(project, skipVerify=True) self.ui.statusbar.showMessage( get_ui_string("app.status.project.created"))
def wrapper(*args, **kw): if self.project_is_required and self.project is None: logUICall.log(get_ui_string("app.error.project.missing"), logUICall.ERROR) return try: logUICall.log('function call %s from module %s' % (f.__name__, f.__module__), logUICall.DEBUG) return f(*args, **kw) except Exception as err: logUICall.log(err, logUICall.ERROR)
def selectExportFile(self): """ event handler for btn_export_select_path - open save file dialog box to select file name for export """ filename = QFileDialog.getSaveFileName(self, get_ui_string("widget.result.export.file.open"), ".", self.ui.cb_export_format.currentText()) if not filename.isNull():
def deleteModifier(self): """ delete selected modifier from mapping scheme. update table view """ mod = self.getSelectedModifier() # make sure there is mod selected if mod is None: logUICall.log(get_ui_string("widget.ms.warning.node.required"), logUICall.WARNING) return # confirm delete answer = QMessageBox.warning(self, get_ui_string("app.confirm.title"), get_ui_string("widget.mod.warning.delete"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: # see MSTableModel about data in mod variable modidx, src_node = mod[4], mod[6] if src_node is not None: # remove modifier src_node.remove_modifier(modidx) self.app.visualizeMappingScheme(self.ms)
def is_range_valid(self): is_valid = True self.ui.lb_notes.setText("") for i in range(len(self.range_values[0])): # minimum must be less than maximum in same row max_val = self.range_values[1][i] min_val = self.range_values[0][i] is_valid = (min_val <= max_val) if not is_valid: # use exception to stop additional checks raise SIDDRangeGroupException(get_ui_string("dlg.attr.error.max", (max_val, min_val))) # and minimum must be exactly 1 larger than maximum from previous row if i > 0: # first row does not have previous max_last = self.range_values[1][i-1] is_valid = (min_val == max_last+1) if not is_valid: # use exception to stop additional checks raise SIDDRangeGroupException(get_ui_string("dlg.attr.error.range", (max_last, min_val))) return is_valid
def verifyInputs(self): """ perform checks on current dataset provided and update UI accordingly """ # remove result self.tab_result.closeResult() # verify current dataset self.ui.statusbar.showMessage(get_ui_string("app.status.ms.processing")) # invoke asynchronously invoke_async(get_ui_string("app.status.processing"), self.project.verify_data) self.tab_datainput.showVerificationResults() # always allow mapping scheme self.ui.mainTabs.setTabEnabled(self.TAB_MS, True) self.ui.mainTabs.setTabEnabled(self.TAB_MOD, True) self.ui.actionMapping_Schemes.setEnabled(True) self.ui.actionResult.setEnabled(True) self.ui.actionProcessing_Options.setEnabled(True) self.ui.statusbar.showMessage(get_ui_string("app.status.input.verified"))
def selectExportFile(self): """ event handler for btn_export_select_path - open save file dialog box to select file name for export """ filename = QFileDialog.getSaveFileName( self, get_ui_string("widget.result.export.file.open"), ".", self.ui.cb_export_format.currentText()) if not filename.isNull(): self.ui.txt_export_select_path.setText(filename)
def saveProj(self): """ save active project """ if self.project is None: return try: self.project.sync(SyncModes.Write) self.ui.statusbar.showMessage(get_ui_string("app.status.project.saved")) except SIDDProjectException as se: if se.error == ProjectErrors.FileNotSet: self.saveProjAs()
@pyqtSlot() def exportData(self): """ event handler for btn_export - do export data """ export_path = str(self.ui.txt_export_select_path.text()) if export_path == "": logUICall.log(get_ui_string("app.error.path.is.null"), logUICall.WARNING) return
@pyqtSlot(QPoint, QObject) def showInfo(self, point, mouseButton): """ event handler for toolInfo @see QGIS tutorial for detail point-polygon search on currently selected layer """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) cur_layer = self.map_layers[cur_layer_idx] # if layer is not in same projection as map canvas # need to project query point if cur_layer.crs() != self.canvas.mapRenderer().destinationCrs(): transform = QgsCoordinateTransform(self.canvas.mapRenderer().destinationCrs(), cur_layer.crs()) point = transform.transform(point) # do query provider = cur_layer.dataProvider() provider.rewind() feature = QgsFeature() colonIndexes = provider.attributeIndexes() # search using point as center of rectangle polygon search_buffer_x = self.canvas.extent().width() * self.SEARCH_BUFFER / self.canvas.width() search_buffer_y = self.canvas.extent().height() * self.SEARCH_BUFFER / self.canvas.height() provider.select(colonIndexes, QgsRectangle(point.x()-search_buffer_x, point.y()-search_buffer_y, point.x()+search_buffer_x, point.y()+search_buffer_y), True) # get selected and display in result detail dialog box selected = [] while provider.nextFeature(feature): # for polygons, only show geometry containing query point if cur_layer.geometryType() == QGis.Polygon: if feature.geometry() is not None and not feature.geometry().contains (point): continue selected.append(feature.attributeMap()) if len(selected)>0: # display result if exists if cur_layer_idx == self.EXPOSURE: self.dlgResultDetail.showExposureData(provider.fields(), selected) else: self.dlgResultDetail.showInfoData(provider.fields(), selected) self.dlgResultDetail.exec_() else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) except Exception as err: # point-in-polygon search is not critical, continue on error
def saveProj(self): """ save active project """ if self.project is None: return try: self.project.sync(SyncModes.Write) self.ui.statusbar.showMessage( get_ui_string("app.status.project.saved")) except SIDDProjectException as se: if se.error == ProjectErrors.FileNotSet: self.saveProjAs()
def exportData(self): """ event handler for btn_export - do export data """ export_path = str(self.ui.txt_export_select_path.text()) if export_path == "": logUICall.log(get_ui_string("app.error.path.is.null"), logUICall.WARNING) return self.app.exportResults(self.export_format, export_path)
def deleteModifier(self): """ delete selected modifier from mapping scheme. update table view """ mod = self.getSelectedModifier() # make sure there is mod selected if mod is None: logUICall.log(get_ui_string("widget.ms.warning.node.required"), logUICall.WARNING) return # confirm delete answer = QMessageBox.warning( self, get_ui_string("app.confirm.title"), get_ui_string("widget.mod.warning.delete"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: # see MSTableModel about data in mod variable modidx, src_node = mod[4], mod[6] if src_node is not None: # remove modifier src_node.remove_modifier(modidx) self.app.visualizeMappingScheme(self.ms)
def wrapper(*args, **kw): self.main_window.setEnabled(False) try: logUICall.log( 'function call %s from module %s' % (f.__name__, f.__module__), logUICall.DEBUG) return f(*args, **kw) except SIDDUIException as uie: logUICall.log(uie, logUICall.WARNING) self.main_window.ui.statusbar.showMessage( get_ui_string('app.error.ui')) except SIDDException as se: logUICall.log(se, logUICall.WARNING) self.main_window.ui.statusbar.showMessage( get_ui_string('app.error.model')) except Exception as e: logUICall.log(e, logUICall.ERROR) self.main_window.ui.statusbar.showMessage( get_ui_string('app.error.unexpected')) finally: self.main_window.setEnabled(True)
def setMS(self, ms, isBranch=False): """ set mapping scheme to be saved set mapping scheme type as 'single-level' if isBranch=True set to 'multi-level' otherwise """ self.ms_to_save = ms self.ui.tree_ms_view.setModel(MSTreeModel(ms)) self.ui.tree_ms_view.setSelectionMode(QAbstractItemView.NoSelection) self.ui.txt_ms_create_date.setText(datetime.now().strftime("%Y-%m-%d %H:%M")) self.ui.txt_ms_create_date.setReadOnly(True) if isBranch: self.ui.lb_title.setText(get_ui_string("dlg.savems.title.branch")) self.ui.txt_ms_type.setText(get_ui_string("app.mslibrary.user.singlelevel")) else: self.ui.lb_title.setText(get_ui_string("dlg.savems.title.tree")) self.ui.txt_ms_type.setText(get_ui_string("app.mslibrary.user.multilevel")) self.ui.txt_ms_type.setReadOnly(True)
def setData(self, index, value, role): """ set data modified by cell edit """ if role == Qt.EditRole: if (index.column() == 0): # first column, change value taxStr = str(value.toString()) # make sure there is no repeat try: self.values.index(taxStr) # no error means taxStr already in self.value found = True except: found = False if found: raise SIDDException(get_ui_string("dlg.msbranch.error.attribute.exists") % taxStr) # do nothing for empty string if taxStr == "": return False # verify taxonomy # passed all checks. set value self.values[index.row()] = taxStr else: # second column, change weight (dVal, sucess) = value.toDouble() # conversion to double failed if not sucess: raise SIDDException(get_ui_string("dlg.msbranch.edit.warning.invalidweight")) # make sure 0 <= dVal <= 100 if dVal < 0 or dVal > 100: raise SIDDException(get_ui_string("dlg.msbranch.edit.warning.invalidweight")) # passed all checks. set value self.weights[index.row()] = round(dVal, 1) self.dataChanged.emit(self.createIndex(0, 0), self.createIndex(self.rowCount(0),self.columnCount(0))) return True return False
def setData(self, index, value, role): """ set data modified by cell edit """ if role == Qt.EditRole: if index.column() == 0: # first column, change value taxStr = str(value.toString()) # make sure there is no repeat try: self.values.index(taxStr) # no error means taxStr already in self.value found = True except: found = False if found: raise SIDDException(get_ui_string("dlg.msbranch.error.attribute.exists") % taxStr) # do nothing for empty string if taxStr == "": return False # verify taxonomy # passed all checks. set value self.values[index.row()] = taxStr else: # second column, change weight (dVal, sucess) = value.toDouble() # conversion to double failed if not sucess: raise SIDDException(get_ui_string("dlg.msbranch.edit.warning.invalidweight")) # make sure 0 <= dVal <= 100 if dVal < 0 or dVal > 100: raise SIDDException(get_ui_string("dlg.msbranch.edit.warning.invalidweight")) # passed all checks. set value self.weights[index.row()] = round(dVal, 1) self.dataChanged.emit(self.createIndex(0, 0), self.createIndex(self.rowCount(0), self.columnCount(0))) return True return False
def verifyInputs(self): """ perform checks on current dataset provided and update UI accordingly """ # remove result self.tab_result.closeResult() # verify current dataset self.ui.statusbar.showMessage( get_ui_string("app.status.ms.processing")) # invoke asynchronously invoke_async(get_ui_string("app.status.processing"), self.project.verify_data) self.tab_datainput.showVerificationResults() # always allow mapping scheme self.ui.mainTabs.setTabEnabled(self.TAB_MS, True) self.ui.mainTabs.setTabEnabled(self.TAB_MOD, True) self.ui.actionMapping_Schemes.setEnabled(True) self.ui.actionResult.setEnabled(True) self.ui.actionProcessing_Options.setEnabled(True) self.ui.statusbar.showMessage( get_ui_string("app.status.input.verified"))
def closeProject(self): """ close opened project and update UI elements accordingly """ # adjust UI in application window self.tab_result.closeAll() # this call must happen first. # otherwise, it locks temporary GIS files self.ui.mainTabs.setTabEnabled(self.TAB_DATA, False) self.ui.mainTabs.setTabEnabled(self.TAB_MS, False) self.ui.mainTabs.setTabEnabled(self.TAB_MOD, False) self.ui.mainTabs.setTabEnabled(self.TAB_RESULT, False) self.showTab(self.TAB_DATA) # disable menu/menu items self.ui.actionSave.setEnabled(False) self.ui.actionSave_as.setEnabled(False) self.ui.actionMapping_Schemes.setEnabled(False) self.ui.actionResult.setEnabled(False) self.ui.actionProcessing_Options.setEnabled(False) if getattr(self, 'project', None) is not None: # save existing project is needed if self.project.require_save: ans = QMessageBox.question( self, get_ui_string("app.window.msg.project.not_saved"), get_ui_string("app.window.msg.project.save_or_not"), buttons=QMessageBox.Yes | QMessageBox.No, defaultButton=QMessageBox.Yes) if ans == QMessageBox.Yes: self.saveProj() # adjust UI in tabs self.tab_datainput.closeProject() self.tab_ms.clearMappingScheme() self.tab_mod.closeMappingScheme() self.project.clean_up() del self.project self.project = None
def setMS(self, ms, isBranch=False): """ set mapping scheme to be saved set mapping scheme type as 'single-level' if isBranch=True set to 'multi-level' otherwise """ self.ms_to_save = ms self.ui.tree_ms_view.setModel(MSTreeModel(ms)) self.ui.tree_ms_view.setSelectionMode(QAbstractItemView.NoSelection) self.ui.txt_ms_create_date.setText( datetime.now().strftime("%Y-%m-%d %H:%M")) self.ui.txt_ms_create_date.setReadOnly(True) if isBranch: self.ui.lb_title.setText(get_ui_string("dlg.savems.title.branch")) self.ui.txt_ms_type.setText( get_ui_string("app.mslibrary.user.singlelevel")) else: self.ui.lb_title.setText(get_ui_string("dlg.savems.title.tree")) self.ui.txt_ms_type.setText( get_ui_string("app.mslibrary.user.multilevel")) self.ui.txt_ms_type.setReadOnly(True)
def searchFeature(self): cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) layer = self.map_layers[cur_layer_idx] fields = [] for fidx in layer.dataProvider().fields(): fields.append(layer.dataProvider().fields()[fidx].name()) dlg_search = DialogSearchFeature(fields) answer = dlg_search.exec_() if answer == QDialog.Accepted: extent = self.findFeatureExtentByAttribute(layer, dlg_search.attribute, dlg_search.value) if extent is not None: self.zoomToExtent(extent) else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) dlg_search.destroy() except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING)
def mapEditTheme(self): """ event handler for btn_edit - identify item on map """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) # build layer render property Dialog for selected layer dlg_render = QDialog() dlg_render.setWindowTitle( get_ui_string('widget.result.renderer.settings')) dlg_render.setModal(True) dlg_render.setFixedSize(530, 370) dlg_render.renderer = QgsRendererV2PropertiesDialog( self.map_layers[cur_layer_idx], self.style, True) dlg_render.renderer.setParent(dlg_render) dlg_render.renderer.setGeometry(QRect(10, 10, 510, 325)) dlg_render.buttonBox = QDialogButtonBox(dlg_render) dlg_render.buttonBox.setGeometry(QRect(10, 335, 510, 25)) dlg_render.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) dlg_render.buttonBox.accepted.connect(dlg_render.accept) dlg_render.buttonBox.accepted.connect(dlg_render.renderer.onOK) dlg_render.buttonBox.rejected.connect(dlg_render.reject) dlg_render.setVisible(True) # get user input and update renderer answer = dlg_render.exec_() if answer == QDialog.Accepted: self.map_layer_renderer[cur_layer_idx] = None self.map_layer_renderer[cur_layer_idx] = self.map_layers[ cur_layer_idx].rendererV2().clone() self.canvas.refresh() dlg_render.destroy() del dlg_render except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING)
def createWizard(self): try: # should not update preview while using wizard self.setVisible(False) self.previewInput = False wizard = WidgetDataWizard(self, Project(self.app_config, self.taxonomy)) if wizard.exec_() == QDialog.Accepted: # setProject makes call to GIS component that requires visibility self.setVisible(True) self.previewInput = True self.setProject(wizard.project) self.ui.statusbar.showMessage(get_ui_string("app.status.project.created")) # else # do nothing? except: pass finally: # return to normal window # these calls are reached # 1. in case any exception occurs, # 2. wizard finished or cancelled self.setVisible(True) self.previewInput = True
def searchFeature(self): cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) layer = self.map_layers[cur_layer_idx] fields = [] for fidx in layer.dataProvider().fields(): fields.append(layer.dataProvider().fields()[fidx].name()) dlg_search = DialogSearchFeature(fields) answer = dlg_search.exec_() if answer == QDialog.Accepted: extent = self.findFeatureExtentByAttribute( layer, dlg_search.attribute, dlg_search.value) if extent is not None: self.zoomToExtent(extent) else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) dlg_search.destroy() except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING)
def __init__(self, qtapp, app_config): """ constructor - initialize UI elements - connect UI elements to callback """ # create UI super(AppMainWindow, self).__init__() AppMainWindow.apiCallChecker.setWindow(self) self.qtapp = qtapp self.app_config = app_config self.taxonomy = get_taxonomy(app_config.get('options', 'taxonomy', 'gem')) self.ui = Ui_mainWindow() self.ui.setupUi(self) self.settings = QSettings(SIDD_COMPANY, '%s %s' %(SIDD_APP_NAME, SIDD_VERSION)); self.restoreGeometry(self.settings.value(self.UI_WINDOW_GEOM).toByteArray()); self.restoreState(self.settings.value(self.UI_WINDOW_STATE).toByteArray()); self.lb_map_location = QLabel(self) self.lb_map_location.resize(self.ui.statusbar.width()/3, self.ui.statusbar.height()) self.ui.statusbar.addPermanentWidget(self.lb_map_location) self.msdb_dao = MSDatabaseDAO(FILE_MS_DB) self.tab_datainput = WidgetDataInput(self) self.ui.mainTabs.addTab(self.tab_datainput, get_ui_string("app.window.tab.input")) self.tab_ms = WidgetMappingSchemes(self) self.ui.mainTabs.addTab(self.tab_ms, get_ui_string("app.window.tab.ms")) self.tab_mod = WidgetSecondaryModifier(self) self.ui.mainTabs.addTab(self.tab_mod, get_ui_string("app.window.tab.mod")) self.tab_result = WidgetResult(self) self.ui.mainTabs.addTab(self.tab_result, get_ui_string("app.window.tab.result")) self.previewInput = True self.about = DialogAbout(self) self.about.setModal(True) self.dlgAttrRange = DialogAttrRanges() self.dlgAttrRange.setModal(True) self.progress = DialogApply(self) self.progress.setModal(True) self.proc_options = DialogProcessingOptions(self) self.proc_options.setModal(True) # connect menu action to slots (ui events) self.ui.mainTabs.currentChanged.connect(self.tabChanged) self.ui.actionProject_Blank.triggered.connect(self.createBlank) self.ui.actionUsing_Data_Wizard.triggered.connect(self.createWizard) self.ui.actionOpen_Existing.triggered.connect(self.loadProj) self.ui.actionSave.triggered.connect(self.saveProj) self.ui.actionSave_as.triggered.connect(self.saveProjAs) self.ui.actionExit.triggered.connect(self.close) self.ui.actionData_Input.triggered.connect(self.changeTab) self.ui.actionMapping_Schemes.triggered.connect(self.changeTab) self.ui.actionResult.triggered.connect(self.changeTab) self.ui.actionProcessing_Options.triggered.connect(self.setProcessingOptions) self.ui.actionAbout.triggered.connect(self.showAbout) # set project to None and adjust ui as needed self.closeProject() self.ui.statusbar.showMessage(get_ui_string("app.status.ready")) # perform clean up from previous runs try: delete_folders_in_dir(get_temp_dir(), "tmp*") except: # cleanup is not-critical. no action taken even if fails pass # hide features if not app_config.get('options', 'parse_modifier', True, bool): self.tab_mod.setVisible(False) self.ui.mainTabs.removeTab(self.TAB_MOD) self.TAB_MOD = self.TAB_MS self.TAB_RESULT -= 1 # hide view menu self.ui.menuView.menuAction().setVisible(False) # hide data wizard self.ui.actionUsing_Data_Wizard.setVisible(False)
def buildExposure(self): """ build exposure """ self.ui.statusbar.showMessage(get_ui_string("app.status.ms.processing")) # verify current dataset to make sure can process exposure self.project.verify_data() # can not proceed if project is not ready for exposure if self.project.status != ProjectStatus.ReadyForExposure: logUICall.log(get_ui_string("project.error.NotEnoughData"), logUICall.WARNING) # show result self.tab_datainput.showVerificationResults() self.ui.mainTabs.setCurrentIndex(self.TAB_DATA) return # close current results self.tab_result.closeResult() self.ui.mainTabs.setTabEnabled(self.TAB_RESULT, True) # reset progress dialog self.progress.setVisible(True) self.progress.ui.pb_progress.setRange(0, self.project.build_exposure_total_steps()) self.progress.ui.txt_progress.clear() self.progress.ui.txt_progress.appendPlainText(get_ui_string("app.status.processing")) self.qtapp.processEvents() cancelled = False error_occured = False error_message = "" curStep = 0 try: for step in self.project.build_exposure_steps(): if cancelled or error_occured: break # use introspection to get operator class class_name = str(step.__class__) # result of above call has format # <class '...'> where ... is the class name of interest class_name = class_name[class_name.find("'")+1:class_name.rfind("'")] # update UI logAPICall.log('\t %s' % step.name, logAPICall.DEBUG) self.progress.ui.txt_progress.appendPlainText(get_ui_string('message.%s'% class_name)) self.progress.ui.pb_progress.setValue(curStep) self.qtapp.processEvents() sleep(0.5) # perform operation step.do_operation() if not self.progress.isVisible(): cancelled = True # operation successful curStep+=1 except Exception as err: # exception are thrown if data is not ready for exposure error_message = err.message error_occured = True self.progress.setVisible(False) if error_occured: # processing cancelled logUICall.log(error_message, logUICall.WARNING) self.ui.statusbar.showMessage(get_ui_string("app.status.cancelled")) elif cancelled: # processing cancelled logUICall.log(get_ui_string("app.status.cancelled"), logUICall.WARNING) self.ui.statusbar.showMessage(get_ui_string("app.status.cancelled")) else: # processing completed self.project.verify_result() self.progress.setVisible(False) # show result self.tab_result.refreshResult() self.ui.mainTabs.setTabEnabled(self.TAB_RESULT, True) self.ui.mainTabs.setCurrentIndex(self.TAB_RESULT) self.ui.statusbar.showMessage(get_ui_string("app.status.exposure.created"))