def show_current_metadata(self): """Show metadata of the current selected layer.""" LOGGER.debug('Showing layer: ' + self.layer.name()) keywords = KeywordIO(self.layer) content_html = keywords.to_message().to_html() full_html = html_header() + content_html + html_footer() self.metadata_preview_web_view.setHtml(full_html)
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, 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(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)
def show_info(self): """Show usage text to the user.""" header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('Shakemap Grid Importer'), **INFO_STYLE) body = self.tr( 'This tool will convert an earthquake \'shakemap\' that is in ' 'grid xml format to a GeoTIFF file. The imported file can be used ' 'in InaSAFE as an input for impact functions that require and ' 'earthquake layer. To use this tool effectively:' ) tips = m.BulletedList() tips.add(self.tr( 'Select a grid.xml for the input layer.')) tips.add(self.tr( 'Choose where to write the output layer to.' )) tips.add(self.tr( 'Choose the interpolation algorithm that should be used when ' 'converting the xml grid to a raster. If unsure keep the default.' )) tips.add(self.tr( 'If you want to obtain shake data you can get it for free from ' 'the USGS shakemap site: ' 'http://earthquake.usgs.gov/earthquakes/shakemap/list.php?y=2013')) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.webView.setHtml(string)
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('User Extents Tool'), **INFO_STYLE) body = self.tr( 'This tool allows you to specify exactly which geographical ' 'region should be used for your analysis. You can either ' 'enter the coordinates directly into the input boxes below ' '(using the same CRS as the canvas is currently set to), or ' '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. ' 'If you enable the \'Toggle scenario outlines\' tool on the ' 'InaSAFE toolbar, your user defined extent will be shown on ' 'the map as a blue rectangle. Please note that when running ' 'your analysis, the effective analysis extent will be the ' 'intersection of the hazard extent, exposure extent and user ' 'extent - thus the entire user extent area may not be used for ' 'analysis.' ) message = m.Message() message.add(heading) message.add(body) string += message.to_html() string += footer self.web_view.setHtml(string)
def test_html_header(self): """Test that we can get the html header. .. versionadded:: 3.0 """ header = html_header() self.assertTrue('bootstrap' in header, 'bootstrap not in ' + header)
def show_messages(self): """Show all messages.""" if isinstance(self.static_message, MessageElement): # Handle sent Message instance string = html_header() if self.static_message is not None: string += self.static_message.to_html() # Keep track of the last ID we had so we can scroll to it self.last_id = 0 for message in self.dynamic_messages: if message.element_id is None: self.last_id += 1 message.element_id = str(self.last_id) html = message.to_html(in_div_flag=True) if html is not None: string += html string += html_footer() elif (isinstance(self.static_message, str)): # Handle sent text directly string = self.static_message elif self.static_message is not None: string = str(self.static_message) elif not self.static_message: # handle dynamic message # Handle sent Message instance string = html_header() # Keep track of the last ID we had so we can scroll to it self.last_id = 0 for message in self.dynamic_messages: if message.element_id is None: self.last_id += 1 message.element_id = str(self.last_id) html = message.to_html(in_div_flag=True) if html is not None: string += html string += html_footer() # Set HTML self.load_html(HTML_STR_MODE, string)
def test_html_header(self): """Test that we can get the html header. .. versionadded:: 3.0 """ header = html_header() self.assertTrue( 'bootstrap' in header, 'bootstrap not in ' + header)
def show_messages(self): """Show all messages.""" if isinstance(self.static_message, MessageElement): # Handle sent Message instance string = html_header() if self.static_message is not None: string += self.static_message.to_html() # Keep track of the last ID we had so we can scroll to it self.last_id = 0 for message in self.dynamic_messages: if message.element_id is None: self.last_id += 1 message.element_id = str(self.last_id) html = message.to_html(in_div_flag=True) if html is not None: string += html string += html_footer() elif (isinstance(self.static_message, str) or isinstance(self.static_message, unicode)): # Handle sent text directly string = self.static_message elif not self.static_message: # handle dynamic message # Handle sent Message instance string = html_header() # Keep track of the last ID we had so we can scroll to it self.last_id = 0 for message in self.dynamic_messages: if message.element_id is None: self.last_id += 1 message.element_id = str(self.last_id) html = message.to_html(in_div_flag=True) if html is not None: string += html string += html_footer() # Set HTML self.load_html(HTML_STR_MODE, string)
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)
def show_help(self): """Show usage info to the user.""" # Read the header and footer html snippets self.main_stacked_widget.setCurrentIndex(0) header = html_header() footer = html_footer() message = metadata_converter_help() string = header string += message.to_html() string += footer self.help_web_view.setHtml(string)
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('Impact Layer Merge Tool'), **INFO_STYLE) body = self.tr( 'This tool will merge the outputs from two impact maps for the ' 'same area. The maps must be created using the same aggregation ' 'areas and same hazard. To use:') tips = m.BulletedList() tips.add( self.tr( 'Run an impact assessment for an area using aggregation. e.g.' 'Flood Impact on Buildings aggregated by municipal boundaries.' )) tips.add( self. tr('Run a second impact assessment for the same area using the same ' 'aggregation. e.g. Flood Impact on People aggregated by ' 'municipal boundaries.')) tips.add( self. tr('Open this tool and select each impact layer from the pick lists ' 'provided below.')) tips.add( self.tr( 'Select the aggregation layer that was used to generate the ' 'first and second impact layer.')) tips.add(self.tr('Select an output directory.')) tips.add( self. tr('Check "Use customized report template" checkbox and select the ' 'report template file if you want to use your own template. Note ' 'that all the map composer components that are needed must be ' 'fulfilled.')) tips.add( self.tr('Click OK to generate the per aggregation area combined ' 'summaries.')) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.web_view.setHtml(string)
def save_log_to_html(self): """Helper to write the log out as an html file.""" html = html_header() html += ( '<img src="file:///%s/img/logos/inasafe-logo-url.png" ' 'title="InaSAFE Logo" alt="InaSAFE Logo" />' % resources_path()) html += ('<h5 class="info"><i class="icon-info-sign icon-white"></i> ' '%s</h5>' % self.tr('Analysis log')) for item in self.dynamic_messages_log: html += "%s\n" % item.to_html() html += html_footer() if self.log_path is not None: html_to_file(html, self.log_path) else: msg = self.tr('log_path is not set') raise InvalidParameterError(msg)
def save_log_to_html(self): """Helper to write the log out as an html file.""" html = html_header() html += ('<img src="file:///%s/img/logos/inasafe-logo-url.png" ' 'title="InaSAFE Logo" alt="InaSAFE Logo" />' % resources_path()) html += ('<h5 class="info"><i class="icon-info-sign icon-white"></i> ' '%s</h5>' % self.tr('Analysis log')) for item in self.dynamic_messages_log: html += "%s\n" % item.to_html() html += html_footer() if self.log_path is not None: html_to_file(html, self.log_path) else: msg = self.tr('log_path is not set') raise InvalidParameterError(msg)
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('Impact Layer Merge Tool'), **INFO_STYLE) body = self.tr( 'This tool will merge the outputs from two impact maps for the ' 'same area. The maps must be created using the same aggregation ' 'areas and same hazard. To use:' ) tips = m.BulletedList() tips.add(self.tr( 'Run an impact assessment for an area using aggregation. e.g.' 'Flood Impact on Buildings aggregated by municipal boundaries.')) tips.add(self.tr( 'Run a second impact assessment for the same area using the same ' 'aggregation. e.g. Flood Impact on People aggregated by ' 'municipal boundaries.')) tips.add(self.tr( 'Open this tool and select each impact layer from the pick lists ' 'provided below.')) tips.add(self.tr( 'Select the aggregation layer that was used to generate the ' 'first and second impact layer.')) tips.add(self.tr( 'Select an output directory.')) tips.add(self.tr( 'Check "Use customized report template" checkbox and select the ' 'report template file if you want to use your own template. Note ' 'that all the map composer components that are needed must be ' 'fulfilled.')) tips.add(self.tr( 'Click OK to generate the per aggregation area combined ' 'summaries.')) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.web_view.setHtml(string)
def show_help(self): """Show usage info to the user. .. versionadded: 3.3 """ # Read the header and footer html snippets self.main_stacked_widget.setCurrentIndex(0) header = html_header() footer = html_footer() string = header message = peta_jakarta_help() string += message.to_html() string += footer self.help_web_view.setHtml(string)
def show_help(self): """Show usage info to the user. .. versionadded: 3.3 """ # Read the header and footer html snippets self.main_stacked_widget.setCurrentIndex(0) header = html_header() footer = html_footer() string = header message = peta_bencana_help() string += message.to_html() string += footer self.help_web_view.setHtml(string)
def show_messages(self): """Show all messages.""" string = html_header() if self.static_message is not None: string += self.static_message.to_html() # Keep track of the last ID we had so we can scroll to it self.last_id = 0 for message in self.dynamic_messages: if message.element_id is None: self.last_id += 1 message.element_id = str(self.last_id) html = message.to_html(in_div_flag=True) if html is not None: string += html string += html_footer() # Set HTML self.load_html(HTML_STR_MODE, string)
def update_warning(self): """Update warning message and enable/disable Ok button.""" if len(self.warning_text) == 0: self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) return header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('Shakemap Grid Importer'), **INFO_STYLE) tips = m.BulletedList() self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) message = m.Message() message.add(heading) for warning in self.warning_text: tips.add(warning) message.add(tips) string += message.to_html() string += footer self.info_web_view.setHtml(string)
def update_warning(self): """Update warning message and enable/disable Ok button.""" if len(self.warning_text) == 0: self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) else: self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('Shakemap Grid Importer'), **INFO_STYLE) tips = m.BulletedList() message = m.Message() message.add(heading) for warning in self.warning_text: tips.add(warning) message.add(tips) string += message.to_html() string += footer self.info_web_view.setHtml(string)
def __init__(self, parent=None): """Constructor for the dialog. :param parent: Parent widget of this dialog :type parent: QWidget """ QtGui.QDialog.__init__(self, parent) self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE %s Help' % get_version())) self.parent = parent header = html_header() footer = html_footer() string = header message = dock_help() string += message.to_html() string += footer self.help_web_view.setHtml(string)
def show_help(self, wizard_step): """Set wizard step and show the help text.""" self.wizard_step = wizard_step header = html_header() footer = html_footer() content = header message = self.wizard_step.help() content += message.to_html() content += footer self.help_web_view.setHtml(content) # Store buttons' state self.next_button_state = self.parent.pbnNext.isEnabled() self.back_button_state = self.parent.pbnBack.isEnabled() # Disable those buttons self.parent.pbnNext.setEnabled(False) self.parent.pbnBack.setEnabled(False)
def show_info(self): """Show basic usage instructions.""" header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('Minimum Needs Calculator'), **INFO_STYLE) body = self.tr( 'This tool will calculated minimum needs for evacuated people. To ' 'use this tool effectively:') tips = m.BulletedList() tips.add( self. tr('Load a polygon layer in QGIS. Typically the layer will ' 'represent administrative districts where people have gone to an ' 'evacuation center.')) tips.add( self. tr('Ensure that the layer has an INTEGER attribute for the number of ' 'displaced people associated with each feature.')) tips.add( self. tr('Use the pick lists below to select the layer and the population ' 'field and then press \'OK\'.')) tips.add( self. tr('A new layer will be added to QGIS after the calculation is ' 'complete. The layer will contain the minimum needs per district ' '/ administrative boundary.')) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.webView.setHtml(string)
def show_info(self): """Show basic usage instructions.""" header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('Minimum Needs Calculator'), **INFO_STYLE) body = self.tr( 'This tool will calculated minimum needs for evacuated people. To ' 'use this tool effectively:' ) tips = m.BulletedList() tips.add(self.tr( 'Load a polygon layer in QGIS. Typically the layer will ' 'represent administrative districts where people have gone to an ' 'evacuation center.')) tips.add(self.tr( 'Ensure that the layer has an INTEGER attribute for the number of ' 'displaced people associated with each feature.' )) tips.add(self.tr( 'Use the pick lists below to select the layer and the population ' 'field and then press \'OK\'.' )) tips.add(self.tr( 'A new layer will be added to QGIS after the calculation is ' 'complete. The layer will contain the minimum needs per district ' '/ administrative boundary.')) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.webView.setHtml(string)
def print_impact_table(self, output_path): """Pint summary from impact layer to PDF. ..note:: The order of the report: 1. Summary table 2. Aggregation table 3. Attribution table :param output_path: Output path. :type output_path: str :return: Path to generated pdf file. :rtype: str :raises: None """ keywords = self._keyword_io.read_keywords(self.layer) if output_path is None: output_path = unique_filename(suffix='.pdf', dir=temp_dir()) summary_table = keywords.get('impact_summary', None) full_table = keywords.get('impact_table', None) aggregation_table = keywords.get('postprocessing_report', None) attribution_table = impact_attribution(keywords) # (AG) We will not use impact_table as most of the IF use that as: # impact_table = impact_summary + some information intended to be # shown on screen (see FloodOsmBuilding) # Unless the impact_summary is None, we will use impact_table as the # alternative html = LOGO_ELEMENT.to_html() html += m.Heading(tr('Analysis Results'), **INFO_STYLE).to_html() if summary_table is None: html += full_table else: html += summary_table if aggregation_table is not None: html += aggregation_table if attribution_table is not None: html += attribution_table.to_html() html = html_header() + html + html_footer() # Print HTML using composition # For QGIS < 2.4 compatibility # QgsMapSettings is added in 2.4 if qgis_version() < 20400: map_settings = QgsMapRenderer() else: map_settings = QgsMapSettings() # A4 Portrait paper_width = 210 paper_height = 297 # noinspection PyCallingNonCallable composition = QgsComposition(map_settings) # noinspection PyUnresolvedReferences composition.setPlotStyle(QgsComposition.Print) composition.setPaperSize(paper_width, paper_height) composition.setPrintResolution(300) # Add HTML Frame # noinspection PyCallingNonCallable html_item = QgsComposerHtml(composition, False) margin_left = 10 margin_top = 10 # noinspection PyCallingNonCallable html_frame = QgsComposerFrame( composition, html_item, margin_left, margin_top, paper_width - 2 * margin_left, paper_height - 2 * margin_top) html_item.addFrame(html_frame) # Set HTML # From QGIS 2.6, we can set composer HTML with manual HTML if qgis_version() < 20600: html_path = unique_filename( prefix='report', suffix='.html', dir=temp_dir()) html_to_file(html, file_path=html_path) html_url = QUrl.fromLocalFile(html_path) html_item.setUrl(html_url) else: # noinspection PyUnresolvedReferences html_item.setContentMode(QgsComposerHtml.ManualHtml) # noinspection PyUnresolvedReferences html_item.setResizeMode(QgsComposerHtml.RepeatUntilFinished) html_item.setHtml(html) html_item.loadHtml() composition.exportAsPDF(output_path) return output_path
def show_current_state(self): """Setup the UI for QTextEdit to show the current state.""" right_panel_heading = QLabel(tr('Status')) right_panel_heading.setFont(big_font) right_panel_heading.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Maximum) self.right_layout.addWidget(right_panel_heading) message = m.Message() if self.layer_mode == layer_mode_continuous: title = tr('Thresholds') else: title = tr('Value maps') message.add(m.Heading(title, **INFO_STYLE)) for i in range(len(self.exposures)): message.add(m.Text(self.exposure_labels[i])) classification = self.get_classification( self.exposure_combo_boxes[i]) if self.layer_mode == layer_mode_continuous: thresholds = self.thresholds.get(self.exposures[i]['key']) if not thresholds or not classification: message.add(m.Paragraph(tr('No classifications set.'))) continue table = m.Table( style_class='table table-condensed table-striped') header = m.Row() header.add(m.Cell(tr('Class name'))) header.add(m.Cell(tr('Minimum'))) header.add(m.Cell(tr('Maximum'))) table.add(header) classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda k: k['value']) for the_class in classes: threshold = thresholds[classification['key']]['classes'][ the_class['key']] row = m.Row() row.add(m.Cell(the_class['name'])) row.add(m.Cell(threshold[0])) row.add(m.Cell(threshold[1])) table.add(row) else: value_maps = self.value_maps.get(self.exposures[i]['key']) if not value_maps or not classification: message.add(m.Paragraph(tr('No classifications set.'))) continue table = m.Table( style_class='table table-condensed table-striped') header = m.Row() header.add(m.Cell(tr('Class name'))) header.add(m.Cell(tr('Value'))) table.add(header) classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda k: k['value']) for the_class in classes: value_map = value_maps[classification['key']][ 'classes'].get(the_class['key'], []) row = m.Row() row.add(m.Cell(the_class['name'])) row.add(m.Cell(', '.join([str(v) for v in value_map]))) table.add(row) message.add(table) # status_text_edit = QTextBrowser(None) status_text_edit = QWebView(None) status_text_edit.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Ignored) status_text_edit.page().mainFrame().setScrollBarPolicy( Qt.Horizontal, Qt.ScrollBarAlwaysOff) html_string = html_header() + message.to_html() + html_footer() status_text_edit.setHtml(html_string) self.right_layout.addWidget(status_text_edit)
def set_welcome_message(self): """Create and insert welcome message.""" string = html_header() string += welcome_message().to_html() string += html_footer() self.welcome_message.setHtml(string)
def generate_html_reports(self, first_report_dict, second_report_dict): """Generate html file for each aggregation units. It also saves the path of the each aggregation unit in self.html_reports. :: Ex. {"jakarta barat": "/home/jakarta barat.html", "jakarta timur": "/home/jakarta timur.html"} :param first_report_dict: Dictionary report from first impact. :type first_report_dict: dict :param second_report_dict: Dictionary report from second impact. :type second_report_dict: dict """ for aggregation_area in first_report_dict: html = html_header() html += ('<table width="100%" style="position:absolute;left:0px;"' 'class="table table-condensed table-striped">') html += '<caption><h4>%s</h4></caption>' % \ aggregation_area.title() html += '<tr>' # First impact on the left side html += '<td width="48%">' html += '<table width="100%">' html += '<thead><th>%s</th></thead>' % \ self.first_impact['exposure_title'].upper() first_exposure_report_dict = first_report_dict[aggregation_area] for first_exposure in first_exposure_report_dict: first_exposure_detail_dict = \ first_exposure_report_dict[first_exposure] html += '<tr><th><i>%s</i></th><th></th></tr>' % \ first_exposure.title() for datum in first_exposure_detail_dict: html += ('<tr>' '<td>%s</td>' '<td>%s</td>' '</tr>') % (datum, first_exposure_detail_dict[datum]) html += '</table>' html += '</td>' # Second impact on the right side if aggregation_area in second_report_dict: # Add spaces between html += '<td width="4%">' html += '</td>' # Second impact report html += '<td width="48%">' html += '<table width="100%">' html += '<thead><th>%s</th></thead>' % \ self.second_impact['exposure_title'].upper() second_exposure_report_dict = \ second_report_dict[aggregation_area] for second_exposure in second_exposure_report_dict: second_exposure_detail_dict = \ second_exposure_report_dict[second_exposure] html += '<tr><th><i>%s</i></th><th></th></tr>' % \ second_exposure.title() for datum in second_exposure_detail_dict: html += ('<tr>' '<td>%s</td>' '<td>%s</td>' '</tr>') % \ (datum, second_exposure_detail_dict[datum]) html += '</table>' html += '</td>' html += '</tr>' html += '</table>' html += html_footer() file_path = '%s.html' % aggregation_area path = os.path.join(temp_dir(self.__class__.__name__), file_path) html_to_file(html, path) self.html_reports[aggregation_area.lower()] = path
def generate_html_reports(self, first_report_dict, second_report_dict): """Generate html file for each aggregation units. It also saves the path of the each aggregation unit in self.html_reports. :: Ex. {"jakarta barat": "/home/jakarta barat.html", "jakarta timur": "/home/jakarta timur.html"} :param first_report_dict: Dictionary report from first impact. :type first_report_dict: dict :param second_report_dict: Dictionary report from second impact. :type second_report_dict: dict """ for aggregation_area in first_report_dict: html = html_header() html += ('<table width="100%" style="position:absolute;left:0px;"' 'class="table table-condensed table-striped">') html += '<caption><h4>%s</h4></caption>' % \ aggregation_area.title() html += '<tr>' # First impact on the left side html += '<td width="48%">' html += '<table width="100%">' html += '<thead><th>%s</th></thead>' % \ self.first_impact['exposure_title'].upper() first_exposure_report_dict = first_report_dict[aggregation_area] for first_exposure in first_exposure_report_dict: first_exposure_detail_dict = \ first_exposure_report_dict[first_exposure] html += '<tr><th><i>%s</i></th><th></th></tr>' % \ first_exposure.title() for datum in first_exposure_detail_dict: html += ('<tr>' '<td>%s</td>' '<td>%s</td>' '</tr>') % (datum, first_exposure_detail_dict[datum]) html += '</table>' html += '</td>' # Second impact on the right side if aggregation_area in second_report_dict: # Add spaces between html += '<td width="4%">' html += '</td>' # Second impact report html += '<td width="48%">' html += '<table width="100%">' html += '<thead><th>%s</th></thead>' % \ self.second_impact['exposure_title'].upper() second_exposure_report_dict = \ second_report_dict[aggregation_area] for second_exposure in second_exposure_report_dict: second_exposure_detail_dict = \ second_exposure_report_dict[second_exposure] html += '<tr><th><i>%s</i></th><th></th></tr>' % \ second_exposure.title() for datum in second_exposure_detail_dict: html += ('<tr>' '<td>%s</td>' '<td>%s</td>' '</tr>') % \ (datum, second_exposure_detail_dict[datum]) html += '</table>' html += '</td>' html += '</tr>' html += '</table>' html += html_footer() file_path = '%s.html' % aggregation_area path = os.path.join( temp_dir(self.__class__.__name__), file_path) html_to_file(html, path) self.html_reports[aggregation_area.lower()] = path
def print_impact_table(self, output_path): """Pint summary from impact layer to PDF. ..note:: The order of the report: 1. Summary table 2. Aggregation table 3. Attribution table :param output_path: Output path. :type output_path: str :return: Path to generated pdf file. :rtype: str :raises: None """ keywords = self._keyword_io.read_keywords(self.layer) if output_path is None: output_path = unique_filename(suffix='.pdf', dir=temp_dir()) try: impact_template = get_report_template(self.layer.source()) summary_table = impact_template.generate_html_report() except: summary_table = keywords.get('impact_summary', None) full_table = keywords.get('impact_table', None) aggregation_table = keywords.get('postprocessing_report', None) attribution_table = impact_attribution(keywords) # (AG) We will not use impact_table as most of the IF use that as: # impact_table = impact_summary + some information intended to be # shown on screen (see FloodOsmBuilding) # Unless the impact_summary is None, we will use impact_table as the # alternative html = m.Brand().to_html() html += m.Heading(tr('Analysis Results'), **INFO_STYLE).to_html() if summary_table is None: html += full_table else: html += summary_table if aggregation_table is not None: html += aggregation_table if attribution_table is not None: html += attribution_table.to_html() html = html_header() + html + html_footer() # Print HTML using composition # For QGIS < 2.4 compatibility # QgsMapSettings is added in 2.4 if qgis_version() < 20400: map_settings = QgsMapRenderer() else: map_settings = QgsMapSettings() # A4 Portrait # TODO: Will break when we try to use larger print layouts TS paper_width = 210 paper_height = 297 # noinspection PyCallingNonCallable composition = QgsComposition(map_settings) # noinspection PyUnresolvedReferences composition.setPlotStyle(QgsComposition.Print) composition.setPaperSize(paper_width, paper_height) composition.setPrintResolution(300) # Add HTML Frame # noinspection PyCallingNonCallable html_item = QgsComposerHtml(composition, False) margin_left = 10 margin_top = 10 # noinspection PyCallingNonCallable html_frame = QgsComposerFrame( composition, html_item, margin_left, margin_top, paper_width - 2 * margin_left, paper_height - 2 * margin_top) html_item.addFrame(html_frame) # Set HTML # From QGIS 2.6, we can set composer HTML with manual HTML if qgis_version() < 20600: html_path = unique_filename( prefix='report', suffix='.html', dir=temp_dir()) html_to_file(html, file_path=html_path) html_url = QUrl.fromLocalFile(html_path) html_item.setUrl(html_url) else: # noinspection PyUnresolvedReferences html_item.setContentMode(QgsComposerHtml.ManualHtml) # noinspection PyUnresolvedReferences html_item.setResizeMode(QgsComposerHtml.RepeatUntilFinished) html_item.setHtml(html) # RMN: This line below breaks in InaSAFE Headless after one # successful call. This is because the function is not # thread safe. Can't do anything about this, so avoid calling this # function in multithreaded way. html_item.loadHtml() composition.exportAsPDF(output_path) return output_path