0002418: Gramps hangs when producing graphs on Windows
svn: r11097
This commit is contained in:
parent
b0f5322346
commit
5c3bffeb21
@ -28,8 +28,8 @@
|
|||||||
import os
|
import os
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
import tempfile
|
import tempfile
|
||||||
import thread
|
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
from types import ClassType, InstanceType
|
from types import ClassType, InstanceType
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
|
||||||
@ -52,7 +52,6 @@ import BaseDoc
|
|||||||
import Config
|
import Config
|
||||||
from ReportBase import CATEGORY_GRAPHVIZ
|
from ReportBase import CATEGORY_GRAPHVIZ
|
||||||
from _ReportDialog import ReportDialog
|
from _ReportDialog import ReportDialog
|
||||||
from _FileEntry import FileEntry
|
|
||||||
from _PaperMenu import PaperFrame
|
from _PaperMenu import PaperFrame
|
||||||
from gen.plug.menu import NumberOption, TextOption, EnumeratedListOption
|
from gen.plug.menu import NumberOption, TextOption, EnumeratedListOption
|
||||||
|
|
||||||
@ -102,6 +101,43 @@ else:
|
|||||||
_GS_CMD = "gs"
|
_GS_CMD = "gs"
|
||||||
else:
|
else:
|
||||||
_GS_CMD = ""
|
_GS_CMD = ""
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Private Functions
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
def _run_long_process_in_thread(func, header):
|
||||||
|
"""
|
||||||
|
This function will spawn a new thread to execute the provided function.
|
||||||
|
While the function is running, a progress bar will be created.
|
||||||
|
The progress bar will show activity while the function executes.
|
||||||
|
|
||||||
|
@param func: A function that will take an unknown amount of time to
|
||||||
|
complete.
|
||||||
|
@type category: callable
|
||||||
|
@param header: A header for the progress bar.
|
||||||
|
Example: "Updating Data"
|
||||||
|
@type name: string
|
||||||
|
@return: nothing
|
||||||
|
|
||||||
|
"""
|
||||||
|
pbar = Utils.ProgressMeter(_('Processing File'))
|
||||||
|
pbar.set_pass(total=40,
|
||||||
|
mode=Utils.ProgressMeter.MODE_ACTIVITY,
|
||||||
|
header=header)
|
||||||
|
|
||||||
|
sys_thread = threading.Thread(target=func)
|
||||||
|
sys_thread.start()
|
||||||
|
|
||||||
|
while sys_thread.isAlive():
|
||||||
|
# The loop runs 20 times per second until the thread completes.
|
||||||
|
# With the progress pass total set at 40, it should move across the bar
|
||||||
|
# every two seconds.
|
||||||
|
time.sleep(0.05)
|
||||||
|
pbar.step()
|
||||||
|
|
||||||
|
pbar.close()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -221,53 +257,6 @@ class GVDocBase(BaseDoc.BaseDoc, BaseDoc.GVDoc):
|
|||||||
|
|
||||||
self.write( '}\n\n' )
|
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, 10)
|
|
||||||
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, node_id, label, shape="", color="",
|
def add_node(self, node_id, label, shape="", color="",
|
||||||
style="", fillcolor="", url="", htmloutput=False):
|
style="", fillcolor="", url="", htmloutput=False):
|
||||||
"""
|
"""
|
||||||
@ -372,7 +361,15 @@ class GVDotDoc(GVDocBase):
|
|||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-4:] != ".dot":
|
if self._filename[-4:] != ".dot":
|
||||||
self._filename += ".dot"
|
self._filename += ".dot"
|
||||||
|
|
||||||
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
|
|
||||||
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
dotfile = open(self._filename, "w")
|
dotfile = open(self._filename, "w")
|
||||||
dotfile.write(self._dot.getvalue())
|
dotfile.write(self._dot.getvalue())
|
||||||
dotfile.close()
|
dotfile.close()
|
||||||
@ -402,10 +399,30 @@ class GVPsDoc(GVDocBase):
|
|||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-3:] != ".ps":
|
if self._filename[-3:] != ".ps":
|
||||||
self._filename += ".ps"
|
self._filename += ".ps"
|
||||||
|
|
||||||
thread.start_new_thread(
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
self.generate_output_file_from_dot_file,
|
|
||||||
('dot -Tps2 -o"%s" "%s"', "application/postscript"))
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -429,10 +446,30 @@ class GVSvgDoc(GVDocBase):
|
|||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-4:] != ".svg":
|
if self._filename[-4:] != ".svg":
|
||||||
self._filename += ".svg"
|
self._filename += ".svg"
|
||||||
|
|
||||||
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
|
|
||||||
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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(
|
# Generate the SVG file.
|
||||||
self.generate_output_file_from_dot_file,
|
os.system( 'dot -Tsvg -o"%s" "%s"' % (self._filename, tmp_dot) )
|
||||||
('dot -Tsvg -o"%s" "%s"', "image/svg"))
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -456,11 +493,31 @@ class GVSvgzDoc(GVDocBase):
|
|||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-5:] != ".svgz":
|
if self._filename[-5:] != ".svgz":
|
||||||
self._filename += ".svgz"
|
self._filename += ".svgz"
|
||||||
|
|
||||||
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
|
|
||||||
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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"))
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# GVPngDoc
|
# GVPngDoc
|
||||||
@ -479,14 +536,34 @@ class GVPngDoc(GVDocBase):
|
|||||||
def close(self):
|
def close(self):
|
||||||
""" Implements GVDocBase.close() """
|
""" Implements GVDocBase.close() """
|
||||||
GVDocBase.close(self)
|
GVDocBase.close(self)
|
||||||
|
|
||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-4:] != ".png":
|
if self._filename[-4:] != ".png":
|
||||||
self._filename += ".png"
|
self._filename += ".png"
|
||||||
|
|
||||||
thread.start_new_thread(
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
self.generate_output_file_from_dot_file,
|
|
||||||
('dot -Tpng -o"%s" "%s"', "image/png"))
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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 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)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -510,10 +587,30 @@ class GVJpegDoc(GVDocBase):
|
|||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-4:] != ".jpg":
|
if self._filename[-4:] != ".jpg":
|
||||||
self._filename += ".jpg"
|
self._filename += ".jpg"
|
||||||
|
|
||||||
thread.start_new_thread(
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
self.generate_output_file_from_dot_file,
|
|
||||||
('dot -Tjpg -o"%s" "%s"', "image/jpeg"))
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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 JPEG 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)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -537,10 +634,30 @@ class GVGifDoc(GVDocBase):
|
|||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-4:] != ".gif":
|
if self._filename[-4:] != ".gif":
|
||||||
self._filename += ".gif"
|
self._filename += ".gif"
|
||||||
|
|
||||||
thread.start_new_thread(
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
self.generate_output_file_from_dot_file,
|
|
||||||
('dot -Tgif -o"%s" "%s"', "image/gif"))
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -567,10 +684,30 @@ class GVPdfGvDoc(GVDocBase):
|
|||||||
# Make sure the extension is correct
|
# Make sure the extension is correct
|
||||||
if self._filename[-4:] != ".pdf":
|
if self._filename[-4:] != ".pdf":
|
||||||
self._filename += ".pdf"
|
self._filename += ".pdf"
|
||||||
|
|
||||||
thread.start_new_thread(
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
self.generate_output_file_from_dot_file,
|
|
||||||
('dot -Tpdf -o"%s" "%s"', "application/pdf"))
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -584,43 +721,55 @@ class GVPdfGsDoc(GVDocBase):
|
|||||||
# GV documentation says dpi is only for image formats.
|
# GV documentation says dpi is only for image formats.
|
||||||
options.menu.get_option_by_name('dpi').set_value(72)
|
options.menu.get_option_by_name('dpi').set_value(72)
|
||||||
GVDocBase.__init__(self, options, paper_style)
|
GVDocBase.__init__(self, options, paper_style)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
""" Implements GVDocBase.close() """
|
""" Implements GVDocBase.close() """
|
||||||
GVDocBase.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
|
# Make sure the extension is correct
|
||||||
self._filename = original_name
|
|
||||||
if self._filename[-4:] != ".pdf":
|
if self._filename[-4:] != ".pdf":
|
||||||
self._filename += ".pdf"
|
self._filename += ".pdf"
|
||||||
|
|
||||||
|
_run_long_process_in_thread(self.__generate, self._filename)
|
||||||
|
|
||||||
|
def __generate(self):
|
||||||
|
"""
|
||||||
|
This function will generate the actual file.
|
||||||
|
It is nice to run this function in the background so that the
|
||||||
|
application does not appear to hang.
|
||||||
|
"""
|
||||||
|
# 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.
|
# Add .5 to remove rounding errors.
|
||||||
paper_size = self._paper.get_size()
|
paper_size = self._paper.get_size()
|
||||||
width_pt = int( (paper_size.get_width_inches() * 72) + 0.5 )
|
width_pt = int( (paper_size.get_width_inches() * 72) + 0.5 )
|
||||||
height_pt = int( (paper_size.get_height_inches() * 72) + 0.5 )
|
height_pt = int( (paper_size.get_height_inches() * 72) + 0.5 )
|
||||||
|
|
||||||
# Convert to PDF using ghostscript
|
# Convert to PDF using ghostscript
|
||||||
command = '%s -q -sDEVICE=pdfwrite -dNOPAUSE -dDEVICEWIDTHPOINTS=%d' \
|
command = '%s -q -sDEVICE=pdfwrite -dNOPAUSE -dDEVICEWIDTHPOINTS=%d' \
|
||||||
' -dDEVICEHEIGHTPOINTS=%d -sOutputFile="%s" "%s" -c quit' \
|
' -dDEVICEHEIGHTPOINTS=%d -sOutputFile="%s" "%s" -c quit' \
|
||||||
% ( _GS_CMD, width_pt, height_pt, self._filename, tmp_ps )
|
% ( _GS_CMD, width_pt, height_pt, self._filename, tmp_ps )
|
||||||
os.system(command)
|
os.system(command)
|
||||||
|
|
||||||
os.remove(tmp_ps)
|
os.remove(tmp_ps)
|
||||||
|
os.remove(tmp_dot)
|
||||||
|
|
||||||
if self.print_req:
|
if self.print_req:
|
||||||
app = Mime.get_application("application/pdf")
|
app = Mime.get_application("application/pdf")
|
||||||
Utils.launch(app[0], self._filename)
|
Utils.launch(app[0], self._filename)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Various Graphviz formats.
|
# Various Graphviz formats.
|
||||||
|
123
src/Utils.py
123
src/Utils.py
@ -1010,81 +1010,118 @@ def media_path_full(db, filename):
|
|||||||
class ProgressMeter:
|
class ProgressMeter:
|
||||||
"""
|
"""
|
||||||
Progress meter class for GRAMPS.
|
Progress meter class for GRAMPS.
|
||||||
|
|
||||||
|
The progress meter has two modes:
|
||||||
|
|
||||||
|
MODE_FRACTION is used when you know the number of steps that will be taken.
|
||||||
|
Set the total number of steps, and then call step() that many times.
|
||||||
|
The progress bar will progress from left to right.
|
||||||
|
|
||||||
|
MODE_ACTIVITY is used when you don't know the number of steps that will be
|
||||||
|
taken. Set up the total number of steps for the bar to get from one end of
|
||||||
|
the bar to the other. Then, call step() as many times as you want. The bar
|
||||||
|
will move from left to right until you stop calling step.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
MODE_FRACTION = 0
|
||||||
|
MODE_ACTIVITY = 1
|
||||||
|
|
||||||
def __init__(self, title, header=''):
|
def __init__(self, title, header=''):
|
||||||
"""
|
"""
|
||||||
Specify the title and the current pass header.
|
Specify the title and the current pass header.
|
||||||
"""
|
"""
|
||||||
self.old_val = -1
|
self.__mode = ProgressMeter.MODE_FRACTION
|
||||||
self.ptop = gtk.Dialog()
|
self.__pbar_max = 100.0
|
||||||
self.ptop.connect('delete_event', self.warn)
|
self.__pbar_index = 0.0
|
||||||
self.ptop.set_has_separator(False)
|
self.__old_val = -1
|
||||||
self.ptop.set_title(title)
|
|
||||||
self.ptop.set_border_width(12)
|
self.__dialog = gtk.Dialog()
|
||||||
self.ptop.vbox.set_spacing(10)
|
self.__dialog.connect('delete_event', self.__warn)
|
||||||
lbl = gtk.Label('<span size="larger" weight="bold">%s</span>' % title)
|
self.__dialog.set_has_separator(False)
|
||||||
lbl.set_use_markup(True)
|
self.__dialog.set_title(title)
|
||||||
self.lbl = gtk.Label(header)
|
self.__dialog.set_border_width(12)
|
||||||
self.lbl.set_use_markup(True)
|
self.__dialog.vbox.set_spacing(10)
|
||||||
self.ptop.vbox.add(lbl)
|
self.__dialog.vbox.set_border_width(24)
|
||||||
self.ptop.vbox.add(self.lbl)
|
self.__dialog.set_size_request(350, 125)
|
||||||
self.ptop.vbox.set_border_width(24)
|
|
||||||
self.pbar = gtk.ProgressBar()
|
tlbl = gtk.Label('<span size="larger" weight="bold">%s</span>' % title)
|
||||||
|
tlbl.set_use_markup(True)
|
||||||
self.ptop.set_size_request(350, 125)
|
self.__dialog.vbox.add(tlbl)
|
||||||
self.ptop.vbox.add(self.pbar)
|
|
||||||
self.ptop.show_all()
|
self.__lbl = gtk.Label(header)
|
||||||
|
self.__lbl.set_use_markup(True)
|
||||||
|
self.__dialog.vbox.add(self.__lbl)
|
||||||
|
|
||||||
|
self.__pbar = gtk.ProgressBar()
|
||||||
|
self.__dialog.vbox.add(self.__pbar)
|
||||||
|
|
||||||
|
self.__dialog.show_all()
|
||||||
if header == '':
|
if header == '':
|
||||||
self.lbl.hide()
|
self.__lbl.hide()
|
||||||
|
|
||||||
def set_pass(self, header, total):
|
def set_pass(self, header="", total=100, mode=MODE_FRACTION):
|
||||||
"""
|
"""
|
||||||
Reset for another pass. Provide a new header and define number
|
Reset for another pass. Provide a new header and define number
|
||||||
of steps to be used.
|
of steps to be used.
|
||||||
"""
|
"""
|
||||||
|
self.__mode = mode
|
||||||
|
self.__pbar_max = total
|
||||||
|
self.__pbar_index = 0.0
|
||||||
|
|
||||||
|
self.__lbl.set_text(header)
|
||||||
if header == '':
|
if header == '':
|
||||||
self.lbl.hide()
|
self.__lbl.hide()
|
||||||
else:
|
else:
|
||||||
self.lbl.show()
|
self.__lbl.show()
|
||||||
self.pbar_max = total
|
|
||||||
self.pbar_index = 0.0
|
if self.__mode is ProgressMeter.MODE_FRACTION:
|
||||||
self.lbl.set_text(header)
|
self.__pbar.set_fraction(0.0)
|
||||||
self.pbar.set_fraction(0.0)
|
else: # ProgressMeter.MODE_ACTIVITY
|
||||||
|
self.__pbar.set_pulse_step(1.0/self.__pbar_max)
|
||||||
|
|
||||||
while gtk.events_pending():
|
while gtk.events_pending():
|
||||||
gtk.main_iteration()
|
gtk.main_iteration()
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
"""Click the progress bar over to the next value. Be paranoid
|
"""Click the progress bar over to the next value. Be paranoid
|
||||||
and insure that it doesn't go over 100%."""
|
and insure that it doesn't go over 100%."""
|
||||||
self.pbar_index = self.pbar_index + 1.0
|
|
||||||
|
|
||||||
if self.pbar_index > self.pbar_max:
|
if self.__mode is ProgressMeter.MODE_FRACTION:
|
||||||
self.pbar_index = self.pbar_max
|
self.__pbar_index = self.__pbar_index + 1.0
|
||||||
|
|
||||||
try:
|
if self.__pbar_index > self.__pbar_max:
|
||||||
val = int(100*self.pbar_index/self.pbar_max)
|
self.__pbar_index = self.__pbar_max
|
||||||
except ZeroDivisionError:
|
|
||||||
val = 0
|
try:
|
||||||
|
val = int(100*self.__pbar_index/self.__pbar_max)
|
||||||
if val != self.old_val:
|
except ZeroDivisionError:
|
||||||
self.pbar.set_text("%d%%" % val)
|
val = 0
|
||||||
self.pbar.set_fraction(val/100.0)
|
|
||||||
self.old_val = val
|
if val != self.__old_val:
|
||||||
|
self.__pbar.set_text("%d%%" % val)
|
||||||
|
self.__pbar.set_fraction(val/100.0)
|
||||||
|
self.__old_val = val
|
||||||
|
else: # ProgressMeter.MODE_ACTIVITY
|
||||||
|
self.__pbar.pulse()
|
||||||
|
|
||||||
while gtk.events_pending():
|
while gtk.events_pending():
|
||||||
gtk.main_iteration()
|
gtk.main_iteration()
|
||||||
|
|
||||||
def warn(self, *obj):
|
def __warn(self, *obj):
|
||||||
|
"""
|
||||||
|
Don't let the user close the progress dialog.
|
||||||
|
"""
|
||||||
WarningDialog(
|
WarningDialog(
|
||||||
_("Attempt to force closing the dialog"),
|
_("Attempt to force closing the dialog"),
|
||||||
_("Please do not force closing this important dialog."),
|
_("Please do not force closing this important dialog."),
|
||||||
self.ptop)
|
self.__dialog)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
||||||
Close the progress meter
|
Close the progress meter
|
||||||
"""
|
"""
|
||||||
self.ptop.destroy()
|
self.__dialog.destroy()
|
||||||
|
|
||||||
def launch(prog_str, path):
|
def launch(prog_str, path):
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user