source: sasview/src/sas/qtgui/Utilities/ReportDialog.py @ 5330be2

ESS_GUIESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 5330be2 was 5330be2, checked in by Piotr Rozyczko <rozyczko@…>, 14 months ago

Fix 2D chart failures with reporting. SASVIEW-950

  • Property mode set to 100644
File size: 6.1 KB
Line 
1import os
2import sys
3import re
4import logging
5from xhtml2pdf import pisa
6
7from PyQt5 import QtWidgets
8from PyQt5 import QtPrintSupport
9
10import sas.qtgui.Utilities.GuiUtils as GuiUtils
11
12from sas.qtgui.Utilities.UI.ReportDialogUI import Ui_ReportDialogUI
13
14
15class ReportDialog(QtWidgets.QDialog, Ui_ReportDialogUI):
16    """
17    Class for stateless grid-like printout of model parameters for mutiple models
18    """
19    def __init__(self, parent=None, report_list=None):
20
21        super(ReportDialog, self).__init__(parent._parent)
22        self.setupUi(self)
23
24        assert isinstance(report_list, list)
25        assert len(report_list) == 3
26
27        self.data_html, self.data_txt, self.data_images = report_list
28
29        # Fill in the table from input data
30        self.setupDialog(self.data_html)
31
32        # Command buttons
33        self.cmdPrint.clicked.connect(self.onPrint)
34        self.cmdSave.clicked.connect(self.onSave)
35
36    def setupDialog(self, output=None):
37        """
38        Display the HTML content in the browser.
39        """
40        if output is not None:
41            self.txtBrowser.setHtml(output)
42
43    def onPrint(self):
44        """
45        Display the print dialog and send the report to printer
46        """
47        # Define the printer
48        printer = QtPrintSupport.QPrinter()
49
50        # Display the print dialog
51        dialog = QtPrintSupport.QPrintDialog(printer)
52        dialog.setModal(True)
53        dialog.setWindowTitle("Print")
54        if dialog.exec_() != QtWidgets.QDialog.Accepted:
55            return
56
57        document = self.txtBrowser.document()
58        try:
59            # pylint chokes on this line with syntax-error
60            # pylint: disable=syntax-error doesn't seem to help
61            document.print(printer)
62        except Exception as ex:
63            # Printing can return various exceptions, let's catch them all
64            logging.error("Print report failed with: " + str(ex))
65
66    def onSave(self):
67        """
68        Display the Save As... prompt and save the report if instructed so
69        """
70        # Choose user's home directory
71        location = os.path.expanduser('~')
72        # Use a sensible filename default
73        default_name = os.path.join(location, 'fit_report.pdf')
74        kwargs = {
75            'parent'   : self,
76            'caption'  : 'Save Report',
77            'directory': default_name,
78            'filter'   : 'PDF file (*.pdf);;HTML file (*.html);;Text file (*.txt)',
79            'options'  : QtWidgets.QFileDialog.DontUseNativeDialog}
80        # Query user for filename.
81        filename_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs)
82        filename = filename_tuple[0]
83        if not filename:
84            return
85        extension = filename_tuple[1]
86
87        try:
88            # extract extension from filter
89            # e.g. "PDF file (*.pdf)" -> ".pdf"
90            ext = extension[extension.find("(")+2:extension.find(")")]
91        except IndexError as ex:
92            # (ext) not found...
93            logging.error("Error while saving report. " + str(ex))
94            return
95        basename, extension = os.path.splitext(filename)
96        if not extension:
97            filename = '.'.join((filename, ext))
98
99        # Create files with charts
100        pictures = self.getPictures(basename)
101
102        # translate png references into html from base64 string to on-disk name
103        cleanr = re.compile('<img src.*$')
104        replacement_name = ""
105        html = self.data_html
106        for picture in pictures:
107            replacement_name += '<img src="'+ picture + '"><p></p>'
108        # <img src="data:image/png;.*>  => <img src=filename>
109        html = re.sub(cleanr, replacement_name, self.data_html)
110
111        if ext.lower() == ".txt":
112            txt_ascii = GuiUtils.replaceHTMLwithASCII(self.data_txt)
113            self.onTXTSave(txt_ascii, filename)
114        if ext.lower() == ".html":
115            self.onHTMLSave(html, filename)
116        if ext.lower() == ".pdf":
117            html_utf = GuiUtils.replaceHTMLwithUTF8(html)
118            pdf_success = self.HTML2PDF(html_utf, filename)
119            # delete images used to create the pdf
120            for pic_name in pictures:
121                os.remove(pic_name)
122            #open pdf viewer
123            if pdf_success == 0:
124                try:
125                    if os.name == 'nt':  # Windows
126                        os.startfile(filename)
127                    elif sys.platform == "darwin":  # Mac
128                        os.system("open %s" % filename)
129                except Exception as ex:
130                    # cannot open pdf.
131                    # We don't know what happened in os.* , so broad Exception is required
132                    logging.error(str(ex))
133
134    def getPictures(self, basename):
135        """
136        Returns list of saved MPL figures
137        """
138        # save figures
139        pictures = []
140        for num, image in enumerate(self.data_images):
141            pic_name = basename + '_img%s.png' % num
142            # save the image for use with pdf writer
143            image.savefig(pic_name)
144            pictures.append(pic_name)
145        return pictures
146
147    @staticmethod
148    def onTXTSave(data, filename):
149        """
150        Simple txt file serializatio
151        """
152        with open(filename, 'w') as f:
153            f.write(data)
154
155    @staticmethod
156    def onHTMLSave(html, filename):
157        """
158        HTML file write
159        """
160        with open(filename, 'w') as f:
161            f.write(html)
162
163    @staticmethod
164    def HTML2PDF(data, filename):
165        """
166        Create a PDF file from html source string.
167        Returns True is the file creation was successful.
168        : data: html string
169        : filename: name of file to be saved
170        """
171        try:
172            # open output file for writing (truncated binary)
173            with open(filename, "w+b") as resultFile:
174                # convert HTML to PDF
175                pisaStatus = pisa.CreatePDF(data.encode("UTF-8"),
176                                            dest=resultFile,
177                                            encoding='UTF-8')
178                return pisaStatus.err
179        except Exception as ex:
180            logging.error("Error creating pdf: " + str(ex))
181        return False
182
183
Note: See TracBrowser for help on using the repository browser.