class LogContext(object): '''Context to log errors and warnings to a log file''' def __init__(self): names = ['zim.export', 'zim.templates', 'zim.formats'] level = logging.INFO self.logger = logging.getLogger('zim') self.level = level self.file = TmpFile(basename='export-log.txt', unique=False, persistent=True) self.file.remove() # clean up previous run self.handler = LogHandler(self.file.path) self.handler.setLevel(self.level) self.handler.addFilter(LogFilter(names)) self.handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s') ) def __enter__(self): #~ self._old_level = self.logger.getEffectiveLevel() #~ if self._old_level > self.level: #~ self.logger.setLevel(self.level) self.logger.addHandler(self.handler) def __exit__(self, exc_type, exc_val, exc_tb): self.logger.removeHandler(self.handler) #~ self.logger.setLevel(self._old_level) self.handler.close() return False # re-raises error
class LogContext(object): '''Context to log errors and warnings to a log file''' def __init__(self): names = ['zim.export', 'zim.templates', 'zim.formats'] level = logging.INFO self.logger = logging.getLogger('zim') self.level = level self.file = TmpFile(basename='export-log.txt', unique=False, persistent=True) self.file.remove() # clean up previous run self.handler = LogHandler(self.file.path) self.handler.setLevel(self.level) self.handler.addFilter(LogFilter(names)) self.handler.setFormatter( logging.Formatter('%(levelname)s: %(message)s')) def __enter__(self): #~ self._old_level = self.logger.getEffectiveLevel() #~ if self._old_level > self.level: #~ self.logger.setLevel(self.level) self.logger.addHandler(self.handler) def __exit__(self, exc_type, exc_val, exc_tb): self.logger.removeHandler(self.handler) #~ self.logger.setLevel(self._old_level) self.handler.close() return False # re-raises error
def print_to_file(self, notebook, page): file = TmpFile('print-to-browser.html', persistent=True, unique=False) template = zim.templates.get_template('html', 'Print') template.set_linker(StaticLinker('html', notebook, page)) html = template.process(notebook, page) file.writelines(html) return file
class EquationGenerator(ImageGeneratorClass): def __init__(self, plugin, notebook, page): ImageGeneratorClass.__init__(self, plugin, notebook, page) self.preferences = plugin.preferences self.template = get_template('plugins', 'equationeditor.tex') self.texfile = TmpFile('equation.tex') def generate_image(self, text): # Filter out empty lines, not allowed in latex equation blocks if isinstance(text, str): text = text.splitlines(True) text = (line for line in text if line and not line.isspace()) text = ''.join(text) #~ print('>>>%s<<<' % text) # Write to tmp file using the template for the header / footer lines = [] self.template.process( lines, { 'equation': text, 'font_size': self.preferences['font_size'], 'dark_mode': self.preferences['dark_mode'] }) self.texfile.writelines(lines) #~ print('>>>%s<<<' % self.texfile.read()) # Call latex logfile = File(self.texfile.path[:-4] + '.log') # len('.tex') == 4 #~ print(">>>", self.texfile, logfile) try: latex = Application('%s -no-shell-escape -halt-on-error' % (latexcmd)) latex.run((self.texfile.basename, ), cwd=self.texfile.dir) except ApplicationError: # log should have details of failure return None, logfile # Call dvipng dvifile = File(self.texfile.path[:-4] + '.dvi') # len('.tex') == 4 pngfile = File(self.texfile.path[:-4] + '.png') # len('.tex') == 4 dvipng = Application('%s -q -bg Transparent -T tight -D %s -o' % (dvipngcmd, self.preferences['output_dpi'])) dvipng.run((pngfile, dvifile)) # output, input # No try .. except here - should never fail # TODO dvipng can start processing before latex finished - can we win speed there ? return pngfile, logfile def cleanup(self): path = self.texfile.path for path in glob.glob(path[:-4] + '.*'): File(path).remove()
def __init__(self): names = ['zim.export', 'zim.templates', 'zim.formats'] level = logging.INFO self.logger = logging.getLogger('zim') self.level = level self.file = TmpFile(basename='export-log.txt', unique=False, persistent=True) self.file.remove() # clean up previous run self.handler = LogHandler(self.file.path) self.handler.setLevel(self.level) self.handler.addFilter(LogFilter(names)) self.handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s'))
def print_to_file(self, notebook, page): file = TmpFile('print-to-browser.html', persistent=True, unique=False) template = zim.templates.get_template('html', 'Print') linker_factory = partial(StaticExportLinker, notebook, template.resources_dir) dumper_factory = zim.formats.get_format('html').Dumper # XXX context = ExportTemplateContext(notebook, linker_factory, dumper_factory, page.basename, [page]) lines = [] template.process(lines, context) file.writelines(lines) return file
def show_side_by_side(self): file = self._get_file() versions = self.versionlist.get_versions() if not (file and versions): raise AssertionError files = map(lambda v: self._get_tmp_file(file, v), versions) if len(files) == 1: tmp = TmpFile(file.basename + '--CURRENT', persistent=True) # need to be persistent, else it is cleaned up before application spawned tmp.writelines(file.readlines()) files.insert(0, tmp) self._side_by_side_app.spawn(files)
class EquationGenerator(ImageGeneratorClass): object_type = 'equation' scriptname = 'equation.tex' imagename = 'equation.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.template = get_template('plugins', 'equationeditor.tex') self.texfile = TmpFile(self.scriptname) def generate_image(self, text): # Filter out empty lines, not allowed in latex equation blocks if isinstance(text, str): text = text.splitlines(True) text = (line for line in text if line and not line.isspace()) text = ''.join(text) #~ print('>>>%s<<<' % text) # Write to tmp file using the template for the header / footer lines = [] self.template.process(lines, {'equation': text}) self.texfile.writelines(lines) #~ print('>>>%s<<<' % self.texfile.read()) # Call latex logfile = File(self.texfile.path[:-4] + '.log') # len('.tex') == 4 #~ print(">>>", self.texfile, logfile) try: latex = Application(latexcmd) latex.run((self.texfile.basename, ), cwd=self.texfile.dir) except ApplicationError: # log should have details of failure return None, logfile # Call dvipng dvifile = File(self.texfile.path[:-4] + '.dvi') # len('.tex') == 4 pngfile = File(self.texfile.path[:-4] + '.png') # len('.tex') == 4 dvipng = Application(dvipngcmd) dvipng.run((pngfile, dvifile)) # output, input # No try .. except here - should never fail # TODO dvipng can start processing before latex finished - can we win speed there ? return pngfile, logfile def cleanup(self): path = self.texfile.path for path in glob.glob(path[:-4] + '.*'): File(path).remove()
def parse_exec(self, args=None): if not (isinstance(args, tuple) and len(args) == 3): raise AssertionError('Custom commands needs 3 arguments') # assert statement could be optimized away notebook, page, pageview = args cmd = split_quoted_strings(self['Desktop Entry']['X-Zim-ExecTool']) if '%f' in cmd: self._tmpfile = TmpFile('tmp-page-source.txt') self._tmpfile.writelines(page.dump('wiki')) cmd[cmd.index('%f')] = self._tmpfile.path if '%d' in cmd: dir = notebook.get_attachments_dir(page) if dir: cmd[cmd.index('%d')] = dir.path else: cmd[cmd.index('%d')] = '' if '%s' in cmd: if hasattr(page, 'source') and isinstance(page.source, File): cmd[cmd.index('%s')] = page.source.path else: cmd[cmd.index('%s')] = '' if '%p' in cmd: cmd[cmd.index('%p')] = page.name if '%n' in cmd: cmd[cmd.index('%n')] = File(notebook.uri).path if '%D' in cmd: dir = notebook.document_root if dir: cmd[cmd.index('%D')] = dir.path else: cmd[cmd.index('%D')] = '' if '%t' in cmd: text = pageview.get_selection() or pageview.get_word() cmd[cmd.index('%t')] = text or '' # FIXME - need to substitute this in arguments + url encoding if '%T' in cmd: text = pageview.get_selection(format='wiki') or pageview.get_word( format='wiki') cmd[cmd.index('%T')] = text or '' # FIXME - need to substitute this in arguments + url encoding return tuple(cmd)
class EquationGenerator(ImageGeneratorClass): object_type = 'equation' scriptname = 'equation.tex' imagename = 'equation.png' def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.template = get_template('plugins', 'equationeditor.tex') self.texfile = TmpFile(self.scriptname) def generate_image(self, text): # Filter out empty lines, not allowed in latex equation blocks if isinstance(text, basestring): text = text.splitlines(True) text = (line for line in text if line and not line.isspace()) text = ''.join(text) #~ print '>>>%s<<<' % text # Write to tmp file using the template for the header / footer lines = [] self.template.process(lines, {'equation': text}) self.texfile.writelines(lines) #~ print '>>>%s<<<' % self.texfile.read() # Call latex logfile = File(self.texfile.path[:-4] + '.log') # len('.tex') == 4 #~ print ">>>", self.texfile, logfile try: latex = Application(latexcmd) latex.run((self.texfile.basename,), cwd=self.texfile.dir) except ApplicationError: # log should have details of failure return None, logfile # Call dvipng dvifile = File(self.texfile.path[:-4] + '.dvi') # len('.tex') == 4 pngfile = File(self.texfile.path[:-4] + '.png') # len('.tex') == 4 dvipng = Application(dvipngcmd) dvipng.run((pngfile, dvifile)) # output, input # No try .. except here - should never fail # TODO dvipng can start processing before latex finished - can we win speed there ? return pngfile, logfile def cleanup(self): path = self.texfile.path for path in glob.glob(path[:-4]+'.*'): File(path).remove()
def show_side_by_side(self): file = self._get_file() versions = self.versionlist.get_versions() if not (file and versions): raise AssertionError files = [self._get_tmp_file(file, v) for v in versions] if len(files) == 1: tmp = TmpFile(file.basename + '--CURRENT', persistent=True) # need to be persistent, else it is cleaned up before application spawned tmp.writelines(file.readlines()) files.insert(0, tmp) self._side_by_side_app.spawn(files)
def print_to_file(self, notebook, page): file = TmpFile('print-to-browser.html', persistent=True, unique=False) template = zim.templates.get_template('html', 'Print') linker_factory = partial(StaticExportLinker, notebook, template.resources_dir) dumper_factory = zim.formats.get_format('html').Dumper # XXX context = ExportTemplateContext( notebook, linker_factory, dumper_factory, page.basename, [page] ) lines = [] template.process(lines, context) file.writelines(lines) return file
def __init__(self, plugin, attachment_folder=None): ImageGeneratorClass.__init__(self, plugin) file = data_file('templates/plugins/gnuploteditor.gnu') assert file, 'BUG: could not find templates/plugins/gnuploteditor.gnu' self.template = GenericTemplate(file.readlines(), name=file) self.attachment_folder = attachment_folder self.plotscriptfile = TmpFile(self.scriptname)
def do_response_ok(self): tmpfile = TmpFile('insert-screenshot.png') selection_mode = False delay = 0 if ScreenshotPicker.has_select_cmd( self.screenshot_command) and self.select_radio.get_active(): selection_mode = True if ScreenshotPicker.has_delay_cmd(self.screenshot_command): delay = self.time_spin.get_value_as_int() options = ScreenshotPicker.get_cmd_options(self.screenshot_command, selection_mode, str(delay)) helper = Application((self.screenshot_command, ) + options) def callback(status, tmpfile): if status == helper.STATUS_OK: name = time.strftime('screenshot_%Y-%m-%d-%H%M%S.png') imgdir = self.notebook.get_attachments_dir(self.page) imgfile = imgdir.new_file(name) tmpfile.rename(imgfile) pageview = self.app_window.pageview pageview.insert_image(imgfile, interactive=False, force=True) else: ErrorDialog( self.ui, _('Some error occurred while running "%s"') % self.screenshot_command).run() # T: Error message in "insert screenshot" dialog, %s will be replaced by application name tmpfile.dir.touch() helper.spawn((tmpfile, ), callback, tmpfile) return True
def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.template = get_template('plugins', 'scoreeditor.ly') self.scorefile = TmpFile(self.scriptname) self.cur_lilypond_version = _get_lilypond_version() self.include_header = plugin.preferences['include_header'] self.include_footer = plugin.preferences['include_footer']
def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) file = data_file('templates/plugins/scoreeditor.ly') assert file, 'BUG: could not find templates/plugins/scoreeditor.ly' self.template = GenericTemplate(file.readlines(), name=file) self.scorefile = TmpFile(self.scriptname) self.cur_lilypond_version = _get_lilypond_version() self.include_header = plugin.preferences['include_header'] self.include_footer = plugin.preferences['include_footer']
def print_to_file(self, page): # FIXME - HACK - dump and parse as wiki first to work # around glitches in pageview parsetree dumper # main visibility when copy pasting bullet lists # Same hack in gui clipboard code from zim.notebook import Path, Page from zim.formats import get_format parsetree = page.get_parsetree() dumper = get_format('wiki').Dumper() text = ''.join( dumper.dump(parsetree) ).encode('utf-8') parser = get_format('wiki').Parser() parsetree = parser.parse(text) page = Page(Path(page.name), parsetree=parsetree) #-- file = TmpFile('print-to-browser.html', persistent=True, unique=False) template = zim.templates.get_template('html', 'Print') template.set_linker(StaticLinker('html', self.ui.notebook, page)) html = template.process(self.ui.notebook, page) file.writelines(html) return file
def __init__(self): names = ['zim.export', 'zim.templates', 'zim.formats'] level = logging.INFO self.logger = logging.getLogger('zim') self.level = level self.file = TmpFile(basename='export-log.txt', unique=False, persistent=True) self.file.remove() # clean up previous run self.handler = LogHandler(self.file.path) self.handler.setLevel(self.level) self.handler.addFilter(LogFilter(names)) self.handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s') )
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 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 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(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 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 LatexGenerator(ImageGeneratorClass): def __init__(self, plugin, notebook, page): ImageGeneratorClass.__init__(self, plugin, notebook, page) self.texfile = TmpFile('latex.tex') print('[PLUGINS:INSERT LATEX] text file: %s' % self.texfile) def generate_image(self, text): if isinstance(text, str): text = text.splitlines(True) text = (line for line in text if line and not line.isspace()) text = ''.join(text) print('[PLUGINS:INSERT LATEX] text written >>>%s<<<' % text) # Write to tmp file self.texfile.write(text) print('[PLUGINS:INSERT LATEX] read from file >>>%s<<<' % self.texfile.read()) # Call latex logfile = File(self.texfile.path[:-4] + '.log') # len('.tex') == 4 print("[PLUGINS:INSERT LATEX] >>>", self.texfile, logfile) try: latex = Application(latex_cmd) latex.run((self.texfile.basename, ), cwd=self.texfile.dir) except ApplicationError: print("[PLUGINS:INSERT LATEX] ApplicationError") return None, logfile png_file = File(self.texfile.path[:-4] + '.png') # len('.tex') == 4 return png_file, logfile def cleanup(self): path = self.texfile.path for path in glob.glob(path[:-4] + '.*'): File(path).remove()
def parse_exec(self, args=None): if not (isinstance(args, tuple) and len(args) == 3): raise AssertionError, 'Custom commands needs 3 arguments' # assert statement could be optimized away notebook, page, pageview = args cmd = split_quoted_strings(self['Desktop Entry']['X-Zim-ExecTool']) if '%f' in cmd: self._tmpfile = TmpFile('tmp-page-source.txt') self._tmpfile.writelines(page.dump('wiki')) cmd[cmd.index('%f')] = self._tmpfile.path if '%d' in cmd: dir = notebook.get_attachments_dir(page) if dir: cmd[cmd.index('%d')] = dir.path else: cmd[cmd.index('%d')] = '' if '%s' in cmd: if hasattr(page, 'source') and isinstance(page.source, File): cmd[cmd.index('%s')] = page.source.path else: cmd[cmd.index('%s')] = '' if '%n' in cmd: cmd[cmd.index('%n')] = File(notebook.uri).path if '%D' in cmd: dir = notebook.document_root if dir: cmd[cmd.index('%D')] = dir.path else: cmd[cmd.index('%D')] = '' if '%t' in cmd: text = pageview.get_selection() or pageview.get_word() cmd[cmd.index('%t')] = text or '' # FIXME - need to substitute this in arguments + url encoding if '%T' in cmd: text = pageview.get_selection(format='wiki') or pageview.get_word(format='wiki') cmd[cmd.index('%T')] = text or '' # FIXME - need to substitute this in arguments + url encoding return tuple(cmd)
def make_screenshot(self, selection_mode, delay): tmpfile = TmpFile('insert-screenshot.png') options = ScreenshotPicker.get_cmd_options(self.screenshot_command, selection_mode, str(delay)) cmd = (self.screenshot_command, ) + options helper = Application(cmd) def callback(status, tmpfile): if status == helper.STATUS_OK: name = time.strftime('screenshot_%Y-%m-%d-%H%M%S.png') imgdir = self.notebook.get_attachments_dir(self.page) imgfile = imgdir.new_file(name) tmpfile.rename(imgfile) pageview = self.pageview pageview.insert_image(imgfile) else: ErrorDialog( self.ui, _('Some error occurred while running "%s"') % self.screenshot_command).run() # T: Error message in "insert screenshot" dialog, %s will be replaced by application name tmpfile.dir.touch() helper.spawn((tmpfile, ), callback, tmpfile) return True def callback(status, tmpfile): if status == helper.STATUS_OK: name = time.strftime('screenshot_%Y-%m-%d-%H%M%S.png') imgdir = self.notebook.get_attachments_dir(self.page) imgfile = imgdir.new_file(name) tmpfile.rename(imgfile) pageview = self.pageview pageview.insert_image(imgfile) else: ErrorDialog( self.ui, _('Some error occurred while running "%s"') % self.screenshot_command).run() # T: Error message in "insert screenshot" dialog, %s will be replaced by application name tmpfile.dir.touch() helper.spawn((tmpfile, ), callback, tmpfile) return True
def testParseExec(self): '''Test parsing of custom tool Exec strings''' # %f for source file as tmp file current page # %d for attachment directory # %s for real source file (if any) # %p for the page name # %n for notebook location (file or directory) # %D for document root # %t for selected text or word under cursor # %T for selected text or word under cursor with wiki format path = self.get_tmp_name() notebook = tests.new_notebook(fakedir=path) page = notebook.get_page(Path('Test:Foo')) pageview = StubPageView() args = (notebook, page, pageview) tmpfile = TmpFile('tmp-page-source.txt').path dir = notebook.dir tool = CustomToolDict() tool.update({ 'Name': 'Test', 'Comment': 'Test 1 2 3', 'X-Zim-ExecTool': 'foo', }) for cmd, wanted in ( ('foo %f', ('foo', tmpfile)), ('foo %d', ('foo', dir.subdir('Test/Foo').path)), ('foo %s', ('foo', page.source.path)), ('foo %p', ('foo', 'Test:Foo')), ('foo %n', ('foo', dir.path)), ('foo %D', ('foo', '')), # no document root ('foo %t', ('foo', 'FooBar')), ('foo %T', ('foo', '**FooBar**')), ): #~ print '>>>', cmd tool['Desktop Entry']['X-Zim-ExecTool'] = cmd self.assertEqual(tool.parse_exec(args), wanted)
def do_response_ok(self): tmpfile = TmpFile('insert-screenshot.png') options = () if COMMAND == 'scrot': if self.select_radio.get_active(): options += ('--select', '--border') # Interactively select a window or rectangle with the mouse. # When selecting a window, grab wm border too else: options += ('--multidisp', ) # For multiple heads, grab shot from each and join them together. delay = self.time_spin.get_value_as_int() if delay > 0: options += ('-d', str(delay)) # Wait NUM seconds before taking a shot. helper = Application((COMMAND, ) + options) def callback(status, tmpfile): if status == helper.STATUS_OK: name = time.strftime('screenshot_%Y-%m-%d-%H%M%S.png') dir = self.notebook.get_attachments_dir(self.page) file = dir.new_file(name) tmpfile.rename(file) self.ui.pageview.insert_image( file, interactive=False) # XXX ui == window else: ErrorDialog( self.ui, _('Some error occurred while running "%s"') % COMMAND).run() # T: Error message in "insert screenshot" dialog, %s will be replaced by application name tmpfile.dir.touch() helper.spawn((tmpfile, ), callback, tmpfile) return True
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()
def on_print_tasklist(self, o): html = self.window.task_list.get_visible_data_as_html() file = TmpFile('print-to-browser.html', persistent=True, unique=False) file.write(html) self.window.ui.open_url('file://%s' % file) # XXX
class CustomToolDict(DesktopEntryDict): '''This is a specialized desktop entry type that is used for custom tools for the "Tools" menu in zim. It uses a non-standard Exec spec with zim specific escapes for "X-Zim-ExecTool". The following fields are expanded: - C{%f} for source file as tmp file current page - C{%d} for attachment directory - C{%s} for real source file (if any) - C{%n} for notebook location (file or directory) - C{%D} for document root - C{%t} for selected text or word under cursor - C{%T} for the selected text including wiki formatting Other additional keys are: - C{X-Zim-ReadOnly} - boolean - C{X-Zim-ShowInToolBar} - boolean - C{X-Zim-ShowInContextMenu} - 'None', 'Text' or 'Page' These tools should always be executed with 3 arguments: notebook, page & pageview. ''' _key_types = { 'X-Zim-ExecTool': 'string', 'X-Zim-ReadOnly': 'boolean', 'X-Zim-ShowInToolBar': 'boolean', } _key_types.update(DesktopEntryDict._key_types) def isvalid(self): '''Check if all required fields are set. @returns: C{True} if all required fields are set ''' entry = self['Desktop Entry'] if entry.get('Type') == 'X-Zim-CustomTool' \ and entry.get('Version') == 1.0 \ and entry.get('Name') \ and entry.get('X-Zim-ExecTool') \ and not entry.get('X-Zim-ReadOnly') is None \ and not entry.get('X-Zim-ShowInToolBar') is None \ and 'X-Zim-ShowInContextMenu' in entry: return True else: logger.error('Invalid custom tool entry: %s %s', self.key, entry) return False def get_pixbuf(self, size): pixbuf = DesktopEntryDict.get_pixbuf(self, size) if pixbuf is None: pixbuf = gtk.Label().render_icon(gtk.STOCK_EXECUTE, size) # FIXME hack to use arbitrary widget to render icon return pixbuf @property def icon(self): return self['Desktop Entry'].get('Icon') or gtk.STOCK_EXECUTE # get('Icon', gtk.STOCK_EXECUTE) still returns empty string if key exists but no value @property def execcmd(self): return self['Desktop Entry']['X-Zim-ExecTool'] @property def isreadonly(self): return self['Desktop Entry']['X-Zim-ReadOnly'] @property def showintoolbar(self): return self['Desktop Entry']['X-Zim-ShowInToolBar'] @property def showincontextmenu(self): return self['Desktop Entry']['X-Zim-ShowInContextMenu'] def parse_exec(self, args=None): if not (isinstance(args, tuple) and len(args) == 3): raise AssertionError, 'Custom commands needs 3 arguments' # assert statement could be optimized away notebook, page, pageview = args cmd = split_quoted_strings(self['Desktop Entry']['X-Zim-ExecTool']) if '%f' in cmd: self._tmpfile = TmpFile('tmp-page-source.txt') self._tmpfile.writelines(page.dump('wiki')) cmd[cmd.index('%f')] = self._tmpfile.path if '%d' in cmd: dir = notebook.get_attachments_dir(page) if dir: cmd[cmd.index('%d')] = dir.path else: cmd[cmd.index('%d')] = '' if '%s' in cmd: if hasattr(page, 'source') and isinstance(page.source, File): cmd[cmd.index('%s')] = page.source.path else: cmd[cmd.index('%s')] = '' if '%n' in cmd: cmd[cmd.index('%n')] = File(notebook.uri).path if '%D' in cmd: dir = notebook.document_root if dir: cmd[cmd.index('%D')] = dir.path else: cmd[cmd.index('%D')] = '' if '%t' in cmd: text = pageview.get_selection() or pageview.get_word() cmd[cmd.index('%t')] = text or '' # FIXME - need to substitute this in arguments + url encoding if '%T' in cmd: text = pageview.get_selection(format='wiki') or pageview.get_word(format='wiki') cmd[cmd.index('%T')] = text or '' # FIXME - need to substitute this in arguments + url encoding return tuple(cmd) _cmd = parse_exec # To hook into Application.spawn and Application.run def run(self, args): self._tmpfile = None Application.run(self, args) if self._tmpfile: notebook, page, pageview = args page.parse('wiki', self._tmpfile.readlines()) self._tmpfile = None def update(self, E=None, **F): self['Desktop Entry'].update(E, **F) # Set sane default for X-Zim-ShowInContextMenus if not (E and 'X-Zim-ShowInContextMenu' in E) \ and not 'X-Zim-ShowInContextMenu' in F: cmd = split_quoted_strings(self['Desktop Entry']['X-Zim-ExecTool']) if any(c in cmd for c in ['%f', '%d', '%s']): context = 'Page' elif '%t' in cmd: context = 'Text' else: context = None self['Desktop Entry']['X-Zim-ShowInContextMenu'] = context
def __init__(self): self.dotfile = TmpFile('diagram-editor.dot') self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4
def __init__(self): self.dotfile = TmpFile(self.scriptname) self.dotfile.touch() self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4
def __init__(self, plugin, attachment_folder=None): ImageGeneratorClass.__init__(self, plugin) self.template = get_template('plugins', 'gnuploteditor.gnu') self.attachment_folder = attachment_folder self.plotscriptfile = TmpFile(self.scriptname)
def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.template = get_template('plugins', 'gnu_r_editor.r') self.plotscriptfile = TmpFile(self.scriptname)
def _get_tmp_file(self, file, version): text = self.vcs.cat(file, version) tmp = TmpFile(file.basename + '--REV%s' % version, persistent=True) # need to be persistent, else it is cleaned up before application spawned tmp.writelines(text) return tmp
def __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) file = data_file('templates/plugins/equationeditor.tex') assert file, 'BUG: could not find templates/plugins/equationeditor.tex' self.template = GenericTemplate(file.readlines(), name=file) self.texfile = TmpFile(self.scriptname)
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 __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 testTmpFile(self): '''Test TmpFile object''' dir = get_tmpdir() file = TmpFile('foo.txt') self.assertTrue(file.ischild(dir))
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 __init__(self, plugin): ImageGeneratorClass.__init__(self, plugin) self.template = get_template('plugins', 'equationeditor.tex') self.texfile = TmpFile(self.scriptname)
def __init__(self, plugin, notebook, page): ImageGeneratorClass.__init__(self, plugin, notebook, page) self.template = get_template('plugins', 'gnu_r_editor.r') self.plotscriptfile = TmpFile('gnu_r_plot.r')
def _get_tmp_file(self, file, version): text = self.vcs.get_version(file, version) tmp = TmpFile(file.basename + '--REV%s' % version, persistent=True) # need to be persistent, else it is cleaned up before application spawned tmp.writelines(text) return tmp
class CustomToolDict(DesktopEntryDict): '''This is a specialized desktop entry type that is used for custom tools for the "Tools" menu in zim. It uses a non-standard Exec spec with zim specific escapes for "X-Zim-ExecTool". The following fields are expanded: - C{%f} for source file as tmp file current page - C{%d} for attachment directory - C{%s} for real source file (if any) - C{%n} for notebook location (file or directory) - C{%D} for document root - C{%t} for selected text or word under cursor - C{%T} for the selected text including wiki formatting Other additional keys are: - C{X-Zim-ReadOnly} - boolean - C{X-Zim-ShowInToolBar} - boolean - C{X-Zim-ShowInContextMenu} - 'None', 'Text' or 'Page' These tools should always be executed with 3 arguments: notebook, page & pageview. ''' _definitions = DesktopEntryDict._definitions + ( ('X-Zim-ExecTool', String(None)), ('X-Zim-ReadOnly', Boolean(True)), ('X-Zim-ShowInToolBar', Boolean(False)), ('X-Zim-ShowInContextMenu', Choice(None, ('Text', 'Page'))), ('X-Zim-ReplaceSelection', Boolean(False)), ) def isvalid(self): '''Check if all required fields are set. @returns: C{True} if all required fields are set ''' entry = self['Desktop Entry'] if entry.get('Type') == 'X-Zim-CustomTool' \ and entry.get('Version') == 1.0 \ and entry.get('Name') \ and entry.get('X-Zim-ExecTool') \ and not entry.get('X-Zim-ReadOnly') is None \ and not entry.get('X-Zim-ShowInToolBar') is None \ and 'X-Zim-ShowInContextMenu' in entry: return True else: logger.error('Invalid custom tool entry: %s %s', self.key, entry) return False def get_pixbuf(self, size): pixbuf = DesktopEntryDict.get_pixbuf(self, size) if pixbuf is None: pixbuf = gtk.Label().render_icon(gtk.STOCK_EXECUTE, size) # FIXME hack to use arbitrary widget to render icon return pixbuf @property def icon(self): return self['Desktop Entry'].get('Icon') or gtk.STOCK_EXECUTE # get('Icon', gtk.STOCK_EXECUTE) still returns empty string if key exists but no value @property def execcmd(self): return self['Desktop Entry']['X-Zim-ExecTool'] @property def isreadonly(self): return self['Desktop Entry']['X-Zim-ReadOnly'] @property def showintoolbar(self): return self['Desktop Entry']['X-Zim-ShowInToolBar'] @property def showincontextmenu(self): return self['Desktop Entry']['X-Zim-ShowInContextMenu'] @property def replaceselection(self): return self['Desktop Entry']['X-Zim-ReplaceSelection'] def parse_exec(self, args=None): if not (isinstance(args, tuple) and len(args) == 3): raise AssertionError, 'Custom commands needs 3 arguments' # assert statement could be optimized away notebook, page, pageview = args cmd = split_quoted_strings(self['Desktop Entry']['X-Zim-ExecTool']) if '%f' in cmd: self._tmpfile = TmpFile('tmp-page-source.txt') self._tmpfile.writelines(page.dump('wiki')) cmd[cmd.index('%f')] = self._tmpfile.path if '%d' in cmd: dir = notebook.get_attachments_dir(page) if dir: cmd[cmd.index('%d')] = dir.path else: cmd[cmd.index('%d')] = '' if '%s' in cmd: if hasattr(page, 'source') and isinstance(page.source, File): cmd[cmd.index('%s')] = page.source.path else: cmd[cmd.index('%s')] = '' if '%p' in cmd: cmd[cmd.index('%p')] = page.name if '%n' in cmd: cmd[cmd.index('%n')] = File(notebook.uri).path if '%D' in cmd: dir = notebook.document_root if dir: cmd[cmd.index('%D')] = dir.path else: cmd[cmd.index('%D')] = '' if '%t' in cmd: text = pageview.get_selection() or pageview.get_word() cmd[cmd.index('%t')] = text or '' # FIXME - need to substitute this in arguments + url encoding if '%T' in cmd: text = pageview.get_selection(format='wiki') or pageview.get_word(format='wiki') cmd[cmd.index('%T')] = text or '' # FIXME - need to substitute this in arguments + url encoding return tuple(cmd) _cmd = parse_exec # To hook into Application.spawn and Application.run def run(self, args, cwd=None): self._tmpfile = None Application.run(self, args, cwd=cwd) if self._tmpfile: notebook, page, pageview = args page.parse('wiki', self._tmpfile.readlines()) self._tmpfile = None def update(self, E=(), **F): self['Desktop Entry'].update(E, **F) # Set sane default for X-Zim-ShowInContextMenus if not (E and 'X-Zim-ShowInContextMenu' in E) \ and not 'X-Zim-ShowInContextMenu' in F: cmd = split_quoted_strings(self['Desktop Entry']['X-Zim-ExecTool']) if any(c in cmd for c in ['%f', '%d', '%s']): context = 'Page' elif '%t' in cmd: context = 'Text' else: context = None self['Desktop Entry']['X-Zim-ShowInContextMenu'] = context
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