GatoFile.py :  » Development » Leo » Leo-4.7.1-final » leo » extensions » Gato » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Leo 
Leo » Leo 4.7.1 final » leo » extensions » Gato » GatoFile.py
#!/usr/bin/env python2.3
################################################################################
#
#       This file is part of Gato (Graph Animation Toolbox) 
#
#  file:   GatoFile.py
#  author: Achim Gaedke (achim.gaedke@zpr.uni-koeln.de)
#
#       Copyright (C) 1998-2005, Alexander Schliep, Winfried Hochstaettler and 
#       Copyright 1998-2001 ZAIK/ZPR, Universitaet zu Koeln
#                                   
#       Contact: schliep@molgen.mpg.de, wh@zpr.uni-koeln.de             
#       Information: http://gato.sf.net
#
#       This library is free software; you can redistribute it and/or
#       modify it under the terms of the GNU Library General Public
#       License as published by the Free Software Foundation; either
#       version 2 of the License, or (at your option) any later version.
#
#       This library is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#       Library General Public License for more details.
#
#       You should have received a copy of the GNU Library General Public
#       License along with this library; if not, write to the Free
#       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#       This file is version $Revision: 1.1 $ 
#                       from $Date: 2007/10/04 14:36:39 $
#             last change by $Author: edream $.
#
################################################################################
import sys
import os
import types
import codecs
import StringIO
import urllib2
import xml.dom.minidom
import Gato
import Graph
import GraphUtil
import Tkinter
import TreeWidget
import TextTreeWidget
import ScrolledText

# code handling:
# the data object model module is unicode
# xml*Element functions return iso-8859-1 strings
# tkinter does not like python unicode, it gets iso-8859-1 strings
# file data are encoded to iso-8859-1

# xmlDecode(unicode) returns iso char string
(_isoEncoder,_isoDecoder,_isoStreamReader,_isoStreamWriter)=codecs.lookup("iso-8859-1")
xmlDecode=lambda x:_isoEncoder(x)[0]
# xmlEnocde(iso_char_string) returns unicode
xmlEncode=lambda x:_isoDecoder(x)[0]
# object that encodes stream data from unicode to iso-8859-1
xmlEncodedStream=_isoStreamWriter

class FileException(Exception):
    """
    is the subclass for all file and xml related things that can go wrong in this module
    """
    def __init__(self, reason):
        """
        takes the reason or explanation as argument
        """
        self.reason=reason
        
class GatoStorageCache:
    """
    singleton list for all accessed/used/cached storage locations
    """
    pass
    
class GatoStorageLocation:
    """
    bundle of common functions for file load/save/selection
    These functions act on the level of graphs and algorithms.
    they propagate the open and save calls to the different file implementations
    """
    
    def __init__(self,fileName=None):
        """
        opens the file and prepares the access
        """
        self.fileName=fileName
        
    def chooseLocation(self,accessMode="rw"):
        """
        opens a suitable dialog to choose a possible location for reading/writing gato data
        """
        
    def __repr__(self):
        """
        a short representation of the instance
        """
        return "<%s: %s>"%(self.__class__.__name__,self.fileName)
        
    def __str__(self):
        """
        should display the name in human understandable manner
        """
        return self.fileName
        
    def readGraph(self,whichGraph=None):
        """
        returns a Graph object
        """
        pass
        
    def readAlgortihm(self, whichAlgorithm=None):
        """
        returns an Algorithm object
        """
        pass
        
    def writeGraph(self, Graph, whichGraph=None):
        """
        puts a graph to the collection of graphs
        """
        pass
        
    def writeAlgorithm(self, Algorithm, whichAlgorithm=None):
        """
        puts a graph to the collection of algorithms
        """
        pass
        
class GatoStorageLocationTest:
    """
    some tests for GatoStorageLocation
    """
    def __init__(self):
        l=GatoStorageLocation("bla")
        print "human readable: %s, python representation %s"%(l,repr(l))
        
        
class GatoDirBranch(TreeWidget.DirBranch):
    """
    """
    def updateChildList(self):
        """
        create/update child list suitable for gato
        """
        oldChildren=self.children
        self.children=[]
        entries=[]
        try:
            entries=os.listdir(self.path)
        except OSError:
            pass
        entries.sort()
        oldEntries=map(lambda c:c.name,oldChildren)
        for entry in entries:
            if entry in oldEntries:
                self.children.append(oldChildren[oldEntries.index(entry)])
            else:
                entrypath=os.path.join(self.path,entry)
                if os.path.isdir(entrypath):
                    self.children.append(GatoDirBranch(parent=self,name=entry))
                elif os.path.isfile(entrypath):
                    # select suitable leaf
                    if entry[-5:]==".gato":
                        self.children.append(GatoFileBranch(parent=self,name=entry))
                    elif entry[-4:]==".xml":
                        self.children.append(xmlGatoFileBranch(parent=self,name=entry))
                    elif entry[-4:]==".alg" and os.path.isfile(entrypath[:-4]+".pro"):
                        self.children.append(algLeaf(parent=self,name=entry))
                    elif entry[-4:]==".cat":
                        self.children.append(catLeaf(parent=self,name=entry))
                        
class GatoFileBranch(TreeWidget.xmlFileBranch):
    """
    ToDo: supports xml files with gato root section
    """
    pass
    
class xmlGatoFileBranch(TreeWidget.xmlFileBranch):
    """
    ToDo supports xml files with gato sections inside
    """
    pass
    
class algLeaf(TreeWidget.Leaf):
    """
    old algortithm file
    """
    def __init__(self,parent=None,name=None):
        TreeWidget.Leaf.__init__(self,parent=parent, name=name)
        self.selectable=1
        
class catLeaf(TreeWidget.Leaf):
    """
    old graph file
    """
    def __init__(self,parent=None,name=None):
        TreeWidget.Leaf.__init__(self,parent=parent, name=name)
        self.selectable=1
        
class GatoTree(TreeWidget.scrolledTree):
    """
    """
    def __init__(self,master):
        TreeWidget.scrolledTree.__init__(self,master)
        self.root=GatoDirBranch(parent=self,name="/",anchor=(1,1))
        self.root.display()
        # show current work directory
        current=os.getcwd()
        currentList=[]
        while current!=self.root.name:
            (current,piece)=os.path.split(current)
            currentList.insert(0,piece)
            # expand all branches on the way
        thisNode=self.root
        thisNode.expand()
        for piece in currentList:
            thisNode=filter(lambda x:x.name==piece,thisNode.children)[0]
            thisNode.expand()
            
        (Nx0,Ny0,Nx1,Ny1)=thisNode.getBoundingBox()
        (Cx0,Cy0,Cx1,Cy1)=self.bbox(Tkinter.ALL)
        self.yview(Tkinter.MOVETO,float(Ny0)/float(Cy1-Cy0))
        
        
class WorkInProgress(Tkinter.Tk):
    """
    my development and test class
    """
    
    def __init__(self):
        Tkinter.Tk.__init__(self)
        self.tree=GatoTree(self)
        self.tree.pack(expand=1,fill=Tkinter.BOTH)
        
    def run(self):
        self.mainloop()
        
        
class xmlAlgorithmElement:

    algorithmElementName="algorithm"
    sourceElementName="text"
    prologElementName="prolog"
    aboutElementName="about"
    
    def __init__(self,dom):
        # test for right tag
        if dom.tagName!=self.algorithmElementName:
            raise FileException("Wrong element name: %s, %s expected"
                                %(dom.tagName,self.algorithmElementName))
        self.domElement=dom
        
    def setAlgorithmFromALGFile(self,fileName):
        """
        writes algorithm data to xml sections
        """
        algorithm=Gato.Algorithm()
        algorithm.Open(fileName)
        self.setAlgorithm(algorithm.source)
        self.setAbout(algorithm.About())
        PrologFileName=fileName[:-4]+'.pro'
        if os.access(PrologFileName,os.R_OK):
            self.setProlog(file(PrologFileName).read())
        else:
            print "Warning: could not read prolog file %s"%PrologFileName
            
    def setProlog(self,text):
        """
        creates/repaces the prolog section
        """
        #create new one
        newProlog=None
        if self.domElement.ownerDocument:
            newProlog=self.domElement.ownerDocument.createElement(self.prologElementName)
            newProlog.appendChild(self.domElement.ownerDocument.createCDATASection(
                xmlEncode(text)
                ))
        else:
            newProlog=xml.dom.Element(self.prologElementName)
            newProlog.appendChild(xml.dom.CDATASection(xmlEncode(text)))
        existingProlog=self.domElement.getElementsByTagName(self.prologElementName)
        if len(existingProlog)>0:
            # replace existing prolog
            self.domElement.repaceChild(newProlog,existingProlog[0])
        else:
            self.domElement.appendChild(newProlog)
            
    def setAlgorithm(self,text):
        """
        creates/repaces the algorithm section
        """
        #create new one
        newAlgorithm=None
        if self.domElement.ownerDocument:
            newAlgorithm=self.domElement.ownerDocument.createElement(self.sourceElementName)
            newAlgorithm.appendChild(self.domElement.ownerDocument.createCDATASection(
                xmlEncode(text)
                ))
        else:
            newAlgorithm=xml.dom.Element(self.sourceElementName)
            newAlgorithm.appendChild(xml.dom.CDATASection(xmlEncode(text)))
        existingAlgorithm=self.domElement.getElementsByTagName(self.sourceElementName)
        if len(existingAlgorithm)>0:
            # replace existing algorithm
            self.domElement.repaceChild(newAlgorithm,existingAlgorithm[0])
        else:
            self.domElement.appendChild(newAlgorithm)
            
    def setAbout(self,text):
        """
        ToDo
        """
        pass
        
    def getTextFromElement(self,tagName):
        "returns the text of specified tag"
        requestedElements=self.domElement.getElementsByTagName(tagName)
        if len(requestedElements)!=1:
            return None
        requestedElement=requestedElements[0]
        text=""
        for e in requestedElement.childNodes:
            if (e.nodeType==xml.dom.minidom.Node.TEXT_NODE or
                e.nodeType==xml.dom.minidom.Node.CDATA_SECTION_NODE):
                text+=e.data
        return xmlDecode(text)
        
    def getText(self):
        t=self.getTextFromElement(self.sourceElementName)
        if t:
            return t
        else:
            return ""
            
    def getAboutAsString(self):
        requestedElements=filter(lambda e:e.nodeType==xml.dom.Node.ELEMENT_NODE and \
                                 e.tagName==self.aboutElementName,
                                 self.domElement.childNodes)
        if len(requestedElements)<1:
            return None
        else:
            return requestedElements[0].toxml()
            
    def getTextAsFile(self):
        """
        creates a StringIO Object from file
        """
        return StringIO.StringIO(self.getText())
        
    def getProlog(self):
        "returns the prolog"
        p=self.getTextFromElement(self.prologElementName)
        if p:
            return p
        else:
            return ""
            
    def getPrologAsFile(self):
        return StringIO.StringIO(self.getProlog())
        
    def getName(self):
        return xmlDecode(self.domElement.getAttribute("name"))
        
    def setName(self,name):
        self.domElement.setAttribute("name",xmlEncode(name))
        
class xmlGraphElement:

    graphElementName="graph"
    
    def __init__(self,graph,name=None):
        """
        called with a dom element: grants access to Graph
        called with a graph and a name string: creates the dom structure from graph
        """
        # test for right tag
        if issubclass(graph.__class__,xml.dom.minidom.Element):
            # we were called with a dom element as argument
            if graph.tagName!=self.graphElementName:
                raise FileException("Wrong element name: %s, %s expected"
                                    %(graph.tagName,self.graphElementName))
            self.domElement=graph
        elif issubclass(graph.__class__,Graph.Graph) and type(name) in types.StringTypes:
            # initialise dom element
            self.domElement=xml.dom.minidom.Element(xmlGraphElement.graphElementName)
            self.setName(name)
            self.setGraph(graph)
        else:
            raise FileException("wrong arguments provided")
            
    def getAboutAsString(self):
        requestedElements=filter(lambda e:e.nodeType==xml.dom.Node.ELEMENT_NODE and e.tagName=="about",
                                 self.domElement.childNodes)
        if len(requestedElements)<1:
            return None
        else:
            return requestedElements[0].toxml()
            
    def getGraph(self):
        """
        returns the Graph object constructed  from this dom element
        """
        return GraphUtil.OpenCATBoxGraph(self.getGraphAsStringIO())
        
    def getGraphAsStringIO(self):
        text=StringIO.StringIO()
        for e in self.domElement.childNodes:
            if (e.nodeType==xml.dom.minidom.Node.TEXT_NODE or
                e.nodeType==xml.dom.minidom.Node.CDATA_SECTION_NODE):
                text.write(xmlDecode(e.data))
        text.seek(0)
        return text
        
    def setGraph(self,graph):
        # we were called with a Graph and a name as arguments
        data=StringIO.StringIO()
        GraphUtil.SaveCATBoxGraph(graph,data)
        #remove all other text nodes
        textNodes=filter(lambda e:e.nodeType==xml.dom.minidom.Node.TEXT_NODE or
                         e.nodeType==xml.dom.minidom.Node.CDATA_SECTION_NODE,
                         self.domElement.childNodes)
        map(self.domElement.removeChild,textNodes)
        # create necessary dom elements
        # maybe xml.dom.minidom.Text is ok, too
        newCDATASection=None
        if self.domElement.ownerDocument:
            newCDATASection=self.domElement.ownerDocument.createCDATASection(
                xmlEncode(data.getvalue())
                )
        else:
            newCDATASection=xml.dom.minidom.CDATASection(xmlEncode(data.getvalue()))
        self.domElement.appendChild(newCDATASection)
        
    def setGraphFromCATFile(self,GraphFile):
        """
        creates a graph object from .cat file and sets it
        this detour assures an actual graph format
        """
        self.setGraph(GraphUtil.OpenCATBoxGraph(GraphFile))
        
    def getName(self):
        return xmlDecode(self.domElement.getAttribute("name"))
        
    def setName(self,name):
        self.domElement.setAttribute("name",xmlEncode(name))
        
class xmlGatoElement:
    """
    is an access and modification interface to the gato dom structure 
    """
    
    gatoElementName="gato"
    
    def __init__(self,_domElement):
        """
        creates the access and modification interface
        """
        # test for right tag
        if _domElement.tagName!=self.gatoElementName:
            raise FileException("Wrong element name: %s, %s expected"
                            %(_domElement.tagName,self.gatoElementName))
        self.domElement=_domElement
        
    def createGraphElement(self,name=None):
        """
        creates a new graph Element
        """
        newDOMElement=None
        if self.domElement.ownerDocument:
            newDOMElement=self.domElement.ownerDocument.createElement(
                xmlGraphElement.graphElementName)
        else:
            newDOMElement=xml.dom.Element(xmlGraphElement.graphElementName)
        newElement=xmlGraphElement(newDOMElement)
        if name is not None:
            newElement.setName(name)
        return newElement
        
    def createAlgorithmElement(self,name=None):
        """
        creates a new algorithm element
        """
        newDOMElement=None
        if self.domElement.ownerDocument:
            newDOMElement=self.domElement.ownerDocument.createElement(
                xmlAlgorithmElement.algorithmElementName)
        else:
            newDOMElement=xml.dom.Element(xmlAlgorithmElement.algorithmElementName)
        newElement=xmlAlgorithmElement(newDOMElement)
        if name is not None:
            newElement.setName(name)
        return newElement
        
    def setName(self,name):
        """
        sets the name attribute for this element
        """
        self.domElement.setAttribute("name",xmlEncode(name))
        
    def getName(self,name):
        """
        gets the name of this element, if unset an empty string
        """
        return xmlDecode(self.domElement.getAttribute("name"))
        
    def getAboutAsString(self):
        requestedElements=filter(lambda e:e.nodeType==xml.dom.Node.ELEMENT_NODE and e.tagName=="about",
                                 self.domElement.childNodes)
        if len(requestedElements)<1:
            return None
        else:
            return requestedElements[0].toxml()
            
    def getGraphElements(self):
        """
        returns all direct child elements with graph's tagName
        """
        return filter(lambda x:(x.nodeType==xml.dom.minidom.Node.ELEMENT_NODE and
                                x.tagName==xmlGraphElement.graphElementName),
                      self.domElement.childNodes)
        
    def getAlgorithmElements(self):
        """
        returns all direct child elements with algorithm's tagName
        """
        return filter(lambda x:(x.nodeType==xml.dom.minidom.Node.ELEMENT_NODE and
                                x.tagName==xmlAlgorithmElement.algorithmElementName),
                      self.domElement.childNodes)
        
    def getGraphNames(self):
        """
        extracts all graph names
        """
        # return a list of name attribute values from graph elements
        return map(lambda x:xmlDecode(x.getAttribute("name")),
                   self.getGraphElements())
        
    def getAlgorithmNames(self):
        """
        extracts all algorithm names
        """
        # return a list of name attribute values from graph elements
        return map(lambda x:xmlDecode(x.getAttribute("name")),
                   self.getAlgorithmElements())
        
    def getGraphByName(self,name):
        """
        gets a xmlGraphElement by its name
        """
        graphs=filter(lambda x:x.getAttribute("name")==name,
                      self.getGraphElements())
        return xmlGraphElement(graphs[0])
        
    def getAlgorithmByName(self,name):
        """
        gets a xmlAlgorithmElement by its name
        """
        graphs=filter(lambda x:x.getAttribute("name")==name,
                      self.getAlgorithmElements())
        return xmlAlgorithmElement(graphs[0])
        
    def getDefaultSelection(self):
        """
        searches for the default selection, e.g.
        only one graph and one algorithm
        """
        defaultSelection={}
        graphs=self.getGraphNames()
        algorithms=self.getAlgorithmNames()
        if len(graphs)<2 and len(algorithms)<2:
            if len(graphs)==1:
                defaultSelection["graph"]=self.getGraphByName(graphs[0])
            if len(algorithms)==1:
                defaultSelection["algorithm"]=self.getAlgorithmByName(algorithms[0])
            return defaultSelection
            
        if self.domElement.hasAttribute("defaultGraph"):
            defaultSelection["graph"]=self.getGraphByName(
                self.domElement.getAttribute("defaultGraph"))
            
        if self.domElement.hasAttribute("defaultAlgorithm"):
            defaultSelection["algorithm"]=self.getAlgorithmByName(
                self.domElement.getAttribute("defaultAlgorithm"))
            
        return defaultSelection
        
    def updateGraphByName(self,graph,name=None):
        """
        appends or replaces a graph, if name not given, the graphs name is taken
        """
        newGraph=None
        newName=None
        if issubclass(graph.__class__,Graph.Graph):
            newGraph=xmlGraphElement(graph,name)
        elif issubclass(graph.__class__,xmlGraphElement):
            newGraph=graph
            if name:
                graph.setName(name)
            else:
                name=graph.getName()
        else:
            raise FileException("argument mismatch!")
            
        graphs=filter(lambda x:x.getAttribute("name")==name,
                      self.getGraphElements())
        if len(graphs):
            # replace graph, more exactly the first one
            self.domElement.replaceChild(newGraph.domElement,graphs[0])
        else:
            # append graph
            self.domElement.appendChild(newGraph.domElement)
            
    def updateAlgorithmByName(self,algorithm,name=None):
        """
        appends or replaces an algorithm
        """
        newAlgorithm=None
        newName=None
        if issubclass(algorithm.__class__,Gato.Algorithm):
            newAlgorithm=xmlAlgorithmElement(algorithm,name)
        elif issubclass(algorithm.__class__,xmlAlgorithmElement):
            newAlgorithm=algorithm
            if name:
                algorithm.setName(name)
            else:
                name=algorithm.getName()
        else:
            raise FileException("argument mismatch!")
            
        algorithms=filter(lambda x:x.getAttribute("name")==name,
                          self.getAlgorithmElements())
        if len(algorithms):
            # replace graph, more exactly the first one
            self.domElement.replaceChild(newAlgorithm.domElement,graphs[0])
        else:
            # append graph
            self.domElement.appendChild(newAlgorithm.domElement)
            
    def removeGraphByName(self,name):
        """
        removes the named graph
        """
        graphs=filter(lambda x:x.getAttribute("name")==name,
                      self.getGraphElements())
        map(self.domElement.removeChild,graphs)
        
    def removeAlgorithmByName(self,name):
        """
        removes the named algorithm
        """
        algorithms=filter(lambda x:x.getAttribute("name")==name,
                          self.getAlgorithmElements())
        map(self.domElement.removeChild,algorithms)
        
class ElementDisplay(Tkinter.Frame):
    """
    displays the selected element
    """
    def __init__(self,master,**config):
        """
        """
        config.update({"width":500, "height":500})
        Tkinter.Frame.__init__(self,master,bg="white",cnf=config)
        self.pack_propagate(0) # keep everything in a rigid frame
        self.displayedWidget=None
        self.displayedNode=None
        
    def clearDisplay(self):
        """
        cleanup and display nothing
        """
        # cleanup radically
        for child in self.children.values():
            child.pack_forget()
            child.destroy()
        self.displayedNode=None
        
    def setDisplay(self,node):
        """
        display node...
        """
        if node is None:
            self.clearDisplay()
            return
        else:
            if self.displayedNode is not None and self.displayedNode==node:
                return #nothing to do
        self.clearDisplay()
        displayedWidget=None
        if node.tagName==xmlGraphElement.graphElementName:
            html_data=xmlGraphElement(node).getAboutAsString()
            displayedWidget=AboutWidget(self,html_data)
            self.displayedNode=node
        elif node.tagName==xmlAlgorithmElement.algorithmElementName:
            displayedWidget=AlgorithmInfoWidget(self,xmlAlgorithmElement(node))
            self.displayedNode=node
        elif node.tagName==xmlGatoElement.gatoElementName:
            html_data=xmlGatoElement(node).getAboutAsString()
            displayedWidget=AboutWidget(self,html_data)
            self.displayedNode=node
        else:
            print "toDo: ",node
            
        if displayedWidget:
            displayedWidget.pack(expand=1,fill=Tkinter.BOTH)
            
            
class AlgorithmInfoWidget(Tkinter.Frame):
    """
    creates an algorithm widget
    """
    
    def __init__(self,master,algorithmElement):
        """
        create it
        """
        Tkinter.Frame.__init__(self,master,highlightthickness=0)
        html_data=algorithmElement.getAboutAsString()
        self.About=AboutWidget(self,html_data)
        self.About.pack(side=Tkinter.TOP,expand=1,fill=Tkinter.BOTH)
        text_data=algorithmElement.getText()
        self.Text=ScrolledText.ScrolledText(self,
                                            background='white', 
                                            wrap='word',
                                            font="Times 10")
        self.Text.insert(Tkinter.END, text_data)
        self.Text.pack(side=Tkinter.TOP,expand=1,fill=Tkinter.BOTH)
        self.Text['state'] = Tkinter.DISABLED 
        
class AboutWidget(ScrolledText.ScrolledText):
    """
    displays html text
    copied and modified from GatoDialogs.py
    Basic class which provides a scrollable area for viewing HTML text
    """
    
    def __init__(self, master, htmlcode):
        ScrolledText.ScrolledText.__init__(self, master,
                                           background='white', 
                                           wrap='word',
                                           font="Times 10",
                                           )
        self.inserthtml(htmlcode)
        
    def Update(self,htmlcode):
        self.inserthtml(htmlcode)
        
    def inserthtml(self, htmlcode):
        if htmlcode is None:
            htmlcode="""<html><body>
            No information avaliable !
            </body></html>
            """
        import formatter
        import GatoDialogs
        self['state'] = Tkinter.NORMAL
        self.delete('0.0', Tkinter.END)
        
        writer = GatoDialogs.HTMLWriter(self, self)
        format = formatter.AbstractFormatter(writer)
        parser = GatoDialogs.MyHTMLParser(format, self)
        parser.feed(htmlcode)
        parser.close()
        
        self['state'] = Tkinter.DISABLED
        
class GatoFileButtonBar(Tkinter.Frame):
    """
    holds the buttons for the node selection dialog
    """
    def __init__(self, master, reporter, cnf={}, **config):
    
        cnf.update(config)
        Tkinter.Frame.__init__(self,master,cnf=cnf)
        self.reporter=reporter
        self.okButton=Tkinter.Button(self,text="Ok",command=lambda e=None :self.reporter("quit"))
        self.okButton.grid(row=0,column=0,sticky=Tkinter.E+Tkinter.W)
        self.cancelButton=Tkinter.Button(self,text="Cancel",command=lambda e=None:self.reporter("cancel"))
        self.cancelButton.grid(row=0,column=1,sticky=Tkinter.E+Tkinter.W)
        self.columnconfigure(0,weight=1)
        self.columnconfigure(1,weight=1)
        
        
class GatoFileStructureWidget(TextTreeWidget.dom_structure_widget):
    """
    customized for .gato files
    """
    
    def __init__(self,master,dom,report_function,**conf):
        """
        report function coordinates the element display
        """
        TextTreeWidget.dom_structure_widget.__init__(self,master,dom,self.report_func,width=30,cnf=conf)
        self.chosenNodes={}
        self.report_to=report_function
        
    def report_func(self,event,*opts):
        """
        reports nodes that are marked aka chosen
        """
        if event=="chosenNode":
            # double click on node, or hit <Return>
            if len(opts)<1 or opts[0] is None:
                return
            node=opts[0]
            # is this a gato element?
            if node.tagName==xmlGatoElement.gatoElementName:
                if self.report_to and not self.report_to(event,node):
                    return
                self.chosenNode(node,xmlGatoElement.gatoElementName)
                # is it a valid graph or algorithm object?
            if self.isGatoMemberElement(node)!=1:
                # nothing to do...
                return
            if node.tagName==xmlAlgorithmElement.algorithmElementName:
                if self.report_to and not self.report_to(event,node):
                    return
                self.chosenNode(node,xmlAlgorithmElement.algorithmElementName)
            elif node.tagName==xmlGraphElement.graphElementName:
                if self.report_to and not self.report_to(event,node):
                    return
                self.chosenNode(node,xmlGraphElement.graphElementName)
        elif event=="selectedNode":
            # selected Node
            if len(opts)<1 or opts[0] is None:
                return
            node=opts[0]
            if self.report_to:
                self.report_to(event, node)
        else:
            print event, opts
            
    def chosenNode(self,node,register):
        """
        mark and save chosen node
        """
        last=self.chosenNodes.get(register)
        if last:
            self.setNodeColor(last,"black")
        if last==node:
            # erase selection
            self.chosenNodes[register]=None
        else:
            # new selection
            self.chosenNodes[register]=node
            self.setNodeColor(node,"red")
            
    def nameNode(self,node):
        """
        chose proper names for node
        """
        if node.nodeType==xml.dom.Node.ELEMENT_NODE:
            myName=xmlDecode(node.tagName)
            if myName==xmlGatoElement.gatoElementName:
                if node.hasAttribute("name"):
                    return "gato: %s"%xmlDecode(node.getAttribute("name"))
                else:
                    return "gato"
            elif myName==xmlGraphElement.graphElementName:
                return "graph: %s"%xmlDecode(node.getAttribute("name"))
            elif myName==xmlAlgorithmElement.algorithmElementName:
                return "algorithm: %s"%xmlDecode(node.getAttribute("name"))
            else:
                return TextTreeWidget.dom_structure_widget.nameNode(self,node)
        else:
            return TextTreeWidget.dom_structure_widget.nameNode(self,node)
            
    def isGatoMemberElement(self,node):
        """
        if this is a subtag of gato, return actual depth
        returns 0, if not in a gato element, or is a gato element itself
        """
        parent=node.parentNode
        if parent:
            if parent.nodeType==xml.dom.Node.DOCUMENT_NODE:
                return 0
            elif parent.nodeType==xml.dom.Node.ELEMENT_NODE and parent.tagName=="gato":
                return 1
            else:
                depth=self.isGatoMemberElement(parent)
                if depth:
                    return depth+1
                else:
                    return 0
        else:
            raise FileException("could not determine, if node is member of gato section")
            
    def isVisible(self,node):
        """
        filter out subsections of graph and algorithm in gato sections
        """
        isMember=self.isGatoMemberElement(node)
        if isMember==0:
            return TextTreeWidget.dom_structure_widget.isVisible(self,node)
        elif isMember>1:
            # hide everything deeper than 1
            return 0
        else:
            # hide everything except graph and algorithm
            if (node.nodeType==xml.dom.Node.ELEMENT_NODE and
                node.tagName in [xmlGraphElement.graphElementName,
                                 xmlAlgorithmElement.algorithmElementName]):
                return 1
            else:
                return 0
                
class GatoDOMDialog(Tkinter.Toplevel):
    """
    contains the xml structure and the display of selected element and some buttons
    opt_choose contains the elements, that may be chosen
    mand_choose contains the elements, that must be choosen
    """
    def __init__(self, master, dom, opt_choose=("algorithm","graph"), mand_choose=(), **config):
        """
        create it
        """
        self.dom=dom
        self.opt_choose=opt_choose
        self.mand_choose=mand_choose
        self.result={} # None in case of canceled dialog, (graphNode, algoNode) in case of selection
        Tkinter.Toplevel.__init__(self,master, cnf=config)
        # the structure widget...
        self.struct_widget=GatoFileStructureWidget(self, self.dom, self.reportFromStructure, font="Times 12")
        self.struct_widget.grid(row=0, column=0, sticky=Tkinter.NSEW)
        # and the element display....
        self.display_widget=ElementDisplay(self,width=400)
        self.display_widget.grid(row=0, column=1, sticky=Tkinter.NSEW)
        # the button bar...
        self.buttons=GatoFileButtonBar(self,self.reportFromButtons)
        self.buttons.grid(row=1, column=0, columnspan=2, sticky=Tkinter.EW)
        self.protocol("WM_DELETE_WINDOW", lambda e=None: self.reportFromButtons("cancel"))
        
    def reportFromStructure(self,event,node):
        """
        coordinates element display
        """
        if event=="selectedNode":
            self.display_widget.setDisplay(node)
        elif event=="chosenNode":
            # should be selected?
            if node and node.nodeType==xml.dom.Node.ELEMENT_NODE and \
               (node.tagName in self.opt_choose or node.tagName in self.mand_choose):
                return 1
                
    def reportFromButtons(self,event):
        """
        gets interesting events from button bar
        """
        if event=="quit":
            # graph
            graph=self.struct_widget.chosenNodes.get(xmlGraphElement.graphElementName)
            if graph:
                self.result[xmlGraphElement.graphElementName]=xmlGraphElement(graph)
            else:
                if xmlGraphElement.graphElementName in self.mand_choose:
                    return
                    # algorithm
            algorithm=self.struct_widget.chosenNodes.get(xmlAlgorithmElement.algorithmElementName)
            if algorithm:
                self.result[xmlAlgorithmElement.algorithmElementName]=xmlAlgorithmElement(algorithm)
            else:
                if xmlAlgorithmElement.algorithmElementName in self.mand_choose:
                    return
                    # gato section
            gato=self.struct_widget.chosenNodes.get(xmlGatoElement.gatoElementName)
            if gato:
                self.result[xmlGatoElement.gatoElementName]=xmlGatoElement(gato)
            else:
                if xmlGatoElement.gatoElementName in self.mand_choose:
                    return
            self.destroy()
            self.quit()
        elif event=="cancel":
            self.result=None
            self.destroy()
            self.quit()
        else:
            raise Exception("unknown event %s"%event)
            
    def run(self):
        """
        runs this dialog
        """
        self.mainloop()
        return self.result
        
class GatoFile:
    """
    encapsulates the dom creation from file
    """
    
    validModes=['r', # expect valid gato file and read this file
                'w', # create new file or overwrite existing file
                ]
    
    def __init__(self,myFile=None, mode='r'):
        """
        open a file and read the dom from it, or provide an empty gato document
        """
        if myFile:
            if mode not in self.validModes:
                raise FileException("mode %c not supported"%mode)
            self.mode=mode
            import types
            
            # test if name or file is given
            if self.mode=='r':
                self.file=None
                self.name=None
                if type(myFile) in types.StringTypes:
                    if os.access(myFile,os.R_OK):
                        self.file=file(myFile,"r")
                        self.name=myFile
                    else:
                        urlRequest=urllib2.Request(myFile)
                        self.file=urllib2.urlopen(urlRequest,"r")
                elif type(myFile)==types.FileType:
                    self.file=myFile
                    
                try:
                    # pull dom out of file
                    self.dom = xml.dom.minidom.parse(self.file)
                except xml.dom.DOMException, e:
                    print e
                    raise FileException(str(e))
                    
            elif self.mode=='w':
                if type(myFile) in types.StringTypes:
                    if os.access(myFile,os.W_OK):
                        self.file=file(myFile,"w")
                        self.name=myFile
                    else:
                        urlRequest=urllib2.Request(myFile)
                        self.file=urllib2.urlopen(urlRequest,"w")
                else:
                    self.file=myFile
                    
                    # create empty document
                self.dom = xml.dom.minidom.Document()
                
        else: #myFile=None
            # without file, but create empty doc, too
            self.dom = xml.dom.minidom.Document()
            # self.dom.appendChild(self.dom.createElement(xmlGatoElement.gatoElementName))
            
    def write(self,_file=None):
        """
        writes the (modified) dom to the file
        """
        # ???? write to right place????
        _thisFile=None
        if _file is not None:
            if type(_file) in types.StringTypes:
                _thisFile=encodedStream(file(_file,"w"))
            elif type(_file)==types.FileType:
                _thisFile=_file
        else:
            _thisFile=self.file
            
        encoding="iso-8859-1"
        _thisFile.write("<?xml version=\"1.0\" encoding=\"%s\" ?>\n"%encoding)
        if self.dom.hasChildNodes():
            for n in self.dom.childNodes:
                n.writexml(xmlEncodedStream(_thisFile))
                
    def getDefaultSelection(self):
        """
        returns the default selected elements
        """
        if (not self.dom.documentElement) or \
               self.dom.documentElement.tagName!=xmlGatoElement.gatoElementName:
            return None
        else:
            return xmlGatoElement(self.dom.documentElement).getDefaultSelection()
            
    def getGatoElements(self):
        """
        returns an xmlGatoElement instance
        """
        return self.dom.getElementsByTagName(xmlGatoElement.gatoElementName)
        
    def appendGatoElement(self,newElement):
        """
        append the element without checking unique name
        """
        if self.dom.hasChildNodes():
            # replace doc root gato node with a more general section
            if self.dom.documentElement.tagName==xmlGatoElement.gatoElementName:
                tmpGatoElement=self.dom.documentElement
                self.dom.replaceChild(self.dom.createElement("xml"),tmpGatoElement)
                self.dom.documentElement.appendChild(tmpGatoElement)
                # append to document element
            self.dom.documentElement.appendChild(newElement.domElement)
        else:
            # start with a gato node as root element
            self.dom.appendChild(newElement.domElement)
            
    def createGatoElement(self,name=None):
        """
        creates a new (opt. unnamed)  Gato element
        """
        newElement=xmlGatoElement(self.dom.createElement(xmlGatoElement.gatoElementName))
        if name is not None:
            newElement.setName(name)
        return newElement
        
    def displaySelectionDialog(self,master):
        """
        runs the dom structure
        """
        w=GatoDOMDialog(master,self.dom)
        return w.run()
        
    def displayGraphSelectionDialog(self,master):
        w=GatoDOMDialog(master,self.dom,to_choose=(('graph',)))
        s=w.run()
        if s:
            return s["graph"]
        else:
            return None
            
    def displayAlgorithmSelectionDialog(self,master):
        w=GatoDOMDialog(master, self.dom,to_choose=(('algorithm',)))
        s=w.run()
        if s:
            return s["algorithm"]
        else:
            return None
            
if __name__=='__main__':
    # some test progs
    WorkInProgress().run()
    
    # old ones
    # f=GatoFile('DFS.gato') # parse an XML file by name
    # f.displayGraphSelectionDialog(Tkinter.Tk())
    
    
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.