예제 #1
0
class InteractionFilterWidget(rb.RaccoonDefaultWidget, DebugTools.DebugObj, tk.Frame):
    """ provide the interaction filter widget
        with different types:

            HBa
            HBd
            HB
            Metal
            vdW
            Pi-stack
            T-stack
            Generic stack
           
   checkbutton   pulldown     entry    button (remove)
        [x] | | [type..] | [ string ] [ x ]
    """
    def __init__(self, parent, manager, settings={}, color=None, debug = False): #, destroy_cb):
        self.color = '#bbff33'
        self.color = color # differenciate filter types?
        rb.RaccoonDefaultWidget.__init__(self, parent) 
        DebugTools.DebugObj.__init__(self, debug)
        tk.Frame.__init__(self, master=self.parent, relief='raised', bg=color,  **self.BORDER)
        self.manager = manager
        self._widgets = [self]

        self.initIcons()
        self.destroy_cb = None # destroy_cb
        self.eventManager = self.manager.eventManager
        #self.eventManager = eventManager
        #self.event = RaccoonEvents.FilterSetSelection()

        self.settings = settings
        self.build()
        self.setfilter()

        # hack to have mouse wheel to work all the time
        for w in self._widgets:
            w.bind("<Button-4>", self.manager.mousescroll)
            w.bind("<Button-5>", self.manager.mousescroll)
            if hasattr(w, 'components'):
                for c in w.components():
                    w.component(c).bind("<Button-4>", self.manager.mousescroll)
                    w.component(c).bind("<Button-5>", self.manager.mousescroll)


    def build(self):
        """ build the widgets"""
        entry_width = 10

        # types strings
        self._notype = '< select type >'
        self.stringToType = { 
                        'HB donor' : 'hbd',
                        'HB acceptor' : 'hba',
                        'HB any' : 'hb',
                        'Metal coord': 'metal',
                        'vdW contact': 'vdw',
                        'Pi-stacking': 'ppi', # XXX check this
                        'T-stacking' : 'tpi', # XXX check this
                        'Any stacking': 'pi', # XXX check this
                    }
        self.typeToString = {}
        for k,v in self.stringToType.items():
            self.typeToString[v] = k

        # active checkbutton
        self.active_var = tk.BooleanVar(value=False)
        self.active = tk.Checkbutton(self, variable=self.active_var, 
            bg=self.color, command=self.trigger)
        #self.active.pack(side='left', anchor='w', expand=0, fill='none')

        # interaction type
        self.typeChoice = OptionMenuFix(self,
            menubutton_font = self.FONT,
            menubutton_bg = self.color,
            menu_font = self.FONT,
            menubutton_width = 15,
            menubutton_bd = 1, menubutton_highlightbackground = 'black',
            menubutton_borderwidth=1, menubutton_highlightcolor='black', 
            menubutton_highlightthickness = 1,
            menubutton_height=1,
            command = self.trigger, # self.typeValidator, # self.trigger,
            items = sorted(self.stringToType.keys())
            )
        self.typeChoice.setvalue(self._notype)
        self.typeChoice.pack(side='left', anchor='w', expand=1, fill='x', padx=3, pady=1)
        self._widgets.append(self.typeChoice)

        # strings
        f = tk.Frame(self) # nested frames to have a decent alignment (Tk sucks(TM) )
        ef = tk.Frame(f) 
        # chain
        self.chain = Pmw.EntryField(ef, entry_font=self.FONT,
            labelpos = 'n', label_font=self.FONT, label_text='chain',
            hull_bg = self.color,
            entry_width=4, entry_justify='center',
            entry_bd = 1, entry_highlightbackground = 'black',
            entry_borderwidth=1, entry_highlightcolor='black', 
            entry_highlightthickness = 1,
            )
        self.chain.pack(side='left', anchor='n', expand=0, fill='x', padx=3 )
        self.chain.component('entry').bind('<Return>', self.return_cb)
        self.chain.component('entry').bind('<Leave>', self.focusLeave_cb)
        self._widgets.append(self.chain)

        # residue
        self.residue = Pmw.EntryField(ef, entry_font=self.FONT,
            labelpos = 'n', label_font=self.FONT, label_text='residue',
            hull_bg = self.color,
            entry_width=entry_width, entry_justify='center',
            entry_highlightbackground = 'black',
            entry_borderwidth=1, entry_highlightcolor='black', 
            entry_highlightthickness = 1,
            )
        self.residue.pack(side='left', anchor='n', expand=1, fill='x', padx=3)
        self.residue.component('entry').bind('<Return>', self.return_cb)
        self.residue.component('entry').bind('<Leave>', self.focusLeave_cb)
        self._widgets.append(self.residue)

        # atom
        self.atom = Pmw.EntryField(ef, entry_font=self.FONT,
            labelpos = 'n', label_font=self.FONT, label_text='atom',
            hull_bg = self.color,
            entry_width=entry_width, entry_justify='center',
            entry_highlightbackground = 'black',
            entry_borderwidth=1, entry_highlightcolor='black', 
            entry_highlightthickness = 1,
            )
        self.atom.pack(side='left', anchor='n', expand=1, fill='x', padx=3)
        self.atom.component('entry').bind('<Return>', self.return_cb)
        self._widgets.append(self.atom)

        s = tk.Frame(f, height=15)
        s.pack(side='bottom', anchor='w', expand=1, fill='both')

        ef.pack(side='top', anchor='w', expand=1, fill='x', padx=3)
        f.pack(side='left', anchor='w', expand=1, fill='both')

        self._widgets.append(s)
        self._widgets.append(ef)
        self._widgets.append(f)


        # wanted/not wanted
        self.wanted = True
        self.wantedButton = tk.Button(self, font=self.FONTbold, image=self._ICON_filtoff, relief='flat')
        selmenu = [ None,
                    ['wanted', 'normal', self.setPositive],
                    ['not wanted', 'normal', self.setNegative],
                    ['disable', 'normal', self.setOff],
                  ]
        menu = rb.RacMenu(self.wantedButton, selmenu, placement='under')
        self.wantedButton.pack(side='left', anchor='w', expand=0, fill='none', padx=1, pady=1)
        self._widgets.append(self.wantedButton)


        # destroy button
        self.destruction = tk.Button(self, text="X", image=self._ICON_del, command=self.destroy,
            bg=self.color,
            relief='flat') #,width=22) #, **self.BORDER)
        self.destruction.pack(side='left', anchor='w', expand=0, fill='none')
        self._widgets.append(self.destruction)


    def initIcons(self):
        """ initialize the icons for the interface"""
        icon_path = CADD.Raccoon2.ICONPATH

        f = icon_path + os.sep + 'removeSmall.png'
        f = icon_path + os.sep + 'removeSmallbw.png'
        self._ICON_del = ImageTk.PhotoImage(Image.open(f))

        f = icon_path + os.sep + 'filt_positive.png'
        f = icon_path + os.sep + 'filt_positiveLight.png'
        self._ICON_filtpos = ImageTk.PhotoImage(Image.open(f))

        f = icon_path + os.sep + 'filt_negativeLight.png'
        self._ICON_filtneg = ImageTk.PhotoImage(Image.open(f))

        f = icon_path + os.sep + 'filt_inactiveLight.png'
        self._ICON_filtoff = ImageTk.PhotoImage(Image.open(f))


    def setPositive(self, event=None):
        """ set the interaction to be wanted"""
        self.wanted = True
        self.wantedButton.configure(image=self._ICON_filtpos, text='A')
        self.enable()
        #self.trigger()

    def setNegative(self, event=None):
        """ set the interaction to be not wanted"""
        self.wanted = False
        self.wantedButton.configure(image=self._ICON_filtneg, text='R')
        self.enable()
        #self.trigger()

    def setOff(self, event=None):
        """ turn off the filter"""
        self.wantedButton.configure(image=self._ICON_filtoff, text='R')
        current = self.active_var.get()
        self.active_var.set(False)
        # the filter was active, it has been disabled
        # so we need to send event for filterEngine to
        # be triggered
        if not self.active_var.get() == current:
            self.sendEvent()
        
    def return_cb(self, event=None):
        """ function called when return is pressed
            in the text fields
        """
        if self.wanted == True:
            self.setPositive()
        else:
            self.setNegative()

    def focusLeave_cb(self, event=None):
        """ trigger status check for entries
            when they loose focus
            Important when the filter has been alread
            activated, then the user changes the text in the
            field
        """
        if not self.isActive():
            return
        self.entryValidator(quiet=False)

    def isActive(self, event=None):
        """ return if the filter is active"""
        return self.active_var.get()

    def disable(self, event=None):  
        """ disable the filter"""
        self.active_var.set(False)

    def enable(self, event=None, quiet=True):  
        """ enable the filter"""
        self.active_var.set(True)
        self.trigger(quiet=quiet)

    def entryValidator(self, string=None, quiet=True):
        """ validate the text entry field
        """
        #if string == None:
        #    string = self.entry.getvalue()
        chain = self.chain.getvalue().strip()
        res = self.residue.getvalue().strip()
        atom = self.atom.getvalue().strip()
        if not chain and not res and not atom:
            self.setOff()
            if not quiet:
                t = 'Interaction specification not valid'
                i = 'error'
                m = ('The interaction must be defined by typing at '
                     'least a chain, residue or atom string.\n'
                     'Single character "?" and multi-character "*" wildcards can be used.'
                    ) 
                tmb.showinfo(parent=self, title=t, icon=i, message=m)
            return False
        return True


    def typeValidator(self, string=None, quiet=False):
        """ validate type selection """
        _type = self.typeChoice.getvalue()
        if _type == self._notype:
            if not quiet:
                t = 'Filter type error'
                i = 'warning'
                m = ('An interaction type must be selected')
                tmb.showinfo(parent=self, title=t, icon=i, message=m)
            self.setOff()
            return False        
        return True

    def isvalid(self, quiet=True):
        """return if the entry is valid"""
        typeCheck = self.typeValidator(quiet=quiet) 
        if not typeCheck: # or not self.isActive():
            return
        if not self.isActive():
            return
        entryCheck = self.entryValidator(quiet=quiet)
        return (typeCheck and entryCheck)

    def trigger(self, event=None, quiet=False):
        """ command executed when the filter is activated"""
        #curr_state = self.isActive() # active_var.get()
        if not self.isvalid(quiet=quiet):
            return
        self.active_var.set(True)
        self.sendEvent()

    def sendEvent(self):
        """ trigger the event"""
        e = RaccoonEvents.FilterInteractionEvent()
        self.eventManager.dispatchEvent(e)

    def getType(self):
        """ return interaction type"""
        return self.stringToType[ self.typeChoice.getvalue() ]

    def getPattern(self):
        """ return interaction text pattern"""
        c = self.chain.getvalue().strip()
        r = self.residue.getvalue().strip()
        a = self.atom.getvalue().strip()
        if c == "": c = "*"
        if r == "": r = "*"
        if a == "": a = "*"
        return "%s:%s:%s" % (c,r,a)


    def setfilter(self, settings={}):
        """ initialize filter with requested values"""
        if settings == {}:
            settings == self.settings
        if settings == {}:
            return
        t = self.settings['type']
        t = self.typeToString[t]
        e = self.settings['patter']
        self.typeChoice.setvalue(t)
        self.entry.setvalue(e)
        if self.isvalid(): self.active_var.set(True)
        # FIXME set this to active?
        #return { 'type' : t, 'pattern' : e }



    def destroy(self, event=None):
        """ remove itself from the list of filters
            and unpack the widget
        """
        t = 'Delete filter'
        i = 'info'
        m = ('Remove this filter?')
        if self.isvalid():
            if not tmb.askyesno(parent=self, title=t, message=m, icon=i):
                return
        self.destroy_cb()
예제 #2
0
class JobSubmissionInterface(rb.RaccoonDefaultWidget):
    """ ask for Project, Exp, VS info..."""
    def __init__(self, parent, jmanager, app, suggest={}):
        """ parent      : tkparent
            jmanager    : job manager tree (to query current prj,exp...)
            app         : containing app
        """
        rb.RaccoonDefaultWidget.__init__(self, parent)
        self.jmanager = jmanager
        self.app = app
        self._new = '<new>'
        self.jobdata = None
        self.suggest = suggest
        self.initIcons()
        self.build()

    def initIcons(self):
        pass

    def close(self, result):
        """ close the window and decides what to do
            if OK requested, check values and start submission
        """
        if result == 'OK':
            if not self.checkinfo():
                return
            p = self.getPrj()
            e = self.getExp()
            t = self.tag_entry.getvalue().strip()
            self.jobdata = {'prj': p, 'exp': e, 'tag': t}
            self.win.deactivate(self.jobdata)
        else:
            self.win.deactivate(False)

    def getPrj(self):
        """ return the project name"""
        m = ('The project name is not valid.\n')
        p = self.prj_pull.getvalue()  # old project
        if p == self._new:
            if not self.prj_new.valid():
                self.errorMsg(m)
                return False
            p = self.prj_new.getvalue()
        return p

    def getExp(self):
        """ return the experiment name"""
        m = ('The experiment name is not valid.\n')
        e = self.exp_pull.getvalue()  # old project
        if e == self._new:
            if not self.exp_new.valid():
                self.errorMsg(m)
                return False
            e = self.exp_new.getvalue()
        return e

    def getTag(self):
        """ return the tag"""
        tag = self.tag_entry.getvalue()
        return tag

    def checkDuplicates(self):
        """ check that the jobs that are going to be 
            submitted do not have the same name of 
            already submitted jobs
        """
        m = ('The submission cannot be performed because there '
             'are already jobs with the same name stored in project %s '
             '/experiment %s.\n\n'
             'Either create new project/experiments or use a different tag.')
        job_info = {
            'prj': self.getPrj(),
            'exp': self.getExp(),
            'tag': self.getTag()
        }
        report = self.app.testSshJobs(job_info)
        e = []
        if len(report['server_duplicates']):
            e.append('the current server')
        if len(report['local_duplicates']):
            e.append('the local client')
        if len(e):
            m = m % (job_info['prj'], job_info['exp'])
            self.errorMsg(m)
            return False
        return True

    def checkinfo(self):
        """ check that user provided info are valid"""
        if not self.getPrj():
            return False
        if not self.getExp():
            return False
        if not self.checkDuplicates():
            return False
        return True

    def errorMsg(self, message):
        """ display submission entries error"""
        t = 'Incorrect name entry'
        i = 'error'
        tmb.showinfo(parent=self.win.interior(),
                     title=t,
                     message=message,
                     icon=i)
        return

    def getinfo(self):
        """ return the user provided info"""
        return self.jobdata

    def _setprjname(self, event=None):
        choice = self.prj_pull.getvalue()
        if choice == self._new:
            self.prj_new.grid(row=4, column=2, sticky='we', padx=4, pady=4)
            self.prj_new.checkentry()
        else:
            self.prj_new.grid_forget()
        exp_list = self._getexplist()
        self.exp_pull.setitems(exp_list)
        self.exp_pull.setvalue(exp_list[-1])
        self.exp_pull.invoke()

    def _getexplist(self, event=None):
        prj = self.prj_pull.getvalue()
        if prj == self._new:
            return [self._new]
        else:
            exp_list = sorted(self.info[prj].keys())
            return exp_list + [self._new]

    def _setexpname(self, event=None):
        choice = self.exp_pull.getvalue()
        if choice == self._new:
            self.exp_new.grid(row=8, column=2, sticky='we', padx=4, pady=4)
            self.exp_new.checkentry()
        else:
            self.exp_new.grid_forget()

    def build(self):
        # get info from the current manager
        self.info = self.jmanager.getTreeGraph()
        self.prj_list = sorted(self.info.keys()) + [self._new]
        #self.prj_list.append(self._new)
        self.win = Pmw.Dialog(parent=self.parent,
                              buttons=('OK', 'Cancel'),
                              title='Submit jobs',
                              command=self.close)
        w = self.win.interior()
        bbox = self.win.component('buttonbox')
        for i in range(bbox.numbuttons()):
            bbox.button(i).configure(font=self.FONT,
                                     default='disabled',
                                     **self.BORDER)

        tk.Label(w, text='Select the new VS properties',
                 font=self.FONT).grid(row=0,
                                      column=1,
                                      sticky='we',
                                      columnspan=3,
                                      padx=5,
                                      pady=5)
        tk.Frame(w, height=2, bd=1, relief='sunken').grid(row=1,
                                                          column=0,
                                                          sticky='ew',
                                                          columnspan=3,
                                                          pady=3)
        # project
        tk.Label(w, text='Project', font=self.FONTbold, width=12,
                 anchor='e').grid(row=3, column=1, sticky='we')
        tk.Label(w, text='', font=self.FONT,
                 width=10).grid(row=4, column=1, sticky='we',
                                pady=5)  # placeholder for entry

        self.prj_pull = OptionMenuFix(w,
                                      menubutton_width=30,
                                      menubutton_font=self.FONT,
                                      menu_font=self.FONT,
                                      menubutton_bd=1,
                                      menubutton_highlightbackground='black',
                                      menubutton_borderwidth=1,
                                      menubutton_highlightcolor='black',
                                      menubutton_highlightthickness=1,
                                      menubutton_height=1,
                                      items=self.prj_list,
                                      initialitem=-1,
                                      command=self._setprjname)
        self.prj_pull.grid(row=3, column=2, sticky='we', padx=3)

        self.prj_new = Pmw.EntryField(w,
                                      value='',
                                      validate={
                                          'validator': hf.validateAscii,
                                          'minstrict': 0
                                      })  #,
        self.prj_new.component('entry').configure(justify='left',
                                                  font=self.FONT,
                                                  bg='pink',
                                                  width=33,
                                                  **self.BORDER)

        # --------------------------------
        tk.Frame(w, height=2, bd=1, relief='sunken').grid(row=6,
                                                          column=0,
                                                          sticky='ew',
                                                          columnspan=3,
                                                          pady=3)

        # experiment
        tk.Label(w,
                 text='Experiment',
                 font=self.FONTbold,
                 width=12,
                 anchor='e').grid(row=7, column=1, sticky='we')
        tk.Label(w, text='', font=self.FONT,
                 width=10).grid(row=8, column=1, sticky='we',
                                pady=5)  # placeholder for entry

        self.exp_pull = OptionMenuFix(w,
                                      labelpos='w',
                                      menubutton_width=30,
                                      menubutton_font=self.FONT,
                                      menu_font=self.FONT,
                                      menubutton_bd=1,
                                      menubutton_highlightbackground='black',
                                      menubutton_borderwidth=1,
                                      menubutton_highlightcolor='black',
                                      menubutton_highlightthickness=1,
                                      menubutton_height=1,
                                      items=[self._new],
                                      initialitem=-1,
                                      command=self._setexpname)
        self.exp_pull.grid(row=7, column=2, sticky='we', padx=3)
        self.exp_new = Pmw.EntryField(w,
                                      value='',
                                      validate={
                                          'validator': hf.validateAscii,
                                          'minstrict': 0
                                      })  #,
        self.exp_new.component('entry').configure(justify='left',
                                                  font=self.FONT,
                                                  bg='pink',
                                                  width=30,
                                                  **self.BORDER)
        # initialize the interface with the projects
        self._setprjname()
        self.prj_pull.setvalue(self.prj_list[-1])

        # --------------------------------
        tk.Frame(w, height=2, bd=1, relief='sunken').grid(row=9,
                                                          column=0,
                                                          sticky='ew',
                                                          columnspan=3,
                                                          pady=3)
        # job tag
        tk.Label(w, text='Optional jobs name tag',
                 font=self.FONT).grid(row=10,
                                      column=1,
                                      columnspan=3,
                                      sticky='we',
                                      padx=5)
        self.tag_entry = Pmw.EntryField(w,
                                        value='',
                                        validate=hf.validateAsciiEmpty)  #,
        self.tag_entry.component('entry').configure(justify='left',
                                                    font=self.FONT,
                                                    bg='white',
                                                    width=30,
                                                    **self.BORDER)
        self.tag_entry.grid(row=11,
                            column=1,
                            columnspan=3,
                            sticky='we',
                            padx=4,
                            pady=4)

        self.win.bind('<Escape>', self.close)
        self.setSuggest()
        self.win.activate()

    def setSuggest(self):
        """ fill the submission with the suggestions"""
        if self.suggest == {}:
            return
        if 'prj' in self.suggest.keys():
            prj = self.suggest.pop('prj')
            self.prj_pull.setvalue(prj)
            self.prj_pull.invoke()
        if 'exp' in self.suggest.keys():
            exp = self.suggest.pop('exp')
            self.exp_pull.setvalue(exp)
            self.exp_pull.invoke()
        if 'tag' in self.suggest.keys():
            tag = self.suggest.pop('tag')
        else:
            tag = 'RESTARTED'
        self.tag_entry.setvalue(tag)
예제 #3
0
class JobSubmissionInterface(rb.RaccoonDefaultWidget):
    """ ask for Project, Exp, VS info..."""

    def __init__(self, parent, jmanager, app, suggest={}):
        """ parent      : tkparent
            jmanager    : job manager tree (to query current prj,exp...)
            app         : containing app
        """
        rb.RaccoonDefaultWidget.__init__(self, parent)
        self.jmanager = jmanager
        self.app = app
        self._new = '<new>'
        self.jobdata = None
        self.suggest = suggest
        self.initIcons()
        self.build()

    def initIcons(self):
        pass

    def close(self, result):
        """ close the window and decides what to do
            if OK requested, check values and start submission
        """
        if result == 'OK':
            if not self.checkinfo():
                return
            p = self.getPrj()
            e = self.getExp()
            t = self.tag_entry.getvalue().strip()
            self.jobdata = {'prj' : p, 'exp': e, 'tag':t} 
            self.win.deactivate(self.jobdata)
        else:
            self.win.deactivate(False)

    def getPrj(self):
        """ return the project name"""
        m = ('The project name is not valid.\n')
        p = self.prj_pull.getvalue() # old project
        if p == self._new:
            if not self.prj_new.valid():
                self.errorMsg(m)
                return False
            p = self.prj_new.getvalue()
        return p

    def getExp(self):
        """ return the experiment name"""
        m = ('The experiment name is not valid.\n')
        e = self.exp_pull.getvalue() # old project
        if e == self._new:
            if not self.exp_new.valid():
                self.errorMsg(m)
                return False
            e = self.exp_new.getvalue()
        return e

    def getTag(self):
        """ return the tag"""
        tag = self.tag_entry.getvalue()
        return tag


    def checkDuplicates(self):
        """ check that the jobs that are going to be 
            submitted do not have the same name of 
            already submitted jobs
        """
        m = ('The submission cannot be performed because there '
             'are already jobs with the same name stored in project %s '
             '/experiment %s.\n\n'
             'Either create new project/experiments or use a different tag.')
        job_info = {'prj' : self.getPrj(),
                    'exp' : self.getExp(),
                    'tag' : self.getTag()
                   }
        report = self.app.testSshJobs(job_info)
        e = []
        if len(report['server_duplicates']):
            e.append('the current server')
        if len(report['local_duplicates']):
            e.append('the local client')
        if len(e):
            m = m % ( job_info['prj'], job_info['exp'])
            self.errorMsg(m)
            return False
        return True

    def checkinfo(self):
        """ check that user provided info are valid"""
        if not self.getPrj():
            return False
        if not self.getExp():
            return False
        if not self.checkDuplicates():
            return False
        return True


    def errorMsg(self, message):
        """ display submission entries error"""
        t = 'Incorrect name entry'
        i = 'error'
        tmb.showinfo(parent=self.win.interior(), title=t, message=message, icon=i)
        return


    def getinfo(self):
        """ return the user provided info"""
        return self.jobdata


    def _setprjname(self, event=None):
        choice = self.prj_pull.getvalue()
        if choice == self._new:
            self.prj_new.grid(row=4, column=2, sticky='we',padx=4,pady=4)
            self.prj_new.checkentry()
        else:
            self.prj_new.grid_forget()
        exp_list = self._getexplist()
        self.exp_pull.setitems( exp_list )
        self.exp_pull.setvalue( exp_list[-1])
        self.exp_pull.invoke()

    def _getexplist(self, event=None):
        prj = self.prj_pull.getvalue()
        if prj == self._new:
            return [self._new]
        else:
            exp_list = sorted(self.info[prj].keys())
            return exp_list + [self._new]

    def _setexpname(self, event=None):
        choice = self.exp_pull.getvalue()
        if choice == self._new:
            self.exp_new.grid(row=8,column=2, sticky='we', padx=4,pady=4)
            self.exp_new.checkentry()
        else:
            self.exp_new.grid_forget()

    def build(self):
        # get info from the current manager
        self.info = self.jmanager.getTreeGraph()
        self.prj_list = sorted(self.info.keys()) + [self._new]
        #self.prj_list.append(self._new)
        self.win = Pmw.Dialog(parent=self.parent, buttons=('OK', 'Cancel'),
            title = 'Submit jobs', command = self.close)
        w = self.win.interior()
        bbox = self.win.component('buttonbox')
        for i in range(bbox.numbuttons()):
            bbox.button(i).configure(font=self.FONT, default='disabled', **self.BORDER)

        tk.Label(w, text='Select the new VS properties', font=self.FONT).grid(row=0,column=1, sticky='we', columnspan=3,padx=5,pady=5)
        tk.Frame(w,height=2,bd=1,relief='sunken').grid(row=1, column=0, sticky='ew', columnspan=3, pady=3)
        # project 
        tk.Label(w, text='Project', font=self.FONTbold, width=12,anchor='e').grid(row=3,column=1,sticky='we')
        tk.Label(w, text='', font=self.FONT, width=10).grid(row=4,column=1,sticky='we',pady=5) # placeholder for entry

        self.prj_pull = OptionMenuFix(w,
               menubutton_width=30,
               menubutton_font=self.FONT,
               menu_font=self.FONT,
               menubutton_bd = 1, menubutton_highlightbackground = 'black',
               menubutton_borderwidth=1, menubutton_highlightcolor='black', 
               menubutton_highlightthickness = 1,
               menubutton_height=1,
               items = self.prj_list,
               initialitem=-1,
               command = self._setprjname)
        self.prj_pull.grid(row=3,column=2,sticky='we',padx=3)

        self.prj_new = Pmw.EntryField(w, value='', validate = {'validator' : hf.validateAscii, 'minstrict': 0}) #,
        self.prj_new.component('entry').configure(justify='left', font=self.FONT, bg='pink',width=33, **self.BORDER)

        # --------------------------------
        tk.Frame(w,height=2,bd=1,relief='sunken').grid(row=6, column=0, sticky='ew', columnspan=3, pady=3)
        
        # experiment
        tk.Label(w, text='Experiment', font=self.FONTbold, width=12,anchor='e').grid(row=7,column=1,sticky='we')
        tk.Label(w, text='', font=self.FONT, width=10).grid(row=8,column=1,sticky='we',pady=5) # placeholder for entry

        self.exp_pull = OptionMenuFix(w,labelpos='w',
                       menubutton_width=30,
                       menubutton_font=self.FONT,
                       menu_font=self.FONT,
               menubutton_bd = 1, menubutton_highlightbackground = 'black',
               menubutton_borderwidth=1, menubutton_highlightcolor='black', 
               menubutton_highlightthickness = 1,
               menubutton_height=1,
                       items=[self._new],
                       initialitem=-1,
                       command = self._setexpname)
        self.exp_pull.grid(row=7, column =2, sticky='we',padx=3)
        self.exp_new = Pmw.EntryField(w, value='', validate = {'validator' : hf.validateAscii, 'minstrict':0}) #,
        self.exp_new.component('entry').configure(justify='left', font=self.FONT, bg='pink',width=30, **self.BORDER)
        # initialize the interface with the projects
        self._setprjname()
        self.prj_pull.setvalue( self.prj_list[-1])

        # --------------------------------
        tk.Frame(w,height=2,bd=1,relief='sunken').grid(row=9, column=0, sticky='ew', columnspan=3, pady=3)
        # job tag 
        tk.Label(w, text='Optional jobs name tag', font=self.FONT).grid(row=10, column=1,columnspan=3,sticky='we',padx=5)
        self.tag_entry = Pmw.EntryField(w, value='', validate = hf.validateAsciiEmpty) #,
        self.tag_entry.component('entry').configure(justify='left', font=self.FONT, bg='white',width=30, **self.BORDER)
        self.tag_entry.grid(row=11,column=1, columnspan=3, sticky='we', padx=4,pady=4)

        self.win.bind('<Escape>', self.close)
        self.setSuggest()
        self.win.activate()


    def setSuggest(self):
        """ fill the submission with the suggestions"""
        if self.suggest == {}:
            return
        if 'prj' in self.suggest.keys():
            prj = self.suggest.pop('prj')
            self.prj_pull.setvalue(prj)
            self.prj_pull.invoke()
        if 'exp' in self.suggest.keys():
            exp = self.suggest.pop('exp')
            self.exp_pull.setvalue(exp)
            self.exp_pull.invoke()
        if 'tag' in self.suggest.keys():
            tag = self.suggest.pop('tag')
        else:
            tag = 'RESTARTED'
        self.tag_entry.setvalue(tag)
예제 #4
0
class InteractionFilterWidget(rb.RaccoonDefaultWidget, DebugTools.DebugObj,
                              tk.Frame):
    """ provide the interaction filter widget
        with different types:

            HBa
            HBd
            HB
            Metal
            vdW
            Pi-stack
            T-stack
            Generic stack
           
   checkbutton   pulldown     entry    button (remove)
        [x] | | [type..] | [ string ] [ x ]
    """
    def __init__(self,
                 parent,
                 manager,
                 settings={},
                 color=None,
                 debug=False):  #, destroy_cb):
        self.color = '#bbff33'
        self.color = color  # differenciate filter types?
        rb.RaccoonDefaultWidget.__init__(self, parent)
        DebugTools.DebugObj.__init__(self, debug)
        tk.Frame.__init__(self,
                          master=self.parent,
                          relief='raised',
                          bg=color,
                          **self.BORDER)
        self.manager = manager
        self._widgets = [self]

        self.initIcons()
        self.destroy_cb = None  # destroy_cb
        self.eventManager = self.manager.eventManager
        #self.eventManager = eventManager
        #self.event = RaccoonEvents.FilterSetSelection()

        self.settings = settings
        self.build()
        self.setfilter()

        # hack to have mouse wheel to work all the time
        for w in self._widgets:
            w.bind("<Button-4>", self.manager.mousescroll)
            w.bind("<Button-5>", self.manager.mousescroll)
            if hasattr(w, 'components'):
                for c in w.components():
                    w.component(c).bind("<Button-4>", self.manager.mousescroll)
                    w.component(c).bind("<Button-5>", self.manager.mousescroll)

    def build(self):
        """ build the widgets"""
        entry_width = 10

        # types strings
        self._notype = '< select type >'
        self.stringToType = {
            'HB donor': 'hbd',
            'HB acceptor': 'hba',
            'HB any': 'hb',
            'Metal coord': 'metal',
            'vdW contact': 'vdw',
            'Pi-stacking': 'ppi',  # XXX check this
            'T-stacking': 'tpi',  # XXX check this
            'Any stacking': 'pi',  # XXX check this
        }
        self.typeToString = {}
        for k, v in self.stringToType.items():
            self.typeToString[v] = k

        # active checkbutton
        self.active_var = tk.BooleanVar(value=False)
        self.active = tk.Checkbutton(self,
                                     variable=self.active_var,
                                     bg=self.color,
                                     command=self.trigger)
        #self.active.pack(side='left', anchor='w', expand=0, fill='none')

        # interaction type
        self.typeChoice = OptionMenuFix(
            self,
            menubutton_font=self.FONT,
            menubutton_bg=self.color,
            menu_font=self.FONT,
            menubutton_width=15,
            menubutton_bd=1,
            menubutton_highlightbackground='black',
            menubutton_borderwidth=1,
            menubutton_highlightcolor='black',
            menubutton_highlightthickness=1,
            menubutton_height=1,
            command=self.trigger,  # self.typeValidator, # self.trigger,
            items=sorted(self.stringToType.keys()))
        self.typeChoice.setvalue(self._notype)
        self.typeChoice.pack(side='left',
                             anchor='w',
                             expand=1,
                             fill='x',
                             padx=3,
                             pady=1)
        self._widgets.append(self.typeChoice)

        # strings
        f = tk.Frame(
            self)  # nested frames to have a decent alignment (Tk sucks(TM) )
        ef = tk.Frame(f)
        # chain
        self.chain = Pmw.EntryField(
            ef,
            entry_font=self.FONT,
            labelpos='n',
            label_font=self.FONT,
            label_text='chain',
            hull_bg=self.color,
            entry_width=4,
            entry_justify='center',
            entry_bd=1,
            entry_highlightbackground='black',
            entry_borderwidth=1,
            entry_highlightcolor='black',
            entry_highlightthickness=1,
        )
        self.chain.pack(side='left', anchor='n', expand=0, fill='x', padx=3)
        self.chain.component('entry').bind('<Return>', self.return_cb)
        self.chain.component('entry').bind('<Leave>', self.focusLeave_cb)
        self._widgets.append(self.chain)

        # residue
        self.residue = Pmw.EntryField(
            ef,
            entry_font=self.FONT,
            labelpos='n',
            label_font=self.FONT,
            label_text='residue',
            hull_bg=self.color,
            entry_width=entry_width,
            entry_justify='center',
            entry_highlightbackground='black',
            entry_borderwidth=1,
            entry_highlightcolor='black',
            entry_highlightthickness=1,
        )
        self.residue.pack(side='left', anchor='n', expand=1, fill='x', padx=3)
        self.residue.component('entry').bind('<Return>', self.return_cb)
        self.residue.component('entry').bind('<Leave>', self.focusLeave_cb)
        self._widgets.append(self.residue)

        # atom
        self.atom = Pmw.EntryField(
            ef,
            entry_font=self.FONT,
            labelpos='n',
            label_font=self.FONT,
            label_text='atom',
            hull_bg=self.color,
            entry_width=entry_width,
            entry_justify='center',
            entry_highlightbackground='black',
            entry_borderwidth=1,
            entry_highlightcolor='black',
            entry_highlightthickness=1,
        )
        self.atom.pack(side='left', anchor='n', expand=1, fill='x', padx=3)
        self.atom.component('entry').bind('<Return>', self.return_cb)
        self._widgets.append(self.atom)

        s = tk.Frame(f, height=15)
        s.pack(side='bottom', anchor='w', expand=1, fill='both')

        ef.pack(side='top', anchor='w', expand=1, fill='x', padx=3)
        f.pack(side='left', anchor='w', expand=1, fill='both')

        self._widgets.append(s)
        self._widgets.append(ef)
        self._widgets.append(f)

        # wanted/not wanted
        self.wanted = True
        self.wantedButton = tk.Button(self,
                                      font=self.FONTbold,
                                      image=self._ICON_filtoff,
                                      relief='flat')
        selmenu = [
            None,
            ['wanted', 'normal', self.setPositive],
            ['not wanted', 'normal', self.setNegative],
            ['disable', 'normal', self.setOff],
        ]
        menu = rb.RacMenu(self.wantedButton, selmenu, placement='under')
        self.wantedButton.pack(side='left',
                               anchor='w',
                               expand=0,
                               fill='none',
                               padx=1,
                               pady=1)
        self._widgets.append(self.wantedButton)

        # destroy button
        self.destruction = tk.Button(
            self,
            text="X",
            image=self._ICON_del,
            command=self.destroy,
            bg=self.color,
            relief='flat')  #,width=22) #, **self.BORDER)
        self.destruction.pack(side='left', anchor='w', expand=0, fill='none')
        self._widgets.append(self.destruction)

    def initIcons(self):
        """ initialize the icons for the interface"""
        icon_path = CADD.Raccoon2.ICONPATH

        f = icon_path + os.sep + 'removeSmall.png'
        f = icon_path + os.sep + 'removeSmallbw.png'
        self._ICON_del = ImageTk.PhotoImage(Image.open(f))

        f = icon_path + os.sep + 'filt_positive.png'
        f = icon_path + os.sep + 'filt_positiveLight.png'
        self._ICON_filtpos = ImageTk.PhotoImage(Image.open(f))

        f = icon_path + os.sep + 'filt_negativeLight.png'
        self._ICON_filtneg = ImageTk.PhotoImage(Image.open(f))

        f = icon_path + os.sep + 'filt_inactiveLight.png'
        self._ICON_filtoff = ImageTk.PhotoImage(Image.open(f))

    def setPositive(self, event=None):
        """ set the interaction to be wanted"""
        self.wanted = True
        self.wantedButton.configure(image=self._ICON_filtpos, text='A')
        self.enable()
        #self.trigger()

    def setNegative(self, event=None):
        """ set the interaction to be not wanted"""
        self.wanted = False
        self.wantedButton.configure(image=self._ICON_filtneg, text='R')
        self.enable()
        #self.trigger()

    def setOff(self, event=None):
        """ turn off the filter"""
        self.wantedButton.configure(image=self._ICON_filtoff, text='R')
        current = self.active_var.get()
        self.active_var.set(False)
        # the filter was active, it has been disabled
        # so we need to send event for filterEngine to
        # be triggered
        if not self.active_var.get() == current:
            self.sendEvent()

    def return_cb(self, event=None):
        """ function called when return is pressed
            in the text fields
        """
        if self.wanted == True:
            self.setPositive()
        else:
            self.setNegative()

    def focusLeave_cb(self, event=None):
        """ trigger status check for entries
            when they loose focus
            Important when the filter has been alread
            activated, then the user changes the text in the
            field
        """
        if not self.isActive():
            return
        self.entryValidator(quiet=False)

    def isActive(self, event=None):
        """ return if the filter is active"""
        return self.active_var.get()

    def disable(self, event=None):
        """ disable the filter"""
        self.active_var.set(False)

    def enable(self, event=None, quiet=True):
        """ enable the filter"""
        self.active_var.set(True)
        self.trigger(quiet=quiet)

    def entryValidator(self, string=None, quiet=True):
        """ validate the text entry field
        """
        #if string == None:
        #    string = self.entry.getvalue()
        chain = self.chain.getvalue().strip()
        res = self.residue.getvalue().strip()
        atom = self.atom.getvalue().strip()
        if not chain and not res and not atom:
            self.setOff()
            if not quiet:
                t = 'Interaction specification not valid'
                i = 'error'
                m = (
                    'The interaction must be defined by typing at '
                    'least a chain, residue or atom string.\n'
                    'Single character "?" and multi-character "*" wildcards can be used.'
                )
                tmb.showinfo(parent=self, title=t, icon=i, message=m)
            return False
        return True

    def typeValidator(self, string=None, quiet=False):
        """ validate type selection """
        _type = self.typeChoice.getvalue()
        if _type == self._notype:
            if not quiet:
                t = 'Filter type error'
                i = 'warning'
                m = ('An interaction type must be selected')
                tmb.showinfo(parent=self, title=t, icon=i, message=m)
            self.setOff()
            return False
        return True

    def isvalid(self, quiet=True):
        """return if the entry is valid"""
        typeCheck = self.typeValidator(quiet=quiet)
        if not typeCheck:  # or not self.isActive():
            return
        if not self.isActive():
            return
        entryCheck = self.entryValidator(quiet=quiet)
        return (typeCheck and entryCheck)

    def trigger(self, event=None, quiet=False):
        """ command executed when the filter is activated"""
        #curr_state = self.isActive() # active_var.get()
        if not self.isvalid(quiet=quiet):
            return
        self.active_var.set(True)
        self.sendEvent()

    def sendEvent(self):
        """ trigger the event"""
        e = RaccoonEvents.FilterInteractionEvent()
        self.eventManager.dispatchEvent(e)

    def getType(self):
        """ return interaction type"""
        return self.stringToType[self.typeChoice.getvalue()]

    def getPattern(self):
        """ return interaction text pattern"""
        c = self.chain.getvalue().strip()
        r = self.residue.getvalue().strip()
        a = self.atom.getvalue().strip()
        if c == "": c = "*"
        if r == "": r = "*"
        if a == "": a = "*"
        return "%s:%s:%s" % (c, r, a)

    def setfilter(self, settings={}):
        """ initialize filter with requested values"""
        if settings == {}:
            settings == self.settings
        if settings == {}:
            return
        t = self.settings['type']
        t = self.typeToString[t]
        e = self.settings['patter']
        self.typeChoice.setvalue(t)
        self.entry.setvalue(e)
        if self.isvalid(): self.active_var.set(True)
        # FIXME set this to active?
        #return { 'type' : t, 'pattern' : e }

    def destroy(self, event=None):
        """ remove itself from the list of filters
            and unpack the widget
        """
        t = 'Delete filter'
        i = 'info'
        m = ('Remove this filter?')
        if self.isvalid():
            if not tmb.askyesno(parent=self, title=t, message=m, icon=i):
                return
        self.destroy_cb()