ECMWF logo Support Portal
changes.mady.by.user Axel Bonet
Saved on Apr 28, 2014
...
Custom GUI
Tkinter can be used to setup an simple GUI client. Suite traverser is described in the cookbook.
As an example, overview.py is provided, while SMS/CDP has such command available.
#!/usr/bin/env python """ tkinter use example with ecflow from a NCEP request, while overview was part of CDP commands """ import Tkinter as tki import ecflow as ec from threading import Thread import Queue, sys, time, os, pwd from scrolledlist import ScrolledList # thanks to NMT # from=http://infohost.nmt.edu/tcc/help/lang/python/examples/scrolledlist/ # firefox $from ; wget $from/scrolledlist.py PROGRAM_NAME = "ecflowview-overview" BUTTON_FONT = ('times', 12) MONO_FONT = ('lucidatypewriter', 14, 'bold') DEBUG = 0 COLORS = { "aborted": "red", "active": "green", "submitted": "cyan", "complete": "yellow", "suspended": "orange", "queued": "blue", "unknwon": "grey" } class Label(object): """ a class to encapsulate what was a global variable""" inst = None def __init__(self, item): Label.inst = item @classmethod def update(cls): if Label.inst is None: return Label.inst.set(time.strftime( "%a, %d %b %Y %H:%M:%S")) class MenuBar(tki.Frame): def __init__(self, parent): tki.Frame.__init__(self, parent) self.__helpButton = self.__createHelp() self.__helpButton.grid(row=0, column=3) self.__updateButton = tki.Button( self, text='Update', font= BUTTON_FONT, command= parent.update) self.__updateButton.grid(row=0, column=2) def __createHelp(self): mb = tki.Menubutton(self, font=BUTTON_FONT, relief= tki.RAISED, text= 'Help') menu = tki.Menu(mb) mb['menu'] = menu url = "https://software.ecmwf.int/wiki/display/ECFLOW/Documentation" def url1(): self.__url(url= url) def url2(): self.__url(url="http://effbot.org/tkinterbook/") menu.add_command(command= url1, label="confluence tutorial?") menu.add_command(command= url2, label="tkinter?") return mb def __url(self, url=None): if url is None: return os.system("firefox " + url) class TaskList(tki.Frame): NAME_WIDTH = 40 NAME_LINES = 80 def __init__(self, parent, kind): tki.Frame.__init__(self, parent) self.__kind = kind self.__callback = None self.__label = tki.Label(self, font=BUTTON_FONT, background= COLORS[kind], text= kind) self.__label.grid(row=0, column=0, sticky= tki.W) self.__scrolledList = ScrolledList( self, width= self.NAME_WIDTH, height= self.NAME_LINES, callback= self.__callback) self.__scrolledList.grid(row=1, column=0) def insert(self, path): self.__scrolledList.append(path) def clear(self): self.__scrolledList.clear() running = [True] class PaceKeeper(): PACE = 60 def __init__(self, item, queue): thr = Thread(target=self.process, args=(queue, running)) self._item = item thr.start() def process(self, queue, running): while running: queue.put(self._item.update) time.sleep(self.PACE) def run(self): self.update() def update(self, verbose=False): while True: print time.clock() self._item.update() time.sleep(self.PACE) class Client(object): """ a class to focus on client-ecFlow-server comm""" def __init__(self, one="local-localhost@31415"): try: nick, hhh = one.split("-") except: hhh = one; nick = None try: host, port = hhh.split("@") except: host = "localhost"; port = 31415 if nick is None: self.nick = "%s@%d" % (host, port) print "# client creation", nick, host, port self.nick = nick self.client = ec.Client(host, port) def process(self, win): Label.update() self.client.sync_local() defs = self.client.get_defs() if defs is None: print("# %s-%: empty content" % ( self.host, self.port)) Label.update() for suite in defs.suites: self.process_nc(suite, win) def process_nc(self, node, win): for item in node.nodes: if isinstance(item, ec.Task): self.process_node(item, win) else: self.process_nc(item, win) def process_node(self, node, wins): for kind, win in wins.items(): status = "%s" % node.get_state() if status != kind: continue win.insert("%s:%s" % (self.nick, node.get_abs_node_path())) # print self.nick, node.get_abs_node_path(), status class Application(tki.Frame): def __init__(self, master=None, client=None, queue=None): tki.Frame.__init__(self, master) if client is None: self.__clients = [ Client("localhost@31415"), ] elif type(client) == set: self.__clients = client else: self.__clients = [ client ] self.__queue = queue width = 640 height = 780 self.canvas = tki.Canvas(width=width, height=height, bg='black') self.grid() self.createWidgets() self.canvas.after(50, self.check_queue) def createWidgets(self): rowx = 1 glob = Label(tki.StringVar(self)) root = self self.__menuBar = MenuBar(root) self.__menuBar.grid(row=0, column=0, sticky=tki.W) self.label = tki.Label(root, textvariable=Label.inst) self.label.grid(row=0, column=2, sticky=tki.E) self.__wins = dict() rowx += 1 colx = 0 kinds = ("active", "aborted", "submitted") for kind in kinds: self.__wins[kind] = TaskList(root, kind) self.__wins[kind].grid(row=rowx, column= colx, sticky=tki.S + tki.E + tki.W) colx += 1 self.update() def check_queue(self): try: self.__queue.get(block=False) except Queue.Empty: pass else: self.update() self.canvas.after(50, self.check_queue) def update(self): Label.update() for kind, win in self.__wins.items(): win.clear() for client in self.__clients: if type(client) == list: for clt in client: clt.process(self.__wins) else: try: client.process(self.__wins) except: pass pass def get_username(): return pwd.getpwuid( os.getuid() )[ 0 ] def get_uid(): return pwd.getpwnam(get_username()).pw_uid if __name__ == '__main__': try: port = 1500 + int(get_uid()) except: port = 31415 if len(sys.argv) == 0: clients = [ Client("localhost%d" % port) ] else: clients = [] for num in xrange(1, len(sys.argv)): clients.append( Client(sys.argv[num]) ) queue = Queue.Queue() # app = AppSms(host, port, queue) app = Application(client= clients, queue= queue) app.master.title(PROGRAM_NAME) app.columnconfigure(0, weight=1) app.rowconfigure(0, weight=1) PaceKeeper(app, queue) app.mainloop()