def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 3.2.3

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    paragraph = m.Paragraph(m.Image('file:///%s/img/screenshots/'
                                    'petabencana-screenshot.png' %
                                    resources_path()),
                            style_class='text-center')
    message.add(paragraph)
    link = m.Link('https://petabencana.id', 'PetaBencana.id')
    body = m.Paragraph(
        tr('This tool will fetch current flood data for Jakarta from '), link)
    tips = m.BulletedList()
    tips.add(
        tr('Check the output directory is correct. Note that the saved '
           'dataset will be called jakarta_flood.shp (and associated files).'))
    tips.add(
        tr('If you wish you can specify a prefix to '
           'add in front of this default name. For example using a prefix '
           'of \'foo-\' will cause the downloaded files to be saved as e.g. '
           '\'foo-rw-jakarta-flood.shp\'. Note that the only allowed prefix '
           'characters are A-Z, a-z, 0-9 and the characters \'-\' and \'_\'. '
           'You can leave this blank if you prefer.'))
    tips.add(
        tr('If a dataset already exists in the output directory it will be '
           'overwritten if the "overwrite existing files" checkbox is ticked.')
    )
    tips.add(
        tr('If the "include date/time in output filename" option is ticked, '
           'the filename will be prefixed with a time stamp e.g. '
           '\'foo-22-Mar-2015-08-01-2015-rw-jakarta-flood.shp\' where the date '
           'timestamp is in the form DD-MMM-YYYY.'))
    tips.add(
        tr('This tool requires a working internet connection and fetching '
           'data will consume your bandwidth.'))
    tips.add(
        m.Link(production_api['help_url'],
               text=tr(
                   'Downloaded data is copyright the PetaBencana contributors'
                   ' (click for more info).')))
    message.add(body)
    message.add(tips)
    return message
Esempio n. 2
0
def _create_section_header(message,
                           table_of_contents,
                           element_id,
                           text,
                           heading_level=1):
    # Warning a side effect here is that the SECTION_STYLE is updated
    # when setting style as we modify the id so we have to make a deep copy
    style = copy.deepcopy(HEADING_LOOKUPS[heading_level])
    style['element_id'] = element_id

    HEADING_COUNTS[heading_level] += 1
    # Reset the heading counts for headings below this level
    # Also calculate the index of the TOC entry
    index_number = ''
    for key in HEADING_COUNTS.keys():
        if key > heading_level:
            HEADING_COUNTS[key] = 0
        else:
            index_number += str(HEADING_COUNTS[key]) + '.'

    header = m.Heading(text, **style)
    link = m.Link('#%s' % element_id, index_number + ' ' + text)
    # See bootstrap docs for ml-1 explanation
    # https://v4-alpha.getbootstrap.com/utilities/spacing/#examples
    paragraph = m.Paragraph(link, style_class='ml-%i' % heading_level)
    table_of_contents.add(paragraph)
    message.add(header)
    def show_info(self):
        """Show usage info to the user."""
        # Read the header and footer html snippets
        header = html_header()
        footer = html_footer()

        string = header

        heading = m.Heading(self.tr('OSM Downloader'), **INFO_STYLE)
        body = self.tr(
            'This tool will fetch building (\'structure\') or road ('
            '\'highway\') data from the OpenStreetMap project for you. '
            'The downloaded data will have InaSAFE keywords defined and a '
            'default QGIS style applied. To use this tool effectively:'
        )
        tips = m.BulletedList()
        tips.add(self.tr(
            'Your current extent will be used to determine the area for which '
            'you want data to be retrieved. You can adjust it manually using '
            'the bounding box options below.'))
        tips.add(self.tr(
            'Check the output directory is correct. Note that the saved '
            'dataset will be called either roads.shp or buildings.shp (and '
            'associated files).'
        ))
        tips.add(self.tr(
            'By default simple file names will be used (e.g. roads.shp, '
            'buildings.shp). If you wish you can specify a prefix to '
            'add in front of this default name. For example using a prefix '
            'of \'padang-\' will cause the downloaded files to be saved as '
            '\'padang-roads.shp\' and \'padang-buildings.shp\'. Note that '
            'the only allowed prefix characters are A-Z, a-z, 0-9 and the '
            'characters \'-\' and \'_\'. You can leave this blank if you '
            'prefer.'
        ))
        tips.add(self.tr(
            'If a dataset already exists in the output directory it will be '
            'overwritten.'
        ))
        tips.add(self.tr(
            'This tool requires a working internet connection and fetching '
            'buildings or roads will consume your bandwidth.'))
        tips.add(m.Link(
            'http://www.openstreetmap.org/copyright',
            text=self.tr(
                'Downloaded data is copyright OpenStreetMap contributors'
                ' (click for more info).')
        ))
        message = m.Message()
        message.add(heading)
        message.add(body)
        message.add(tips)
        string += message.to_html()
        string += footer

        self.web_view.setHtml(string)
Esempio n. 4
0
def _create_section_header(message, table_of_contents, id, text):
    # Warning a side effect here is that the SECTION_STYLE is updated
    # when setting style as we don't have a deep copy
    style = SECTION_STYLE
    style['element_id'] = id
    header = m.Heading(text, **style)
    link = m.Link('#%s' % id, text)
    paragraph = m.Paragraph(link)
    table_of_contents.add(paragraph)
    message.add(header)
Esempio n. 5
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 3.2.2

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    body = tr('This tool will fetch building (\'structure\') or road ('
              '\'highway\') data from the OpenStreetMap project for you. '
              'The downloaded data will have InaSAFE keywords defined and a '
              'default QGIS style applied. To use this tool effectively:')
    tips = m.BulletedList()
    tips.add(
        tr('Your current extent, when opening this window, will be used to '
           'determine the area for which you want data to be retrieved.'
           'You can interactively select the area by using the '
           '\'select on map\' button - which will temporarily hide this '
           'window and allow you to drag a rectangle on the map. After you '
           'have finished dragging the rectangle, this window will '
           'reappear.'))
    tips.add(
        tr('Check the output directory is correct. Note that the saved '
           'dataset will be called either roads.shp or buildings.shp (and '
           'associated files).'))
    tips.add(
        tr('By default simple file names will be used (e.g. roads.shp, '
           'buildings.shp). If you wish you can specify a prefix to '
           'add in front of this default name. For example using a prefix '
           'of \'padang-\' will cause the downloaded files to be saved as '
           '\'padang-roads.shp\' and \'padang-buildings.shp\'. Note that '
           'the only allowed prefix characters are A-Z, a-z, 0-9 and the '
           'characters \'-\' and \'_\'. You can leave this blank if you '
           'prefer.'))
    tips.add(
        tr('If a dataset already exists in the output directory it will be '
           'overwritten.'))
    tips.add(
        tr('This tool requires a working internet connection and fetching '
           'buildings or roads will consume your bandwidth.'))
    tips.add(
        m.Link('http://www.openstreetmap.org/copyright',
               text=tr(
                   'Downloaded data is copyright OpenStreetMap contributors'
                   ' (click for more info).')))
    message.add(body)
    message.add(tips)
    return message
Esempio n. 6
0
def _citations_to_message(message, definition):
    citations = m.Message()
    bullets = m.BulletedList()
    for citation in definition['citations']:
        if citation['text'] in [None, '']:
            continue
        if citation['link'] in [None, '']:
            bullets.add(m.Paragraph(citation['text']))
        else:
            bullets.add(m.Paragraph(m.Link(citation['link'],
                                           citation['text'])))
    if not bullets.is_empty():
        citations.add(m.Paragraph(m.ImportantText(tr('Citations:'))))
        citations.add(bullets)
        message.add(citations)
Esempio n. 7
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 4.1.0

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    message.add(
        m.Paragraph(
            tr('This section of the help documentation is intended for advanced '
               'users who want to modify the internals of InaSAFE. It assumes that '
               'you have basic coding skills. All examples are in python unless '
               'otherwise stated.')))
    message.add(m.Heading(tr('Defining a new hazard type'),
                          **SUBSECTION_STYLE))
    message.add(m.Heading(tr('Background'), **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('In the previous versions of InaSAFE, we spent a lot of effort '
           'building one impact function per hazard/exposure combination (and '
           'sometimes multiple impact functions per combination). In our new '
           'architecture, we try to deal with everything in the same way - by '
           'following a standardized process of converting the hazard dataset '
           'into a classified polygon layer and then calculating the impacted '
           'and affected areas using a standard work-flow. A simplified version '
           'of this work-flow is described in illustration 1.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Because of this change, you will no longer see an impact function '
           'selector in the dock widget and there are no longer any \'impact '
           'function options\' as we had in previous versions of InaSAFE. In '
           'the new system, almost all configuration is managed through '
           'metadata (created using the keywords wizard).'))

    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Also, in all versions prior to Version 4.0, we made heavy use of '
           'interpolation in order to determine whether buildings or other '
           'exposure layers are impacted. While this is a commonly used '
           'technique in GIS, it often leads to non - intuitive looking '
           'reports. Under our new architecture, we always use geometric '
           'overlay operations to make a determination whether an exposure '
           'feature is affected or not. The implication of this is that we '
           'produce intuitive and easily verifiable impact layers. You can '
           'see an example in Illustration 2.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Stepping away from the two previously mentioned paradigms allows '
           'us to simply add new hazard types to the metadata driven impact '
           'function by adding new metadata types to the InaSAFE sources. '
           'In the next chapter we show you how this was achieved and how '
           'it can be repeated for further hazards using the example of '
           'tropical cyclones.'))
    message.add(paragraph)
    message.add(m.Heading(tr('Adding a new hazard'), **BLUE_CHAPTER_STYLE))
    link = m.Link('https://github.com/inasafe/inasafe/pull/3539/files',
                  tr('Pull Request #3539'))
    paragraph = m.Paragraph(
        tr('The whole work needed can be looked at in '), link,
        tr('. Please bear in mind that the paths of the files are now '
           'safe/definitions/xxx.py and not safe/definitionsv4/xxx.py since '
           'v4 is the default codebase. In the next sections we will show '
           'each file that needs to be extended in order to add a new hazard '
           'type.'))
    message.add(paragraph)

    # Setting up units

    message.add(
        m.Heading(tr('safe/definitions/units.py'), **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('If you are adding an hazard that uses units that are not yet known '
           'to InaSAFE, you need to define them in units.py'))
    message.add(paragraph)
    paragraph = m.PreformattedText(
        _get_definition_from_module(units, 'unit_kilometres_per_hour'))
    message.add(paragraph)

    # Setting up style

    message.add(m.Heading('safe/definitions/colors.py', **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        'If you are adding an hazard that has more classes than any other '
        'hazards you’ll need to add additional colors for the additional '
        'classes in colors.py. You might also define other colors if you '
        'don\'t want to use the standard colors. For the sake of homogeneous '
        'map reports, this addition should not be taken lightly.')
    message.add(paragraph)
    # Don't translate this
    paragraph = m.PreformattedText('very_dark_red = Qcolor(\'#710017\')')
    message.add(paragraph)

    # Setting up hazard classification

    message.add(
        m.Heading('safe/definitions/hazard_classifications.py',
                  **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('Add the classifications you want to make available for your new '
           'hazard type. You can add as many classes as you want in the '
           'classes list.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Also, a classification can support multiple units so you don\'t '
           'have to define different classifications just to have the same '
           'classification in two or more different units. These are defined '
           'in the multiple_units attribute of the classification.'))
    message.add(paragraph)

    paragraph = m.PreformattedText(
        _get_definition_from_module(hazard_classifications,
                                    'cyclone_au_bom_hazard_classes'))
    message.add(paragraph)

    # Setting up wizard questions

    message.add(
        m.Heading('safe/gui/tools/wizard/wizard_strings.py',
                  **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(tr('Define the questions for the wizard:'))
    message.add(paragraph)
    # don not translate
    message.add(
        m.PreformattedText(
            'cyclone_kilometres_per_hour_question = tr(\'wind speed in km/h\')'
        ))
    message.add(
        m.PreformattedText(
            'cyclone_miles_per_hour_question = tr(\'wind speed in mph\')'))
    message.add(
        m.PreformattedText(
            'cyclone_knots_question = tr(\'wind speed in kn\')'))

    # Setting up

    message.add(m.Heading('safe/definitions/hazard.py', **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('Finally define new hazard and add it to the hazard_all list:'))
    message.add(paragraph)
    paragraph = m.PreformattedText(
        _get_definition_from_module(hazard, 'hazard_cyclone'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Finally define new hazard and add it to the hazard_all list:'))
    message.add(paragraph)
    paragraph = m.PreformattedText(
        _get_definition_from_module(hazard, 'hazard_all'))
    message.add(paragraph)
    return message
Esempio n. 8
0
def definition_to_message(definition,
                          message=None,
                          table_of_contents=None,
                          heading_level=None):
    """Helper function to render a definition to a message.

    :param definition: A definition dictionary (see definitions package).
    :type definition: dict

    :param message: The message that the definition should be appended to.
    :type message: safe_extras.parameters.message.Message

    :param table_of_contents: Table of contents that the headings should be
        included in.
    :type message: safe_extras.parameters.message.Message

    :param heading_level: Optional style to apply to the definition
        heading. See HEADING_LOOKUPS
    :type heading_level: int

    :returns: Message
    :rtype: str
    """

    if message is None:
        message = m.Message()

    if table_of_contents is None:
        table_of_contents = m.Message()

    if heading_level:
        _create_section_header(message,
                               table_of_contents,
                               definition['name'].replace(' ', '-'),
                               definition['name'],
                               heading_level=heading_level)
    else:
        header = m.Paragraph(m.ImportantText(definition['name']))
        message.add(header)

    # If the definition has an icon, we put the icon and description side by
    # side in a table otherwise just show the description as a paragraph
    url = _definition_icon_url(definition)
    if url is None:
        message.add(m.Paragraph(definition['description']))
        if 'citations' in definition:
            _citations_to_message(message, definition)
    else:
        LOGGER.info('Creating mini table for definition description: ' + url)
        table = m.Table(style_class='table table-condensed')
        row = m.Row()
        row.add(m.Cell(m.Image(url, **MEDIUM_ICON_STYLE)))
        row.add(m.Cell(definition['description']))
        table.add(row)
        for citation in definition['citations']:
            if citation['text'] in [None, '']:
                continue
            row = m.Row()
            row.add(m.Cell(''))
            if citation['link'] in [None, '']:
                row.add(m.Cell(citation['text']))
            else:
                row.add(m.Cell(m.Link(citation['link'], citation['text'])))
            table.add(row)
        message.add(table)

    url = _definition_screenshot_url(definition)
    if url:
        message.add(m.Paragraph(m.Image(url), style_class='text-center'))

    # types contains e.g. hazard_all
    if 'types' in definition:
        for sub_definition in definition['types']:
            definition_to_message(sub_definition,
                                  message,
                                  table_of_contents,
                                  heading_level=3)

    #
    # Notes section if available
    #

    if 'notes' in definition:
        # Start a notes details group too since we have an exposure
        message.add(m.Heading(tr('Notes:'), **DETAILS_STYLE))
        message.add(m.Heading(tr('General notes:'), **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['notes']:
            if type(note) is dict:
                bullets = _add_dict_to_bullets(bullets, note)
            elif note:
                bullets.add(m.Text(note))
        message.add(bullets)
        if 'citations' in definition:
            _citations_to_message(message, definition)

    # This only for EQ
    if 'earthquake_fatality_models' in definition:
        current_function = current_earthquake_model_name()
        paragraph = m.Paragraph(
            'The following earthquake fatality models are available in '
            'InaSAFE. Note that you need to set one of these as the '
            'active model in InaSAFE Options. The currently active model is: ',
            m.ImportantText(current_function))
        message.add(paragraph)

        models_definition = definition['earthquake_fatality_models']
        for model in models_definition:
            message.add(m.Heading(model['name'], **DETAILS_SUBGROUP_STYLE))
            if 'description' in model:
                paragraph = m.Paragraph(model['description'])
                message.add(paragraph)
            for note in model['notes']:
                paragraph = m.Paragraph(note)
                message.add(paragraph)
            _citations_to_message(message, model)

    for exposure in exposure_all:
        extra_exposure_notes = specific_notes(definition, exposure)
        if extra_exposure_notes:
            title = tr(u'Notes for exposure : {exposure_name}').format(
                exposure_name=exposure['name'])
            message.add(m.Heading(title, **DETAILS_SUBGROUP_STYLE))
            bullets = m.BulletedList()
            for note in extra_exposure_notes:
                if type(note) is dict:
                    bullets = _add_dict_to_bullets(bullets, note)
                elif note:
                    bullets.add(m.Text(note))
            message.add(bullets)

    if 'continuous_notes' in definition:
        message.add(
            m.Heading(tr('Notes for continuous datasets:'),
                      **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['continuous_notes']:
            bullets.add(m.Text(note))
        message.add(bullets)

    if 'classified_notes' in definition:
        message.add(
            m.Heading(tr('Notes for classified datasets:'),
                      **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['classified_notes']:
            bullets.add(m.Text(note))
        message.add(bullets)

    if 'single_event_notes' in definition:
        message.add(m.Heading(tr('Notes for single events'), **DETAILS_STYLE))
        if len(definition['single_event_notes']) < 1:
            message.add(m.Paragraph(tr('No single event notes defined.')))
        else:
            bullets = m.BulletedList()
            for note in definition['single_event_notes']:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'multi_event_notes' in definition:
        message.add(
            m.Heading(tr('Notes for multi events / scenarios:'),
                      **DETAILS_STYLE))
        if len(definition['multi_event_notes']) < 1:
            message.add(m.Paragraph(tr('No multi-event notes defined.')))
        else:
            bullets = m.BulletedList()
            for note in definition['multi_event_notes']:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'actions' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Actions:'))))
        bullets = m.BulletedList()
        for note in definition['actions']:
            if type(note) is dict:
                bullets = _add_dict_to_bullets(bullets, note)
            elif note:
                bullets.add(m.Text(note))
        message.add(bullets)

    for exposure in exposure_all:
        extra_exposure_actions = specific_actions(definition, exposure)
        if extra_exposure_actions:
            title = tr(u'Actions for exposure : {exposure_name}').format(
                exposure_name=exposure['name'])
            message.add(m.Heading(title, **DETAILS_SUBGROUP_STYLE))
            bullets = m.BulletedList()
            for note in extra_exposure_actions:
                if type(note) is dict:
                    bullets = _add_dict_to_bullets(bullets, note)
                elif note:
                    bullets.add(m.Text(note))
            message.add(bullets)

    if 'continuous_hazard_units' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Units:'))))
        table = m.Table(style_class='table table-condensed table-striped')
        row = m.Row()
        row.add(m.Cell(tr('Name'), header=True))
        row.add(m.Cell(tr('Plural'), header=True))
        row.add(m.Cell(tr('Abbreviation'), header=True))
        row.add(m.Cell(tr('Details'), header=True))
        table.add(row)
        for unit in definition['continuous_hazard_units']:
            row = m.Row()
            row.add(m.Cell(unit['name']))
            row.add(m.Cell(unit['plural_name']))
            row.add(m.Cell(unit['abbreviation']))
            row.add(m.Cell(unit['description']))
            table.add(row)
        message.add(table)

    if 'fields' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Fields:'))))
        table = _create_fields_table()

        if 'extra_fields' in definition:
            all_fields = definition['fields'] + definition['extra_fields']
        else:
            all_fields = definition['fields']

        for field in all_fields:
            _add_field_to_table(field, table)
        message.add(table)

    if 'classifications' in definition:
        message.add(m.Heading(tr('Hazard classifications'), **DETAILS_STYLE))
        message.add(
            m.Paragraph(definitions.hazard_classification['description']))
        for inasafe_class in definition['classifications']:
            definition_to_message(inasafe_class,
                                  message,
                                  table_of_contents,
                                  heading_level=3)

    if 'classes' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Classes:'))))
        is_hazard = definition['type'] == hazard_classification_type
        if is_hazard:
            table = _make_defaults_hazard_table()
        else:
            table = _make_defaults_exposure_table()

        for inasafe_class in definition['classes']:
            row = m.Row()
            if is_hazard:
                # name() on QColor returns its hex code
                if 'color' in inasafe_class:
                    colour = inasafe_class['color'].name()
                    row.add(
                        m.Cell(u'',
                               attributes='style="background: %s;"' % colour))
                else:
                    row.add(m.Cell(u' '))

            row.add(m.Cell(inasafe_class['name']))

            if is_hazard:
                if 'affected' in inasafe_class:
                    row.add(m.Cell(tr(inasafe_class['affected'])))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                if inasafe_class.get('fatality_rate') > 0:
                    # we want to show the rate as a scientific notation
                    rate = html_scientific_notation_rate(
                        inasafe_class['fatality_rate'])
                    rate = u'%s%%' % rate
                    row.add(m.Cell(rate))
                elif inasafe_class.get('fatality_rate') == 0:
                    row.add(m.Cell('0%'))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                if 'displacement_rate' in inasafe_class:
                    rate = inasafe_class['displacement_rate'] * 100
                    rate = u'%.0f%%' % rate
                    row.add(m.Cell(rate))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if 'string_defaults' in inasafe_class:
                defaults = None
                for default in inasafe_class['string_defaults']:
                    if defaults:
                        defaults += ',%s' % default
                    else:
                        defaults = default
                row.add(m.Cell(defaults))
            else:
                row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                # Min may be a single value or a dict of values so we need
                # to check type and deal with it accordingly
                if 'numeric_default_min' in inasafe_class:
                    if isinstance(inasafe_class['numeric_default_min'], dict):
                        bullets = m.BulletedList()
                        minima = inasafe_class['numeric_default_min']
                        for key, value in minima.iteritems():
                            bullets.add(u'%s : %s' % (key, value))
                        row.add(m.Cell(bullets))
                    else:
                        row.add(m.Cell(inasafe_class['numeric_default_min']))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                # Max may be a single value or a dict of values so we need
                # to check type and deal with it accordingly
                if 'numeric_default_max' in inasafe_class:
                    if isinstance(inasafe_class['numeric_default_max'], dict):
                        bullets = m.BulletedList()
                        maxima = inasafe_class['numeric_default_max']
                        for key, value in maxima.iteritems():
                            bullets.add(u'%s : %s' % (key, value))
                        row.add(m.Cell(bullets))
                    else:
                        row.add(m.Cell(inasafe_class['numeric_default_max']))
                else:
                    row.add(m.Cell(tr('unspecified')))

            table.add(row)
            # Description goes in its own row with spanning
            row = m.Row()
            row.add(m.Cell(''))
            row.add(m.Cell(inasafe_class['description'], span=7))
            table.add(row)

        # For hazard classes we also add the 'not affected' class manually:
        if definition['type'] == definitions.hazard_classification_type:
            row = m.Row()
            colour = definitions.not_exposed_class['color'].name()
            row.add(m.Cell(u'', attributes='style="background: %s;"' % colour))
            description = definitions.not_exposed_class['description']
            row.add(m.Cell(description, span=7))
            table.add(row)

        message.add(table)

    if 'affected' in definition:
        if definition['affected']:
            message.add(
                m.Paragraph(
                    tr('Exposure entities in this class ARE considered affected'
                       )))
        else:
            message.add(
                m.Paragraph(
                    tr('Exposure entities in this class are NOT considered '
                       'affected')))

    if 'optional' in definition:
        if definition['optional']:
            message.add(
                m.Paragraph(
                    tr('This class is NOT required in the hazard keywords.')))
        else:
            message.add(
                m.Paragraph(
                    tr('This class IS required in the hazard keywords.')))

    return message
Esempio n. 9
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 4.0.0

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    # We will store a contents section at the top for easy navigation
    table_of_contents = m.Message()
    # and this will be the main message that we create
    message = m.Message()

    _create_section_header(message,
                           table_of_contents,
                           'overview',
                           tr('Overview'),
                           heading_level=1)
    ##
    # Credits and disclaimers ...
    ##
    _create_section_header(message,
                           table_of_contents,
                           'disclaimer',
                           tr('Disclaimer'),
                           heading_level=2)
    message.add(m.Paragraph(definitions.messages.disclaimer()))

    _create_section_header(message,
                           table_of_contents,
                           'limitations',
                           tr('Limitations and License'),
                           heading_level=2)
    bullets = m.BulletedList()
    for item in definitions.limitations():
        bullets.add(item)
    message.add(bullets)

    ##
    # Basic concepts ...
    ##
    ##
    # Help dialog contents ...
    ##
    _create_section_header(message,
                           table_of_contents,
                           'glossary',
                           tr('Glossary of terms'),
                           heading_level=1)

    last_group = None
    table = None
    for key, value in definitions.concepts.iteritems():
        current_group = value['group']
        if current_group != last_group:
            if last_group is not None:
                message.add(table)
            _create_section_header(message,
                                   table_of_contents,
                                   current_group.replace(' ', '-'),
                                   current_group,
                                   heading_level=2)
            table = _start_glossary_table(current_group)
            last_group = current_group
        row = m.Row()
        term = value['key'].replace('_', ' ').title()
        description = m.Message(value['description'])
        for citation in value['citations']:
            if citation['text'] in [None, '']:
                continue
            if citation['link'] in [None, '']:
                description.add(m.Paragraph(citation['text']))
            else:
                description.add(
                    m.Paragraph(m.Link(citation['link'], citation['text'])))
        row.add(m.Cell(term))
        row.add(m.Cell(description))
        url = _definition_icon_url(value)
        if url:
            row.add(m.Cell(m.Image(url, **MEDIUM_ICON_STYLE)))
        else:
            row.add(m.Cell(''))
        table.add(row)
    # ensure the last group's table is added
    message.add(table)

    ##
    # Help dialog contents ...
    ##
    _create_section_header(message,
                           table_of_contents,
                           'core-functionality',
                           tr('Core functionality and tools'),
                           heading_level=1)

    _create_section_header(message,
                           table_of_contents,
                           'dock',
                           tr('The InaSAFE Dock'),
                           heading_level=2)
    message.add(dock_help())

    _create_section_header(message,
                           table_of_contents,
                           'reports',
                           tr('InaSAFE Reports'),
                           heading_level=2)
    message.add(report_help())

    _create_section_header(
        message,
        table_of_contents,
        'extents',
        tr('Managing analysis extents with the extents selector'),
        heading_level=2)
    message.add(extent_help())

    _create_section_header(message,
                           table_of_contents,
                           'options',
                           tr('InaSAFE Options'),
                           heading_level=2)
    message.add(options_help())

    _create_section_header(message,
                           table_of_contents,
                           'batch-runner',
                           tr('The Batch Runner'),
                           heading_level=2)
    message.add(batch_help())

    _create_section_header(message,
                           table_of_contents,
                           'osm-downloader',
                           tr('The OpenStreetmap Downloader'),
                           heading_level=2)
    message.add(osm_help())

    _create_section_header(message,
                           table_of_contents,
                           'petabencana-downloader',
                           tr('The PetaBencana Downloader'),
                           heading_level=2)
    message.add(petabencana_help())

    _create_section_header(message,
                           table_of_contents,
                           'shakemap-converter',
                           tr('The Shakemap Converter'),
                           heading_level=2)
    message.add(shakemap_help())

    _create_section_header(message,
                           table_of_contents,
                           'multi-buffer-tool',
                           tr('The Multi Buffer Tool'),
                           heading_level=2)
    message.add(multi_buffer_help())

    # Field mapping tool has a few added bits to enumerate the groups
    _create_section_header(message,
                           table_of_contents,
                           'field-mapping-tool',
                           tr('The Field Mapping Tool'),
                           heading_level=2)
    message.add(field_mapping_tool_help())

    _create_section_header(message,
                           table_of_contents,
                           'exposure-groups',
                           tr('Exposure Groups'),
                           heading_level=3)
    message.add(
        m.Paragraph(
            'The following demographic groups apply only to vector population '
            'exposure layers:'))
    for group in population_field_groups:
        definition_to_message(group,
                              message,
                              table_of_contents,
                              heading_level=4)

    _create_section_header(message,
                           table_of_contents,
                           'aggregation-groups',
                           tr('Aggregation Groups'),
                           heading_level=3)
    message.add(
        m.Paragraph(
            'The following demographic groups apply only to aggregation layers:'
        ))
    for group in aggregation_field_groups:
        definition_to_message(group,
                              message,
                              table_of_contents,
                              heading_level=4)

    # End of field mapping tool help

    # Keep this last in the tool section please as it has subsections
    # and so uses the top level section style
    _create_section_header(message,
                           table_of_contents,
                           'minimum-needs',
                           tr('Minimum Needs'),
                           heading_level=2)
    _create_section_header(message,
                           table_of_contents,
                           'minimum-needs-tool',
                           tr('The minimum needs tool'),
                           heading_level=3)
    message.add(needs_help())
    _create_section_header(message,
                           table_of_contents,
                           'minimum-manager',
                           tr('The minimum needs manager'),
                           heading_level=3)
    message.add(needs_manager_help())

    ##
    #  Analysis workflow
    ##

    _create_section_header(message,
                           table_of_contents,
                           'analysis-steps',
                           tr('Analysis steps'),
                           heading_level=1)
    _create_section_header(message,
                           table_of_contents,
                           'analysis-internal-process',
                           tr('Analysis internal process'),
                           heading_level=2)
    analysis = definitions.concepts['analysis']
    message.add(analysis['description'])
    url = _definition_screenshot_url(analysis)
    if url:
        message.add(m.Paragraph(m.Image(url), style_class='text-center'))

    _create_section_header(message,
                           table_of_contents,
                           'analysis-progress-reporting',
                           tr('Progress reporting steps'),
                           heading_level=2)
    steps = definitions.analysis_steps.values()
    for step in steps:
        definition_to_message(step,
                              message,
                              table_of_contents,
                              heading_level=3)

    ##
    #  Hazard definitions
    ##

    _create_section_header(message,
                           table_of_contents,
                           'hazards',
                           tr('Hazard Concepts'),
                           heading_level=1)

    hazard_category = definitions.hazard_category
    definition_to_message(hazard_category,
                          message,
                          table_of_contents,
                          heading_level=2)

    hazards = definitions.hazards
    definition_to_message(hazards, message, table_of_contents, heading_level=2)

    ##
    #  Exposure definitions
    ##

    _create_section_header(message,
                           table_of_contents,
                           'exposures',
                           tr('Exposure Concepts'),
                           heading_level=1)
    exposures = definitions.exposures

    definition_to_message(exposures,
                          message,
                          table_of_contents,
                          heading_level=2)

    ##
    #  Defaults
    ##

    _create_section_header(message,
                           table_of_contents,
                           'defaults',
                           tr('InaSAFE Defaults'),
                           heading_level=1)
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Default value'), header=True))
    row.add(m.Cell(tr('Default min'), header=True))
    row.add(m.Cell(tr('Default max'), header=True))
    row.add(m.Cell(tr('Description'), header=True))
    table.add(row)
    defaults = [
        definitions.youth_ratio_default_value,
        definitions.adult_ratio_default_value,
        definitions.elderly_ratio_default_value,
        definitions.female_ratio_default_value,
        definitions.feature_rate_default_value
    ]
    for default in defaults:
        row = m.Row()
        row.add(m.Cell(default['name']))
        row.add(m.Cell(default['default_value']))
        row.add(m.Cell(default['min_value']))
        row.add(m.Cell(default['max_value']))
        row.add(m.Cell(default['description']))
        table.add(row)
    message.add(table)

    ##
    #  All Fields
    ##

    _create_section_header(message,
                           table_of_contents,
                           'all-fields',
                           tr('Fields'),
                           heading_level=1)
    _create_section_header(message,
                           table_of_contents,
                           'input-fields',
                           tr('Input dataset fields'),
                           heading_level=2)
    _create_fields_section(message, table_of_contents, tr('Exposure fields'),
                           definitions.exposure_fields)
    _create_fields_section(message, table_of_contents, tr('Hazard fields'),
                           definitions.hazard_fields)
    _create_fields_section(message, table_of_contents,
                           tr('Aggregation fields'),
                           definitions.aggregation_fields)
    _create_section_header(message,
                           table_of_contents,
                           'output-fields',
                           tr('Output dataset fields'),
                           heading_level=2)
    _create_fields_section(message, table_of_contents, tr('Impact fields'),
                           definitions.impact_fields)
    _create_fields_section(message, table_of_contents,
                           tr('Aggregate hazard fields'),
                           definitions.aggregate_hazard_fields)
    _create_fields_section(message, table_of_contents,
                           tr('Aggregation summary fields'),
                           definitions.aggregation_summary_fields)
    _create_fields_section(message, table_of_contents,
                           tr('Exposure summary table fields'),
                           definitions.exposure_summary_table_fields)
    _create_fields_section(message, table_of_contents, tr('Analysis fields'),
                           definitions.analysis_fields)

    ##
    #  Geometries
    ##

    _create_section_header(message,
                           table_of_contents,
                           'geometries',
                           tr('Layer Geometry Types'),
                           heading_level=1)
    _create_section_header(message,
                           table_of_contents,
                           'vector-geometries',
                           tr('Vector'),
                           heading_level=2)
    definition_to_message(definitions.layer_geometry_point,
                          message,
                          table_of_contents,
                          heading_level=3)
    definition_to_message(definitions.layer_geometry_line,
                          message,
                          table_of_contents,
                          heading_level=3)
    definition_to_message(definitions.layer_geometry_polygon,
                          message,
                          table_of_contents,
                          heading_level=3)
    _create_section_header(message,
                           table_of_contents,
                           'raster-geometries',
                           tr('Raster'),
                           heading_level=2)
    definition_to_message(definitions.layer_geometry_raster,
                          message,
                          table_of_contents,
                          heading_level=3)

    ##
    #  Layer Modes
    ##

    _create_section_header(message,
                           table_of_contents,
                           'layer-modes',
                           tr('Layer Modes'),
                           heading_level=1)
    definition_to_message(definitions.layer_mode,
                          message,
                          table_of_contents,
                          heading_level=2)

    ##
    #  Layer Purposes
    ##

    _create_section_header(message,
                           table_of_contents,
                           'layer-purposes',
                           tr('Layer Purposes'),
                           heading_level=1)
    definition_to_message(definitions.layer_purpose_hazard,
                          message,
                          table_of_contents,
                          heading_level=2)
    definition_to_message(definitions.layer_purpose_exposure,
                          message,
                          table_of_contents,
                          heading_level=2)
    definition_to_message(definitions.layer_purpose_aggregation,
                          message,
                          table_of_contents,
                          heading_level=2)
    definition_to_message(definitions.layer_purpose_exposure_summary,
                          message,
                          table_of_contents,
                          heading_level=2)
    definition_to_message(definitions.layer_purpose_aggregate_hazard_impacted,
                          message,
                          table_of_contents,
                          heading_level=2)
    definition_to_message(definitions.layer_purpose_aggregation_summary,
                          message,
                          table_of_contents,
                          heading_level=2)
    definition_to_message(definitions.layer_purpose_exposure_summary_table,
                          message,
                          table_of_contents,
                          heading_level=2)
    definition_to_message(definitions.layer_purpose_profiling,
                          message,
                          table_of_contents,
                          heading_level=2)

    ##
    # All units
    ##

    _create_section_header(message,
                           table_of_contents,
                           'all-units',
                           tr('All Units'),
                           heading_level=1)
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Plural'), header=True))
    row.add(m.Cell(tr('Abbreviation'), header=True))
    row.add(m.Cell(tr('Details'), header=True))
    table.add(row)
    for unit in definitions.units_all:
        row = m.Row()
        row.add(m.Cell(unit['name']))
        row.add(m.Cell(unit['plural_name']))
        row.add(m.Cell(unit['abbreviation']))
        row.add(m.Cell(unit['description']))
        table.add(row)
    message.add(table)

    ##
    #  Post processors
    ##

    _create_section_header(message,
                           table_of_contents,
                           'post-processors',
                           tr('Post Processors'),
                           heading_level=1)
    _create_section_header(message,
                           table_of_contents,
                           'post-processor-input-types',
                           tr('Post Processor Input Types'),
                           heading_level=2)
    table = _create_post_processor_subtable(post_processor_input_types)
    message.add(table)

    _create_section_header(message,
                           table_of_contents,
                           'post-processor-input-values',
                           tr('Post Processor Input Values'),
                           heading_level=2)
    table = _create_post_processor_subtable(post_processor_input_values)
    message.add(table)

    _create_section_header(message,
                           table_of_contents,
                           'post-processor-process-values',
                           tr('Post Processor Process Types'),
                           heading_level=2)
    table = _create_post_processor_subtable(
        definitions.post_processor_process_types)
    message.add(table)

    _create_section_header(message,
                           table_of_contents,
                           'post-processors',
                           tr('Post Processors'),
                           heading_level=2)
    post_processors = safe.definitions.post_processors
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Input Fields'), header=True))
    row.add(m.Cell(tr('Output Fields'), header=True))
    table.add(row)
    for post_processor in post_processors:
        row = m.Row()
        row.add(m.Cell(post_processor['name']))
        # Input fields
        bullets = m.BulletedList()
        for key, value in post_processor['input'].iteritems():
            bullets.add(key)
        row.add(m.Cell(bullets))
        # Output fields
        bullets = m.BulletedList()
        for key, value in post_processor['output'].iteritems():
            name = value['value']['name']
            formula_type = value['type']['key']
            if formula_type == 'formula':
                formula = value['formula']
            else:
                # We use python introspection because the processor
                # uses a python function for calculations
                formula = value['function'].__name__
                formula += ' ('
                formula += value['function'].__doc__
                formula += ')'
            bullets.add('%s  %s. : %s' % (name, formula_type, formula))

        row.add(m.Cell(bullets))
        table.add(row)
        # Add the descriptions
        row = m.Row()
        row.add(m.Cell(''))
        row.add(m.Cell(post_processor['description'], span=2))
        table.add(row)
    message.add(table)

    ##
    # Developer documentation
    ##

    _create_section_header(message,
                           table_of_contents,
                           'developer-guide',
                           tr('Developer Guide'),
                           heading_level=1)
    message.add(developer_help())

    # Finally we add the table of contents at the top
    full_message = m.Message()
    # Contents is not a link so reset style
    style = SECTION_STYLE
    style['element_id'] = ''
    header = m.Heading(tr('Contents'), **style)
    full_message.add(header)
    full_message.add(table_of_contents)
    full_message.add(message)
    return full_message
Esempio n. 10
0
def definition_to_message(definition, heading_style=None):
    """Helper function to render a definition to a message.

    :param definition: A definition dictionary (see definitions package).
    :type definition: dict

    :param heading_style: Optional style to apply to the definition
        heading. See safe.messaging.styles
    :type heading_style: dict


    :returns: Message
    :rtype: str
    """

    if heading_style:
        header = m.Heading(definition['name'], **heading_style)
    else:
        header = m.Paragraph(m.ImportantText(definition['name']))
    message = m.Message()
    message.add(header)
    # If the definition has an icon, we put the icon and description side by
    # side in a table otherwise just show the description as a paragraph
    url = _definition_icon_url(definition)
    if url is None:
        LOGGER.info('No URL for definition icon')
        message.add(m.Paragraph(definition['description']))
        for citation in definition['citations']:
            if citation['text'] in [None, '']:
                continue
            if citation['link'] in [None, '']:
                message.add(m.Paragraph(citation['text']))
            else:
                message.add(
                    m.Paragraph(m.Link(citation['link'], citation['text'])))
    else:
        LOGGER.info('Creating mini table for definition description: ' + url)
        table = m.Table(style_class='table table-condensed')
        row = m.Row()
        row.add(m.Cell(m.Image(url, **MEDIUM_ICON_STYLE)))
        row.add(m.Cell(definition['description']))
        table.add(row)
        for citation in definition['citations']:
            if citation['text'] in [None, '']:
                continue
            row = m.Row()
            row.add(m.Cell(''))
            if citation['link'] in [None, '']:
                row.add(m.Cell(citation['text']))
            else:
                row.add(m.Cell(m.Link(citation['link'], citation['text'])))
            table.add(row)
        message.add(table)

    url = _definition_screenshot_url(definition)
    if url:
        message.add(m.Image(url))

    # types contains e.g. hazard_all
    if 'types' in definition:
        for sub_definition in definition['types']:
            message.add(
                definition_to_message(sub_definition, RED_CHAPTER_STYLE))

    #
    # Notes section if available
    #

    if 'notes' in definition:
        # Start a notes details group too since we have an exposure
        message.add(m.Heading(tr('Notes:'), **DETAILS_STYLE))
        message.add(m.Heading(tr('General notes:'), **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['notes']:
            bullets.add(m.Text(note))
        message.add(bullets)

    # This only for EQ
    if 'earthquake_fatality_models' in definition:
        for model in definition['earthquake_fatality_models']:
            message.add(m.Heading(model['name'], **DETAILS_SUBGROUP_STYLE))
            bullets = m.BulletedList()
            for note in model['notes']:
                bullets.add(m.Text(note))
                message.add(bullets)

    for exposure in exposure_all:
        extra_exposure_notes = specific_notes(definition, exposure)
        if extra_exposure_notes:
            title = tr(u'Notes for exposure : {exposure_name}').format(
                exposure_name=exposure['name'])
            message.add(m.Heading(title, **DETAILS_SUBGROUP_STYLE))
            bullets = m.BulletedList()
            for note in extra_exposure_notes:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'continuous_notes' in definition:
        message.add(
            m.Heading(tr('Notes for continuous datasets:'),
                      **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['continuous_notes']:
            bullets.add(m.Text(note))
        message.add(bullets)

    if 'classified_notes' in definition:
        message.add(
            m.Heading(tr('Notes for classified datasets:'),
                      **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['classified_notes']:
            bullets.add(m.Text(note))
        message.add(bullets)

    if 'single_event_notes' in definition:
        message.add(m.Heading(tr('Notes for single events'), **DETAILS_STYLE))
        if len(definition['single_event_notes']) < 1:
            message.add(m.Paragraph(tr('No single event notes defined.')))
        else:
            bullets = m.BulletedList()
            for note in definition['single_event_notes']:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'multi_event_notes' in definition:
        message.add(
            m.Heading(tr('Notes for multi events / scenarios:'),
                      **DETAILS_STYLE))
        if len(definition['multi_event_notes']) < 1:
            message.add(m.Paragraph(tr('No multi-event notes defined.')))
        else:
            bullets = m.BulletedList()
            for note in definition['multi_event_notes']:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'actions' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Actions:'))))
        bullets = m.BulletedList()
        for note in definition['actions']:
            bullets.add(m.Text(note))
        message.add(bullets)

    for exposure in exposure_all:
        extra_exposure_actions = specific_actions(definition, exposure)
        if extra_exposure_actions:
            title = tr(u'Actions for exposure : {exposure_name}').format(
                exposure_name=exposure['name'])
            message.add(m.Heading(title, **DETAILS_SUBGROUP_STYLE))
            bullets = m.BulletedList()
            for note in extra_exposure_actions:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'continuous_hazard_units' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Units:'))))
        table = m.Table(style_class='table table-condensed table-striped')
        row = m.Row()
        row.add(m.Cell(tr('Name')), header_flag=True)
        row.add(m.Cell(tr('Plural')), header_flag=True)
        row.add(m.Cell(tr('Abbreviation')), header_flag=True)
        row.add(m.Cell(tr('Details')), header_flag=True)
        table.add(row)
        for unit in definition['continuous_hazard_units']:
            row = m.Row()
            row.add(m.Cell(unit['name']))
            row.add(m.Cell(unit['plural_name']))
            row.add(m.Cell(unit['abbreviation']))
            row.add(m.Cell(unit['description']))
            table.add(row)
        message.add(table)

    if 'extra_fields' and 'fields' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Fields:'))))
        table = _create_fields_table()
        all_fields = definition['fields'] + definition['extra_fields']
        for field in all_fields:
            _add_field_to_table(field, table)
        message.add(table)

    if 'classifications' in definition:
        message.add(m.Heading(tr('Hazard classifications'), **DETAILS_STYLE))
        message.add(
            m.Paragraph(definitions.hazard_classification['description']))
        for inasafe_class in definition['classifications']:
            message.add(
                definition_to_message(inasafe_class, DETAILS_SUBGROUP_STYLE))

    if 'classes' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Classes:'))))
        table = _make_defaults_table()
        for inasafe_class in definition['classes']:
            row = m.Row()
            # name() on QColor returns its hex code
            if 'color' in inasafe_class:
                colour = inasafe_class['color'].name()
                row.add(
                    m.Cell(u'', attributes='style="background: %s;"' % colour))
            else:
                row.add(m.Cell(u' '))

            row.add(m.Cell(inasafe_class['name']))
            if 'affected' in inasafe_class:
                row.add(m.Cell(tr(inasafe_class['affected'])))
            else:
                row.add(m.Cell(tr('unspecified')))

            if 'displacement_rate' in inasafe_class:
                rate = inasafe_class['displacement_rate'] * 100
                rate = u'%s%%' % rate
                row.add(m.Cell(rate))
            else:
                row.add(m.Cell(tr('unspecified')))

            if 'string_defaults' in inasafe_class:
                defaults = None
                for default in inasafe_class['string_defaults']:
                    if defaults:
                        defaults += ',%s' % default
                    else:
                        defaults = default
                row.add(m.Cell(defaults))
            else:
                row.add(m.Cell(tr('unspecified')))
            # Min may be a single value or a dict of values so we need
            # to check type and deal with it accordingly
            if 'numeric_default_min' in inasafe_class:
                if isinstance(inasafe_class['numeric_default_min'], dict):
                    bullets = m.BulletedList()
                    minima = inasafe_class['numeric_default_min']
                    for key, value in minima.iteritems():
                        bullets.add(u'%s : %s' % (key, value))
                    row.add(m.Cell(bullets))
                else:
                    row.add(m.Cell(inasafe_class['numeric_default_min']))
            else:
                row.add(m.Cell(tr('unspecified')))

            # Max may be a single value or a dict of values so we need
            # to check type and deal with it accordingly
            if 'numeric_default_max' in inasafe_class:
                if isinstance(inasafe_class['numeric_default_max'], dict):
                    bullets = m.BulletedList()
                    maxima = inasafe_class['numeric_default_max']
                    for key, value in maxima.iteritems():
                        bullets.add(u'%s : %s' % (key, value))
                    row.add(m.Cell(bullets))
                else:
                    row.add(m.Cell(inasafe_class['numeric_default_max']))
            else:
                row.add(m.Cell(tr('unspecified')))

            table.add(row)
            # Description goes in its own row with spanning
            row = m.Row()
            row.add(m.Cell(''))
            row.add(m.Cell(inasafe_class['description'], span=6))
            table.add(row)
        # For hazard classes we also add the 'not affected' class manually:
        if definition['type'] == definitions.hazard_classification_type:
            row = m.Row()
            colour = definitions.not_exposed_class['color'].name()
            row.add(m.Cell(u'', attributes='style="background: %s;"' % colour))
            description = definitions.not_exposed_class['description']
            row.add(m.Cell(description, span=5))
            table.add(row)

        message.add(table)

    if 'affected' in definition:
        if definition['affected']:
            message.add(
                m.Paragraph(
                    tr('Exposure entities in this class ARE considered affected'
                       )))
        else:
            message.add(
                m.Paragraph(
                    tr('Exposure entities in this class are NOT considered '
                       'affected')))

    if 'optional' in definition:
        if definition['optional']:
            message.add(
                m.Paragraph(
                    tr('This class is NOT required in the hazard keywords.')))
        else:
            message.add(
                m.Paragraph(
                    tr('This class IS required in the hazard keywords.')))

    return message
Esempio n. 11
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 3.2.2

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    body = tr('This tool will fetch building (\'structure\') or road ('
              '\'highway\') data from the OpenStreetMap project for you. '
              'The downloaded data will have InaSAFE keywords defined and a '
              'default QGIS style applied. To use this tool effectively:')
    tips = m.BulletedList()
    tips.add(
        tr('Your current extent, when opening this window, will be used to '
           'determine the area for which you want data to be retrieved. '
           'You can interactively select the area by using the '
           '\'select on map\' button - which will temporarily hide this '
           'window and allow you to drag a rectangle on the map. After you '
           'have finished dragging the rectangle, this window will '
           'reappear.'))
    tips.add(
        tr('Check the output directory is correct. Note that the saved '
           'dataset will be named after the type of data being downloaded '
           'e.g. roads.shp or buildings.shp (and associated files).'))
    tips.add(
        tr('By default simple file names will be used (e.g. roads.shp, '
           'buildings.shp). If you wish you can specify a prefix to '
           'add in front of this default name. For example using a prefix '
           'of \'padang-\' will cause the downloaded files to be saved as '
           '\'padang-roads.shp\' and \'padang-buildings.shp\'. Note that '
           'the only allowed prefix characters are A-Z, a-z, 0-9 and the '
           'characters \'-\' and \'_\'. You can leave this blank if you '
           'prefer.'))
    tips.add(
        tr('If a dataset already exists in the output directory it will be '
           'overwritten.'))
    tips.add(
        tr('This tool requires a working internet connection and fetching '
           'buildings or roads will consume your bandwidth.'))
    tips.add(
        m.Link('http://www.openstreetmap.org/copyright',
               text=tr(
                   'Downloaded data is copyright OpenStreetMap contributors '
                   '(click for more info).')))
    message.add(m.Paragraph(body))
    message.add(tips)

    message.add(
        m.Paragraph(
            # format 'When the __Political boundaries__' for proper i18n
            tr('When the %s '
               'box in the Feature types menu is ticked, the Political boundary '
               'options panel will be enabled. The panel lets you select which '
               'admin level you wish to download. The admin levels are country '
               'specific. When you select an admin level, the local name for '
               'that admin level will be shown. You can change which country '
               'is used for the admin level description using the country drop '
               'down menu. The country will be automatically set to coincide '
               'with the view extent if a matching country can be found.') %
            (m.ImportantText(tr('Political boundaries')).to_html(), )))
    message.add(
        m.Paragraph(
            m.ImportantText(tr('Note: ')),
            tr('We have only provide presets for a subset of the available '
               'countries. If you want to know what the levels are for your '
               'country, please check on the following web page: '),
            m.Link(
                'http://wiki.openstreetmap.org/wiki/Tag:boundary%3Dadministrative',
                text=tr('List of OSM Admin Boundary definitions '))))

    return message