def _initializes_minimum_needs_fields(): """Initialize minimum needs fields. Minimum needs definitions are taken from currently used profile. """ needs_profile = NeedsProfile() needs_profile.load() fields = [] needs_parameters = needs_profile.get_needs_parameters() for need_parameter in needs_parameters: if isinstance(need_parameter, ResourceParameter): format_args = { 'namespace': minimum_needs_namespace, 'key': _normalize_field_name(need_parameter.name), 'name': need_parameter.name, 'field_name': _normalize_field_name(need_parameter.name), } key = '{namespace}__{key}_count_field'.format(**format_args) name = '{name}'.format(**format_args) field_name = '{namespace}__{field_name}'.format(**format_args) field_type = QVariant.LongLong # See issue #4039 length = 11 # See issue #4039 precision = 0 absolute = True replace_null = False description = need_parameter.description field_definition = { 'key': key, 'name': name, 'field_name': field_name, 'type': field_type, 'length': length, 'precision': precision, 'absolute': absolute, 'description': description, 'replace_null': replace_null, 'unit_abbreviation': need_parameter.unit.abbreviation, # Link to need_parameter 'need_parameter': need_parameter } fields.append(field_definition) return fields
def population_infographic_extractor(impact_report, component_metadata): """Extracting aggregate result of demographic. :param impact_report: the impact report that acts as a proxy to fetch all the data that extractor needed :type impact_report: safe.report.impact_report.ImpactReport :param component_metadata: the component metadata. Used to obtain information about the component we want to render :type component_metadata: safe.report.report_metadata. ReportComponentsMetadata :return: context for rendering phase :rtype: dict .. versionadded:: 4.0 """ context = {} extra_args = component_metadata.extra_args """Initializations""" hazard_layer = impact_report.hazard analysis_layer = impact_report.analysis analysis_layer_fields = analysis_layer.keywords['inasafe_fields'] icons = component_metadata.extra_args.get('icons') # this report sections only applies if it is a population report. population_fields = [ population_count_field['key'], exposure_count_field['key'] % (exposure_population['key'], ), ] + [f['key'] for f in minimum_needs_fields] for item in population_fields: if item in analysis_layer_fields: break else: return context # We try to get total affected field # if it didn't exists, check other fields to show total_affected_fields = [ total_affected_field['key'], # We might want to check other fields, but turn it off until further # discussion population_count_field['key'], exposure_count_field['key'] % (exposure_population['key'], ), ] for item in total_affected_fields: if item in analysis_layer_fields: total_affected = value_from_field_name(analysis_layer_fields[item], analysis_layer) total_affected_field_used = item break else: return context if displaced_field['key'] in analysis_layer_fields: total_displaced = value_from_field_name( analysis_layer_fields[displaced_field['key']], analysis_layer) else: return context sections = OrderedDict() """People Section""" # Take default value from definitions people_header = resolve_from_dictionary(extra_args, ['sections', 'people', 'header']) people_items = resolve_from_dictionary(extra_args, ['sections', 'people', 'items']) # create context for affected infographic sub_header = resolve_from_dictionary(people_items[0], 'sub_header') # retrieve relevant header based on the fields we showed. sub_header = sub_header[total_affected_field_used] affected_infographic = PeopleInfographicElement( header=sub_header, icon=icons.get(total_affected_field['key']), number=total_affected) # create context for displaced infographic sub_header = resolve_from_dictionary(people_items[1], 'sub_header') sub_header_note_format = resolve_from_dictionary(people_items[1], 'sub_header_note_format') rate_description_format = resolve_from_dictionary( people_items[1], 'rate_description_format') rate_description = [] hazard_classification = layer_hazard_classification(hazard_layer) for hazard_class in hazard_classification['classes']: displacement_rate = hazard_class.get('displacement_rate', 0) if displacement_rate: rate_description.append( rate_description_format.format(**hazard_class)) rate_description_string = ', '.join(rate_description) sub_header_note = sub_header_note_format.format( rate_description=rate_description_string) displaced_infographic = PeopleInfographicElement( header=sub_header, header_note=sub_header_note, icon=icons.get(displaced_field['key']), number=total_displaced) sections['people'] = { 'header': people_header, 'items': [affected_infographic, displaced_infographic] } """Vulnerability Section""" # Take default value from definitions vulnerability_items = resolve_from_dictionary( extra_args, ['sections', 'vulnerability', 'items']) vulnerability_section_header = resolve_from_dictionary( extra_args, ['sections', 'vulnerability', 'header']) vulnerability_section_sub_header_format = resolve_from_dictionary( extra_args, ['sections', 'vulnerability', 'sub_header_format']) infographic_elements = [] for group in vulnerability_items: fields = group['fields'] group_header = group['sub_group_header'] bootstrap_column = group['bootstrap_column'] element_column = group['element_column'] headers = group['headers'] elements = [] for field, header in zip(fields, headers): field_key = field['key'] try: field_name = analysis_layer_fields[field_key] value = value_from_field_name(field_name, analysis_layer) except KeyError: # It means the field is not there continue if value: value_percentage = value * 100.0 / total_displaced else: value_percentage = 0 infographic_element = PeopleVulnerabilityInfographicElement( header=header, icon=icons.get(field_key), number=value, percentage=value_percentage) elements.append(infographic_element) if elements: infographic_elements.append({ 'group_header': group_header, 'bootstrap_column': bootstrap_column, 'element_column': element_column, 'items': elements }) total_displaced_rounded = format_number(total_displaced, enable_rounding=True, is_population=True) sections['vulnerability'] = { 'header': vulnerability_section_header, 'small_header': vulnerability_section_sub_header_format.format( number_displaced=total_displaced_rounded), 'items': infographic_elements } """Minimum Needs Section""" minimum_needs_header = resolve_from_dictionary( extra_args, ['sections', 'minimum_needs', 'header']) empty_unit_string = resolve_from_dictionary( extra_args, ['sections', 'minimum_needs', 'empty_unit_string']) items = [] for item in minimum_needs_fields: need = item['need_parameter'] if isinstance(need, ResourceParameter): needs_count = value_from_field_name(item['field_name'], analysis_layer) if need.unit.abbreviation: unit_string = '{unit}/{frequency}'.format( unit=need.unit.abbreviation, frequency=need.frequency) else: unit_string = empty_unit_string item = PeopleMinimumNeedsInfographicElement(header=item['name'], icon=icons.get( item['key']), number=needs_count, unit=unit_string) items.append(item) # TODO: get from impact function provenance later needs_profile = NeedsProfile() sections['minimum_needs'] = { 'header': minimum_needs_header, 'small_header': needs_profile.provenance, 'items': items, } """Population Charts""" population_donut_path = impact_report.component_absolute_output_path( 'population-chart-png') css_label_classes = [] try: population_chart_context = impact_report.metadata.component_by_key( 'population-chart').context['context'] """ :type: safe.report.extractors.infographic_elements.svg_charts. DonutChartContext """ for pie_slice in population_chart_context.slices: label = pie_slice['label'] if not label: continue css_class = label.replace(' ', '').lower() css_label_classes.append(css_class) except KeyError: population_chart_context = None sections['population_chart'] = { 'img_path': resource_url(population_donut_path), 'context': population_chart_context, 'css_label_classes': css_label_classes } context['brand_logo'] = resource_url( resources_path('img', 'logos', 'inasafe-logo-white.png')) context['sections'] = sections context['title'] = analysis_layer.title() or value_from_field_name( analysis_name_field['field_name'], analysis_layer) return context
def __init__(self, parent=None, dock=None): """Constructor for the minimum needs dialog. :param parent: Parent widget of this dialog. :type parent: QWidget :param dock: Dock widget instance that we can notify of changes. :type dock: Dock """ QtWidgets.QDialog.__init__(self, parent) # List of parameters with the translated name. self.resource_parameters = { 'Resource name': tr('Resource name'), 'Resource description': tr('Resource description'), 'Unit': tr('Unit'), 'Units': tr('Units'), 'Unit abbreviation': tr('Unit abbreviation'), 'Minimum allowed': tr('Minimum allowed'), 'Maximum allowed': tr('Maximum allowed'), 'Default': tr('Default'), 'Frequency': tr('Frequency'), 'Readable sentence': tr('Readable sentence') } self.setupUi(self) icon = resources_path('img', 'icons', 'show-minimum-needs.svg') self.setWindowIcon(QtGui.QIcon(icon)) self.dock = dock # These are in the little button bar at the bottom # 'Remove resource' button # noinspection PyUnresolvedReferences self.remove_resource_button.clicked.connect(self.remove_resource) self.remove_resource_button.setIcon( QIcon(os.path.join( resources_path(), 'img', 'icons', 'remove.svg'))) # Add resource # noinspection PyUnresolvedReferences self.add_resource_button.clicked.connect(self.add_new_resource) self.add_resource_button.setIcon( QIcon(os.path.join( resources_path(), 'img', 'icons', 'add.svg'))) # Edit resource # noinspection PyUnresolvedReferences self.edit_resource_button.clicked.connect(self.edit_resource) self.edit_resource_button.setIcon( QIcon(os.path.join( resources_path(), 'img', 'icons', 'edit.svg'))) # Discard changes to a resource self.discard_changes_button = QPushButton(self.tr('Discard changes')) self.button_box.addButton( self.discard_changes_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.discard_changes_button.clicked.connect(self.discard_changes) # Restore defaults profiles self.restore_defaults_button = QPushButton(self.tr('Restore defaults')) self.button_box.addButton( self.restore_defaults_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.restore_defaults_button.clicked.connect(self.restore_defaults) # Save changes to a resource self.save_resource_button = QPushButton(self.tr('Save resource')) self.button_box.addButton( self.save_resource_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.save_resource_button.clicked.connect(self.save_resource) # Export profile button self.export_profile_button = QPushButton(self.tr('Export ...')) self.button_box.addButton( self.export_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.export_profile_button.clicked.connect(self.export_profile) # Import profile button self.import_profile_button = QPushButton(self.tr('Import ...')) self.button_box.addButton( self.import_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.import_profile_button.clicked.connect(self.import_profile) # New profile button self.new_profile_button = QPushButton(self.tr('New')) self.button_box.addButton( self.new_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.new_profile_button.clicked.connect(self.new_profile) # Save profile button self.save_profile_button = QPushButton(self.tr('Save')) self.button_box.addButton( self.save_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.save_profile_button.clicked.connect(self.save_profile) # 'Save as' profile button self.save_profile_as_button = QPushButton(self.tr('Save as')) self.button_box.addButton( self.save_profile_as_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.save_profile_as_button.clicked.connect( self.save_profile_as) # Set up things for context help self.help_button = self.button_box.button( QtWidgets.QDialogButtonBox.Help) # Allow toggling the help button self.help_button.setCheckable(True) self.help_button.toggled.connect(self.help_toggled) self.main_stacked_widget.setCurrentIndex(1) self.minimum_needs = NeedsProfile() self.edit_item = None # Remove profile button # noinspection PyUnresolvedReferences self.remove_profile_button.clicked.connect(self.remove_profile) # These are all buttons that will get hidden on context change # to the profile editing view self.profile_editing_buttons = list() self.profile_editing_buttons.append(self.remove_resource_button) self.profile_editing_buttons.append(self.add_resource_button) self.profile_editing_buttons.append(self.edit_resource_button) self.profile_editing_buttons.append(self.export_profile_button) self.profile_editing_buttons.append(self.import_profile_button) self.profile_editing_buttons.append(self.new_profile_button) self.profile_editing_buttons.append(self.save_profile_button) self.profile_editing_buttons.append(self.save_profile_as_button) # We also keep a list of all widgets to disable in context of resource # editing (not hidden, just disabled) self.profile_editing_widgets = self.profile_editing_buttons self.profile_editing_widgets.append(self.remove_profile_button) self.profile_editing_widgets.append(self.profile_combo) # These are all buttons that will get hidden on context change # to the resource editing view self.resource_editing_buttons = list() self.resource_editing_buttons.append(self.discard_changes_button) self.resource_editing_buttons.append(self.save_resource_button) for item in self.resource_editing_buttons: item.hide() self.load_profiles() # Next 2 lines fixes issues #1388 #1389 #1390 #1391 if self.profile_combo.count() > 0: self.select_profile(0) # initial sync profile_combo and resource list self.clear_resource_list() self.populate_resource_list() self.set_up_resource_parameters() # Only do this afterward load_profiles to avoid the resource list # being updated # noinspection PyUnresolvedReferences self.profile_combo.activated.connect(self.select_profile) # noinspection PyUnresolvedReferences self.stacked_widget.currentChanged.connect(self.page_changed) self.select_profile(self.profile_combo.currentIndex())
def __init__(self, parent=None): """Constructor for the minimum needs dialog. :param parent: Parent widget of this dialog. :type parent: QWidget """ QtGui.QDialog.__init__(self, parent) self.setupUi(self) # These are in the little button bar at the top # 'Remove resource' button # noinspection PyUnresolvedReferences self.remove_resource_button.clicked.connect(self.remove_resource) self.remove_resource_button.setIcon( QIcon(os.path.join( resources_path(), 'img', 'icons', 'remove.svg'))) # Add resource # noinspection PyUnresolvedReferences self.add_resource_button.clicked.connect(self.add_new_resource) self.add_resource_button.setIcon( QIcon(os.path.join( resources_path(), 'img', 'icons', 'add.svg'))) # Edit resource # noinspection PyUnresolvedReferences self.edit_resource_button.clicked.connect(self.edit_resource) self.edit_resource_button.setIcon( QIcon(os.path.join( resources_path(), 'img', 'icons', 'edit.svg'))) # Discard changes to a resource self.discard_changes_button = QPushButton(self.tr('Discard changes')) self.button_box.addButton( self.discard_changes_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.discard_changes_button.clicked.connect(self.discard_changes) # Save changes to a resource self.save_resource_button = QPushButton(self.tr('Save resource')) self.button_box.addButton( self.save_resource_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.save_resource_button.clicked.connect(self.save_resource) # Export profile button self.export_profile_button = QPushButton(self.tr('Export ...')) self.button_box.addButton( self.export_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.export_profile_button.clicked.connect(self.export_profile) # Import profile button self.import_profile_button = QPushButton(self.tr('Import ...')) self.button_box.addButton( self.import_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.import_profile_button.clicked.connect(self.import_profile) # New profile button self.new_profile_button = QPushButton(self.tr('New')) self.button_box.addButton( self.new_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.new_profile_button.clicked.connect(self.new_profile) # Save profile button self.save_profile_button = QPushButton(self.tr('Save')) self.button_box.addButton( self.save_profile_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.save_profile_button.clicked.connect(self.save_profile) # 'Save as' profile button self.save_profile_as_button = QPushButton(self.tr('Save as')) self.button_box.addButton( self.save_profile_as_button, QDialogButtonBox.ActionRole) # noinspection PyUnresolvedReferences self.save_profile_as_button.clicked.connect( self.save_profile_as) # Set up context help self.help_context = 'needs_manager' help_button = self.button_box.button(QtGui.QDialogButtonBox.Help) help_button.clicked.connect(self.show_help) self.minimum_needs = NeedsProfile() self.edit_item = None # Remove profile button # noinspection PyUnresolvedReferences self.remove_profile_button.clicked.connect(self.remove_profile) # These are all buttons that will get hidden on context change # to the profile editing view self.profile_editing_buttons = list() self.profile_editing_buttons.append(self.remove_resource_button) self.profile_editing_buttons.append(self.add_resource_button) self.profile_editing_buttons.append(self.edit_resource_button) self.profile_editing_buttons.append(self.export_profile_button) self.profile_editing_buttons.append(self.import_profile_button) self.profile_editing_buttons.append(self.new_profile_button) self.profile_editing_buttons.append(self.save_profile_button) self.profile_editing_buttons.append(self.save_profile_as_button) # We also keep a list of all widgets to disable in context of resource # editing (not hidden, just disabled) self.profile_editing_widgets = self.profile_editing_buttons self.profile_editing_widgets.append(self.remove_profile_button) self.profile_editing_widgets.append(self.profile_combo) # These are all buttons that will get hidden on context change # to the resource editing view self.resource_editing_buttons = list() self.resource_editing_buttons.append(self.discard_changes_button) self.resource_editing_buttons.append(self.save_resource_button) for item in self.resource_editing_buttons: item.hide() self.load_profiles() # Next 2 lines fixes issues #1388 #1389 #1390 #1391 if self.profile_combo.count() > 0: self.select_profile(0) self.clear_resource_list() self.populate_resource_list() self.set_up_resource_parameters() # Only do this afterward load_profiles to avoid the resource list # being updated # noinspection PyUnresolvedReferences self.profile_combo.activated.connect(self.select_profile) # noinspection PyUnresolvedReferences self.stacked_widget.currentChanged.connect(self.page_changed)