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

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 ce30949 was ce30949, checked in by Torin Cooper-Bennun <torin.cooper-bennun@…>, 14 months ago

fix typo

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