class DialogWithImage(QDialog): def __init__(self): QDialog.__init__(self) self.main_widget = QWidget(self) self.main_widget.setMinimumSize(QSize(100, 100)) self.label = QLabel() self.buttonBox = QDialogButtonBox(self.main_widget) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.buttonBox.accepted.connect(self.Apply) # Access the layout of the MessageBox to add the checkbox self.container = QVBoxLayout(self.main_widget) self.container.addWidget(self.label) self.container.addWidget(self.buttonBox) self.container.setAlignment(Qt.AlignCenter) self.container.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.container) def Apply(self): self.close()
class DialogWithImage(QDialog): def __init__(self, interface): QDialog.__init__(self, interface.mainWindow()) self.iface = interface self.main_widget = QWidget(self) self.main_widget.setMinimumSize(QSize(100, 100)) self.label = QLabel() self.buttonBox = QDialogButtonBox(self.main_widget) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.buttonBox.accepted.connect(self.Apply) # Access the layout of the MessageBox to add the checkbox self.container = QVBoxLayout(self.main_widget) self.container.addWidget(self.label) self.container.addWidget(self.buttonBox) self.container.setAlignment(Qt.AlignCenter) self.container.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.container) def Apply(self): self.close()
def getWidgetFromParameter(self, param): # TODO Create Parameter widget class that holds the logic # for creating a widget that belongs to the parameter. if isinstance(param, ParameterRaster): layers = dataobjects.getRasterLayers() items = [] if param.optional: items.append((self.NOT_SELECTED, None)) for layer in layers: items.append((self.getExtendedLayerName(layer), layer)) item = InputLayerSelectorPanel(items, param) elif isinstance(param, ParameterVector): if self.somethingDependsOnThisParameter(param) or self.alg.allowOnlyOpenedLayers: item = QComboBox() layers = dataobjects.getVectorLayers(param.shapetype) layers.sort(key=lambda lay: lay.name()) if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(self.getExtendedLayerName(layer), layer) item.currentIndexChanged.connect(self.updateDependentFields) item.name = param.name else: layers = dataobjects.getVectorLayers(param.shapetype) items = [] if param.optional: items.append((self.NOT_SELECTED, None)) for layer in layers: items.append((self.getExtendedLayerName(layer), layer)) # if already set, put first in list for i, (name, layer) in enumerate(items): if layer and layer.source() == param.value: items.insert(0, items.pop(i)) item = InputLayerSelectorPanel(items, param) elif isinstance(param, ParameterTable): if self.somethingDependsOnThisParameter(param): item = QComboBox() layers = dataobjects.getTables() if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(layer.name(), layer) item.currentIndexChanged.connect(self.updateDependentFields) item.name = param.name else: layers = dataobjects.getTables() items = [] if param.optional: items.append((self.NOT_SELECTED, None)) for layer in layers: items.append((layer.name(), layer)) # if already set, put first in list for i, (name, layer) in enumerate(items): if layer and layer.source() == param.value: items.insert(0, items.pop(i)) item = InputLayerSelectorPanel(items, param) elif isinstance(param, ParameterBoolean): item = QCheckBox() if param.default: item.setChecked(True) else: item.setChecked(False) elif isinstance(param, ParameterTableField) or isinstance(param, ParameterTableMultipleField): if isinstance(param, ParameterTableMultipleField): item = ListMultiSelectWidget() else: item = QComboBox() if param.parent in self.dependentItems: items = self.dependentItems[param.parent] else: items = [] self.dependentItems[param.parent] = items items.append(param) parent = self.alg.getParameterFromName(param.parent) if isinstance(parent, ParameterVector): layers = dataobjects.getVectorLayers(parent.shapetype) else: layers = dataobjects.getTables() if len(layers) > 0: if param.optional and isinstance(param, ParameterTableField): item.addItem(self.tr('[not set]')) item.addItems(self.getFields(layers[0], param.datatype)) elif isinstance(param, ParameterSelection): item = QComboBox() item.addItems(param.options) if param.default: item.setCurrentIndex(param.default) elif isinstance(param, ParameterFixedTable): item = FixedTablePanel(param) elif isinstance(param, ParameterRange): item = RangePanel(param) elif isinstance(param, ParameterFile): item = FileSelectionPanel(param.isFolder, param.ext) elif isinstance(param, ParameterMultipleInput): if param.datatype == ParameterMultipleInput.TYPE_FILE: item = MultipleInputPanel(datatype=ParameterMultipleInput.TYPE_FILE) else: if param.datatype == ParameterMultipleInput.TYPE_RASTER: options = dataobjects.getRasterLayers(sorting=False) elif param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY: options = dataobjects.getVectorLayers(sorting=False) else: options = dataobjects.getVectorLayers([param.datatype], sorting=False) opts = [self.getExtendedLayerName(opt) for opt in options] item = MultipleInputPanel(opts) elif isinstance(param, ParameterNumber): item = NumberInputPanel(param.default, param.min, param.max, param.isInteger) elif isinstance(param, ParameterExtent): item = ExtentSelectionPanel(self.parent, self.alg, param.default) elif isinstance(param, ParameterPoint): item = PointSelectionPanel(self.parent, param.default) elif isinstance(param, ParameterCrs): item = CrsSelectionPanel(param.default) elif isinstance(param, ParameterString): if param.multiline: verticalLayout = QVBoxLayout() verticalLayout.setSizeConstraint( QLayout.SetDefaultConstraint) textEdit = QPlainTextEdit() if param.default: textEdit.setPlainText(param.default) verticalLayout.addWidget(textEdit) item = textEdit else: item = QLineEdit() if param.default: item.setText(unicode(param.default)) elif isinstance(param, ParameterGeometryPredicate): item = GeometryPredicateSelectionPanel(param.enabledPredicates) if param.left: widget = self.valueItems[param.left] if isinstance(widget, InputLayerSelectorPanel): widget = widget.cmbText widget.currentIndexChanged.connect(item.onLeftLayerChange) item.leftLayer = widget.itemData(widget.currentIndex()) if param.right: widget = self.valueItems[param.right] if isinstance(widget, InputLayerSelectorPanel): widget = widget.cmbText widget.currentIndexChanged.connect(item.onRightLayerChange) item.rightLayer = widget.itemData(widget.currentIndex()) item.updatePredicates() if param.default: item.setValue(param.default) else: item = QLineEdit() if param.default: item.setText(unicode(param.default)) return item
class FieldMappingTab(QWidget, object): """Widget class for field mapping.""" def __init__(self, field_group=None, parent=None, iface=None): """Constructor.""" # Init from parent class QWidget.__init__(self, parent) # Attributes self.layer = None self.metadata = {} self.parent = parent self.iface = iface self.field_group = field_group self.setting = QSettings() # TODO(IS): Make dynamic # Main container self.main_layout = QVBoxLayout() # Inner layout self.header_layout = QHBoxLayout() self.content_layout = QHBoxLayout() self.footer_layout = QHBoxLayout() # Header self.header_label = QLabel() self.header_label.setWordWrap(True) # Content self.field_layout = QVBoxLayout() self.parameter_layout = QHBoxLayout() self.field_description = QLabel(tr('List of fields')) self.field_list = QListWidget() self.field_list.setSelectionMode(QAbstractItemView.ExtendedSelection) self.field_list.setDragDropMode(QAbstractItemView.DragDrop) self.field_list.setDefaultDropAction(Qt.MoveAction) self.field_list.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) # noinspection PyUnresolvedReferences self.field_list.itemSelectionChanged.connect(self.update_footer) # Footer self.footer_label = QLabel() self.footer_label.setWordWrap(True) # Parameters self.extra_parameters = [(GroupSelectParameter, GroupSelectParameterWidget)] self.parameters = [] self.parameter_container = None # Adding to layout self.header_layout.addWidget(self.header_label) self.field_layout.addWidget(self.field_description) self.field_layout.addWidget(self.field_list) self.field_layout.setSizeConstraint(QLayout.SetMaximumSize) self.content_layout.addLayout(self.field_layout) self.content_layout.addLayout(self.parameter_layout) self.footer_layout.addWidget(self.footer_label) self.main_layout.addLayout(self.header_layout) self.main_layout.addLayout(self.content_layout) self.main_layout.addLayout(self.footer_layout) self.setLayout(self.main_layout) def set_layer(self, layer, keywords=None): """Set layer and update UI accordingly. :param layer: A vector layer that has been already patched with metadata. :type layer: QgsVectorLayer :param keywords: Custom keyword for the layer. :type keywords: dict, None """ self.layer = layer if keywords is not None: self.metadata = keywords else: # Check if it has keywords if not hasattr(layer, 'keywords'): message = 'Layer {layer_name} does not have keywords.'.format( layer_name=layer.name()) raise KeywordNotFoundError(message) self.metadata = layer.keywords self.populate_parameter() def populate_field_list(self, excluded_fields=None): """Helper to add field of the layer to the list. :param excluded_fields: List of field that want to be excluded. :type excluded_fields: list """ # Populate fields list if excluded_fields is None: excluded_fields = [] self.field_list.clear() for field in self.layer.fields(): # Skip if it's excluded if field.name() in excluded_fields: continue # Skip if it's not number (float, int, etc) if field.type() not in qvariant_numbers: continue field_item = QListWidgetItem(self.field_list) field_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field.name()) field_item.setText(field.name()) self.field_list.addItem(field_item) def populate_parameter(self): """Helper to setup the parameter widget.""" used_fields = [] self.parameters = [] for field in self.field_group.get('fields', []): selected_option = DO_NOT_REPORT options = OrderedDict([ (DO_NOT_REPORT, { 'label': tr('Do not report'), 'value': None, 'type': STATIC, 'constraint': {} }), ]) # Example: count if field['absolute']: # Used in field options field_label = tr('Count fields') else: # Example: ratio # Used in field options field_label = tr('Ratio fields') global_default_value = get_inasafe_default_value_qsetting( self.setting, GLOBAL, field['key']) options[GLOBAL_DEFAULT] = { 'label': tr('Global default'), 'value': global_default_value, 'type': STATIC, 'constraint': {} } default_custom_value = get_inasafe_default_value_qsetting( self.setting, RECENT, field['key']) custom_value = self.metadata.get('inasafe_default_values', {}).get( field['key'], default_custom_value) if field['key'] in self.metadata.get('inasafe_default_values', {}): if custom_value == global_default_value: selected_option = GLOBAL_DEFAULT else: selected_option = CUSTOM_VALUE min_value = field['default_value'].get('min_value', 0) max_value = field['default_value'].get('max_value', 100) default_step = (max_value - min_value) / 100.0 step = field['default_value'].get('increment', default_step) options[CUSTOM_VALUE] = { 'label': tr('Custom'), 'value': custom_value, 'type': SINGLE_DYNAMIC, 'constraint': { 'min': min_value, 'max': max_value, 'step': step } } custom_fields = self.metadata.get('inasafe_fields', {}).get(field['key'], []) if field['key'] in self.metadata.get('inasafe_fields', {}): selected_option = FIELDS if isinstance(custom_fields, str): custom_fields = [custom_fields] options[FIELDS] = { 'label': field_label, 'value': custom_fields, 'type': MULTIPLE_DYNAMIC, 'constraint': {} } used_fields.extend(custom_fields) parameter = GroupSelectParameter() parameter.guid = field['key'] parameter.name = field['name'] parameter.options = options parameter.selected = selected_option parameter.help_text = field['help_text'] parameter.description = field['description'] self.parameters.append(parameter) self.parameter_container = ParameterContainer( parameters=self.parameters, extra_parameters=self.extra_parameters, vertical=False) self.parameter_container.setup_ui() constraints = self.field_group.get('constraints', {}) for key, value in list(constraints.items()): self.parameter_container.add_validator( validators[key], kwargs=value['kwargs'], validation_message=value['message']) self.parameter_layout.addWidget(self.parameter_container) default_ratio_help_text = tr( 'By default, InaSAFE will calculate the default ratio ' 'however users have the option to include this in the ' 'analysis report. If you do not want to see the default ' 'results in the report choose "do not report".') # Set move or copy if self.field_group.get('exclusive', False): # If exclusive, do not add used field. self.populate_field_list(excluded_fields=used_fields) # Use move action since it's exclusive self.field_list.setDefaultDropAction(Qt.MoveAction) # Just make sure that the signal is disconnected try: # noinspection PyUnresolvedReferences self.field_list.itemChanged.disconnect(self.drop_remove) except TypeError: pass # Set header header_text = self.field_group['description'] header_text += '\n\n' + default_ratio_help_text header_text += '\n\n' + tr( 'You can only map one field to one concept.') else: # If not exclusive, add all field. self.populate_field_list() # Use copy action since it's not exclusive self.field_list.setDefaultDropAction(Qt.CopyAction) # noinspection PyUnresolvedReferences self.field_list.itemChanged.connect( partial(self.drop_remove, field_list=self.field_list)) self.connect_drop_remove_parameter() # Set header header_text = self.field_group['description'] header_text += '\n\n' + default_ratio_help_text header_text += '\n\n' + tr( 'You can map one field to more than one concepts.') self.header_label.setText(header_text) def get_parameter_value(self): """Get parameter of the tab. :returns: Dictionary of parameters by type in this format: {'fields': {}, 'values': {}}. :rtype: dict """ parameters = self.parameter_container.get_parameters(True) field_parameters = {} value_parameters = {} for parameter in parameters: if parameter.selected_option_type() in [SINGLE_DYNAMIC, STATIC]: value_parameters[parameter.guid] = parameter.value elif parameter.selected_option_type() == MULTIPLE_DYNAMIC: field_parameters[parameter.guid] = parameter.value return {'fields': field_parameters, 'values': value_parameters} def update_footer(self): """Update footer when the field list change.""" field_item = self.field_list.currentItem() if not field_item: self.footer_label.setText('') return field_name = field_item.data(Qt.UserRole) field = self.layer.fields().field(field_name) index = self.layer.fields().lookupField(field_name) unique_values = list(self.layer.uniqueValues(index)) pretty_unique_values = ', '.join([str(v) for v in unique_values[:10]]) footer_text = tr('Field type: {0}\n').format(field.typeName()) footer_text += tr('Unique values: {0}').format(pretty_unique_values) self.footer_label.setText(footer_text) def connect_drop_remove_parameter(self): parameter_widgets = self.parameter_container.get_parameter_widgets() for parameter_widget in parameter_widgets: field_list = parameter_widget.widget().list_widget field_list.itemChanged.connect( partial(self.drop_remove, field_list=field_list)) @staticmethod def drop_remove(*args, **kwargs): """Action when we need to remove dropped item. :param *args: Position arguments. :type *args: list :param kwargs: Keywords arguments. :type kwargs: dict """ dropped_item = args[0] field_list = kwargs['field_list'] num_duplicate = 0 for i in range(field_list.count()): if dropped_item.text() == field_list.item(i).text(): num_duplicate += 1 if num_duplicate > 1: # Notes(IS): For some reason, removeItemWidget is not working. field_list.takeItem(field_list.row(dropped_item))
class ProgressDialog(QDialog): """ Progress dialog shows progress bar for algorithm. """ def __init__(self, iface): QDialog.__init__(self, iface.mainWindow()) self.workerThread = None self.state = False self.outputLoc = None self.resultStatus = None self.reRun = False self.savedProj = None # Build GUI Elements self.setWindowTitle("SEILAPLAN wird ausgeführt") self.resize(500, 100) self.container = QVBoxLayout() self.progressBar = QProgressBar(self) self.progressBar.setMinimumWidth(500) self.statusLabel = QLabel(self) self.hbox = QHBoxLayout() self.cancelButton = QDialogButtonBox() self.closeButton = QDialogButtonBox() self.resultLabel = ClickLabel(self) self.resultLabel.setMaximumWidth(500) self.resultLabel.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)) self.resultLabel.setWordWrap(True) self.rerunButton = QPushButton("Berechnungen wiederholen") self.rerunButton.setVisible(False) spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.cancelButton.setStandardButtons(QDialogButtonBox.Cancel) self.cancelButton.clicked.connect(self.onAbort) self.closeButton.setStandardButtons(QDialogButtonBox.Close) self.closeButton.clicked.connect(self.onClose) self.hbox.addWidget(self.rerunButton) self.hbox.addItem(spacer) self.hbox.addWidget(self.cancelButton) self.hbox.setAlignment(self.cancelButton, Qt.AlignHCenter) self.hbox.addWidget(self.closeButton) self.hbox.setAlignment(self.closeButton, Qt.AlignHCenter) self.closeButton.hide() self.container.addWidget(self.progressBar) self.container.addWidget(self.statusLabel) self.container.addWidget(self.resultLabel) self.container.addLayout(self.hbox) self.container.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.container) def setThread(self, workerThread): self.workerThread = workerThread self.connectProgressSignals() def connectProgressSignals(self): # Connet signals of thread self.workerThread.sig_jobEnded.connect(self.jobEnded) self.workerThread.sig_jobError.connect(self.onError) self.workerThread.sig_value.connect(self.valueFromThread) self.workerThread.sig_range.connect(self.rangeFromThread) self.workerThread.sig_text.connect(self.textFromThread) self.workerThread.sig_result.connect(self.resultFromThread) self.rerunButton.clicked.connect(self.onRerun) def run(self): # Show modal dialog window (QGIS is still responsive) self.show() # start event loop self.exec_() def jobEnded(self, success): self.setWindowTitle("SEILAPLAN") if success: self.statusLabel.setText("Berechnungen abgeschlossen.") self.progressBar.setValue(self.progressBar.maximum()) self.setFinalMessage() else: # If there was an abort by the user self.statusLabel.setText("Berechnungen abgebrochen.") self.progressBar.setValue(self.progressBar.minimum()) self.finallyDo() self.rerunButton.setVisible(True) def valueFromThread(self, value): self.progressBar.setValue(value) def rangeFromThread(self, range_vals): self.progressBar.setRange(range_vals[0], range_vals[1]) def maxFromThread(self, max): self.progressBar.setValue(self.progressBar.maximum()) def textFromThread(self, value): self.statusLabel.setText(value) def resultFromThread(self, result): [self.outputLoc, self.resultStatus] = result def setFinalMessage(self): self.resultLabel.clicked.connect(self.onResultClicked) self.resultLabel.blockSignals(True) linkToFolder = ('<html><head/><body><p></p><p><a href=' '"file:////{0}"><span style="text-decoration: ' 'underline; color:#0000ff;">{0}</span></a></p>' '</body></html>'.format(self.outputLoc)) # Optimization successful if self.resultStatus == 1: self.resultLabel.setText(textOK + linkToFolder) self.resultLabel.blockSignals(False) # Cable takes off of support elif self.resultStatus == 2: self.resultLabel.setText(textSeil + linkToFolder) self.resultLabel.blockSignals(False) # Optimization partially successful elif self.resultStatus == 3: self.resultLabel.setText(textHalf + linkToFolder) self.resultLabel.blockSignals(False) # Optimization not successful elif self.resultStatus == 4: self.resultLabel.setText(textBad) self.setLayout(self.container) def onResultClicked(self): # Open a folder window if sys.platform == 'darwin': # MAC subprocess.call(["open", "-R", self.outputLoc]) elif sys.platform.startswith('linux'): # LINUX subprocess.Popen(["xdg-open", self.outputLoc]) elif 'win32' in sys.platform: # WINDOWS from subprocess import CalledProcessError try: subprocess.check_call(['explorer', self.outputLoc]) except CalledProcessError: pass def onAbort(self): self.setWindowTitle("SEILAPLAN") self.statusLabel.setText("Laufender Prozess wird abgebrochen...") self.workerThread.cancel() # Terminates process cleanly def onError(self, exception_string): self.setWindowTitle("SEILAPLAN: Berechnung fehlgeschlagen") self.statusLabel.setText("Ein Fehler ist aufgetreten:") self.resultLabel.setText(exception_string) self.progressBar.setValue(self.progressBar.minimum()) self.finallyDo() def onRerun(self): self.reRun = True self.onClose() def finallyDo(self): self.cancelButton.hide() self.closeButton.show() def onClose(self): self.close()
def getWidgetFromParameter(self, param): # TODO Create Parameter widget class that holds the logic # for creating a widget that belongs to the parameter. if isinstance(param, ParameterRaster): layers = dataobjects.getRasterLayers() items = [] if param.optional: items.append((self.NOT_SELECTED, None)) for layer in layers: items.append((self.getExtendedLayerName(layer), layer)) item = InputLayerSelectorPanel(items, param) elif isinstance(param, ParameterVector): if self.somethingDependsOnThisParameter(param) or self.alg.allowOnlyOpenedLayers: item = QComboBox() layers = dataobjects.getVectorLayers(param.datatype) layers.sort(key=lambda lay: lay.name()) if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(self.getExtendedLayerName(layer), layer) item.currentIndexChanged.connect(self.updateDependentFields) item.name = param.name else: layers = dataobjects.getVectorLayers(param.datatype) items = [] if param.optional: items.append((self.NOT_SELECTED, None)) for layer in layers: items.append((self.getExtendedLayerName(layer), layer)) # if already set, put first in list for i, (name, layer) in enumerate(items): if layer and layer.source() == param.value: items.insert(0, items.pop(i)) item = InputLayerSelectorPanel(items, param) elif isinstance(param, ParameterTable): if self.somethingDependsOnThisParameter(param): item = QComboBox() layers = dataobjects.getTables() if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(layer.name(), layer) item.currentIndexChanged.connect(self.updateDependentFields) item.name = param.name else: layers = dataobjects.getTables() items = [] if param.optional: items.append((self.NOT_SELECTED, None)) for layer in layers: items.append((layer.name(), layer)) # if already set, put first in list for i, (name, layer) in enumerate(items): if layer and layer.source() == param.value: items.insert(0, items.pop(i)) item = InputLayerSelectorPanel(items, param) elif isinstance(param, ParameterBoolean): item = QCheckBox() if param.default: item.setChecked(True) else: item.setChecked(False) elif isinstance(param, ParameterTableField) or isinstance(param, ParameterTableMultipleField): if isinstance(param, ParameterTableMultipleField): item = ListMultiSelectWidget() else: item = QComboBox() if param.parent in self.dependentItems: items = self.dependentItems[param.parent] else: items = [] self.dependentItems[param.parent] = items items.append(param) parent = self.alg.getParameterFromName(param.parent) if isinstance(parent, ParameterVector): layers = dataobjects.getVectorLayers(parent.datatype) else: layers = dataobjects.getTables() if len(layers) > 0: if param.optional and isinstance(param, ParameterTableField): item.addItem(self.tr('[not set]')) item.addItems(self.getFields(layers[0], param.datatype)) elif isinstance(param, ParameterSelection): item = QComboBox() item.addItems(param.options) if param.default: item.setCurrentIndex(param.default) elif isinstance(param, ParameterFixedTable): item = FixedTablePanel(param) elif isinstance(param, ParameterRange): item = RangePanel(param) elif isinstance(param, ParameterFile): item = FileSelectionPanel(param.isFolder, param.ext) elif isinstance(param, ParameterMultipleInput): if param.datatype == dataobjects.TYPE_FILE: item = MultipleInputPanel(datatype=dataobjects.TYPE_FILE) else: if param.datatype == dataobjects.TYPE_RASTER: options = dataobjects.getRasterLayers(sorting=False) elif param.datatype == dataobjects.TYPE_VECTOR_ANY: options = dataobjects.getVectorLayers(sorting=False) else: options = dataobjects.getVectorLayers([param.datatype], sorting=False) opts = [self.getExtendedLayerName(opt) for opt in options] item = MultipleInputPanel(opts) elif isinstance(param, ParameterNumber): item = NumberInputPanel(param.default, param.min, param.max, param.isInteger) elif isinstance(param, ParameterExtent): item = ExtentSelectionPanel(self.parent, self.alg, param.default) elif isinstance(param, ParameterPoint): item = PointSelectionPanel(self.parent, param.default) elif isinstance(param, ParameterCrs): item = CrsSelectionPanel(param.default) elif isinstance(param, ParameterString): if param.multiline: verticalLayout = QVBoxLayout() verticalLayout.setSizeConstraint( QLayout.SetDefaultConstraint) textEdit = QPlainTextEdit() if param.default: textEdit.setPlainText(param.default) verticalLayout.addWidget(textEdit) item = textEdit else: item = QLineEdit() if param.default: item.setText(unicode(param.default)) elif isinstance(param, ParameterGeometryPredicate): item = GeometryPredicateSelectionPanel(param.enabledPredicates) if param.left: widget = self.valueItems[param.left] if isinstance(widget, InputLayerSelectorPanel): widget = widget.cmbText widget.currentIndexChanged.connect(item.onLeftLayerChange) item.leftLayer = widget.itemData(widget.currentIndex()) if param.right: widget = self.valueItems[param.right] if isinstance(widget, InputLayerSelectorPanel): widget = widget.cmbText widget.currentIndexChanged.connect(item.onRightLayerChange) item.rightLayer = widget.itemData(widget.currentIndex()) item.updatePredicates() if param.default: item.setValue(param.default) else: item = QLineEdit() if param.default: item.setText(unicode(param.default)) return item
class ProgressDialog(QDialog): """ Progress dialog shows progress bar for algorithm. """ def __init__(self, iface): QDialog.__init__(self, iface.mainWindow()) self.workerThread = None self.state = False self.resultStatus = None self.doReRun = False self.wasCanceled = False self.wasSuccessful = False self.savedProj = None self.result = None self.messageTxt = { 'msg_optimierung': self.tr('Berechnung der optimalen Stuetzenpositionen...'), 'msg_seillinie': self.tr('Berechnung der optimale Seillinie...') } # Build GUI Elements self.setWindowTitle(self.tr("SEILAPLAN wird ausgefuehrt")) self.resize(500, 100) self.container = QVBoxLayout() self.progressBar = QProgressBar(self) self.progressBar.setMinimumWidth(500) self.statusLabel = QLabel(self) self.hbox = QHBoxLayout() self.cancelButton = QDialogButtonBox() self.closeButton = QDialogButtonBox() self.resultLabel = QLabel(self) self.resultLabel.setMaximumWidth(500) self.resultLabel.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)) self.resultLabel.setWordWrap(True) spacer1 = QSpacerItem(20, 20, QSizePolicy.Fixed, QSizePolicy.Fixed) self.rerunButton = QPushButton(self.tr("zurueck zum Startfenster")) self.rerunButton.setVisible(False) spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.cancelButton.setStandardButtons(QDialogButtonBox.Cancel) self.cancelButton.button(QDialogButtonBox.Cancel).setText(self.tr("Abbrechen")) self.cancelButton.clicked.connect(self.onAbort) self.closeButton.setStandardButtons(QDialogButtonBox.Close) self.closeButton.button(QDialogButtonBox.Close).setText(self.tr("Schliessen")) self.closeButton.clicked.connect(self.onClose) self.hbox.addWidget(self.rerunButton) self.hbox.addItem(spacer2) self.hbox.addWidget(self.cancelButton) self.hbox.setAlignment(self.cancelButton, Qt.AlignHCenter) self.hbox.addWidget(self.closeButton) self.hbox.setAlignment(self.closeButton, Qt.AlignHCenter) self.closeButton.hide() self.container.addWidget(self.progressBar) self.container.addWidget(self.statusLabel) self.container.addWidget(self.resultLabel) self.container.addItem(spacer1) self.container.addLayout(self.hbox) self.container.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.container) # noinspection PyMethodMayBeStatic def tr(self, message, **kwargs): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString Parameters ---------- **kwargs """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate(type(self).__name__, message) def setThread(self, workerThread): self.workerThread = workerThread self.connectThreadSignals() def connectThreadSignals(self): # Connect signals of thread self.workerThread.sig_jobEnded.connect(self.jobEnded) self.workerThread.sig_jobError.connect(self.onError) self.workerThread.sig_value.connect(self.valueFromThread) self.workerThread.sig_range.connect(self.rangeFromThread) self.workerThread.sig_text.connect(self.textFromThread) self.workerThread.sig_result.connect(self.resultFromThread) self.rerunButton.clicked.connect(self.onRerun) def run(self): # Show modal dialog window (QGIS is still responsive) self.show() # start event loop self.exec() def jobEnded(self, success): self.setWindowTitle("SEILAPLAN") if success: self.progressBar.setValue(self.progressBar.maximum()) self.wasSuccessful = True # Close progress dialog so that adjustment window can be opened self.close() else: # If there was an abort by the user self.statusLabel.setText(self.tr("Berechnungen abgebrochen.")) self.progressBar.setValue(self.progressBar.minimum()) self.finallyDo() def valueFromThread(self, value): self.progressBar.setValue(int(value)) def rangeFromThread(self, range_vals): self.progressBar.setRange(int(round(range_vals[0])), int(round(range_vals[1]))) def maxFromThread(self, max): self.progressBar.setValue(self.progressBar.maximum()) def textFromThread(self, message): self.statusLabel.setText(self.messageTxt[message]) def resultFromThread(self, resultStatus): self.resultStatus = resultStatus # resultStatus: # 1 = Optimization successful # 2 = Cable takes off from support # 3 = Optimization partially successful def onAbort(self): self.setWindowTitle('SEILAPLAN') self.statusLabel.setText(self.tr( 'Laufender Prozess wird abgebrochen...')) self.workerThread.cancel() # Terminates process cleanly self.wasCanceled = True def onError(self, exception_string): self.setWindowTitle(self.tr('SEILAPLAN: Berechnung fehlgeschlagen')) self.statusLabel.setText(self.tr('Ein Fehler ist aufgetreten:')) self.resultLabel.setText(self.tr(exception_string)) self.resultLabel.setHidden(False) self.progressBar.setValue(self.progressBar.minimum()) self.setLayout(self.container) self.finallyDo() def onRerun(self): self.doReRun = True self.onClose() def finallyDo(self): self.rerunButton.setVisible(True) self.cancelButton.hide() self.closeButton.show() def onClose(self): self.close()
class FieldMappingTab(QWidget, object): """Widget class for field mapping.""" def __init__(self, field_group=None, parent=None, iface=None): """Constructor.""" # Init from parent class QWidget.__init__(self, parent) # Attributes self.layer = None self.metadata = {} self.parent = parent self.iface = iface self.field_group = field_group self.setting = QSettings() # TODO(IS): Make dynamic # Main container self.main_layout = QVBoxLayout() # Inner layout self.header_layout = QHBoxLayout() self.content_layout = QHBoxLayout() self.footer_layout = QHBoxLayout() # Header self.header_label = QLabel() self.header_label.setWordWrap(True) # Content self.field_layout = QVBoxLayout() self.parameter_layout = QHBoxLayout() self.field_description = QLabel(tr('List of fields')) self.field_list = QListWidget() self.field_list.setSelectionMode(QAbstractItemView.ExtendedSelection) self.field_list.setDragDropMode(QAbstractItemView.DragDrop) self.field_list.setDefaultDropAction(Qt.MoveAction) self.field_list.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Expanding) # noinspection PyUnresolvedReferences self.field_list.itemSelectionChanged.connect(self.update_footer) # Footer self.footer_label = QLabel() self.footer_label.setWordWrap(True) # Parameters self.extra_parameters = [ (GroupSelectParameter, GroupSelectParameterWidget) ] self.parameters = [] self.parameter_container = None # Adding to layout self.header_layout.addWidget(self.header_label) self.field_layout.addWidget(self.field_description) self.field_layout.addWidget(self.field_list) self.field_layout.setSizeConstraint(QLayout.SetMaximumSize) self.content_layout.addLayout(self.field_layout) self.content_layout.addLayout(self.parameter_layout) self.footer_layout.addWidget(self.footer_label) self.main_layout.addLayout(self.header_layout) self.main_layout.addLayout(self.content_layout) self.main_layout.addLayout(self.footer_layout) self.setLayout(self.main_layout) def set_layer(self, layer, keywords=None): """Set layer and update UI accordingly. :param layer: A vector layer that has been already patched with metadata. :type layer: QgsVectorLayer :param keywords: Custom keyword for the layer. :type keywords: dict, None """ self.layer = layer if keywords is not None: self.metadata = keywords else: # Check if it has keywords if not hasattr(layer, 'keywords'): message = 'Layer {layer_name} does not have keywords.'.format( layer_name=layer.name()) raise KeywordNotFoundError(message) self.metadata = layer.keywords self.populate_parameter() def populate_field_list(self, excluded_fields=None): """Helper to add field of the layer to the list. :param excluded_fields: List of field that want to be excluded. :type excluded_fields: list """ # Populate fields list if excluded_fields is None: excluded_fields = [] self.field_list.clear() for field in self.layer.fields(): # Skip if it's excluded if field.name() in excluded_fields: continue # Skip if it's not number (float, int, etc) if field.type() not in qvariant_numbers: continue field_item = QListWidgetItem(self.field_list) field_item.setFlags( Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field.name()) field_item.setText(field.name()) self.field_list.addItem(field_item) def populate_parameter(self): """Helper to setup the parameter widget.""" used_fields = [] self.parameters = [] for field in self.field_group.get('fields', []): selected_option = DO_NOT_REPORT options = OrderedDict([ (DO_NOT_REPORT, { 'label': tr('Do not report'), 'value': None, 'type': STATIC, 'constraint': {} }), ]) # Example: count if field['absolute']: # Used in field options field_label = tr('Count fields') else: # Example: ratio # Used in field options field_label = tr('Ratio fields') global_default_value = get_inasafe_default_value_qsetting( self.setting, GLOBAL, field['key']) options[GLOBAL_DEFAULT] = { 'label': tr('Global default'), 'value': global_default_value, 'type': STATIC, 'constraint': {} } default_custom_value = get_inasafe_default_value_qsetting( self.setting, RECENT, field['key']) custom_value = self.metadata.get( 'inasafe_default_values', {}).get( field['key'], default_custom_value) if field['key'] in self.metadata.get( 'inasafe_default_values', {}): if custom_value == global_default_value: selected_option = GLOBAL_DEFAULT else: selected_option = CUSTOM_VALUE min_value = field['default_value'].get('min_value', 0) max_value = field['default_value'].get('max_value', 100) default_step = (max_value - min_value) / 100.0 step = field['default_value'].get('increment', default_step) options[CUSTOM_VALUE] = { 'label': tr('Custom'), 'value': custom_value, 'type': SINGLE_DYNAMIC, 'constraint': { 'min': min_value, 'max': max_value, 'step': step } } custom_fields = self.metadata.get('inasafe_fields', {}).get( field['key'], []) if field['key'] in self.metadata.get('inasafe_fields', {}): selected_option = FIELDS if isinstance(custom_fields, str): custom_fields = [custom_fields] options[FIELDS] = { 'label': field_label, 'value': custom_fields, 'type': MULTIPLE_DYNAMIC, 'constraint': {} } used_fields.extend(custom_fields) parameter = GroupSelectParameter() parameter.guid = field['key'] parameter.name = field['name'] parameter.options = options parameter.selected = selected_option parameter.help_text = field['help_text'] parameter.description = field['description'] self.parameters.append(parameter) self.parameter_container = ParameterContainer( parameters=self.parameters, extra_parameters=self.extra_parameters, vertical=False ) self.parameter_container.setup_ui() constraints = self.field_group.get('constraints', {}) for key, value in list(constraints.items()): self.parameter_container.add_validator( validators[key], kwargs=value['kwargs'], validation_message=value['message']) self.parameter_layout.addWidget(self.parameter_container) default_ratio_help_text = tr( 'By default, InaSAFE will calculate the default ratio ' 'however users have the option to include this in the ' 'analysis report. If you do not want to see the default ' 'results in the report choose "do not report".') # Set move or copy if self.field_group.get('exclusive', False): # If exclusive, do not add used field. self.populate_field_list(excluded_fields=used_fields) # Use move action since it's exclusive self.field_list.setDefaultDropAction(Qt.MoveAction) # Just make sure that the signal is disconnected try: # noinspection PyUnresolvedReferences self.field_list.itemChanged.disconnect(self.drop_remove) except TypeError: pass # Set header header_text = self.field_group['description'] header_text += '\n\n' + default_ratio_help_text header_text += '\n\n' + tr( 'You can only map one field to one concept.') else: # If not exclusive, add all field. self.populate_field_list() # Use copy action since it's not exclusive self.field_list.setDefaultDropAction(Qt.CopyAction) # noinspection PyUnresolvedReferences self.field_list.itemChanged.connect( partial(self.drop_remove, field_list=self.field_list)) self.connect_drop_remove_parameter() # Set header header_text = self.field_group['description'] header_text += '\n\n' + default_ratio_help_text header_text += '\n\n' + tr( 'You can map one field to more than one concepts.') self.header_label.setText(header_text) def get_parameter_value(self): """Get parameter of the tab. :returns: Dictionary of parameters by type in this format: {'fields': {}, 'values': {}}. :rtype: dict """ parameters = self.parameter_container.get_parameters(True) field_parameters = {} value_parameters = {} for parameter in parameters: if parameter.selected_option_type() in [SINGLE_DYNAMIC, STATIC]: value_parameters[parameter.guid] = parameter.value elif parameter.selected_option_type() == MULTIPLE_DYNAMIC: field_parameters[parameter.guid] = parameter.value return { 'fields': field_parameters, 'values': value_parameters } def update_footer(self): """Update footer when the field list change.""" field_item = self.field_list.currentItem() if not field_item: self.footer_label.setText('') return field_name = field_item.data(Qt.UserRole) field = self.layer.fields().field(field_name) index = self.layer.fields().lookupField(field_name) unique_values = list(self.layer.uniqueValues(index)) pretty_unique_values = ', '.join([str(v) for v in unique_values[:10]]) footer_text = tr('Field type: {0}\n').format(field.typeName()) footer_text += tr('Unique values: {0}').format(pretty_unique_values) self.footer_label.setText(footer_text) def connect_drop_remove_parameter(self): parameter_widgets = self.parameter_container.get_parameter_widgets() for parameter_widget in parameter_widgets: field_list = parameter_widget.widget().list_widget field_list.itemChanged.connect( partial(self.drop_remove, field_list=field_list)) @staticmethod def drop_remove(*args, **kwargs): """Action when we need to remove dropped item. :param *args: Position arguments. :type *args: list :param kwargs: Keywords arguments. :type kwargs: dict """ dropped_item = args[0] field_list = kwargs['field_list'] num_duplicate = 0 for i in range(field_list.count()): if dropped_item.text() == field_list.item(i).text(): num_duplicate += 1 if num_duplicate > 1: # Notes(IS): For some reason, removeItemWidget is not working. field_list.takeItem(field_list.row(dropped_item))