Coverage Report - orca.bookmarks

ModuleCoverage %
orca.bookmarks
26%
1
# Orca
2
#
3
# Copyright 2005-2007 Sun Microsystems Inc.
4
#
5
# This library is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU Library General Public
7
# License as published by the Free Software Foundation; either
8
# version 2 of the License, or (at your option) any later version.
9
#
10
# This library is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
# Library General Public License for more details.
14
#
15
# You should have received a copy of the GNU Library General Public
16
# License along with this library; if not, write to the
17
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
# Boston, MA 02111-1307, USA.
19
20 1
"""Provides the default implementation for bookmarks in Orca."""
21
22 1
import pickle
23 1
import os
24
25 1
import speech
26 1
import flat_review
27 1
import settings
28 1
import orca_state
29
30 1
from orca_i18n import _
31 1
from orca_i18n import ngettext  # for ngettext support
32
33 2
class Bookmarks:
34 1
    """Represents a default bookmark handler."""
35 1
    def __init__(self, script):
36 79
        self._script = script
37 79
        self._bookmarks = {} 
38 79
        self._loadBookmarks() 
39 79
        self._currentbookmarkindex = None
40
41 1
    def goToBookmark(self, inputEvent, index=None):
42
        """ Go to the bookmark indexed by inputEvent.hw_code """
43
        # establish the _bookmarks index
44 0
        index = index or inputEvent.hw_code
45
46 0
        try:
47 0
            context = self._script.getFlatReviewContext()
48 0
            context_info = self._bookmarks[index]
49 0
            context.setCurrent(context_info['line'], context_info['zone'], \
50 0
                                context_info['word'], context_info['char'])
51 0
            self._bookmarks[index] = context_info
52 0
        except KeyError:
53 0
            self._script.systemBeep()
54 0
            return
55
56 0
        self._script.flatReviewContext = context
57 0
        self._script._reviewCurrentItem(inputEvent)
58
59
        # update the currentbookmark
60 0
        self._currentbookmarkindex = index
61
62 1
    def addBookmark(self, inputEvent):
63
        """ Add an in-page accessible object bookmark for this key. """
64 0
        context = self._script.getFlatReviewContext()
65 0
        self._bookmarks[inputEvent.hw_code] = self._contextToBookmark(context)
66
67
        # Translators: this announces that a bookmark has been entered.  
68
        # Orca allows users to tell it to remember a particular spot in an 
69
        # application window and provides keystrokes for the user to jump to 
70
        # those spots.  These spots are known as 'bookmarks'. 
71
        #
72 0
        utterances = [_('bookmark entered')]
73 0
        utterances.extend(self._script.speechGenerator.getSpeech( \
74 0
                          context.getCurrentAccessible(), False))
75 0
        speech.speakUtterances(utterances)
76
77 1
    def bookmarkCurrentWhereAmI(self, inputEvent):
78
        """ Report "Where am I" information for this bookmark relative to the 
79
        current pointer location."""
80 0
        try:
81 0
            context = self._bookmarkToContext(self._bookmarks[inputEvent.hw_code])
82 0
        except KeyError:
83 0
            self._script.systemBeep()
84 0
            return   
85
86 0
        obj = context.getCurrentAccessible()    
87 0
        cur_obj = orca_state.locusOfFocus
88
89
        # Are they the same object?
90 0
        if self._script.isSameObject(cur_obj, obj):
91
            # Translators: this announces that the current object is the same
92
            # object pointed to by the bookmark.
93
            #
94 0
            speech.speak(_('bookmark is current object'))
95 0
            return
96
        # Are their parents the same?
97 0
        elif self._script.isSameObject(cur_obj.parent, obj.parent):
98
            # Translators: this announces that the current object's parent and 
99
            # the parent of the object pointed to by the bookmark are the same.
100
            #
101 0
            speech.speak(_('bookmark and current object have same parent'))
102 0
            return
103
104
        # Do they share a common ancestor?
105
        # bookmark's ancestors
106 0
        bookmark_ancestors = []
107 0
        p = obj.parent
108 0
        while p:
109 0
            bookmark_ancestors.append(p)
110 0
            p = p.parent
111
        # look at current object's ancestors to compare to bookmark's ancestors    
112 0
        p = cur_obj.parent
113 0
        while p:
114 0
            if bookmark_ancestors.count(p) > 0:
115
                # Translators: this announces that the bookmark and the current
116
                # object share a common ancestor
117
                #
118 0
                speech.speak(_('shared ancestor %s') %p.role)
119 0
                return
120 0
            p = p.parent
121
122
        # Translators: This announces that a comparison between the bookmark
123
        # and the current object can not be determined.
124
        #
125 0
        speech.speak(_('comparison unknown'))
126
127 1
    def saveBookmarks(self, inputEvent):
128
        """ Save the bookmarks for this script. """        
129 0
        try:
130 0
            self._saveBookmarksToDisk(self._bookmarks)
131
            # Translators: this announces that a bookmark has been saved to 
132
            # disk
133
            #
134 0
            speech.speak(_('bookmarks saved'))
135 0
        except IOError:
136
            # Translators: this announces that a bookmark could not be saved to 
137
            # disk
138
            #
139 0
            speech.speak(_('bookmarks could not be saved'))
140
141 1
    def goToNextBookmark(self, inputEvent):
142
        """ Go to the next bookmark location.  If no bookmark has yet to be
143
        selected, the first bookmark will be used.  """
144
145
        # get the hardware keys that have registered bookmarks
146 0
        hwkeys = self._bookmarks.keys()
147 0
        hwkeys.sort()
148
149
        # no bookmarks have been entered
150 0
        if len(hwkeys) == 0:
151 0
            self._script.systemBeep()
152 0
            return
153
        # only 1 bookmark or we are just starting out
154 0
        elif len(hwkeys) == 1 or self._currentbookmarkindex is None:
155 0
            self.goToBookmark(None, index=hwkeys[0])
156 0
            return
157
158
        # find current bookmark hw_code in our sorted list.  
159
        # Go to next one if possible
160 0
        try:
161 0
            index = hwkeys.index(self._currentbookmarkindex)
162 0
            self.goToBookmark(None, index=hwkeys[index+1])
163 0
        except (ValueError, KeyError, IndexError):
164 0
            self.goToBookmark(None, index=hwkeys[0])
165
166 1
    def goToPrevBookmark(self, inputEvent):
167
        # get the hardware keys that have registered bookmarks
168 0
        hwkeys = self._bookmarks.keys()
169 0
        hwkeys.sort()
170
171
        # no bookmarks have been entered
172 0
        if len(hwkeys) == 0:
173 0
            self._script.systemBeep()
174 0
            return
175
        # only 1 bookmark or we are just starting out
176 0
        elif len(hwkeys) == 1 or self._currentbookmarkindex is None:
177 0
            self.goToBookmark(None, index=hwkeys[0])
178 0
            return
179
180
        # find current bookmark hw_code in our sorted list.  
181
        # Go to previous one if possible
182 0
        try:
183 0
            index = hwkeys.index(self._currentbookmarkindex)
184 0
            self.goToBookmark(None, index=hwkeys[index-1])
185 0
        except (ValueError, KeyError, IndexError):
186 0
            self.goToBookmark(None, index=hwkeys[0])
187
188 1
    def _loadBookmarks(self):
189
        """ Load this scripts saved bookmarks."""
190 79
        self._bookmarks = self._readBookmarksFromDisk() or {}
191
192 1
    def _readBookmarksFromDisk(self):
193
        """ Read saved bookmarks from disk.  Currently an unpickled object
194
        that represents a bookmark """
195 79
        orcaDir = settings.userPrefsDir
196 79
        orcaBookmarksDir = os.path.join(orcaDir, "bookmarks")
197 79
        try:
198 79
            input = open( os.path.join( orcaBookmarksDir, \
199 79
                        '%s.pkl' %self._script.name.split(' ')[0]), "r")
200 0
            bookmarks = pickle.load(input)
201 0
            input.close()
202 0
            return bookmarks
203 79
        except (IOError, EOFError, OSError):
204 79
            return None
205
206 1
    def _saveBookmarksToDisk(self, bookmarksObj):
207
        """ Write bookmarks to disk.  bookmarksObj must be a pickleable 
208
        object. """
209 0
        orcaDir = settings.userPrefsDir
210 0
        orcaBookmarksDir = os.path.join(orcaDir, "bookmarks")
211
        # create directory if it does not exist.  correct place??
212 0
        try:
213 0
            os.stat(orcaBookmarksDir)
214 0
        except OSError:
215 0
            os.mkdir(orcaBookmarksDir)
216 0
        output = open( os.path.join( orcaBookmarksDir, \
217 0
                    '%s.pkl' %self._script.name.split(' ')[0]), "w", os.O_CREAT)
218 0
        pickle.dump(bookmarksObj, output)
219 0
        output.close()
220
221 1
    def _contextToBookmark(self, context):
222
        """Converts a flat_review.Context object into a bookmark."""
223 0
        context_info = {}
224 0
        context_info['zone'] = context.zoneIndex
225 0
        context_info['char'] = context.charIndex
226 0
        context_info['word'] = context.wordIndex
227 0
        context_info['line'] = context.lineIndex
228 0
        return context_info
229
230 1
    def _bookmarkToContext(self, bookmark):
231
        """Converts a bookmark into a flat_review.Context object."""
232 0
        context = self._script.getFlatReviewContext()
233 0
        context.setCurrent(bookmark['line'], bookmark['zone'], \
234 0
                           bookmark['word'], bookmark['char'])
235 0
        return context