import sys, os, subprocess
import traceback
import warnings
import hal
from optparse import Option, OptionParser
import gtk
import gtk.glade
import gobject
import signal
import gladevcp.makepins
from gladevcp.gladebuilder import GladeBuilder
from gladevcp import xembed
from hal_glib import GStat
GSTAT = GStat()
options = [ Option( '-c', dest='component', metavar='NAME'
, help="Set component name to NAME. Default is basename of UI file")
, Option( '-d', action='store_true', dest='debug'
, help="Enable debug output")
, Option( '-g', dest='geometry', default="", help="""Set geometry WIDTHxHEIGHT+XOFFSET+YOFFSET.
Values are in pixel units, XOFFSET/YOFFSET is referenced from top left of screen
use -g WIDTHxHEIGHT for just setting size or -g +XOFFSET+YOFFSET for just position""")
, Option( '-H', dest='halfile', metavar='FILE'
, help="execute hal statements from FILE with halcmd after the component is set up and ready")
, Option( '-m', dest='maximum', default=False, help="Force panel window to maxumize")
, Option( '-r', dest='gtk_rc', default="",
help="read custom GTK rc file to set widget style")
, Option( '-R', dest='gtk_workaround', action='store_false',default=True,
help="disable workaround for GTK bug to properly read ~/.gtkrc-2.0 gtkrc files")
, Option( '-t', dest='theme', default="", help="Set gtk theme. Default is system theme")
, Option( '-x', dest='parent', type=int, metavar='XID'
, help="Reparent gladevcp into an existing window XID instead of creating a new top level window")
, Option( '--xid', action='store_true', dest='push_XID'
, help="reparent window into a plug add push the plug xid number to standardout")
, Option( '-u', dest='usermod', action='append', default=[], metavar='FILE'
, help='Use FILEs as additional user defined modules with handlers')
, Option( '-U', dest='useropts', action='append', metavar='USEROPT', default=[]
, help='pass USEROPTs to Python modules')
, Option( '--always_above', action='store_true', dest='always_above_flag'
, help="Request the window To always be above other windows")
]
signal_func = 'on_unix_signal'
gladevcp_debug = 0
def dbg(string):
global gladevcp_debug
if not gladevcp_debug: return
print string
def on_window_destroy(widget, data=None):
gtk.main_quit()
class Trampoline(object):
def __init__(self,methods):
self.methods = methods
def __call__(self, *a, **kw):
for m in self.methods:
m(*a, **kw)
def load_handlers(usermod,halcomp,builder,useropts):
hdl_func = 'get_handlers'
mod = object = None
def add_handler(method, f):
if method in handlers:
handlers[method].append(f)
else:
handlers[method] = [f]
handlers = {}
for u in usermod:
(directory,filename) = os.path.split(u)
(basename,extension) = os.path.splitext(filename)
if directory == '':
directory = '.'
if directory not in sys.path:
sys.path.insert(0,directory)
dbg('adding import dir %s' % directory)
try:
mod = __import__(basename)
except ImportError,msg:
print "module '%s' skipped - import error: %s" %(basename,msg)
continue
dbg("module '%s' imported OK" % mod.__name__)
try:
h = getattr(mod,hdl_func,None)
if h and callable(h):
dbg("module '%s' : '%s' function found" % (mod.__name__,hdl_func))
objlist = h(halcomp,builder,useropts)
else:
dbg("module '%s': no '%s' function - registering only functions as callbacks" % (mod.__name__,hdl_func))
objlist = [mod]
for object in objlist:
dbg("Registering handlers in module %s object %s" % (mod.__name__, object))
if isinstance(object, dict):
methods = dict.items()
else:
methods = map(lambda n: (n, getattr(object, n, None)), dir(object))
for method,f in methods:
if method.startswith('_'):
continue
if callable(f):
dbg("Register callback '%s' in %s" % (method, object))
add_handler(method, f)
except Exception, e:
print "gladevcp: trouble looking for handlers in '%s': %s" %(basename, e)
traceback.print_exc()
for n,v in list(handlers.items()):
if len(v) == 1:
handlers[n] = v[0]
else:
handlers[n] = Trampoline(v)
return handlers, mod, object
def main():
global gladevcp_debug
(progdir, progname) = os.path.split(sys.argv[0])
usage = "usage: %prog [options] myfile.ui"
parser = OptionParser(usage=usage)
parser.disable_interspersed_args()
parser.add_options(options)
(opts, args) = parser.parse_args()
if not args:
parser.print_help()
sys.exit(1)
gladevcp_debug = debug = opts.debug
xmlname = args[0]
if opts.component is None:
opts.component = os.path.splitext(os.path.basename(xmlname))[0]
try:
builder = gtk.Builder()
builder.add_from_file(xmlname)
except:
try:
dbg("**** GLADE VCP INFO: Not a builder project, trying to load as a lib glade project")
builder = gtk.glade.XML(xmlname)
builder = GladeBuilder(builder)
except Exception,e:
print >> sys.stderr, "**** GLADE VCP ERROR: With xml file: %s : %s" % (xmlname,e)
sys.exit(0)
window = builder.get_object("window1")
window.set_title(opts.component)
try:
halcomp = hal.component(opts.component)
except:
print >> sys.stderr, "*** GLADE VCP ERROR: Asking for a HAL component using a name that already exists."
sys.exit(0)
panel = gladevcp.makepins.GladePanel( halcomp, xmlname, builder, None)
handlers, mod, obj = load_handlers(opts.usermod,halcomp,builder,opts.useropts)
panel.set_handler(obj)
builder.connect_signals(handlers)
if opts.push_XID:
if not opts.debug:
warnings.filterwarnings("ignore")
gtk.gdk.error_trap_push()
forward = os.environ.get('QTVCP_FORWARD_EVENTS_TO', None)
if forward:
xembed.keyboard_forward(window, forward)
if opts.parent:
if not opts.debug:
warnings.filterwarnings("ignore")
gtk.gdk.error_trap_push()
window = xembed.reparent(window, opts.parent)
forward = os.environ.get('AXIS_FORWARD_EVENTS_TO', None)
if forward:
xembed.keyboard_forward(window, forward)
window.connect("destroy", on_window_destroy)
window.show()
if "+" in opts.geometry:
try:
j = opts.geometry.partition("+")
pos = j[2].partition("+")
window.move( int(pos[0]), int(pos[2]) )
except:
print >> sys.stderr, "**** GLADE VCP ERROR: With window position data"
parser.print_usage()
sys.exit(1)
if "x" in opts.geometry:
try:
if "+" in opts.geometry:
j = opts.geometry.partition("+")
t = j[0].partition("x")
else:
t = window_geometry.partition("x")
window.resize( int(t[0]), int(t[2]) )
except:
print >> sys.stderr, "**** GLADE VCP ERROR: With window resize data"
parser.print_usage()
sys.exit(1)
if opts.gtk_workaround:
dbg( "activating GTK bug workaround for gtkrc files")
for o in builder.get_objects():
if isinstance(o, gtk.Widget):
name = gtk.Buildable.get_name(o)
if name: o.set_name(name)
if opts.gtk_rc:
dbg( "**** GLADE VCP INFO: %s reading gtkrc file '%s'" %(opts.component,opts.gtk_rc))
gtk.rc_add_default_file(opts.gtk_rc)
gtk.rc_parse(opts.gtk_rc)
if opts.theme:
dbg("**** GLADE VCP INFO: Switching %s to '%s' theme" %(opts.component,opts.theme))
settings = gtk.settings_get_default()
settings.set_string_property("gtk-theme-name", opts.theme, "")
if opts.maximum:
window.window.maximize()
if opts.always_above_flag:
window.set_keep_above(True)
if opts.halfile:
if opts.halfile[-4:] == ".tcl":
cmd = ["haltcl", opts.halfile]
else:
cmd = ["halcmd", "-f", opts.halfile]
res = subprocess.call(cmd, stdout=sys.stdout, stderr=sys.stderr)
if res:
print >> sys.stderr, "'%s' exited with %d" %(' '.join(cmd), res)
sys.exit(res)
halcomp.ready()
GSTAT.forced_update()
if opts.push_XID or opts.parent:
gdkwin = window.get_window()
w_id = gdkwin.xid
print >> sys.stdout,w_id
sys.stdout.flush()
if handlers.has_key(signal_func):
dbg("Register callback '%s' for SIGINT and SIGTERM" %(signal_func))
signal.signal(signal.SIGTERM, handlers[signal_func])
signal.signal(signal.SIGINT, handlers[signal_func])
try:
gtk.main()
except KeyboardInterrupt:
sys.exit(0)
finally:
halcomp.exit()
if opts.parent or opts.push_XID:
gtk.gdk.flush()
error = gtk.gdk.error_trap_pop()
if error and opts.debug:
print >> sys.stderr, "**** GLADE VCP ERROR: X Protocol Error: %s" % str(error)
if __name__ == '__main__':
main()