class DitaaGenerator(ImageGeneratorClass): uses_log_file = False object_type = "shaape" scriptname = "shaape.dia" imagename = "shaape.png" def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.dotfile = TmpFile(self.scriptname) self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + ".png") # len('.dot') == 4 def generate_image(self, text): # Write to tmp file self.dotfile.write(text) # Call GraphViz try: dot = Application(dotcmd) dot.run(("-o", self.pngfile, self.dotfile)) except ApplicationError: return None, None # Sorry, no log else: return self.pngfile, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class SequenceDiagramGenerator(ImageGeneratorClass): uses_log_file = False object_type = 'seqdiagram' scriptname = 'seqdiagram.diag' imagename = 'seqdiagram.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.diagfile = TmpFile(self.scriptname) self.diagfile.touch() self.pngfile = File(self.diagfile.path[:-5] + '.png') # len('.diag') == 5 def generate_image(self, text): # Write to tmp file self.diagfile.write(text) # Call seqdiag try: diag = Application(diagcmd) diag.run((self.pngfile, self.diagfile)) except ApplicationError: return None, None # Sorry, no log else: return self.pngfile, None def cleanup(self): self.diagfile.remove() self.pngfile.remove()
class DitaaGenerator(ImageGeneratorClass): uses_log_file = False object_type = 'ditaa' scriptname = 'ditaa.dia' imagename = 'ditaa.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.dotfile = TmpFile(self.scriptname) self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4 def generate_image(self, text): # Write to tmp file self.dotfile.write(text) # Call GraphViz try: dot = Application(dotcmd) dot.run((self.dotfile, '-o', self.pngfile)) except ApplicationError: return None, None # Sorry, no log else: return self.pngfile, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class SequenceDiagramGenerator(ImageGeneratorClass): uses_log_file = False object_type = 'seqdiagram' scriptname = 'seqdiagram.diag' imagename = 'seqdiagram.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.diagfile = TmpFile(self.scriptname) self.diagfile.touch() self.pngfile = File(self.diagfile.path[:-5] + '.png') # len('.diag') == 5 def generate_image(self, text): # Write to tmp file self.diagfile.write(text) # Call seqdiag try: diag = Application(diagcmd) diag.run((self.pngfile, self.diagfile)) except ApplicationError: return None, None # Sorry, no log else: return self.pngfile, None def cleanup(self): self.diagfile.remove() self.pngfile.remove()
class DiagramGenerator(ImageGeneratorClass): uses_log_file = False type = 'diagram' scriptname = 'diagram.dot' imagename = 'diagram.png' def __init__(self): self.dotfile = TmpFile(self.scriptname) self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4 def generate_image(self, text): if isinstance(text, basestring): text = text.splitlines(True) # Write to tmp file self.dotfile.writelines(text) # Call GraphViz try: dot = Application(dotcmd) dot.run((self.pngfile, self.dotfile)) except ApplicationError: return None, None # Sorry, no log else: return self.pngfile, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class DiagramGenerator(object): # TODO: generic base class for image generators type = 'diagram' basename = 'diagram.dot' def __init__(self): self.dotfile = TmpFile('diagram-editor.dot') self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4 def generate_image(self, text): if isinstance(text, basestring): text = text.splitlines(True) # Write to tmp file self.dotfile.writelines(text) # Call GraphViz dot = Application(dotcmd) dot.run((self.pngfile, self.dotfile)) return self.pngfile, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class PlantumlGenerator(ImageGeneratorClass): def __init__(self, plugin, notebook, page): ImageGeneratorClass.__init__(self, plugin, notebook, page) self.dotfile = TmpFile('umldiagram.puml') self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-5] + '.png') # len('.puml') == 5 def generate_image(self, text): # Write to tmp file self.dotfile.writelines(text) # Call PlantUML try: dot = Application(dotcmd) dot.run((self.pngfile, self.dotfile)) except ApplicationError: return None, None # Sorry, no log else: if self.pngfile.exists(): return self.pngfile, None else: # When supplying a dot file with a syntax error, the dot command # doesn't return an error code (so we don't raise # ApplicationError), but we still don't have a png file to # return, so return None. return None, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class PlantumlGenerator(ImageGeneratorClass): uses_log_file = False object_type = 'plantuml' scriptname = 'plantuml.pu' imagename = 'plantuml.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.dotfile = TmpFile(self.scriptname) self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-3] + '.png') # len('.pu') == 3 def generate_image(self, text): if isinstance(text, basestring): text = text.splitlines(True) # Write to tmp file self.dotfile.writelines(text) # Call PlantUML try: dot = Application(dotcmd) dot.run(('', self.dotfile)) except ApplicationError: return None, None # Sorry, no log else: return self.pngfile, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class DiagramGenerator(ImageGeneratorClass): uses_log_file = False object_type = 'diagram' scriptname = 'diagram.dot' imagename = 'diagram.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.dotfile = TmpFile(self.scriptname) self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4 def generate_image(self, text): if isinstance(text, basestring): text = text.splitlines(True) # Write to tmp file self.dotfile.writelines(text) # Call GraphViz try: dot = Application(dotcmd) dot.run((self.pngfile, self.dotfile)) except ApplicationError: return None, None # Sorry, no log else: if self.pngfile.exists(): return self.pngfile, None else: # When supplying a dot file with a syntax error, the dot command # doesn't return an error code (so we don't raise # ApplicationError), but we still don't have a png file to # return, so return None. return None, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class DiagramGenerator(ImageGeneratorClass): uses_log_file = False object_type = 'diagram' scriptname = 'diagram.dot' imagename = 'diagram.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.dotfile = TmpFile(self.scriptname) self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4 def generate_image(self, text): if isinstance(text, basestring): text = text.splitlines(True) # Write to tmp file self.dotfile.writelines(text) # Call GraphViz try: dot = Application(dotcmd) dot.run((self.pngfile, self.dotfile)) except ApplicationError: return None, None # Sorry, no log else: if self.pngfile.exists(): return self.pngfile, None else: # When supplying a dot file with a syntax error, the dot command # doesn't return an error code (so we don't raise # ApplicationError), but we still don't have a png file to # return, so return None. return None, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class PlantumlGenerator(ImageGeneratorClass): def __init__(self, plugin, notebook, page): ImageGeneratorClass.__init__(self, plugin, notebook, page) self.dotfile = TmpFile('plantuml.pu') self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-3] + '.png') # len('.pu') == 3 def generate_image(self, text): # Write to tmp file self.dotfile.write(text) # Call GraphViz try: dot = Application(dotcmd) dot.run((self.dotfile, )) except ApplicationError as e: print(e) return None, None # Sorry, no log else: return self.pngfile, None def cleanup(self): self.dotfile.remove() self.pngfile.remove()
class ConfigFile(object): '''Container object for a config file Maps to a "base" file in the home folder, used to write new values, and one or more default files, e.g. in C{/usr/share/zim}, which are the fallback to get default values @ivar file: the underlying file object for the base config file in the home folder @note: this class implement similar API to the L{File} class but is explicitly not a sub-class of L{File} because config files should typically not be moved, renamed, etc. It just implements the reading and writing methods. ''' def __init__(self, path, file=None): '''Constructor @param path: either basename as string or tuple with relative path, is resolved relative to the default config dir for zim. @param file: optional argument for some special case to override the base file in the home folder. ''' if isinstance(path, basestring): path = (path,) self._path = tuple(path) if file: self.file = file else: self.file = File((XDG_CONFIG_HOME, 'zim') + self._path) def __repr__(self): return '<%s: %s>' % (self.__class__.__name__, self.file.path) def __eq__(self, other): return isinstance(other, ConfigFile) \ and other._path == self._path \ and other.file == self.file @property def basename(self): return self.file.basename def default_files(self): '''Generator that yields default config files (read-only) to use instead of the standard file when it is still empty. Typically only the first one is used. ''' for dir in config_dirs(): default = dir.file(self._path) if default.exists(): yield default def touch(self): '''Ensure the custom file in the home folder exists. Either by copying a default config file, or touching an empty file. Intended to be called before trying to edit the file with an external editor. ''' if not self.file.exists(): for file in self.default_files(): file.copyto(self.file) break else: self.file.touch() # create empty file def read(self, fail=False): '''Read the base file or first default file @param fail: if C{True} a L{FileNotFoundError} error is raised when neither the base file or a default file are found. If C{False} it will return C{''} for a non-existing file. @returns: file content as a string ''' try: return self.file.read() except FileNotFoundError: for file in self.default_files(): return file.read() else: if fail: raise else: return '' def readlines(self, fail=False): '''Read the base file or first default file @param fail: if C{True} a L{FileNotFoundError} error is raised when neither the base file or a default file are found. If C{False} it will return C{[]} for a non-existing file. @returns: file content as a list of lines ''' try: return self.file.readlines() except FileNotFoundError: for file in self.default_files(): return file.readlines() else: if fail: raise else: return [] # Not implemented: read_async and readlines_async def write(self, text): '''Write base file, see L{File.write()}''' self.file.write(text) def writelines(self, lines): '''Write base file, see L{File.writelines()}''' self.file.writelines(lines) def write_async(self, text, callback=None, data=None): '''Write base file async, see L{File.write_async()}''' return self.file.write_async(text, callback=callback, data=data) def writelines_async(self, lines, callback=None, data=None): '''Write base file async, see L{File.writelines_async()}''' return self.file.writelines_async(lines, callback=callback, data=data) def remove(self): '''Remove user file, leaves default files in place''' if self.file.exists(): return self.file.remove()