~ubuntu-branches/ubuntu/vivid/dogtail/vivid-proposed

« back to all changes in this revision

Viewing changes to examples/recorder.py

  • Committer: Bazaar Package Importer
  • Author(s): Jose Carlos Garcia Sogo
  • Date: 2006-12-16 10:57:30 UTC
  • mfrom: (1.2.1 upstream) (3.1.1 edgy)
  • Revision ID: james.westby@ubuntu.com-20061216105730-utt6mcidfssawo7j
Tags: 0.6.1-3
pyhton-at-spi has to be added as dependency (Closes: #402752)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# Dogtail demo script
3
 
__author__ = 'David Malcolm <dmalcolm@redhat.com>'
4
 
 
5
 
# Event recorder.
6
 
# FIXME: under construction
7
 
# The event handler callback seems to trap and lose Ctrl-C so you need to be ready to be
8
 
# kill the python process via some other means
9
 
 
10
 
import atspi
11
 
import dogtail.tree
12
 
 
13
 
def logEvent(event):
14
 
    source = event.source
15
 
    if isinstance(source, atspi.Accessible):
16
 
        sourceStr = " source:%s"%(str(dogtail.tree.Node(source)))
17
 
    else:
18
 
        sourceStr = ""
19
 
    print "Got event: %s%s"%(event.type, sourceStr)
20
 
 
21
 
 
22
 
class Writer:
23
 
    """
24
 
    Abstract base class for writing out events
25
 
    """
26
 
    def recordClick(self, node):
27
 
        raise NotImplementedError
28
 
    
29
 
class ScriptWriter(Writer):
30
 
    """
31
 
    Abstract Writer subclass which writes out Python scripts
32
 
    """
33
 
    pass
34
 
 
35
 
class OOScriptWriter(ScriptWriter):
36
 
    """
37
 
    Concrete Writer subclass which writes out Python scripts in an object-oriented
38
 
    style
39
 
    """
40
 
    def __init__(self):
41
 
        # maintain a dict from variable names to search paths
42
 
        self.variables = {}
43
 
        self.debug = False
44
 
        self.debugVariables = False
45
 
 
46
 
    def generateVariableName(self, predicate):
47
 
        # Ensure uniqueness
48
 
        result = predicate.makeScriptVariableName()
49
 
        if result in self.variables:
50
 
            # This variable name is already in use; need to append a number:
51
 
            index = 1
52
 
            while result+str(index) in self.variables:
53
 
                index+=1
54
 
            return result+str(index)
55
 
        else:
56
 
            return result
57
 
 
58
 
    def printVariables(self):
59
 
        # debug hook
60
 
        print "variables:"
61
 
        for (varName, varAbsPath) in self.variables.iteritems():
62
 
            print "varName:%s -> absPath:%s"%(varName, varAbsPath)        
63
 
 
64
 
    def generateAbsSearchPathMethodCall(self, absSearchPath):
65
 
        """
66
 
        Generates a method call that identifies the absolute search path,
67
 
        optimizing away prefixes where possible with variable names.
68
 
        """
69
 
        # We optimize away the longest common absolute path prefix, i.e. the
70
 
        # shortest relative path suffix:
71
 
        if self.debug:
72
 
            print "*******************"
73
 
            print "generateAbsSearchPathMethodCall for %s"%absSearchPath
74
 
            self.printVariables()
75
 
            
76
 
        shortestRelativePath = None
77
 
        for (varName, varAbsPath) in self.variables.iteritems():
78
 
            relPath = varAbsPath.getRelativePath(absSearchPath)
79
 
            if relPath:
80
 
                if shortestRelativePath:
81
 
                    if relPath.length() < shortestRelativePath[2].length():
82
 
                        shortestRelativePath = (varName, varAbsPath, relPath)
83
 
                else:
84
 
                    shortestRelativePath = (varName, varAbsPath, relPath)
85
 
 
86
 
        if self.debug:
87
 
            if shortestRelativePath:
88
 
                (varName, varAbsPath, relPath) = shortestRelativePath
89
 
                print "shortestRelativePath: (%s, %s, %s)"%(varName, varAbsPath, relPath)
90
 
            else:
91
 
                print "shortestRelativePath: None"
92
 
            print "*******************"
93
 
 
94
 
        if shortestRelativePath:
95
 
            (varName, varAbsPath, relPath) = shortestRelativePath
96
 
            return varName+relPath.makeScriptMethodCall()
97
 
        else:
98
 
            # Have to specify it as an absolute path:
99
 
            return "root"+absSearchPath.makeScriptMethodCall()
100
 
    
101
 
    def recordClick(self, node):
102
 
        searchPath = node.getAbsoluteSearchPath()
103
 
 
104
 
        if self.debug:
105
 
            print "----------------------------------"
106
 
            print "click on %s"%searchPath
107
 
            print "Full script would be: root%s"%searchPath.makeScriptMethodCall()
108
 
            
109
 
        # Generate variables for nodes likely to be referred to often (application, window)
110
 
        # FIXME: make this smarter?
111
 
        for i in [1,2,3]:
112
 
            if i<searchPath.length():
113
 
 
114
 
                prefixPath = searchPath.getPrefix(i)
115
 
 
116
 
                if self.debugVariables:
117
 
                    print "Considering: %s"%prefixPath
118
 
 
119
 
                if not prefixPath in self.variables.values():
120
 
                    if self.debugVariables:
121
 
                        print "It is not yet a variable"
122
 
                        self.printVariables()
123
 
                        
124
 
                    varName = prefixPath.getPredicate(i-1).makeScriptVariableName()
125
 
                    print varName+" = "+self.generateAbsSearchPathMethodCall(prefixPath)
126
 
                    self.variables[varName]=prefixPath
127
 
                else:
128
 
                    if self.debugVariables:
129
 
                        print "It is already a variable"
130
 
 
131
 
        result = self.generateAbsSearchPathMethodCall(searchPath)
132
 
        result +=".click()"
133
 
 
134
 
        if self.debug:
135
 
            print "----------------------------------"
136
 
 
137
 
        print result
138
 
 
139
 
class ProceduralScriptWriter(ScriptWriter):
140
 
    """
141
 
    Concrete Writer subclass which writes out Python scripts in a procedural
142
 
    style
143
 
    """
144
 
    def recordClick(self, node):
145
 
        # FIXME: not yet written
146
 
        raise NotImplementedError
147
 
 
148
 
# Singleton EventRecorder
149
 
global recorder
150
 
 
151
 
# Test event recording class; under construction
152
 
class EventRecorder:
153
 
    def __init__(self):
154
 
        self.writer = OOScriptWriter()
155
 
        self.__registerEvents()
156
 
        self.lastFocussedNode = None
157
 
        self.absoluteNodePaths = True
158
 
 
159
 
    def __registerEvents(self):
160
 
        # Only specific events are recorded:
161
 
 
162
 
        # Focus events:
163
 
        atspi.EventListener(marshalOnFocus, ["focus:"]) 
164
 
 
165
 
        # Mouse button-1 clicks:
166
 
        atspi.EventListener(marshalOnMouseClick, ["mouse:button:1p"])
167
 
 
168
 
        # Window creation:
169
 
        atspi.EventListener(marshalOnWindowCreate, ["window:create"])
170
 
 
171
 
    def onFocus(self, event): 
172
 
        # logEvent(event)
173
 
        sourceNode = dogtail.tree.Node(event.source)
174
 
        #print "Focus on %s"%str(sourceNode)
175
 
        #path = sourceNode.getAbsoluteSourcePath()
176
 
        #print "SourcePath: %s"%path
177
 
        #print "    Script: %s"%path.make
178
 
        self.lastFocussedNode = sourceNode
179
 
 
180
 
    def onMouseClick(self, event): 
181
 
        # logEvent(event)
182
 
        sourceNode = dogtail.tree.Node(event.source)
183
 
        # sourceNode seems to always be set to "main" (other events come through on all objects)
184
 
        # so we pretend the click was on the last node to be focussed
185
 
        # print "Click on %s"%str(self.getLogStringForNode(self.lastFocussedNode))
186
 
        if self.lastFocussedNode!=None:
187
 
            self.writer.recordClick(self.lastFocussedNode)
188
 
 
189
 
    def onWindowCreate(self, event):
190
 
        # logEvent(event)
191
 
        sourceNode = dogtail.tree.Node(event.source)
192
 
        # print "Window creation: %s"%str(sourceNode)
193
 
 
194
 
    def getLogStringForNode(self, node):
195
 
        if self.absoluteNodePaths:
196
 
            return node.getAbsoluteSearchPath()
197
 
        else:
198
 
            return node
199
 
    
200
 
# Under construction.  These ought to be methods, but am having Python assertion
201
 
# failures in refcounting when trying to hook them up using lambda expressions; grrr...
202
 
def marshalOnFocus(event): 
203
 
    recorder.onFocus(event)
204
 
 
205
 
def marshalOnMouseClick(event):
206
 
    recorder.onMouseClick(event)
207
 
 
208
 
def marshalOnWindowCreate(event): 
209
 
    recorder.onWindowCreate(event)
210
 
 
211
 
recorder = EventRecorder()
212
 
#recorder.writer.debug = True
213
 
#recorder.writer.debugVariables = True
214
 
atspi.event_main()