Пример #1
0
	def testSaveCopyDialog(self):
		'''Test SaveCopyDialog'''
		tmp_dir = self.create_tmp_dir('testSaveCopyDialog')
		file = File((tmp_dir, 'save_copy.txt'))
		self.assertFalse(file.exists())
		dialog = zim.gui.SaveCopyDialog(self.ui)
		dialog.set_file(file)
Пример #2
0
def get_template(format, template):
	'''Returns a Template object for a template name, file path, or File object'''
	# NOTE: here the "category" needs to be a format at the same time !
	if isinstance(template, File):
		file = template
	else:
		if not is_path_re.match(template):
			file = None
			path = list(data_dirs(('templates', format)))
			path.reverse()
			for dir in path:
				for basename in dir.list():
					name = basename.rsplit('.')[0] # robust if no '.' in basename
					if name == template:
						file = dir.file(basename)
						if file.exists(): # is a file
							break

			if not file:
				file = File(template)
		else:
			file = File(template)

	logger.info('Loading template from: %s', file)
	if not file.exists():
		raise AssertionError, 'No such file: %s' % file

	basename, ext = file.basename.rsplit('.', 1)
	resources = file.dir.subdir(basename)

	return Template(file.readlines(), format, name=file.path, resources_dir=resources)
Пример #3
0
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()
Пример #4
0
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()
Пример #5
0
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()
Пример #6
0
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()
Пример #7
0
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()
Пример #8
0
	def testImportPageDialog(self):
		'''Test ImportPageDialog'''
		tmp_dir = self.create_tmp_dir('testImportPageDialog')
		file = File((tmp_dir, 'import_page.txt'))
		file.write('test 123\n')
		self.assertTrue(file.exists())
		dialog = zim.gui.ImportPageDialog(self.ui)
		dialog.set_file(file)
Пример #9
0
 def testImportPageDialog(self):
     '''Test ImportPageDialog'''
     tmp_dir = self.create_tmp_dir('testImportPageDialog')
     file = File((tmp_dir, 'import_page.txt'))
     file.write('test 123\n')
     self.assertTrue(file.exists())
     dialog = zim.gui.ImportPageDialog(self.ui)
     dialog.set_file(file)
Пример #10
0
	def runTest(self):
		from pprint import pprint

		from zim.fs import File
		file = File('./tests/data/TestTemplate.html')

		templ = Template(file)
		#~ pprint(templ.parts) # parser output

		output = []
		templ.process(output, {
			'title': 'THIS IS THE TITLE',
			'generator': {
				'name': 'ZIM VERSION',
			},
			'navigation': {
				'prev': None,
				'next': None,
			},
			'links': {},
			'pages': [
				{ # page
					'name': 'page',
					'heading': 'HEAD',
					'body': 'BODY',
					'properties': {
						'type': 'PAGE',
					},
					'backlinks': [
						{'name': 'LINK1'},
						{'name': 'LINK2'},
						{'name': 'LINK3'},
					],
					'attachments': [
						{'name': 'FILE1', 'basename': 'FILE1', 'size': '1k'},
						{'name': 'FILE2', 'basename': 'FILE2', 'size': '1k'},
					],
				},
			],
			'uri': ExpressionFunction(lambda l: "URL:%s" % l['name']),
			'anchor': ExpressionFunction(lambda l: "ANCHOR:%s" % l['name']),
		})
		#~ print ''.join(output)

		# TODO assert something

		### Test empty template OK as well
		dir = Dir(self.create_tmp_dir())
		file = dir.file('empty.html')

		self.assertRaises(FileNotFoundError, Template, file)

		file.touch()
		templ = Template(file)
		output = []
		templ.process(output, {})
		self.assertEqual(output, [])
Пример #11
0
    def testPropertiesDialog(self):
        '''Test PropertiesDialog'''
        from zim.gui.propertiesdialog import PropertiesDialog
        self.ui.readonly = True
        dialog = PropertiesDialog(self.ui)
        dialog.assert_response_ok()

        from zim.config import INIConfigFile
        notebook = self.ui.notebook
        file = notebook.dir.file('notebook.zim')
        notebook.config = NotebookConfig(file)
        self.ui.readonly = False

        config1 = {
            'name': 'Notebook Foo',
            'interwiki': None,
            'home': Path('Home'),
            'icon': './icon.png',
            'document_root': File('/foo').path,  # win32 save test
            'shared': False,
            'profile': None,
        }
        config2 = {
            'name': 'Notebook Bar',
            'interwiki': 'FooBar',
            'home': Path('HomeSweetHome'),
            'icon': './picture.png',
            'document_root': File('/bar').path,  # win32 save test
            'shared': True,
            'profile': 'foo',
        }
        notebook.save_properties(**config1)
        for key in config1:
            self.assertEqual(notebook.config['Notebook'][key], config1[key])

        dialog = PropertiesDialog(self.ui)
        dialog.assert_response_ok()

        for key in config1:
            self.assertEqual(notebook.config['Notebook'][key], config1[key])
        self.assertEqual(notebook.name, config1['name'])
        self.assertEqual(notebook.get_home_page(), config1['home'])
        self.assertEqual(notebook.icon,
                         notebook.dir.file(config1['icon']).path)
        self.assertEqual(notebook.document_root, Dir(config1['document_root']))

        dialog = PropertiesDialog(self.ui)
        dialog.form.update(config2)
        dialog.assert_response_ok()

        for key in config1:
            self.assertEqual(notebook.config['Notebook'][key], config2[key])
        self.assertEqual(notebook.name, config2['name'])
        self.assertEqual(notebook.get_home_page(), config2['home'])
        self.assertEqual(notebook.icon,
                         notebook.dir.file(config2['icon']).path)
        self.assertEqual(notebook.document_root, Dir(config2['document_root']))
Пример #12
0
def set_basedirs(_ignore_test=False):
	'''This method sets the global configuration paths for according to the
	freedesktop basedir specification.
	Called automatically when module is first loaded, should be
	called explicitly only when environment has changed.
	'''
	global ZIM_DATA_DIR
	global XDG_DATA_HOME
	global XDG_DATA_DIRS
	global XDG_CONFIG_HOME
	global XDG_CONFIG_DIRS
	global XDG_CACHE_HOME

	# Cast string to folder
	import zim
	zim_data_dir = File(zim.ZIM_EXECUTABLE).dir.subdir('data')
	if zim_data_dir.exists():
		ZIM_DATA_DIR = zim_data_dir

	if os.name == 'nt':
		APPDATA = os.environ['APPDATA']

		XDG_DATA_HOME = Dir(
			os.environ.get('XDG_DATA_HOME', APPDATA + r'\zim\data'))

		XDG_DATA_DIRS = \
			_split_environ_dir_list(os.environ.get('XDG_DATA_DIRS'), ('~/.local/share/',)) # Backwards compatibility

		XDG_CONFIG_HOME = Dir(
			os.environ.get('XDG_CONFIG_HOME', APPDATA + r'\zim\config'))

		XDG_CONFIG_DIRS = \
			_split_environ_dir_list(os.environ.get('XDG_CONFIG_DIRS'), ('~/.config/',)) # Backwards compatibility

		XDG_CACHE_HOME = Dir(
			os.environ.get('XDG_CACHE_HOME', APPDATA + r'\zim\cache'))
	else:
		XDG_DATA_HOME = Dir(
			os.environ.get('XDG_DATA_HOME', '~/.local/share/'))

		XDG_DATA_DIRS = \
			_split_environ_dir_list(os.environ.get('XDG_DATA_DIRS'), ('/usr/share/', '/usr/local/share/'))

		XDG_CONFIG_HOME = Dir(
			os.environ.get('XDG_CONFIG_HOME', '~/.config/'))

		XDG_CONFIG_DIRS = \
			_split_environ_dir_list(os.environ.get('XDG_CONFIG_DIRS'), ('/etc/xdg/',))

		XDG_CACHE_HOME = Dir(
			os.environ.get('XDG_CACHE_HOME', '~/.cache'))

		if os.environ.get('ZIM_TEST_RUNNING') and not _ignore_test:
			# See tests/__init__.py, we load more folders then we really want
			# because the needs of Gtk, but want to restrict it here for all
			# zim internal use
			XDG_DATA_DIRS = [Dir(os.environ['TEST_XDG_DATA_DIRS'])]
Пример #13
0
	def runTest(self):
		tmp_dir = self.create_tmp_dir()

		file = File((tmp_dir, 'test.txt'))
		file.write('test 123')
		self.assertTrue(file.exists())

		dialog = FileDialog(None, 'Test')
		dialog.set_file(file)
Пример #14
0
    def runTest(self):
        tmp_dir = self.create_tmp_dir()

        file = File((tmp_dir, 'test.txt'))
        file.write('test 123')
        self.assertTrue(file.exists())

        dialog = FileDialog(None, 'Test')
        dialog.set_file(file)
Пример #15
0
    def runTest(self):
        from pprint import pprint

        from zim.fs import File
        file = File('./tests/data/TestTemplate.html')

        templ = Template(file)
        #~ pprint(templ.parts) # parser output

        output = []
        templ.process(output, {
         'title': 'THIS IS THE TITLE',
         'generator': {
          'name': 'ZIM VERSION',
         },
         'navigation': {
          'prev': None,
          'next': None,
         },
         'links': {},
         'pages': [
          { # page
           'name': 'page',
           'heading': 'HEAD',
           'body': 'BODY',
           'properties': {
            'type': 'PAGE',
           },
           'backlinks': [
            {'name': 'LINK1'},
            {'name': 'LINK2'},
            {'name': 'LINK3'},
           ],
           'attachments': [
            {'name': 'FILE1', 'basename': 'FILE1', 'size': '1k'},
            {'name': 'FILE2', 'basename': 'FILE2', 'size': '1k'},
           ],
          },
         ],
         'uri': ExpressionFunction(lambda l: "URL:%s" % l['name']),
         'anchor': ExpressionFunction(lambda l: "ANCHOR:%s" % l['name']),
        })
        #~ print ''.join(output)

        # TODO assert something

        ### Test empty template OK as well
        dir = Dir(self.create_tmp_dir())
        file = dir.file('empty.html')

        self.assertRaises(FileNotFoundError, Template, file)

        file.touch()
        templ = Template(file)
        output = []
        templ.process(output, {})
        self.assertEqual(output, [])
Пример #16
0
def _get_path_object(path):
	if isinstance(path, str):
		file = File(path)
		if file.exists(): # exists and is a file
			path = file
		else:
			path = Dir(path)
	else:
		assert isinstance(path, (File, Dir))
	return path
Пример #17
0
def build_notebook(location):
	'''Create a L{Notebook} object for a file location
	Tries to automount file locations first if needed
	@param location: a L{FilePath} or a L{NotebookInfo}
	@returns: a L{Notebook} object and a L{Path} object or C{None}
	@raises FileNotFoundError: if file location does not exist and could not be mounted
	'''
	uri = location.uri
	page = None

	# Decipher zim+file:// uris
	if uri.startswith('zim+file://'):
		uri = uri[4:]
		if '?' in uri:
			uri, page = uri.split('?', 1)
			page = url_decode(page)
			page = Path(page)

	# Automount if needed
	filepath = FilePath(uri)
	if not (filepath.exists() or filepath.__add__('zim.notebook').exists()):
		# The folder of a mount point can exist, so check for specific content
		mount_notebook(filepath)
		if not filepath.exists():
			raise FileNotFoundError(filepath)

	# Figure out the notebook dir
	if filepath.isdir():
		dir = Dir(uri)
		file = None
	else:
		file = File(uri)
		dir = file.dir

	if file and file.basename == 'notebook.zim':
		file = None
	else:
		parents = list(dir)
		parents.reverse()
		for parent in parents:
			if parent.file('notebook.zim').exists():
				dir = parent
				break

	# Resolve the page for a file
	if file:
		path = file.relpath(dir)
		if '.' in path:
			path, _ = path.rsplit('.', 1) # remove extension
		path = path.replace('/', ':')
		page = Path(path)

	# And finally create the notebook
	notebook = Notebook.new_from_dir(dir)
	return notebook, page
Пример #18
0
	def get_file(self):
		file = File(self.uistate['output_file'])
		if file.exists():
			ok = QuestionDialog(self, (
				_('File exists'), # T: message heading
				_('This file already exists.\n'
				  'Do you want to overwrite it?') # T: detailed message, answers are Yes and No
			)).run()
			if not ok:
				return None
		return file
Пример #19
0
	def get_file(self):
		file = File(self.uistate['output_file'])
		if file.exists():
			ok = QuestionDialog(self, (
				_('File exists'), # T: message heading
				_('This file already exists.\n'
				  'Do you want to overwrite it?' ) # T: detailed message, answers are Yes and No
			) ).run()
			if not ok:
				return None
		return file
Пример #20
0
	def delete_file(self, file=None, refresh=False):
		'''Deletes a file and refreshes the treeview if refresh == True'''
		if not file:
			file = self.selected_file
			refresh = True
		logger.debug('Deleting %s' % file)
		file = File(file)
		if file.exists():
			file.cleanup()
		if refresh:
			self.treeview.model.remove(self.iter)
Пример #21
0
def get_template(format, name):
	'''Returns a Template object for a tempalte name or a file path'''
	if is_path_re.match(name):
		file = File(name)
	else:
		templates = list_templates(format)
		#~ if not name in templates: FIXME exception type
			#~ raise
		file = File(templates[name])
	logger.info('Loading template from: %s', file)
	return Template(file.readlines(), format, name=file)
Пример #22
0
	def _append(self, info):
		path = File(info.uri).path
		text = '<b>%s</b>\n<span foreground="#5a5a5a" size="small">%s</span>' % \
				(encode_markup_text(info.name), encode_markup_text(path))
				# T: Path label in 'open notebook' dialog

		if info.icon and File(info.icon).exists():
			w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_BUTTON)
			pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(File(info.icon).path, w, h)
		else:
			pixbuf = None

		self.append((False, info.name, text, pixbuf, info))
Пример #23
0
def set_basedirs():
	'''This method sets the global configuration paths for according to the
	freedesktop basedir specification.
	Called automatically when module is first loaded, should be
	called explicitly only when environment has changed.
	'''
	global ZIM_DATA_DIR
	global XDG_DATA_HOME
	global XDG_DATA_DIRS
	global XDG_CONFIG_HOME
	global XDG_CONFIG_DIRS
	global XDG_CACHE_HOME

	# Cast string to folder
	import zim
	zim_data_dir = File(zim.ZIM_EXECUTABLE).dir.subdir('data')
	if zim_data_dir.exists():
		ZIM_DATA_DIR = zim_data_dir

	if os.name == 'nt':
		APPDATA = environ['APPDATA']

		XDG_DATA_HOME = Dir(
			environ.get('XDG_DATA_HOME', APPDATA + r'\zim\data'))

		XDG_DATA_DIRS = map(Dir,
			environ.get_list('XDG_DATA_DIRS', '~/.local/share/')) # Backwards compatibility

		XDG_CONFIG_HOME = Dir(
			environ.get('XDG_CONFIG_HOME', APPDATA + r'\zim\config'))

		XDG_CONFIG_DIRS = map(Dir,
			environ.get_list('XDG_CONFIG_DIRS', '~/.config/')) # Backwards compatibility

		XDG_CACHE_HOME = Dir(
			environ.get('XDG_CACHE_HOME', APPDATA + r'\zim\cache'))
	else:
		XDG_DATA_HOME = Dir(
			environ.get('XDG_DATA_HOME', '~/.local/share/'))

		XDG_DATA_DIRS = map(Dir,
			environ.get_list('XDG_DATA_DIRS', ('/usr/share/', '/usr/local/share/')))

		XDG_CONFIG_HOME = Dir(
			environ.get('XDG_CONFIG_HOME', '~/.config/'))

		XDG_CONFIG_DIRS = map(Dir,
			environ.get_list('XDG_CONFIG_DIRS', ('/etc/xdg/',)))

		XDG_CACHE_HOME = Dir(
			environ.get('XDG_CACHE_HOME', '~/.cache'))
Пример #24
0
    def resolve_file(self, filename, path=None):
        '''Resolve a file or directory path relative to a page or
		Notebook

		This method is intended to lookup file links found in pages and
		turn resolve the absolute path of those files.

		File URIs and paths that start with '~/' or '~user/' are
		considered absolute paths. Also windows path names like
		'C:\\user' are recognized as absolute paths.

		Paths that starts with a '/' are taken relative to the
		to the I{document root} - this can e.g. be a parent directory
		of the notebook. Defaults to the filesystem root when no document
		root is set. (So can be relative or absolute depending on the
		notebook settings.)

		Paths starting with any other character are considered
		attachments. If C{path} is given they are resolved relative to
		the I{attachment folder} of that page, otherwise they are
		resolved relative to the I{notebook folder} - if any.

		The file is resolved purely based on the path, it does not have
		to exist at all.

		@param filename: the (relative) file path or uri as string
		@param path: a L{Path} object for the page
		@returns: a L{File} object.
		'''
        assert isinstance(filename, str)
        filename = filename.replace('\\', '/')
        if filename.startswith('~') or filename.startswith('file:/'):
            return File(filename)
        elif filename.startswith('/'):
            dir = self.document_root or Dir('/')
            return dir.file(filename)
        elif is_win32_path_re.match(filename):
            if not filename.startswith('/'):
                filename = '/' + filename
                # make absolute on Unix
            return File(filename)
        else:
            if path:
                dir = self.get_attachments_dir(path)
                return File(
                    (dir.path, filename)
                )  # XXX LocalDir --> File -- will need get_abspath to resolve
            else:
                dir = Dir(self.layout.root.path)  # XXX
                return File((dir, filename))
Пример #25
0
	def testFS(self):
		'''Test async FS operations'''

		self.path = self.create_tmp_dir('testFS')+'/file.txt'

		file = File(self.path)

		op1 = file.write_async('foo bar 1\n')
		op2 = file.write_async('foo bar 2\n')

		op1.wait()
		op2.wait()

		self.assertEqual(file.read(), 'foo bar 2\n')
Пример #26
0
def get_template(category, template):
	'''Returns a Template object for a template name or file path
	@param category: the template category (e.g. "html"). Use to resolve
	the template if a template name is given
	@param template: the template name or file path
	'''
	assert isinstance(template, basestring)

	if is_path_re.match(template):
		file = File(template)
	else:
		file = None
		for dir in data_dirs(('templates', category)):
			for basename in dir.list():
				name = basename.rsplit('.')[0] # robust if no '.' in basename
				if basename == template or name == template:
					file = dir.file(basename)
					if file.exists(): # is a file
						break
			if file and file.exists():
				break
		else:
			file = File(template)
			if not file.exists():
				raise PathLookupError, _('Could not find template "%s"') % template
					# T: Error message in template lookup

	if not file.exists():
		raise PathLookupError, _('No such file: %s') % file
			# T: Error message in template lookup

	logger.info('Loading template from: %s', file)
	#~ basename, ext = file.basename.rsplit('.', 1)
	#~ resources = file.dir.subdir(basename)
	return Template(file)
Пример #27
0
def _link_tree(links, notebook, path):
    # Convert a list of links (of any type) into a parsetree
    #~ print('LINKS: ', links)
    #~ print('NOTEBOOK and PATH:', notebook, path)
    builder = ParseTreeBuilder()
    builder.start(FORMATTEDTEXT)
    for i in range(len(links)):
        if i > 0:
            builder.text(' ')

        link = links[i]
        type = link_type(link)
        isimage = False
        if type == 'file':
            try:
                file = File(link)
                isimage = file.isimage()
            except:
                pass

        logger.debug('Pasting link: %s (type: %s, isimage: %s)', link, type,
                     isimage)

        if isimage:
            src = notebook.relative_filepath(file, path) or file.uri
            builder.append(IMAGE, {'src': src})
        elif link.startswith('@'):
            # FIXME - is this ever used ??
            builder.append(TAG, {'name': links[i][1:]}, links[i])
        else:
            name = None
            if type == 'page':
                target = Path(Path.makeValidPageName(
                    link))  # Assume links are always absolute
                href = notebook.pages.create_link(path, target)
                link = href.to_wiki_link()
                if notebook.config['Notebook']['short_relative_links']:
                    name = href.parts()[-1]
            elif type == 'file':
                file = File(link)  # Assume links are always URIs
                link = notebook.relative_filepath(file, path) or file.uri

            builder.append(LINK, {'href': link}, name or link)

    builder.end(FORMATTEDTEXT)
    tree = builder.get_parsetree()
    tree.resolve_images(notebook, path)
    tree.decode_urls()
    return tree
Пример #28
0
    def _append(self, info):
        path = File(info.uri).path
        text = '<b>%s</b>\n<span foreground="#5a5a5a" size="small">%s</span>' % \
          (encode_markup_text(info.name), encode_markup_text(path))
        # T: Path label in 'open notebook' dialog

        if info.icon and File(info.icon).exists():
            w, h = strip_boolean_result(
                Gtk.icon_size_lookup(Gtk.IconSize.BUTTON))
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                File(info.icon).path, w, h)
        else:
            pixbuf = None

        self.append((False, info.name, text, pixbuf, info))
Пример #29
0
def _link_tree(links, notebook, path):
	# Convert a list of links (of any type) into a parsetree
	#~ print 'LINKS: ', links
	#~ print 'NOTEBOOK and PATH:', notebook, path
	builder = TreeBuilder()
	builder.start('zim-tree')
	for i in range(len(links)):
		if i > 0:
			builder.data(' ')

		link = links[i]
		type = link_type(link)
		isimage = False
		if type == 'file':
			try:
				file = File(link)
				isimage = file.isimage()
			except:
				pass

		logger.debug('Pasting link: %s (type: %s, isimage: %s)', link, type, isimage)

		if isimage:
			src = notebook.relative_filepath(file, path) or file.uri
			builder.start('img', {'src': src})
			builder.end('img')
		elif link.startswith('@'):
			# FIXME - is this ever used ??
			builder.start('tag', {'name': links[i][1:]})
			builder.data(links[i])
			builder.end('tag')
		else:
			if type == 'page':
				href = Path(notebook.cleanup_pathname(link)) # Assume links are always absolute
				link = notebook.relative_link(path, href) or link
			elif type == 'file':
				file = File(link) # Assume links are always URIs
				link = notebook.relative_filepath(file, path) or file.uri

			builder.start('link', {'href': link})
			builder.data(link)
			builder.end('link')

	builder.end('zim-tree')
	tree = ParseTree(builder.close())
	tree.resolve_images(notebook, path)
	tree.decode_urls()
	return tree
Пример #30
0
    def parse_old_format(self, text):
        '''Parses the config and cache and populates the list

		Method for backward compatibility with list format with no
		section headers and a whitespace separator between notebook
		name and uri.

		@param text: a string or a list of lines
		'''
        # Old format is name, value pair, separated by whitespace
        # with all other whitespace escaped by a \
        # Default was _default_ which could refer a notebook name.
        if isinstance(text, str):
            text = text.splitlines(True)

        fields_re = re.compile(
            r'(?:\\.|\S)+')  # match escaped char or non-whitespace
        escaped_re = re.compile(r'\\(.)')  # match single escaped char

        default = None
        defaulturi = None
        uris = []
        for line in text:
            if not line or line.isspace() or line.startswith('#'):
                continue

            cols = fields_re.findall(line.strip())
            if len(cols) == 2:
                name = escaped_re.sub(r'\1', cols[0])
                path = escaped_re.sub(r'\1', cols[1])
                if name == '_default_':
                    default = path
                else:
                    uri = File(path).uri
                    uris.append(uri)
                    if name == default:
                        defaulturi = uri

        if default and not defaulturi:
            defaulturi = File(default).uri

        # Populate ourselves
        for uri in uris:
            info = NotebookInfo(uri)
            self.append(info)

        if defaulturi:
            self.set_default(defaulturi)
Пример #31
0
	def runTest(self):
		for creator in self.creators:
			thumbdir = Dir(self.create_tmp_dir(creator.__name__))

			dir = Dir('./data/pixmaps')
			for i, basename in enumerate(dir.list()):
				file = dir.file(basename)
				thumbfile = thumbdir.file('thumb--' + basename)

				self.assertFalse(thumbfile.exists())
				pixbuf = creator(file, thumbfile, THUMB_SIZE_NORMAL)
				self.assertIsInstance(pixbuf, gtk.gdk.Pixbuf)
				self.assertTrue(thumbfile.exists())

				pixbuf = gtk.gdk.pixbuf_new_from_file(thumbfile.encodedpath)
				self.assertEqual(pixbuf.get_option('tEXt::Thumb::URI'), file.uri)
				self.assertTrue(pixbuf.get_option('tEXt::Thumb::URI').startswith('file:///'))
					# Specific requirement of spec to use file:/// and not file://localhost/
				self.assertEqual(int(pixbuf.get_option('tEXt::Thumb::MTime')), int(file.mtime()))

			self.assertTrue(i > 3)

			thumbfile = thumbdir.file('thumb-test.txt')
			self.assertRaises(
				ThumbnailCreatorFailure,
				creator, File('./README.txt'), thumbfile, THUMB_SIZE_NORMAL
			)
Пример #32
0
	def generate_image(self, text):
		if isinstance(text, basestring):
			text = text.splitlines(True)

		plotscriptfile = self.plotscriptfile
		pngfile = File(plotscriptfile.path[:-2] + '.png')

		plot_script = "".join(text)

		template_vars = {
			'gnu_r_plot_script': plot_script,
			'png_fname': pngfile.path.replace('\\', '/'),
				# Even on windows, GNU R expects unix path seperator
		}

		# Write to tmp file usign the template for the header / footer
		plotscriptfile.writelines(
			self.template.process(template_vars)
		)
		#print '>>>%s<<<' % plotscriptfile.read()

		# Call GNU R
		try:
			gnu_r = Application(gnu_r_cmd)
			#~ gnu_r.run(args=('-f', plotscriptfile.basename, ), cwd=plotscriptfile.dir)
			gnu_r.run(args=('-f', plotscriptfile.basename, '--vanilla'), cwd=plotscriptfile.dir)
		except:
			return None, None # Sorry, no log
		else:
			return pngfile, None
Пример #33
0
    def generate_image(self, text):
        plotscriptfile = self.plotscriptfile
        pngfile = File(plotscriptfile.path[:-4] + '.png')

        template_vars = { # they go in the template
         'gnuplot_script': text,
         'png_fname': pngfile.path,
        }
        if self.attachment_folder and self.attachment_folder.exists():
            template_vars['attachment_folder'] = self.attachment_folder.path
        else:
            template_vars['attachment_folder'] = ''

        # Write to tmp file using the template for the header / footer
        lines = []
        self.template.process(lines, template_vars)
        plotscriptfile.writelines(lines)
        #~ print '>>>\n%s<<<' % plotscriptfile.read()

        # Call Gnuplot
        try:
            gnu_gp = Application(gnuplot_cmd)
            gnu_gp.run(args=(plotscriptfile.basename, ),
                       cwd=plotscriptfile.dir)
            # you call it as % gnuplot output.plt

        except ApplicationError:
            return None, None  # Sorry - no log
        else:
            return pngfile, None
Пример #34
0
	def __init__(self, ui, tool=None):
		Dialog.__init__(self, ui, _('Edit Custom Tool')) # T: Dialog title
		self.set_help(':Help:Custom Tools')
		self.vbox.set_spacing(12)

		if tool:
			name = tool.name
			comment = tool.comment
			execcmd = tool.execcmd
			readonly = tool.isreadonly
			toolbar = tool.showintoolbar
		else:
			name = ''
			comment = ''
			execcmd = ''
			readonly = False
			toolbar = False

		self.add_form((
			('Name', 'string', _('Name')), # T: Input in "Edit Custom Tool" dialog
			('Comment', 'string', _('Description')), # T: Input in "Edit Custom Tool" dialog
			('X-Zim-ExecTool', 'string', _('Command')), # T: Input in "Edit Custom Tool" dialog
		), {
			'Name': name,
			'Comment': comment,
			'X-Zim-ExecTool': execcmd,
		}, trigger_response=False)

		# FIXME need ui builder to take care of this as well
		self.iconbutton = IconChooserButton(stock=gtk.STOCK_EXECUTE)
		if tool and tool.icon and tool.icon != gtk.STOCK_EXECUTE:
			try:
				self.iconbutton.set_file(File(tool.icon))
			except Exception, error:
				logger.exception('Could not load: %s', tool.icon)
Пример #35
0
    def testAttachFileDialogCallback(self):
        from zim.gui.widgets import PromptExistingFileDialog

        notebook = self.setUpNotebook(mock=tests.MOCK_ALWAYS_REAL,
                                      content={'Foo': 'test123'})
        self.ui = setupGtkInterface(self, notebook=notebook)

        path = Path('Foo')
        file = File('data/zim.png')

        self.ui.do_attach_file(path, file)

        def do_overwrite(dialog):
            assert isinstance(dialog, PromptExistingFileDialog)
            dialog.do_response_overwrite()

        def do_new_file(dialog):
            assert isinstance(dialog, PromptExistingFileDialog)
            dialog.do_response_ok()

        with tests.DialogContext(do_overwrite):
            self.ui.do_attach_file(path, file)

        with tests.DialogContext(do_new_file):
            self.ui.do_attach_file(path, file)
Пример #36
0
 def on_item_activated(self, iconview, path):
     from zim.fs import File
     store = iconview.get_model()
     iter = store.get_iter(path)
     file = self.folder.file(store[iter][BASENAME_COL])
     file = File(file)
     self.opener.open_file(file)
Пример #37
0
    def on_drag_data_received(self, iconview, dragcontext, x, y, selectiondata,
                              info, time):
        assert selectiondata.target in URI_TARGET_NAMES
        names = unpack_urilist(selectiondata.data)
        files = [File(uri) for uri in names if uri.startswith('file://')]
        action = dragcontext.action
        logger.debug('Drag received %s, %s', action, files)

        if action == gtk.gdk.ACTION_MOVE:
            self._move_files(files)
        elif action == gtk.gdk.ACTION_ASK:
            menu = gtk.Menu()

            item = gtk.MenuItem(
                _('_Move Here'))  # T: popup menu action on drag-drop of a file
            item.connect('activate', lambda o: self._move_files(files))
            menu.append(item)

            item = gtk.MenuItem(
                _('_Copy Here'))  # T: popup menu action on drag-drop of a file
            item.connect('activate', lambda o: self._copy_files(files))
            menu.append(item)

            menu.append(gtk.SeparatorMenuItem())
            item = gtk.MenuItem(
                _('Cancel'))  # T: popup menu action on drag-drop of a file
            # cancel action needs no action
            menu.append(item)

            menu.show_all()
            menu.popup(None, None, None, 1, time)
        else:
            # Assume gtk.gdk.ACTION_COPY or gtk.gdk.ACTION_DEFAULT
            # on windows we get "0" which is not mapped to any action
            self._copy_files(files)
Пример #38
0
    def testUIInterface(self):
        # test ui.new_page_from_text()

        name = 'foo:new page quicknote'
        text = '''\
======= New Page =======
Test 1 2 3

attachment {{./zim16.png}}
'''
        wanted = '''\
<?xml version='1.0' encoding='utf-8'?>
<zim-tree><h level="1">New Page</h>
<p>Test 1 2 3
</p>
<p>attachment <img src="./zim16.png" />
</p></zim-tree>'''

        dirname = self.create_tmp_dir(name='import_source')
        File('./icons/zim16.png').copyto(Dir(dirname))

        ui = setupGtkInterface(self)
        path = ui.new_page_from_text(text, name, attachments=dirname)
        page = ui.notebook.get_page(path)
        attachments = ui.notebook.get_attachments_dir(path)

        self.assertEqual(page.get_parsetree().tostring(), wanted)
        self.assertIn('zim16.png', Dir(attachments.path).list())
Пример #39
0
	def dump_img(self, tag, attrib, strings=None):
		imagepath = self.linker.img(attrib['src'])
		if not self.is_supported_image(imagepath):
			attrib.setdefault('href', attrib['src'])
			return self.dump_link(tag, attrib, strings)

		# We try to get images about the same visual size,
		# therefore need to specify dot density 96 dpi seems to be
		# common for computer monitors
		dpi = 96

		if 'width' in attrib and not 'height' in attrib:
			options = 'width=%fin, keepaspectratio=true' \
					% (float(attrib['width']) / dpi)
		elif 'height' in attrib and not 'width' in attrib:
			options = 'height=%fin, keepaspectratio=true' \
					% (float(attrib['height']) / dpi)
		elif 'height' in attrib and 'width' in attrib:
			options = 'height=%fin, width=%fin' \
					% (float(attrib['height']) / dpi, float(attrib['width']) / dpi)
		else:
			options = ''

		if imagepath.startswith('file://'):
			imagepath = File(imagepath).path # avoid URIs here
		image = '\\includegraphics[%s]{%s}' % (options, imagepath)

		if 'href' in attrib:
			href = self.linker.link(attrib['href'])
			return ['\\href{%s}{%s}' % (href, image)]
		else:
			return [image]
Пример #40
0
    def _stitch_fileextension(self, file, basename):
        '''Stitches the file extension from 'basename' to the path of 'file'
		and returns a File object.
		'''
        i = basename.rfind('.')
        j = file.path.rfind('.')
        return File(file.path[:j] + basename[i:])
Пример #41
0
    def init_uistate(self):
        # Switch between folder selection or file selection based
        # on whether we selected full notebook or single page in the
        # first page
        self.uistate.setdefault('output_folder', None, Dir)
        self.uistate.setdefault('index_page', '')
        self.uistate.setdefault('output_file', None, File)

        show_file = self.uistate.get('selection') == 'page'
        if show_file:
            self.form.widgets['folder'].set_sensitive(False)
            self.form.widgets['folder'].hide()
            self.form.widgets['file'].set_sensitive(True)
            self.form.widgets['file'].show()
        else:
            self.form.widgets['folder'].set_sensitive(True)
            self.form.widgets['folder'].show()
            self.form.widgets['file'].set_sensitive(False)
            self.form.widgets['file'].hide()

        if show_file:
            basename = self.uistate['selected_page'].basename
            ext = zim.formats.get_format(
                self.uistate['format']).info['extension']

            if self.uistate['output_file'] \
            and isinstance(self.uistate['output_file'], File):
                dir = self.uistate['output_file'].dir
                file = dir.file(encode_filename(basename + '.' + ext))
            else:
                file = File('~/' + encode_filename(basename + '.' + ext))
            self.uistate['output_file'] = file

        self.form['file'] = self.uistate['output_file']
        self.form['folder'] = self.uistate['output_folder']
Пример #42
0
    def runTest(self):
        '''Test FileEntry widget'''
        from zim.fs import adapt_from_newfs, Dir
        dir = Dir(self.notebook.folder)  # XXX

        path = Path('Foo:Bar')
        entry = self.entry
        entry.set_use_relative_paths(self.notebook, path)

        home = Dir('~')
        for file, text in (
            (home.file('zim-test.txt'), '~/zim-test.txt'),
            (dir.file('Foo/Bar/test.txt'), './test.txt'),
            (File('/test.txt'), File('/test.txt').path),  # win32 save
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), os_native_path(text))
            self.assertEqual(entry.get_file(), file)

        self.notebook.config['Notebook'][
            'document_root'] = './notebook_document_root'
        doc_root = self.notebook.document_root
        self.assertEqual(doc_root, dir.subdir('notebook_document_root'))

        for file, text in (
            (home.file('zim-test.txt'), os_native_path('~/zim-test.txt')),
            (dir.file('Foo/Bar/test.txt'), os_native_path('./test.txt')),
            (File('/test.txt'), File('/test.txt').uri),  # win32 save
            (doc_root.file('test.txt'), '/test.txt'),
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), text)
            self.assertEqual(entry.get_file(), file)

        entry.set_use_relative_paths(self.notebook, None)

        for file, text in (
            (home.file('zim-test.txt'), os_native_path('~/zim-test.txt')),
            (dir.file('Foo/Bar/test.txt'),
             os_native_path('./Foo/Bar/test.txt')),
            (File('/test.txt'), File('/test.txt').uri),  # win32 save
            (doc_root.file('test.txt'), '/test.txt'),
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), text)
            self.assertEqual(entry.get_file(), file)

        entry.set_use_relative_paths(notebook=None)

        for file, text in (
            (home.file('zim-test.txt'), '~/zim-test.txt'),
                #~ (dir.file('Foo/Bar/test.txt'), './test.txt'),
            (File('/test.txt'), File('/test.txt').path),  # win32 save
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), text)
            self.assertEqual(entry.get_file(), file)
Пример #43
0
    def runTest(self):
        '''Test FileEntry widget'''
        path = Path('Foo:Bar')
        entry = self.entry
        entry.set_use_relative_paths(self.notebook, path)

        home = Dir('~')
        dir = self.notebook.dir
        for file, text in (
            (home.file('zim-test.txt'), '~/zim-test.txt'),
            (dir.file('Foo/Bar/test.txt'), './test.txt'),
            (File('/test.txt'), File('/test.txt').path),  # win32 save
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), os_native_path(text))
            self.assertEqual(entry.get_file(), file)

        self.notebook.config['Notebook'][
            'document_root'] = './notebook_document_root'
        self.notebook.do_properties_changed()  # parse config
        doc_root = self.notebook.document_root
        self.assertEqual(doc_root, dir.subdir('notebook_document_root'))

        for file, text in (
            (home.file('zim-test.txt'), os_native_path('~/zim-test.txt')),
            (dir.file('Foo/Bar/test.txt'), os_native_path('./test.txt')),
            (File('/test.txt'), File('/test.txt').uri),  # win32 save
            (doc_root.file('test.txt'), '/test.txt'),
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), text)
            self.assertEqual(entry.get_file(), file)

        entry.set_use_relative_paths(self.notebook, None)

        for file, text in (
            (home.file('zim-test.txt'), os_native_path('~/zim-test.txt')),
            (dir.file('Foo/Bar/test.txt'),
             os_native_path('./Foo/Bar/test.txt')),
            (File('/test.txt'), File('/test.txt').uri),  # win32 save
            (doc_root.file('test.txt'), '/test.txt'),
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), text)
            self.assertEqual(entry.get_file(), file)

        entry.set_use_relative_paths(notebook=None)

        for file, text in (
            (home.file('zim-test.txt'), '~/zim-test.txt'),
                #~ (dir.file('Foo/Bar/test.txt'), './test.txt'),
            (File('/test.txt'), File('/test.txt').path),  # win32 save
        ):
            entry.set_file(file)
            self.assertEqual(entry.get_text(), text)
            self.assertEqual(entry.get_file(), file)
Пример #44
0
	def testResolveFile(self):
		'''Test notebook.resolve_file()'''
		path = Path('Foo:Bar')
		dir = self.notebook.dir
		self.notebook.config['Notebook']['document_root'] = './notebook_document_root'
		self.notebook.do_properties_changed() # parse config
		doc_root = self.notebook.document_root
		self.assertEqual(doc_root, dir.subdir('notebook_document_root'))
		for link, wanted, cleaned in (
			('~/test.txt', File('~/test.txt'), '~/test.txt'),
			(r'~\test.txt', File('~/test.txt'), '~/test.txt'),
			('file:///test.txt', File('file:///test.txt'), None),
			('file:/test.txt', File('file:///test.txt'), None),
			('file://localhost/test.txt', File('file:///test.txt'), None),
			('/test.txt', doc_root.file('test.txt'), '/test.txt'),
			('../../notebook_document_root/test.txt', doc_root.file('test.txt'), '/test.txt'),
			('./test.txt', dir.file('Foo/Bar/test.txt'), './test.txt'),
			(r'.\test.txt', dir.file('Foo/Bar/test.txt'), './test.txt'),
			('../test.txt', dir.file('Foo/test.txt'), '../test.txt'),
			(r'..\test.txt', dir.file('Foo/test.txt'), '../test.txt'),
			('../Bar/Baz/test.txt', dir.file('Foo/Bar/Baz/test.txt'), './Baz/test.txt'),
			(r'C:\foo\bar', File('file:///C:/foo/bar'), None),
			(r'Z:\foo\bar', File('file:///Z:/foo/bar'), None),
		):
			#~ print link, '>>', self.notebook.resolve_file(link, path)
			self.assertEqual(
				self.notebook.resolve_file(link, path), wanted)
			self.assertEqual(
				self.notebook.relative_filepath(wanted, path), cleaned)

		# check relative path without Path
		self.assertEqual(
			self.notebook.relative_filepath(doc_root.file('foo.txt')), '/foo.txt')
		self.assertEqual(
			self.notebook.relative_filepath(dir.file('foo.txt')), './foo.txt')
Пример #45
0
def _link_tree(links, notebook, path):
    # Convert a list of links (of any type) into a parsetree
    #~ print 'LINKS: ', links
    #~ print 'NOTEBOOK and PATH:', notebook, path
    builder = ParseTreeBuilder()
    builder.start(FORMATTEDTEXT)
    for i in range(len(links)):
        if i > 0:
            builder.text(' ')

        link = links[i]
        type = link_type(link)
        isimage = False
        if type == 'file':
            try:
                file = File(link)
                isimage = file.isimage()
            except:
                pass

        logger.debug('Pasting link: %s (type: %s, isimage: %s)', link, type,
                     isimage)

        if isimage:
            src = notebook.relative_filepath(file, path) or file.uri
            builder.append(IMAGE, {'src': src})
        elif link.startswith('@'):
            # FIXME - is this ever used ??
            builder.append(TAG, {'name': links[i][1:]}, links[i])
        else:
            if type == 'page':
                href = Path(notebook.cleanup_pathname(
                    link))  # Assume links are always absolute
                link = notebook.relative_link(path, href) or link
            elif type == 'file':
                file = File(link)  # Assume links are always URIs
                link = notebook.relative_filepath(file, path) or file.uri

            builder.append(LINK, {'href': link}, link)

    builder.end(FORMATTEDTEXT)
    tree = builder.get_parsetree()
    tree.resolve_images(notebook, path)
    tree.decode_urls()
    return tree
Пример #46
0
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()
Пример #47
0
	def generate_image(self, text):

		(version, text) = self.extract_version(text)
		text = ''.join(text)
		#~ print '>>>%s<<<' % text

		# Write to tmp file using the template for the header / footer
		scorefile = self.scorefile
		lines = []
		self.template.process(lines, {
			'score': text,
			'version': version or '',
			'include_header': self.include_header or '',
			'include_footer': self.include_footer or '',
		} )
		scorefile.writelines(lines)
		#~ print '>>>%s<<<' % scorefile.read()

		# Call convert-ly to convert document of current version of
		# Lilypond.
		clogfile = File(scorefile.path[:-3] + '-convertly.log') # len('.ly) == 3
		try:
			convertly = Application(convertly_cmd)
			convertly.run((scorefile.basename,), cwd=scorefile.dir)
		except ApplicationError:
			clogfile.write('convert-ly failed.\n')
			return None, clogfile


		# Call lilypond to generate image.
		logfile = File(scorefile.path[:-3] + '.log') # len('.ly') == 3
		try:
			lilypond = Application(lilypond_cmd)
			lilypond.run(('-dlog-file=' + logfile.basename[:-4], scorefile.basename,), cwd=scorefile.dir)
		except ApplicationError:
			# log should have details of failure
			return None, logfile
		pngfile = File(scorefile.path[:-3] + '.png') # len('.ly') == 3

		return pngfile, logfile
Пример #48
0
	def testError(self):

		def creator_with_failure(*a):
			raise ThumbnailCreatorFailure

		def creator_with_error(*a):
			raise ValueError

		file = File('./data/zim.png')
		self.assertTrue(file.exists())
		self.assertTrue(file.isimage())

		for creator in creator_with_failure, creator_with_error:
			#~ print ">>", creator.__name__
			queue = ThumbnailQueue(creator)
			queue.queue_thumbnail_request(file, 64)

			with tests.LoggingFilter('zim.plugins.attachmentbrowser', 'Exception'):
				queue.start()
				while not queue.queue_empty():
					r = queue.get_ready_thumbnail()
					self.assertIsNone(r[0], None)
Пример #49
0
	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)
Пример #50
0
	def testAttachFileDialog(self):
		'''Test AttachFileDialog'''
		tmp_dir = self.create_tmp_dir('testAttachFileDialog')
		file = File((tmp_dir, 'file_to_be_attached'))
		file.write('Test 1 2 3\n')
		newfile = File((tmp_dir, 'attachments', 'Test', 'foo', 'file_to_be_attached'))
		self.assertTrue(file.exists())
		self.assertFalse(newfile.exists())

		dialog = zim.gui.AttachFileDialog(self.ui, path=Path('Test:foo'))
		dialog.set_file(file)
Пример #51
0
	def __init__(self):
		self.dotfile = TmpFile('diagram-editor.dot')
		self.dotfile.touch()
		self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4
Пример #52
0
	def runTest(self):
		plugins = PluginManager.list_installed_plugins()
		self.assertTrue(len(plugins) > 10)
		self.assertTrue('spell' in plugins)
		self.assertTrue('linkmap' in plugins)

		pluginindex = File('data/manual/Plugins.txt').read()

		seen = {
			'name': set(),
			'description': set(),
			'help': set(),
		}
		for name in plugins:
			#~ print '>>', name
			klass = PluginManager.get_plugin_class(name)

			# test plugin info
			for key in ('name', 'description', 'author'):
				self.assertTrue(
					klass.plugin_info.get(key),
					'Plugin %s misses info field \'%s\'' % (name, key)
				)

			for key in ('name', 'description', 'help'):
				self.assertIn(key, klass.plugin_info, 'Plugin %s missing "%s"' % (name, key))
				value = klass.plugin_info[key]
				self.assertFalse(
					value in seen[key],
					'Value for \'%s\' in %s seen before - copy-paste error ?' % (key, name)
				)
				seen[key].add(value)

			# test manual page present and at least documents preferences
			page = klass.plugin_info['help']
			self.assertTrue(page.startswith('Plugins:'), 'Help page for %s not valid' % name)

			rellink = "+%s" % page[8:]
			self.assertIn(rellink, pluginindex, 'Missing links "%s" in manual/Plugins.txt' % rellink)

			file = File('data/manual/' + page.replace(':', '/').replace(' ', '_') + '.txt')
			self.assertTrue(file.exists(), 'Missing file: %s' % file)

			manual = file.read()
			for pref in klass.plugin_preferences:
				label = pref[2]
				if '\n' in label:
					label, x = label.split('\n', 1)
					label = label.rstrip(',')
				self.assertIn(label, manual, 'Preference "%s" for %s plugin not documented in manual page' % (label, name))

			# test dependencies data
			dep = klass.check_dependencies()
			self.assertTrue(isinstance(dep,tuple))
			check, dep = dep
			self.assertTrue(isinstance(check,bool))
			self.assertTrue(isinstance(dep,list))
			for i in range(len(dep)):
				self.assertTrue(isinstance(dep[i],tuple))
				self.assertTrue(isinstance(dep[i][0],str))
				self.assertTrue(isinstance(dep[i][1],bool))
				self.assertTrue(isinstance(dep[i][2],bool))
Пример #53
0
def set_basedirs():
	'''This method sets the global configuration paths for according to the
	freedesktop basedir specification.
	Called automatically when module is first loaded, should be
	called explicitly only when environment has changed.
	'''
	global ZIM_DATA_DIR
	global XDG_DATA_HOME
	global XDG_DATA_DIRS
	global XDG_CONFIG_HOME
	global XDG_CONFIG_DIRS
	global XDG_CACHE_HOME

	# Cast string to folder
	import zim
	zim_data_dir = File(zim.ZIM_EXECUTABLE).dir.subdir('data')
	if zim_data_dir.exists():
		ZIM_DATA_DIR = zim_data_dir

	if os.name == 'nt':
		APPDATA = environ['APPDATA']

		XDG_DATA_HOME = Dir(
			environ.get('XDG_DATA_HOME', APPDATA + r'\zim\data'))

		XDG_DATA_DIRS = map(Dir,
			environ.get_list('XDG_DATA_DIRS', '~/.local/share/')) # Backwards compatibility

		XDG_CONFIG_HOME = Dir(
			environ.get('XDG_CONFIG_HOME', APPDATA + r'\zim\config'))

		XDG_CONFIG_DIRS = map(Dir,
			environ.get_list('XDG_CONFIG_DIRS', '~/.config/')) # Backwards compatibility

		try:
			import _winreg as wreg
			wreg_key = wreg.OpenKey(
				wreg.HKEY_CURRENT_USER,
				r'Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders')
			cache_dir = str(wreg.QueryValueEx(wreg_key, "Cache")[0].replace(u'%USERPROFILE%', environ['USERPROFILE']))
			wreg.CloseKey(wreg_key)
		except:
			cache_dir = APPDATA + r'\zim\cache'
			# Not using TMP here because it is cleaned too often

		XDG_CACHE_HOME = Dir(
			environ.get('XDG_CACHE_HOME', cache_dir + r'\zim'))
	else:
		XDG_DATA_HOME = Dir(
			environ.get('XDG_DATA_HOME', '~/.local/share/'))

		XDG_DATA_DIRS = map(Dir,
			environ.get_list('XDG_DATA_DIRS', ('/usr/share/', '/usr/local/share/')))

		XDG_CONFIG_HOME = Dir(
			environ.get('XDG_CONFIG_HOME', '~/.config/'))

		XDG_CONFIG_DIRS = map(Dir,
			environ.get_list('XDG_CONFIG_DIRS', ('/etc/xdg/',)))

		XDG_CACHE_HOME = Dir(
			environ.get('XDG_CACHE_HOME', '~/.cache'))
Пример #54
0
	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
Пример #55
0
 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
Пример #56
0
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()
Пример #57
0
def main(argv):
    """Run the main program

    Depending on the commandline given and whether or not there is
    an instance of zim running already, this method may return
    immediatly, or go into the mainloop untill the program is exitted.

    @param argv: commandline arguments, e.g. from C{sys.argv}

    @raises UsageError: when number of arguments is not correct
    @raises GetOptError: when invalid options are found
    """
    global ZIM_EXECUTABLE

    # FIXME - this returns python.exe on my windows test
    ZIM_EXECUTABLE = argv[0]
    zim_exec_file = File(ZIM_EXECUTABLE)
    if zim_exec_file.exists():
        # We were given an absolute path, e.g. "python ./zim.py"
        ZIM_EXECUTABLE = zim_exec_file.path

    # Check for special commandline args for ipc, does not return
    # if handled
    import zim.ipc

    zim.ipc.handle_argv()

    # Let getopt parse the option list
    short = "".join(shortopts.keys())
    for s, l in shortopts.items():
        if l.endswith("="):
            short = short.replace(s, s + ":")
    long = list(longopts) + list(commands)
    for opts in commandopts.values():
        long.extend(opts)

    opts, args = gnu_getopt(argv[1:], short, long)

    # First figure out which command to execute
    cmd = "gui"  # default
    if opts:
        o = opts[0][0].lstrip("-")
        if o in shortopts:
            o = shortopts[o].rstrip("=")
        if o in commands:
            opts.pop(0)
            cmd = o

    # If it is a simple command execute it and return
    if cmd == "version":
        print "zim %s\n" % __version__
        print __copyright__, "\n"
        print __license__
        return
    elif cmd == "help":
        print usagehelp.replace("zim", argv[0])
        print optionhelp
        return

    # Otherwise check the number of arguments
    if cmd in maxargs and len(args) > maxargs[cmd]:
        raise UsageError

    # --manual is an alias for --gui /usr/share/zim/manual
    if cmd == "manual":
        cmd = "gui"
        args.insert(0, data_dir("manual").path)

    # Now figure out which options are allowed for this command
    allowedopts = list(longopts)
    allowedopts.extend(commandopts[cmd])

    # Convert options into a proper dict
    optsdict = {}
    for o, a in opts:
        o = str(o.lstrip("-"))  # str() -> no unicode for keys
        if o in shortopts:
            o = shortopts[o].rstrip("=")

        if o + "=" in allowedopts:
            o = o.replace("-", "_")
            optsdict[o] = a
        elif o in allowedopts:
            o = o.replace("-", "_")
            optsdict[o] = True
        else:
            raise GetoptError, ("--%s is not allowed in combination with --%s" % (o, cmd), o)

    # --port is the only option that is not of type string
    if "port" in optsdict and not optsdict["port"] is None:
        try:
            optsdict["port"] = int(optsdict["port"])
        except ValueError:
            raise GetoptError, ("--port takes an integer argument", "port")

    # set logging output level for logging root (format has been set in zim.py)
    if not ZIM_EXECUTABLE[-4:].lower() == ".exe":
        # for most platforms
        level = logging.WARN
    else:
        # if running from Windows compiled .exe
        level = logging.ERROR
    if optsdict.pop("verbose", False):
        level = logging.INFO
    if optsdict.pop("debug", False):
        level = logging.DEBUG  # no "elif" !
    logging.getLogger().setLevel(level)

    logger.info("This is zim %s", __version__)
    if level == logging.DEBUG:
        logger.debug("Python version is %s", str(sys.version_info))
        logger.debug("Platform is %s", os.name)
        logger.debug(get_zim_revision())
        log_basedirs()

    # Now we determine the class to handle this command
    # and start the application ...
    logger.debug("Running command: %s", cmd)
    if cmd in ("export", "index", "search"):
        if not len(args) >= 1:
            default = _get_default_or_only_notebook()
            if not default:
                raise UsageError
            handler = NotebookInterface(notebook=default)
        else:
            handler = NotebookInterface(notebook=args[0])

        handler.load_plugins()  # should this go somewhere else ?

        if cmd == "search":
            if not len(args) == 2:
                raise UsageError
            optsdict["query"] = args[1]
        elif len(args) == 2:
            optsdict["page"] = args[1]

        method = getattr(handler, "cmd_" + cmd)
        method(**optsdict)
    elif cmd == "gui":
        notebook = None
        page = None
        if args:
            from zim.notebook import resolve_notebook

            notebook, page = resolve_notebook(args[0])
            if not notebook:
                notebook = File(args[0]).uri
                # make sure daemon approves of this uri and proper
                # error dialog is shown as a result by GtkInterface
            if len(args) == 2:
                page = args[1]

        if "list" in optsdict:
            del optsdict["list"]  # do not use default
        elif not notebook:
            import zim.notebook

            default = _get_default_or_only_notebook()
            if default:
                notebook = default
                logger.info("Opening default notebook")

        # DGT: HACK for debuger
        if "standalone" in optsdict or DEBUG:
            import zim.gui

            try:
                del optsdict["standalone"]
            except:
                pass

            if not notebook:
                import zim.gui.notebookdialog

                notebook = zim.gui.notebookdialog.prompt_notebook()
                if not notebook:
                    return  # User canceled notebook dialog
            handler = zim.gui.GtkInterface(notebook, page, **optsdict)
            handler.main()
        else:
            from zim.ipc import start_server_if_not_running, ServerProxy

            if not notebook:
                import zim.gui.notebookdialog

                notebook = zim.gui.notebookdialog.prompt_notebook()
                if not notebook:
                    return  # User canceled notebook dialog

            start_server_if_not_running()
            server = ServerProxy()
            gui = server.get_notebook(notebook)
            gui.present(page, **optsdict)

            logger.debug(
                """
NOTE FOR BUG REPORTS:
    At this point zim has send the command to open a notebook to a
    background process and the current process will now quit.
    If this is the end of your debug output it is probably not useful
    for bug reports. Please close all zim windows, quit the
    zim trayicon (if any), and try again.
"""
            )
    elif cmd == "server":
        standalone = optsdict.pop("standalone", False)
        # No daemon support for server, so no option doesn't
        # do anything for now
        gui = optsdict.pop("gui", False)
        if gui:
            import zim.gui.server

            zim.gui.server.main(*args, **optsdict)
        else:
            import zim.www

            zim.www.main(*args, **optsdict)
    elif cmd == "plugin":
        import zim.plugins

        try:
            pluginname = args.pop(0)
        except IndexError:
            raise UsageError
        module = zim.plugins.get_plugin_module(pluginname)
        module.main(*args)
Пример #58
0
 def __init__(self):
     self.dotfile = TmpFile(self.scriptname)
     self.dotfile.touch()
     self.pngfile = File(self.dotfile.path[:-4] + '.png') # len('.dot') == 4