safe/gui/tools/wizard/step_kw45_inasafe_fields.py
# coding=utf-8
"""InaSAFE Wizard Step InaSAFE Fields."""
# noinspection PyPackageRequirements
import logging
from parameters.qt_widgets.parameter_container import ParameterContainer
from parameters.select_parameter import SelectParameter
from safe import messaging as m
from safe.definitions.constants import no_field
from safe.definitions.layer_geometry import layer_geometry_raster
from safe.definitions.layer_purposes import (layer_purpose_aggregation)
from safe.definitions.utilities import get_fields, get_compulsory_fields
from safe.gui.tools.wizard.wizard_step import (
WizardStep, get_wizard_step_ui_class)
from safe.utilities.i18n import tr
__copyright__ = "Copyright 2016, The InaSAFE Project"
__license__ = "GPL version 3"
__email__ = "info@inasafe.org"
__revision__ = '$Format:%H$'
FORM_CLASS = get_wizard_step_ui_class(__file__)
LOGGER = logging.getLogger('InaSAFE')
class StepKwInaSAFEFields(WizardStep, FORM_CLASS):
"""InaSAFE Wizard Step InaSAFE Fields."""
def __init__(self, parent=None):
"""Constructor for the tab.
:param parent: parent - widget to use as parent (Wizard Dialog).
:type parent: QWidget
"""
WizardStep.__init__(self, parent)
self.parameters = []
self.parameter_container = ParameterContainer()
self.kwExtraKeywordsGridLayout.addWidget(self.parameter_container)
def is_ready_to_next_step(self):
"""Check if the step is complete. If so, there is
no reason to block the Next button.
:returns: True if new step may be enabled.
:rtype: bool
"""
return True
def get_next_step(self):
"""Find the proper step when user clicks the Next button.
:returns: The step to be switched to
:rtype: WizardStep instance or None
"""
layer_purpose = self.parent.step_kw_purpose.selected_purpose()
if layer_purpose['key'] != layer_purpose_aggregation['key']:
subcategory = self.parent.step_kw_subcategory. \
selected_subcategory()
else:
subcategory = {'key': None}
# We don't use field mapping for populated place exposure. Use the
# population point instead.
# inasafe_fields = self.get_inasafe_fields()
# If population field is set, must go to field mapping step first.
# if population_count_field['key'] in inasafe_fields.keys():
# return self.parent.step_kw_fields_mapping
# Check if it can go to inasafe default field step
default_inasafe_fields = get_fields(
layer_purpose['key'],
subcategory['key'],
replace_null=True,
in_group=False)
if default_inasafe_fields:
return self.parent.step_kw_default_inasafe_fields
# Any other case
return self.parent.step_kw_source
def inasafe_fields_for_the_layer(self):
"""Return a list of inasafe fields the current layer.
:returns: A list where each value represents inasafe field.
:rtype: list
"""
if (self.parent.get_layer_geometry_key()
== layer_geometry_raster['key']):
return []
# Get hazard or exposure value
layer_purpose_key = self.parent.step_kw_purpose.selected_purpose()[
'key']
if layer_purpose_key != layer_purpose_aggregation['key']:
subcategory_key = self.parent.step_kw_subcategory.\
selected_subcategory()['key']
else:
subcategory_key = None
# Get all fields with replace_null = False
inasafe_fields = get_fields(
layer_purpose_key,
subcategory_key,
replace_null=False,
in_group=False)
# remove compulsory field since it has been set in previous step
try:
inasafe_fields.remove(get_compulsory_fields(
layer_purpose_key, subcategory_key))
except ValueError:
pass
return inasafe_fields
# noinspection PyTypeChecker
def set_widgets(self):
"""Set widgets on the Extra Keywords tab."""
existing_inasafe_field = self.parent.get_existing_keyword(
'inasafe_fields')
# Remove old container and parameter
if self.parameter_container:
self.kwExtraKeywordsGridLayout.removeWidget(
self.parameter_container)
if self.parameters:
self.parameters = []
# Iterate through all inasafe fields
for inasafe_field in self.inasafe_fields_for_the_layer():
# Option for Not Available
option_list = [no_field]
for field in self.parent.layer.fields():
# Check the field type
if isinstance(inasafe_field['type'], list):
if field.type() in inasafe_field['type']:
field_name = field.name()
option_list.append('%s' % field_name)
else:
if field.type() == inasafe_field['type']:
field_name = field.name()
option_list.append('%s' % field_name)
# If there is no option, pass
if option_list == [no_field]:
continue
# Create SelectParameter
select_parameter = SelectParameter()
select_parameter.guid = inasafe_field['key']
select_parameter.name = inasafe_field['name']
select_parameter.is_required = False
select_parameter.description = inasafe_field['description']
select_parameter.help_text = inasafe_field['help_text']
select_parameter.element_type = str
select_parameter.options_list = option_list
select_parameter.value = no_field
# Check if there is already value in the metadata.
if existing_inasafe_field:
existing_value = existing_inasafe_field.get(
inasafe_field['key'])
if existing_value:
if existing_value in select_parameter.options_list:
select_parameter.value = existing_value
self.parameters.append(select_parameter)
# Create the parameter container and add to the wizard.
self.parameter_container = ParameterContainer(self.parameters)
self.parameter_container.setup_ui()
self.kwExtraKeywordsGridLayout.addWidget(self.parameter_container)
if not self.parameters:
no_field_message = tr(
'There is no available field that has match type for the '
'InaSAFE fields. You can click next.')
self.lblInaSAFEFields.setText(no_field_message)
def get_inasafe_fields(self):
"""Return inasafe fields from the current wizard state.
:returns: Dictionary of key and value from InaSAFE Fields.
:rtype: dict
"""
inasafe_fields = {}
parameters = self.parameter_container.get_parameters(True)
for parameter in parameters:
if not parameter.value == no_field:
inasafe_fields[parameter.guid] = parameter.value
return inasafe_fields
def clear(self):
"""Clear current state."""
# Adapted from http://stackoverflow.com/a/13103617/1198772
for i in reversed(list(range(self.kwExtraKeywordsGridLayout.count()))):
self.kwExtraKeywordsGridLayout.itemAt(i).widget().setParent(None)
self.parameters = []
self.parameter_container = ParameterContainer()
@property
def step_name(self):
"""Get the human friendly name for the wizard step.
:returns: The name of the wizard step.
:rtype: str
"""
return tr('InaSAFE Field Step')
def help_content(self):
"""Return the content of help for this step wizard.
We only needs to re-implement this method in each wizard step.
:returns: A message object contains help.
:rtype: m.Message
"""
message = m.Message()
message.add(m.Paragraph(tr(
'In this wizard step: {step_name}, you will be able to '
'set a field that corresponded with a InaSAFE field '
'concept.').format(step_name=self.step_name)))
return message