def __init__(self, app): self._app = app self._info = {} self._enabled = False self.type = "system" self.enabled = Listeners()
def __init__(self, pref_dir=None): Pref.__init__(self) if pref_dir is None: self._pref_dir = get_user_pref_dir() else: self._pref_dir = pref_dir # listener self.changed = Listeners()
def __init__(self, rootdir=None): """rootdir -- Root directory of notebook""" NoteBookDir.__init__(self, rootdir, notebook=self) self.pref = NoteBookPreferences() if rootdir is not None: self._attr["title"] = os.path.basename(rootdir) else: self._attr["title"] = None self._dirty = set() self._trash = None self._attr["order"] = 0 # init notebook attributes self._init_default_attr() # init trash if rootdir: self._trash_path = get_trash_dir(self.get_path()) else: self._trash_path = None # listeners self.node_changed = Listeners() # signature = (node, recurse) # add node types self._init_default_node_types()
def __init__(self, pref_dir=None): Pref.__init__(self) if pref_dir is None: self._pref_dir = get_user_pref_dir() else: self._pref_dir = pref_dir # listener self.changed = Listeners() self.changed.add(self._on_changed)
def __init__(self, rootdir=None): """rootdir -- Root directory of notebook""" NoteBookDir.__init__(self, rootdir, notebook=self) self.pref = NoteBookPreferences() if rootdir is not None: self._attr["title"] = os.path.basename(rootdir) else: self._attr["title"] = None self._dirty = set() self._trash = None self._attr["order"] = 0 # init notebook attributes self.notebook_attrs = {} for attr in g_default_attrs: self.notebook_attrs[attr.key] = attr if rootdir: self._trash_path = get_trash_dir(self.get_path()) # listeners self.node_changed = Listeners() # node, recurse
class KeepNotePreferences (Pref): """Preference data structure for the KeepNote application""" def __init__(self, pref_dir=None): Pref.__init__(self) if pref_dir is None: self._pref_dir = get_user_pref_dir() else: self._pref_dir = pref_dir # listener self.changed = Listeners() self.changed.add(self._on_changed) def get_pref_dir(self): """Returns preference directory""" return self._pref_dir def _on_changed(self): """Listener for preference changes""" self.write() #========================================= # Input/Output def read(self): """Read preferences from file""" # ensure preference file exists if not os.path.exists(get_user_pref_file(self._pref_dir)): # write default try: init_user_pref_dir(self._pref_dir) self.write() except Exception, e: raise KeepNotePreferenceError("Cannot initialize preferences", e) try: # read preferences xml tree = ET.ElementTree( file=get_user_pref_file(self._pref_dir)) # parse xml # check tree structure matches current version root = tree.getroot() if root.tag == "keepnote": p = root.find("pref") if p is None: # convert from old preference version import keepnote.compat.pref as old old_pref = old.KeepNotePreferences() old_pref.read(get_user_pref_file(self._pref_dir)) data = old_pref._get_data() else: # get data object from xml d = p.find("dict") if d is not None: data = plist.load_etree(d) else: data = orderdict.OrderDict() # set data self._data.clear() self._data.update(data) except Exception, e: raise KeepNotePreferenceError("Cannot read preferences", e)
def __init__(self, textbuffer): self.undo_stack = UndoStack(MAX_UNDOS) self._next_action = None self._buffer = textbuffer self.after_changed = Listeners()
class UndoHandler(object): """TextBuffer Handler that provides undo/redo functionality""" def __init__(self, textbuffer): self.undo_stack = UndoStack(MAX_UNDOS) self._next_action = None self._buffer = textbuffer self.after_changed = Listeners() def on_insert_text(self, textbuffer, it, text, length): """Callback for text insert""" # NOTE: GTK does not give us a proper UTF string, so fix it text = unicode(text, "utf_8") length = len(text) # setup next action offset = it.get_offset() self._next_action = InsertAction( textbuffer, offset, text, length, cursor_insert=(offset == textbuffer.get_iter_at_mark( textbuffer.get_insert()).get_offset())) def on_delete_range(self, textbuffer, start, end): """Callback for delete range""" # setup next action self._next_action = DeleteAction( textbuffer, start.get_offset(), end.get_offset(), start.get_slice(end), textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_offset()) def on_insert_pixbuf(self, textbuffer, it, pixbuf): """Callback for inserting a pixbuf""" pass def on_insert_child_anchor(self, textbuffer, it, anchor): """Callback for inserting a child anchor""" # setup next action self._next_action = InsertChildAction(textbuffer, it.get_offset(), anchor) def on_apply_tag(self, textbuffer, tag, start, end): """Callback for tag apply""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), True) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_remove_tag(self, textbuffer, tag, start, end): """Callback for tag remove""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), False) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_changed(self, textbuffer): """Callback for buffer change""" # process actions that have changed the buffer if not self._next_action: return textbuffer.begin_user_action() # add action to undo stack action = self._next_action self._next_action = None self.undo_stack.do(action.do, action.undo, False) # perfrom additional "clean-up" actions # note: only if undo/redo is not currently in progress if not self.undo_stack.is_in_progress(): self.after_changed.notify(action) textbuffer.end_user_action()
class KeepNotePreferences(Pref): """Preference data structure for the KeepNote application""" def __init__(self, pref_dir=None): Pref.__init__(self) if pref_dir is None: self._pref_dir = get_user_pref_dir() else: self._pref_dir = pref_dir # listener self.changed = Listeners() self.changed.add(self._on_changed) def get_pref_dir(self): """Returns preference directory""" return self._pref_dir def _on_changed(self): """Listener for preference changes""" self.write() #========================================= # Input/Output def read(self): """Read preferences from file""" # ensure preference file exists if not os.path.exists(get_user_pref_file(self._pref_dir)): # write default try: init_user_pref_dir(self._pref_dir) self.write() except Exception, e: raise KeepNotePreferenceError("Cannot initialize preferences", e) try: # read preferences xml tree = ET.ElementTree(file=get_user_pref_file(self._pref_dir)) # parse xml # check tree structure matches current version root = tree.getroot() if root.tag == "keepnote": p = root.find("pref") if p is None: # convert from old preference version import keepnote.compat.pref as old old_pref = old.KeepNotePreferences() old_pref.read(get_user_pref_file(self._pref_dir)) data = old_pref._get_data() else: # get data object from xml d = p.find("dict") if d is not None: data = plist.load_etree(d) else: data = orderdict.OrderDict() # set data self._data.clear() self._data.update(data) except Exception, e: raise KeepNotePreferenceError("Cannot read preferences", e)
class UndoHandler(object): """TextBuffer Handler that provides undo/redo functionality""" def __init__(self, textbuffer): self.undo_stack = UndoStack(MAX_UNDOS) self._next_action = None self._buffer = textbuffer self.after_changed = Listeners() def on_insert_text(self, textbuffer, it, text, length): """Callback for text insert""" # NOTE: GTK does not give us a proper UTF string, so fix it text = unicode(text, "utf_8") length = len(text) # setup next action offset = it.get_offset() self._next_action = InsertAction( textbuffer, offset, text, length, cursor_insert=(offset == textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_offset()), ) def on_delete_range(self, textbuffer, start, end): """Callback for delete range""" # setup next action self._next_action = DeleteAction( textbuffer, start.get_offset(), end.get_offset(), start.get_slice(end), textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_offset(), ) def on_insert_pixbuf(self, textbuffer, it, pixbuf): """Callback for inserting a pixbuf""" pass def on_insert_child_anchor(self, textbuffer, it, anchor): """Callback for inserting a child anchor""" # setup next action self._next_action = InsertChildAction(textbuffer, it.get_offset(), anchor) def on_apply_tag(self, textbuffer, tag, start, end): """Callback for tag apply""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), True) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_remove_tag(self, textbuffer, tag, start, end): """Callback for tag remove""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), False) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_changed(self, textbuffer): """Callback for buffer change""" # process actions that have changed the buffer if not self._next_action: return textbuffer.begin_user_action() # add action to undo stack action = self._next_action self._next_action = None self.undo_stack.do(action.do, action.undo, False) # perfrom additional "clean-up" actions # note: only if undo/redo is not currently in progress if not self.undo_stack.is_in_progress(): self.after_changed.notify(action) textbuffer.end_user_action()
class Extension(object): """KeepNote Extension""" version = (1, 0) key = "" name = "untitled" author = "no author" website = "http://rasm.ods.org/keepnote" description = "base extension" visible = True def __init__(self, app): self._app = app self._enabled = False self.type = "system" self.enabled = Listeners() def enable(self, enable): """Enable/disable extension""" # check dependencies self.check_depends() # mark extension as enabled self._enabled = enable # notify listeners self.enabled.notify(enable) # return whether the extension is enabled return self._enabled def is_enabled(self): """Returns True if extension is enabled""" return self._enabled def check_depends(self): """Checks whether dependencies are met. Throws exception on failure""" for dep in self.get_depends(): if not self._app.dependency_satisfied(dep): raise DependencyError(self, dep) def get_depends(self): """ Returns dependencies of extension Dependencies returned as a list of tuples (NAME, REL, EXTRA) NAME is a string identify an extension (or 'keepnote' itself). EXTRA is an object whose type depends on REL REL is a string representing a relation. Options are: Version relations. For each of these values for REL, the EXTRA field is interpreted as VERSION (see below): '>=' the version must be greater than or equal to '>' the version must be greater than '==' the version must be exactly equal to '<=' the version must less than or equal to '<' the version must be less than '!=' the version must not be equal to Other relations. 'no' the extension must not exist. EXTRA is None. Possible values for EXTRA: VERSION This is a tuple representing a version number. ex: the tuple (0, 6, 1) represents version 0.6.1 All dependencies must be met to enable an extension. A extension name can appear more than once if several relations are required (such as specifying a range of valid version numbers). """ return [("keepnote", ">=", (0, 6, 1))] #=============================== # filesystem paths def get_base_dir(self, exist=True): """Returns the directory containing the extensions code""" path = self._app.get_extension_base_dir(self.key) if exist and not os.path.exists(path): os.makedirs(path) return path def get_data_dir(self, exist=True): """Returns the directory for storing data specific to this extension""" path = self._app.get_extension_data_dir(self.key) if exist and not os.path.exists(path): os.makedirs(path) return path def get_data_file(self, filename, exist=True): """ Returns a full path to a file within the extension's data directory """ return os.path.join(self.get_data_dir(exist), filename)
def get_listeners(self, key): listeners = self._listeners.get(key, None) if listeners is None: listeners = Listeners() self._listeners[key] = listeners return listeners
class Extension (object): """KeepNote Extension""" version = (1, 0) key = "" name = "untitled" author = "no author" website = "http://keepnote.org" description = "base extension" visible = True def __init__(self, app): self._app = app self._info = {} self._enabled = False self.type = "system" self.enabled = Listeners() def read_info(self): """Populate extension info""" path = self.get_base_dir(False) self._info = read_extension_info(path) # populate info self.version = parse_extension_version(self._info["version"]) self.name = self._info["name"] self.author = self._info["author"] self.website = self._info["website"] self.description = self._info["description"] def get_info(self, key): return self._info.get(key, None) def enable(self, enable): """Enable/disable extension""" # check dependencies self.check_depends() # mark extension as enabled self._enabled = enable # notify listeners self.enabled.notify(enable) # return whether the extension is enabled return self._enabled def is_enabled(self): """Returns True if extension is enabled""" return self._enabled def check_depends(self): """Checks whether dependencies are met. Throws exception on failure""" for dep in self.get_depends(): if not self._app.dependency_satisfied(dep): raise DependencyError(self, dep) def get_depends(self): """ Returns dependencies of extension Dependencies returned as a list of tuples (NAME, REL, EXTRA) NAME is a string identify an extension (or 'keepnote' itself). EXTRA is an object whose type depends on REL REL is a string representing a relation. Options are: Version relations. For each of these values for REL, the EXTRA field is interpreted as VERSION (see below): '>=' the version must be greater than or equal to '>' the version must be greater than '==' the version must be exactly equal to '<=' the version must less than or equal to '<' the version must be less than '!=' the version must not be equal to Other relations. 'no' the extension must not exist. EXTRA is None. Possible values for EXTRA: VERSION This is a tuple representing a version number. ex: the tuple (0, 6, 1) represents version 0.6.1 All dependencies must be met to enable an extension. A extension name can appear more than once if several relations are required (such as specifying a range of valid version numbers). """ return [("keepnote", ">=", (0, 6, 1))] #=============================== # filesystem paths def get_base_dir(self, exist=True): """ Returns the directory containing the extension's code If 'exists' is True, create directory if it does not exists. """ path = self._app.get_extension_base_dir(self.key) if exist and not os.path.exists(path): os.makedirs(path) return path def get_data_dir(self, exist=True): """ Returns the directory for storing data specific to this extension If 'exists' is True, create directory if it does not exists. """ path = self._app.get_extension_data_dir(self.key) if exist and not os.path.exists(path): os.makedirs(path) return path def get_data_file(self, filename, exist=True): """ Returns a full path to a file within the extension's data directory If 'exists' is True, create directory if it does not exists. """ return os.path.join(self.get_data_dir(exist), filename)
class KeepNotePreferences(Pref): """Preference data structure for the KeepNote application""" def __init__(self, pref_dir=None): Pref.__init__(self) if pref_dir is None: self._pref_dir = get_user_pref_dir() else: self._pref_dir = pref_dir # listener self.changed = Listeners() # self.changed.add(self._on_changed) def get_pref_dir(self): """Returns preference directory""" return self._pref_dir # def _on_changed(self): # """Listener for preference changes""" # self.write() # ========================================= # Input/Output def read(self): """Read preferences from file""" # ensure preference file exists if not os.path.exists(get_user_pref_file(self._pref_dir)): # write default try: init_user_pref_dir(self._pref_dir) self.write() except Exception as e: raise KeepNotePreferenceError("Cannot initialize preferences", e) try: # read preferences xml tree = ElementTree.ElementTree( file=get_user_pref_file(self._pref_dir)) # parse xml # check tree structure matches current version root = tree.getroot() if root.tag == "keepnote": p = root.find("pref") if p is None: # convert from old preference version import keepnote.compat.pref as old old_pref = old.KeepNotePreferences() old_pref.read(get_user_pref_file(self._pref_dir)) data = old_pref._get_data() else: # get data object from xml d = p.find("dict") if d is not None: data = plist.load_etree(d) else: data = orderdict.OrderDict() # set data self._data.clear() self._data.update(data) except Exception as e: raise KeepNotePreferenceError("Cannot read preferences", e) # notify listeners self.changed.notify() def write(self): """Write preferences to file""" try: if not os.path.exists(self._pref_dir): init_user_pref_dir(self._pref_dir) out = safefile.open(get_user_pref_file(self._pref_dir), "w", codec="utf-8") out.write(u'<?xml version="1.0" encoding="UTF-8"?>\n' u'<keepnote>\n' u'<pref>\n') plist.dump(self._data, out, indent=4, depth=4) out.write(u'</pref>\n' u'</keepnote>\n') out.close() except (IOError, OSError) as e: log_error(e, sys.exc_info()[2]) raise NoteBookError(_("Cannot save preferences"), e)