bug report 2214: fix for "Graphviz reports cause GRAMPS to hang for long periods of time"
svn: r10796
This commit is contained in:
		@@ -28,6 +28,8 @@
 | 
			
		||||
import os
 | 
			
		||||
from cStringIO import StringIO
 | 
			
		||||
import tempfile
 | 
			
		||||
import thread
 | 
			
		||||
import threading
 | 
			
		||||
from types import ClassType, InstanceType
 | 
			
		||||
from gettext import gettext as _
 | 
			
		||||
 | 
			
		||||
@@ -213,7 +215,54 @@ class GVDocBase(BaseDoc.BaseDoc,BaseDoc.GVDoc):
 | 
			
		||||
                self.write( '  fontsize="%d";\n' % self.notesize )
 | 
			
		||||
 | 
			
		||||
        self.write( '}\n\n' )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def animate_progress_bar(self):
 | 
			
		||||
        """
 | 
			
		||||
        The progress bar wont animate unless it is pulsed,
 | 
			
		||||
        so a timer is created to regularly call this method.
 | 
			
		||||
        """
 | 
			
		||||
        self.progress.pbar.pulse()
 | 
			
		||||
 | 
			
		||||
        # Schedule the next pulse
 | 
			
		||||
        self.progress_timer = threading.Timer(1.0, self.animate_progress_bar)
 | 
			
		||||
        self.progress_timer.start()
 | 
			
		||||
 | 
			
		||||
    def generate_output_file_from_dot_file(self, dotcommand, mimetype):
 | 
			
		||||
        """
 | 
			
		||||
        We now have the entire content of the .dot file.  Last thing
 | 
			
		||||
        we need to do is to call dot (part of the Graphviz package)
 | 
			
		||||
        to generate the .png, .gif, ...etc... output file.  Note that
 | 
			
		||||
        this can take a relatively long time for large or complicated
 | 
			
		||||
        graphs, so this method is called on a 2nd thread to prevent
 | 
			
		||||
        GRAMPS from appearing to have "hung".
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.progress = Utils.ProgressMeter(_('Processing File'), '')
 | 
			
		||||
        self.progress.set_pass(self.filename, 0)
 | 
			
		||||
        self.progress.pbar.set_pulse_step(0.1)
 | 
			
		||||
 | 
			
		||||
        # Start a timer to ensure the progress bar is animated
 | 
			
		||||
        self.animate_progress_bar()
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle, tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
 | 
			
		||||
        # Use the temporary dot file to generate the final output file
 | 
			
		||||
        os.system(dotcommand % (self.filename, tmp_dot))
 | 
			
		||||
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
 | 
			
		||||
        if mimetype and self.print_req:
 | 
			
		||||
            app = Mime.get_application(mimetype)
 | 
			
		||||
            Utils.launch(app[0], self.filename)     
 | 
			
		||||
 | 
			
		||||
        self.progress_timer.cancel()
 | 
			
		||||
        self.progress.close()
 | 
			
		||||
 | 
			
		||||
    def add_node(self, id, label, shape="", color="", 
 | 
			
		||||
                 style="", fillcolor="", url="", htmloutput=False ):
 | 
			
		||||
        """
 | 
			
		||||
@@ -342,21 +391,9 @@ class GVPsDoc(GVDocBase):
 | 
			
		||||
        if self.filename[-3:] != ".ps":
 | 
			
		||||
            self.filename += ".ps"
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
 | 
			
		||||
        # Generate the PS file.
 | 
			
		||||
        os.system( 'dot -Tps2 -o"%s" "%s"' % (self.filename,tmp_dot) )
 | 
			
		||||
        
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
        
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("application/postscript")
 | 
			
		||||
            Utils.launch(app[0], self.filename)
 | 
			
		||||
        thread.start_new_thread(
 | 
			
		||||
            self.generate_output_file_from_dot_file,
 | 
			
		||||
            ('dot -Tps2 -o"%s" "%s"', "application/postscript"))
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
@@ -379,21 +416,9 @@ class GVSvgDoc(GVDocBase):
 | 
			
		||||
        if self.filename[-4:] != ".svg":
 | 
			
		||||
            self.filename += ".svg"
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
 | 
			
		||||
        # Generate the SVG file.
 | 
			
		||||
        os.system( 'dot -Tsvg -o"%s" "%s"' % (self.filename,tmp_dot) )
 | 
			
		||||
        
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
        
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("image/svg")
 | 
			
		||||
            Utils.launch(app[0], self.filename)
 | 
			
		||||
        thread.start_new_thread(
 | 
			
		||||
            self.generate_output_file_from_dot_file,
 | 
			
		||||
            ('dot -Tsvg -o"%s" "%s"', "image/svg"))
 | 
			
		||||
            
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
@@ -416,21 +441,9 @@ class GVSvgzDoc(GVDocBase):
 | 
			
		||||
        if self.filename[-5:] != ".svgz":
 | 
			
		||||
            self.filename += ".svgz"
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
 | 
			
		||||
        # Generate the SVGZ file.
 | 
			
		||||
        os.system( 'dot -Tsvgz -o"%s" "%s"' % (self.filename,tmp_dot) )
 | 
			
		||||
        
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
        
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("image/svgz")
 | 
			
		||||
            Utils.launch(app[0], self.filename)
 | 
			
		||||
        thread.start_new_thread(
 | 
			
		||||
            self.generate_output_file_from_dot_file,
 | 
			
		||||
            ('dot -Tsvgz -o"%s" "%s"', "image/svgz"))
 | 
			
		||||
            
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
@@ -448,27 +461,15 @@ class GVPngDoc(GVDocBase):
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        GVDocBase.close(self)
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        # Make sure the extension is correct
 | 
			
		||||
        if self.filename[-4:] != ".png":
 | 
			
		||||
            self.filename += ".png"
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
        thread.start_new_thread(
 | 
			
		||||
            self.generate_output_file_from_dot_file,
 | 
			
		||||
            ('dot -Tpng -o"%s" "%s"', "image/png"))
 | 
			
		||||
 | 
			
		||||
        # Generate the PNG file.
 | 
			
		||||
        os.system( 'dot -Tpng -o"%s" "%s"' % (self.filename,tmp_dot) )
 | 
			
		||||
        
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
        
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("image/png")
 | 
			
		||||
            Utils.launch(app[0], self.filename)     
 | 
			
		||||
            
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
# GVJpegDoc
 | 
			
		||||
@@ -490,22 +491,10 @@ class GVJpegDoc(GVDocBase):
 | 
			
		||||
        if self.filename[-4:] != ".jpg":
 | 
			
		||||
            self.filename += ".jpg"
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
        thread.start_new_thread(
 | 
			
		||||
            self.generate_output_file_from_dot_file,
 | 
			
		||||
            ('dot -Tjpg -o"%s" "%s"', "image/jpeg"))
 | 
			
		||||
 | 
			
		||||
        # Generate the JPG file.
 | 
			
		||||
        os.system( 'dot -Tjpg -o"%s" "%s"' % (self.filename,tmp_dot) )
 | 
			
		||||
        
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
        
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("image/jpeg")
 | 
			
		||||
            Utils.launch(app[0], self.filename)
 | 
			
		||||
            
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
# GVGifDoc
 | 
			
		||||
@@ -527,21 +516,9 @@ class GVGifDoc(GVDocBase):
 | 
			
		||||
        if self.filename[-4:] != ".gif":
 | 
			
		||||
            self.filename += ".gif"
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
 | 
			
		||||
        # Generate the GIF file.
 | 
			
		||||
        os.system( 'dot -Tgif -o"%s" "%s"' % (self.filename,tmp_dot) )
 | 
			
		||||
        
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
        
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("image/gif")
 | 
			
		||||
            Utils.launch(app[0], self.filename)     
 | 
			
		||||
        thread.start_new_thread(
 | 
			
		||||
            self.generate_output_file_from_dot_file,
 | 
			
		||||
            ('dot -Tgif -o"%s" "%s"', "image/gif"))
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
@@ -567,21 +544,9 @@ class GVPdfGvDoc(GVDocBase):
 | 
			
		||||
        if self.filename[-4:] != ".pdf":
 | 
			
		||||
            self.filename += ".pdf"
 | 
			
		||||
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
 | 
			
		||||
        # Generate the PDF file.
 | 
			
		||||
        os.system( 'dot -Tpdf -o"%s" "%s"' % (self.filename,tmp_dot) )
 | 
			
		||||
        
 | 
			
		||||
        # Delete the temporary dot file
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
        
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("application/pdf")
 | 
			
		||||
            Utils.launch(app[0], self.filename)
 | 
			
		||||
        thread.start_new_thread(
 | 
			
		||||
            self.generate_output_file_from_dot_file,
 | 
			
		||||
            ('dot -Tpdf -o"%s" "%s"', "application/pdf"))
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
@@ -595,33 +560,30 @@ class GVPdfGsDoc(GVDocBase):
 | 
			
		||||
        # GV documentation says dpi is only for image formats.
 | 
			
		||||
        options.handler.options_dict['dpi'] = 72
 | 
			
		||||
        GVDocBase.__init__(self, options, paper_style)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        GVDocBase.close(self)
 | 
			
		||||
        
 | 
			
		||||
        # First step is to create a temporary .ps file
 | 
			
		||||
        original_name = self.filename
 | 
			
		||||
        if self.filename[-3:] != ".ps":
 | 
			
		||||
            self.filename += ".ps"
 | 
			
		||||
 | 
			
		||||
        self.generate_output_file_from_dot_file(
 | 
			
		||||
            'dot -Tps -o"%s" "%s"', None)
 | 
			
		||||
 | 
			
		||||
        tmp_ps = self.filename
 | 
			
		||||
 | 
			
		||||
        # Make sure the extension is correct
 | 
			
		||||
        self.filename = original_name
 | 
			
		||||
        if self.filename[-4:] != ".pdf":
 | 
			
		||||
            self.filename += ".pdf"
 | 
			
		||||
            
 | 
			
		||||
        # Create a temporary dot file
 | 
			
		||||
        (handle,tmp_dot) = tempfile.mkstemp(".dot" )
 | 
			
		||||
        dotfile = os.fdopen(handle,"w")
 | 
			
		||||
        dotfile.write(self.dot.getvalue())
 | 
			
		||||
        dotfile.close()
 | 
			
		||||
 | 
			
		||||
        # Create a temporary Postscript file
 | 
			
		||||
        (handle,tmp_ps) = tempfile.mkstemp(".ps" )
 | 
			
		||||
        os.close( handle )
 | 
			
		||||
 | 
			
		||||
        # Generate Postscript using dot
 | 
			
		||||
        command = 'dot -Tps -o"%s" "%s"' % ( tmp_ps, tmp_dot )
 | 
			
		||||
        os.system(command)
 | 
			
		||||
 | 
			
		||||
        # Add .5 to remove rounding errors.
 | 
			
		||||
        paper_size = self.paper.get_size()
 | 
			
		||||
        width_pt = int( (paper_size.get_width_inches() * 72) + 0.5 )
 | 
			
		||||
        height_pt = int( (paper_size.get_height_inches() * 72) + 0.5 )
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        # Convert to PDF using ghostscript
 | 
			
		||||
        command = '%s -q -sDEVICE=pdfwrite -dNOPAUSE -dDEVICEWIDTHPOINTS=%d' \
 | 
			
		||||
                  ' -dDEVICEHEIGHTPOINTS=%d -sOutputFile="%s" "%s" -c quit' \
 | 
			
		||||
@@ -629,7 +591,6 @@ class GVPdfGsDoc(GVDocBase):
 | 
			
		||||
        os.system(command)
 | 
			
		||||
 | 
			
		||||
        os.remove(tmp_ps)
 | 
			
		||||
        os.remove(tmp_dot)
 | 
			
		||||
 | 
			
		||||
        if self.print_req:
 | 
			
		||||
            app = Mime.get_application("application/pdf")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user