Package conduit :: Package modules :: Module TomboyModule
[hide private]

Source Code for Module conduit.modules.TomboyModule

  1  import dbus 
  2  import dbus.glib 
  3  import logging 
  4  import string 
  5  log = logging.getLogger("modules.Tomboy") 
  6   
  7  import conduit 
  8  import conduit.TypeConverter as TypeConverter 
  9  import conduit.dataproviders.DataProvider as DataProvider 
 10  import conduit.dataproviders.AutoSync as AutoSync 
 11  import conduit.Exceptions as Exceptions 
 12  import conduit.datatypes.Note as Note 
 13  import conduit.datatypes.File as File 
 14  import conduit.utils as Utils 
 15   
 16  MODULES = { 
 17          "TomboyNoteTwoWay" :        { "type": "dataprovider"    }, 
 18          "TomboyNoteConverter" :     { "type": "converter"       } 
 19  } 
 20   
21 -class TomboyNote(Note.Note):
22 """ 23 Stores both the text and xml representations of the note 24 """
25 - def __init__(self, title, contents, xml):
26 Note.Note.__init__(self, title, contents) 27 self.xml = xml
28
29 - def get_xml(self):
30 return self.xml
31
32 - def __getstate__(self):
33 data = Note.Note.__getstate__(self) 34 data["xml"] = self.xml 35 return data
36
37 - def __setstate__(self, data):
38 self.xml = data["xml"] 39 Note.Note.__setstate__(self, data)
40
41 -class TomboyNoteConverter(TypeConverter.Converter):
42 NOTE_EXTENSION = ".xml" 43 ILLEGAL_TITLE_CHARS = " /"
44 - def __init__(self):
45 self.conversions = { 46 "note,note/tomboy" : self.note_to_tomboy_note, 47 "note/tomboy,file" : self.tomboy_note_to_file, 48 "file,note/tomboy" : self.file_to_tomboy_note, 49 }
50
51 - def note_to_tomboy_note(self, note, **kwargs):
52 n = TomboyNote( 53 title=note.get_title(), 54 contents=note.get_contents(), 55 xml=None 56 ) 57 return n
58
59 - def tomboy_note_to_file(self, note, **kwargs):
60 content = note.get_xml() 61 #Old tomboy made this note, fallback to plain text 62 if content == None: 63 content = note.get_contents() 64 65 #replace the following characters in the note 66 #title with an underscore 67 filename = note.get_title().translate( 68 string.maketrans( 69 self.ILLEGAL_TITLE_CHARS, 70 "_"*len(self.ILLEGAL_TITLE_CHARS) 71 ) 72 ) 73 f = File.TempFile(content) 74 f.force_new_filename(filename) 75 f.force_new_file_extension(self.NOTE_EXTENSION) 76 return f
77
78 - def file_to_tomboy_note(self, f, **kwargs):
79 title,ext = f.get_filename_and_extension() 80 text = f.get_contents_as_text() 81 #A tomboy formatted XML file 82 if text.startswith('<?xml version="1.0" encoding="utf-8"?>') and text.find('xmlns="http://beatniksoftware.com/tomboy">') > 0: 83 note = TomboyNote( 84 title=Utils.xml_extract_value_from_tag("title", text), 85 contents=None, 86 xml=text 87 ) 88 #A bog standard text file 89 else: 90 note = TomboyNote( 91 title=title, 92 contents=text, 93 xml=None 94 ) 95 return note
96
97 -class TomboyNoteTwoWay(DataProvider.TwoWay, AutoSync.AutoSync):
98 """ 99 LUID is the tomboy uid string 100 """ 101 _name_ = "Tomboy Notes" 102 _description_ = "Sync your Tomboy notes" 103 _category_ = conduit.dataproviders.CATEGORY_NOTES 104 _module_type_ = "twoway" 105 _in_type_ = "note/tomboy" 106 _out_type_ = "note/tomboy" 107 _icon_ = "tomboy" 108 _configurable_ = False 109 110 TOMBOY_DBUS_PATH = "/org/gnome/Tomboy/RemoteControl" 111 TOMBOY_DBUS_IFACE = "org.gnome.Tomboy" 112 TOMBOY_MIN_VERSION = (0, 5, 10) 113 TOMBOY_COMPLETE_XML_VERSION = (0 ,9 ,0) 114
115 - def __init__(self, *args):
116 DataProvider.TwoWay.__init__(self) 117 AutoSync.AutoSync.__init__(self) 118 self.notes = [] 119 self.remoteTomboy = None 120 self.supportsCompleteXML = False 121 122 self._connect_to_tomboy()
123
124 - def _connect_to_tomboy(self):
125 if self.remoteTomboy != None: 126 return True 127 128 bus = dbus.SessionBus() 129 if Utils.dbus_service_available(TomboyNoteTwoWay.TOMBOY_DBUS_IFACE, bus): 130 obj = bus.get_object(TomboyNoteTwoWay.TOMBOY_DBUS_IFACE, TomboyNoteTwoWay.TOMBOY_DBUS_PATH) 131 app = dbus.Interface(obj, "org.gnome.Tomboy.RemoteControl") 132 version = tuple(int(item) for item in str(app.Version()).split('.')) 133 if version >= TomboyNoteTwoWay.TOMBOY_MIN_VERSION: 134 self.remoteTomboy = app 135 self.remoteTomboy.connect_to_signal("NoteAdded", lambda uid: self.handle_added(str(uid))) 136 self.remoteTomboy.connect_to_signal("NoteSaved", lambda uid: self.handle_modified(str(uid))) 137 self.remoteTomboy.connect_to_signal("NoteDeleted", lambda uid, x: self.handle_deleted(str(uid))) 138 self.supportsCompleteXML = version >= TomboyNoteTwoWay.TOMBOY_COMPLETE_XML_VERSION 139 log.info("Using Tomboy Version %s" % str(version)) 140 return True 141 return False
142
143 - def _update_note(self, uid, note):
144 log.debug("Updating note uid: %s" % uid) 145 if note.get_xml() != None: 146 ok = self.remoteTomboy.SetNoteCompleteXml( 147 uid, 148 note.get_xml() 149 ) 150 else: 151 ok = self.remoteTomboy.SetNoteContents( 152 uid, 153 note.get_contents() 154 ) 155 156 if not ok: 157 raise Exceptions.SyncronizeError("Error setting Tomboy note content (uri: %s)" % uid)
158
159 - def _get_note_mtime(self, uid):
160 try: 161 timestr = self.remoteTomboy.GetNoteChangeDate(uid) 162 mtime = Utils.datetime_from_timestamp(int(timestr)) 163 except: 164 log.warn("Error parsing tomboy note modification time") 165 mtime = None 166 return mtime
167
168 - def _get_note(self, uid):
169 #Get the whole xml and strip out the tags 170 log.debug("Getting note: %s" % uid) 171 172 xml = None 173 if self.supportsCompleteXML: 174 xml = str(self.remoteTomboy.GetNoteCompleteXml(uid)) 175 176 n = TomboyNote( 177 title=str(self.remoteTomboy.GetNoteTitle(uid)), 178 contents=str(self.remoteTomboy.GetNoteContents(uid)), 179 xml=xml 180 ) 181 n.set_UID(str(uid)) 182 n.set_mtime(self._get_note_mtime(uid)) 183 n.set_open_URI(str(uid)) 184 return n
185
186 - def _create_note(self, note):
187 uid = str(self.remoteTomboy.CreateNamedNote(note.get_title())) 188 self._update_note(uid, note) 189 return uid
190
191 - def initialize(self):
192 """ 193 Loads the tomboy source if the user has used tomboy before 194 """ 195 return True
196
197 - def refresh(self):
198 DataProvider.TwoWay.refresh(self) 199 self.notes = [] 200 if self._connect_to_tomboy(): 201 self.notes = [str(i) for i in self.remoteTomboy.ListAllNotes()] 202 else: 203 raise Exceptions.RefreshError("Tomboy not available")
204
205 - def get(self, uri):
206 DataProvider.TwoWay.get(self, uri) 207 return self._get_note(uri)
208
209 - def get_all(self):
210 DataProvider.TwoWay.get_all(self) 211 return self.notes
212
213 - def put(self, note, overwrite, LUID=None):
214 """ 215 Stores a Note in Tomboy. 216 """ 217 DataProvider.TwoWay.put(self, note, overwrite, LUID) 218 log.debug("Put note LUID: %s" % LUID) 219 220 #Check if the note, or one with same title exists 221 existingNote = None 222 if LUID != None: 223 if self.remoteTomboy.NoteExists(LUID): 224 existingNote = self._get_note(LUID) 225 else: 226 LUID = self.remoteTomboy.FindNote(note.get_title()) 227 if LUID != "": 228 existingNote = self._get_note(str(LUID)) 229 230 #compare with the existing note 231 if existingNote != None: 232 comp = note.compare(existingNote) 233 log.debug("Comparing new %s with existing %s" % (note.get_title(),existingNote.get_title())) 234 if comp == conduit.datatypes.COMPARISON_EQUAL: 235 log.info("Notes are equal") 236 elif overwrite == True or comp == conduit.datatypes.COMPARISON_NEWER: 237 log.info("Updating note") 238 self._update_note(LUID, note) 239 else: 240 raise Exceptions.SynchronizeConflictError(comp, existingNote, note) 241 else: 242 log.info("Saving new Note") 243 LUID = self._create_note(note) 244 245 return self.get(LUID).get_rid()
246
247 - def delete(self, LUID):
248 if self.remoteTomboy.NoteExists(LUID): 249 if self.remoteTomboy.DeleteNote(LUID): 250 log.debug("Deleted note %s" % LUID) 251 return 252 253 log.warn("Error deleting note %s" % LUID)
254
255 - def finish(self, aborted, error, conflict):
256 DataProvider.TwoWay.finish(self) 257 self.notes = []
258
259 - def get_UID(self):
260 return Utils.get_user_string()
261