#!/usr/bin/env python # the main GUI program. Relies on fract4d libs to do the real work version = '3.1' # python stdlib import sys import os import getopt # gettext import gettext os.environ.setdefault('LANG', 'en') if os.path.isdir('po'): gettext.install('gnofract4d','po') else: gettext.install('gnofract4d') # gtk try: import gtk except ImportError, err: print _("Can't find PyGTK. You need to install it before you can run Gnofract 4D.") sys.exit(1) # check for pygtk >=1.99 pygtk_ok = True try: (major,minor,patch) = gtk.pygtk_version if major < 2: if minor < 99: pygtk_ok = False import gobject except Exception: pygtk_ok = False if not pygtk_ok: print _("Sorry, your PyGTK version (%d.%d.%d) is too old. You need at least 1.99" % \ gtk.pygtk_version) sys.exit(1) try: # newer pygtk's are incompatible with older ones. In most cases I # try the new version and fall back to the older if it's missing. See utils.py. # In these cases I can't, so hiding the DeprecationWarnings so users # don't have to suffer import warnings # we use ItemFactory because I want this to carry on working with older PyGTK's, # so UIManager is out, and the differences between the 2 are too large to hide warnings.filterwarnings( "ignore", ".*UIManager.*", DeprecationWarning, ".*", 0) # newer pygtk's don't need us to call gobject.type_register, but older ones # most certainly do. warnings.filterwarnings( "ignore", ".*GObject-registered.*", DeprecationWarning, ".*", 0) except Exception, exn : print exn pass try: libdir = '%%PREFIX%%/lib' # we install our libs privately instead of to site-packages sys.path.append(os.path.join(libdir, 'gnofract4d')) # gui modules from fract4dgui import main_window, preferences, utils from fract4d import fractal except ImportError, err: print _(''' Can't import a required module. If you haven't set up Gnofract 4D yet, run './setup.py build' Error was: '%s' ''') % err sys.exit(1) # Threads are optional because RedHat seem to compile pygtk # without thread support. Grrr. try: #gtk.gdk.threads_init() #utils.threads_enabled = True pass except: pass class Options: "Gathers command-line args, wraps crappy getOpt interface" def __init__(self,args): (self.basename,self.func) = (None,None) (self.innername,self.innerfunc) = (None,None) (self.outername,self.outerfunc) = (None,None) self.maxiter = -1 self.trace = False self.paramchanges = {} self.quit_now = False self.quit_when_done = False self.output = "" self.explore = False self.save_filename = None self.extra_paths = [] self.map = None (self.width, self.height) = (0,0) longparams = [ "params=", "maxiter=", "width=", "height=", "save=", "help", "path=", "formula=", "inner=", "outer=", "map=", "xcenter=","ycenter=","zcenter=","wcenter=", "xyangle=","xzangle=","xwangle=","yzangle=","ywangle=","zwangle=", "magnitude=", "quit", "explorer", "trace", "version"] (opts, self.args) = getopt.getopt( args, "p:m:i:j:s:f:qhP:Xv", longparams) for (name, val) in opts: if name=="-p" or name=="--params": self.args.insert(0,val) elif name=="-m" or name=="--maxiter": self.maxiter=int(val) elif name=="-q" or name=="--quit": self.quit_when_done = True elif name=="-s" or name=="--save": self.save_filename = val elif name=="-i" or name=="--width": self.width = int(val) elif name=="-j" or name=="--height": self.height = int(val) elif name=="-h" or name=="--help": self.output += help() self.quit_now = True elif name=="-P" or name=="--path": self.extra_paths.append(val) elif name=="-X" or name=="--explorer": self.explore = True elif name=="-f" or name=="--formula": (self.basename,self.func) = self.splitarg(val,name) elif name=="--inner": (self.innername,self.innerfunc) = self.splitarg(val,name) elif name=="--outer": (self.outername,self.outerfunc) = self.splitarg(val,name) elif (name=="--map"): self.map = val elif name=="--version" or name=="-v": self.print_version() self.quit_now = True elif name=="--trace": self.trace = True else: # see if it's a positional param pname = name[2:].upper() if hasattr(fractal.T,pname): pnum = getattr(fractal.T,pname) self.paramchanges[pnum]= val else: print "Unknown argument", name, val def splitarg(self,val, name): n = val.rfind('#') if n==-1: help() print "ERROR: %s should be file#func" % name sys.exit(1) (file, func) = (val[:n], val[n+1:]) path = os.path.dirname(file) if path: self.extra_paths.append(path) basename = os.path.basename(file) return (basename,func) def print_version(self): try: gtk_version = "%d.%d.%d" % gtk.gtk_version except: gtk_version = "unknown" try: pygtk_version = "%d.%d.%d" % gtk.pygtk_version except: pygtk_version = "unknown" self.output += """Gnofract 4D %s GTK %s PyGTK %s""" % (version, gtk_version, pygtk_version) def help(): return """Gnofract 4D %s Usage: gnofract4d [flags] [paramfile] To generate an image non-interactively, use: gnofract4d -s myimage.png -q myfractal.fct General Flags: -h --help\t\tShow this message -v --version\t\tShow version info -q --quit\t\tExit as soon as the image is finished -X --explorer\t\tStart in explorer mode Fractal Settings: -p --params FILE\tUse FILE as a parameter file -s --save IMAGEFILE\tSave image to IMAGEFILE after calculation -i --width N\t\tMake image N pixels wide -j --height N\t\tMake image N pixels tall -P --path P\t\tAdd P to the formula search path -f --formula F#func\tUse formula 'func' from file F --inner F#func\tUse coloring algorithm 'func' from file F --outer F#func\tUse coloring algorithm 'func' from file F -m --maxiter N\t\tUse N as maximum number of iterations --map FILE\t\tLoad map file FILE Positional Parameters: --xcenter N --ycenter N --zcenter N --wcenter N --xyangle N --xzangle N --xwangle N --yzangle N --ywangle N --zwangle N --magnitude N Obscure settings: --trace\t\tProduce voluminous tracing output """ % version def main(): # parse the options try: options = Options(sys.argv[1:]) except getopt.GetoptError, err: print help() print "Error parsing arguments: %s" % err return 1 # having parsed them, apply them. The reason for this 2-pass # approach is that it matters what order these operations are # done in, but it shouldn't matter what order params are # presented on the command-line if len(options.output) > 0: print options.output if options.quit_now: sys.exit(0) mainWindow = main_window.MainWindow() mainWindow.apply_options(options) if mainWindow.f.thaw(): mainWindow.on_fractal_change() gtk.main() def main_n(n): for i in xrange(n): main() if __name__ == '__main__': if os.environ.get("DO_GF4D_PROFILE"): import hotshot prof = hotshot.Profile("gf4d.prof") prof.runcall(main_n, 5) prof.close() else: main()