Package Pyblio :: Package Cite :: Package WP :: Module OpenOffice
[hide private]
[frames] | no frames]

Source Code for Module Pyblio.Cite.WP.OpenOffice

  1  # -*- coding: utf-8 -*- 
  2  # This file is part of pybliographer 
  3  #  
  4  # Copyright (C) 1998-2006 Frederic GOBRY 
  5  # Email : gobry@pybliographer.org 
  6  #           
  7  # This program is free software; you can redistribute it and/or 
  8  # modify it under the terms of the GNU General Public License 
  9  # as published by the Free Software Foundation; either version 2  
 10  # of the License, or (at your option) any later version. 
 11  #    
 12  # This program is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 15  # GNU General Public License for more details.  
 16  #  
 17  # You should have received a copy of the GNU General Public License 
 18  # along with this program; if not, write to the Free Software 
 19  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 20  #  
 21   
 22  """ 
 23  A simple API to cite references in OpenOffice.org 
 24   
 25  Based on code from Bibus <http://bibus-biblio.sourceforge.net/>. 
 26  """ 
 27   
 28  import uno 
 29  from gettext import gettext as _ 
 30   
 31  from Pyblio.Cite.WP import CommunicationError, OperationError 
 32  from Pyblio.Store import Key 
 33   
 34  DIRECT_VALUE    = uno.getConstantByName("com.sun.star.beans.PropertyState.DIRECT_VALUE") 
 35  PARAGRAPH_BREAK = uno.getConstantByName("com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK") 
 36   
 37  PropertyValue          = uno.getClass("com.sun.star.beans.PropertyValue") 
 38  NoSuchElementException = uno.getClass("com.sun.star.container.NoSuchElementException") 
 39  NoConnectException     = uno.getClass("com.sun.star.connection.NoConnectException") 
 40   
 41  ITALIC = (uno.getConstantByName("com.sun.star.awt.FontSlant.ITALIC"), 
 42            uno.getConstantByName("com.sun.star.awt.FontSlant.NONE")) 
 43   
 44  OO_BIBLIOGRAPHIC_FIELDS = {} 
 45  for f in ('Custom1', 'Custom2', 'Identifier'): 
 46      OO_BIBLIOGRAPHIC_FIELDS[f] = \ 
 47          uno.getConstantByName("com.sun.star.text.BibliographyDataField." + f.upper()) 
 48   
 49  from Pyblio.Format.OpenOffice import Generator, ITALIC 
 50   
 51  import re 
 52   
 53  _x_pyblio_re = re.compile(r'X-PYBLIO<(\d+)>') 
 54  _x_pyblio_extra_re = re.compile(r'X-PYBLIO-EXTRA:(.*)') 
 55   
56 -class OOo(object):
57 MASTER = 'com.sun.star.text.FieldMaster.Bibliography' 58 59 FRAME = u'Bibliography (Pybliographer)' 60
61 - def __init__(self, connection=('pipe', 'OOo_pipe')):
62 self.remote = connection 63 self.smgr = None 64 return
65
66 - def is_connected(self):
67 return self.smgr is not None
68
69 - def disconnect(self):
70 self.smgr = None 71 self.desktop = None 72 self.model = None 73 self.controller = None 74 self.cursor = None 75 self.text = None 76 self.tfm = None 77 self.frame = None
78
79 - def connect(self):
80 if self.is_connected(): 81 return 82 83 localContext = uno.getComponentContext() 84 resolver = localContext.ServiceManager.createInstanceWithContext( 85 "com.sun.star.bridge.UnoUrlResolver", localContext ) 86 87 if self.remote[0] == 'pipe': 88 cnx_parameter = 'pipe,name=%s' % self.remote[1] 89 elif self.remote[0] == 'socket': 90 cnx_parameter = 'socket,host=%s,port=%d' % self.remote[1:] 91 else: 92 cnx_parameter = '' 93 try: 94 ctx = resolver.resolve("uno:%s;urp;StarOffice.ComponentContext" % ( 95 cnx_parameter)) 96 except NoConnectException, msg: 97 raise CommunicationError(_("Unable to contact OpenOffice.org: %s" % msg)) 98 99 self.smgr = ctx.ServiceManager 100 self.desktop = self.smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx) 101 102 self.model = self.desktop.getCurrentComponent() 103 if not (self.model and self.model.getImplementationName() == 'SwXTextDocument'): 104 raise OperationError(_("You are not in a text document")) 105 106 self.controller = self.model.getCurrentController() 107 self.cursor = self.controller.getViewCursor() 108 self.text = self.model.Text 109 110 try: 111 self.tfm = self.model.getTextFieldMasters().getByName(self.MASTER) 112 except NoSuchElementException: 113 self.tfm = self.model.createInstance(self.MASTER) 114 115 # Try to get an existing frame of content 116 try: 117 self.frame = self.model.getTextSections().getByName(self.FRAME) 118 except NoSuchElementException: 119 self.frame = None 120 return
121
122 - def cite(self, keys, db):
123 """ Insert a list of references in the document, at the 124 cursor location. Each reference is a tuple 125 (visible_key, internal_id, extra_data) 126 """ 127 for ref, key, extra in keys: 128 oref = self._makeRef(ref, key, extra) 129 c = self.cursor.Text.createTextCursorByRange(self.cursor) 130 c.Text.insertTextContent(c, oref, True) 131 self.cursor.setPropertyToDefault('CharStyleName') 132 return
133
134 - def fetch(self):
135 """ Fetch all the references in the document, in order of appearance """ 136 137 refs = list(self.tfm.getPropertyValue('DependentTextFields')) 138 # We need to reorder the fields by checking their relative 139 # position. 140 def cmp(a, b): 141 return self.text.compareRegionStarts(b.Anchor.Start, 142 a.Anchor.Start)
143 refs.sort(cmp) 144 return [r for r in [self._parseRef(ref) for ref in refs] if r]
145
146 - def update_keys(self, keymap):
147 # Update the existing keys according to the new values. Simply 148 # modifying the fields leads to an inconsistent display 149 # (probably an openoffice bug). So this method simply 150 # overwrites the existing TextField with the updated one. 151 refs = list(self.tfm.getPropertyValue('DependentTextFields')) 152 for ref in refs: 153 fields = self._parseRef(ref) 154 if not fields: 155 continue 156 uid, old_name, extra = fields 157 if uid in keymap: 158 nref = self._makeRef(uid, keymap[uid], extra) 159 c = self.cursor.Text.createTextCursorByRange(ref.getAnchor()) 160 c.Text.insertTextContent(c, nref, True) 161 162 return self.fetch()
163
164 - def update_biblio(self):
165 if not self.frame: 166 self._createFrame() 167 168 f = self.frame 169 t = self.text 170 c = self.text.createTextCursorByRange(self.frame.Anchor.Start) 171 172 f.Anchor.setString('') 173 return Generator(t, c)
174
175 - def _createFrame(self):
176 self.frame = self.model.createInstance("com.sun.star.text.TextSection") 177 self.frame.setName(self.FRAME) 178 179 self.text.insertString(self.cursor, '\x0a', False) 180 c = self.cursor.Text.createTextCursorByRange(self.cursor) 181 self.text.insertString(c, '\x0a', False) 182 c.goLeft(1, False) 183 self.text.insertTextContent(c, self.frame, False) 184 185 c = self.text.createTextCursorByRange(self.frame.Anchor.Start) 186 c.CharPosture = ITALIC[0] 187 self.text.insertString(c, _('Bibliography will appear here...'), False) 188 c.CharPosture = ITALIC[1] 189 190 return self.frame
191
192 - def _makeRef(self, ref, visible_key, extra):
193 """ Create a reference ready to be inserted in the document. """ 194 195 if extra is not None: 196 extra = 'X-PYBLIO-EXTRA:%s' % extra 197 198 oref = self.model.createInstance("com.sun.star.text.TextField.Bibliography") 199 oref.Fields = (PropertyValue('Identifier', 0, visible_key, DIRECT_VALUE), 200 PropertyValue('Custom1', 0, 'X-PYBLIO<%s>' % ref, DIRECT_VALUE), 201 PropertyValue('Custom2', 0, extra, DIRECT_VALUE),) 202 return oref
203
204 - def _parseRef(self, r):
205 ref, key, extra = ( 206 r.Fields[OO_BIBLIOGRAPHIC_FIELDS['Custom1']].Value, 207 r.Fields[OO_BIBLIOGRAPHIC_FIELDS['Identifier']].Value, 208 r.Fields[OO_BIBLIOGRAPHIC_FIELDS['Custom2']].Value) 209 210 if extra: 211 m = _x_pyblio_extra_re.match(extra) 212 if m: 213 extra = m.group(1) 214 else: 215 extra = None 216 m = _x_pyblio_re.match(ref) 217 if m: 218 return (Key(m.group(1)), key, extra) 219 return None
220