def testRemoveTemplate(self):
		dialog = TemplateEditorDialog(None)
		select_by_name(dialog.view, 'foo_test')
		file = LocalFile(XDG_DATA_HOME.file('zim/templates/html/foo_test.html').path)
		self.assertTrue(file.exists())
		dialog.on_delete()
		self.assertFalse(file.exists())
Exemple #2
0
 def _db_check(self):
     try:
         if self.get_property('db_version') == DB_VERSION:
             pass
         else:
             logger.debug('Index db_version out of date')
             self._db_init()
     except sqlite3.OperationalError:
         # db is there but table does not exist
         logger.debug('Operational error, init tabels')
         self._db_init()
     except sqlite3.DatabaseError:
         assert not self.dbpath == ':memory:'
         logger.warning('Overwriting possibly corrupt database: %s',
                        self.dbpath)
         self.db.close()
         file = LocalFile(self.dbpath)
         try:
             file.remove()
         except:
             logger.exception('Could not delete: %s', file)
             # TODO: how to recover form this ? - seems fatal
         finally:
             self._db = self._new_connection()
             self._db_init()
	def testCopyTemplate(self):
		dialog = TemplateEditorDialog(None)
		select_by_name(dialog.view, 'foo_test')

		def do_copy(dialog):
			dialog.set_input(name='new_foo_test')
			dialog.assert_response_ok()

		with tests.DialogContext(do_copy):
			dialog.on_copy()

		file = LocalFile(XDG_DATA_HOME.file('zim/templates/html/new_foo_test.html').path)
		self.assertTrue(file.exists())
Exemple #4
0
 def _db_recover(self):
     assert not self.dbpath == ':memory:'
     logger.warning('Overwriting possibly corrupt database: %s',
                    self.dbpath)
     file = LocalFile(self.dbpath)
     try:
         file.remove(cleanup=False)
     except:
         logger.error(
             'Could not access database file, running in-memory database')
         self.dbpath = ':memory:'
     finally:
         self._db = sqlite3.Connection(self.dbpath)
         self._db.row_factory = sqlite3.Row
         self._db_init()
    def __init__(self, file, page=None):
        '''Constructor
		@param file: a L{File} object
		@param page: an optional L{Path} object for the top level page
		'''
        if isinstance(file, OldFile):
            file = LocalFile(file.path)
        self.file = file

        basename = file.basename
        if '.' in basename:
            basename, x = basename.rsplit('.', 1)
        self.dir = file.parent().folder(basename + '_files')
        self.relative_root = file.parent()

        self.namespace = page
Exemple #6
0
    def on_drag_data_received(self, iconview, dragcontext, x, y, selectiondata,
                              info, time):
        assert selectiondata.get_target().name() in URI_TARGET_NAMES
        names = unpack_urilist(selectiondata.get_data())
        files = [LocalFile(uri) for uri in names if uri.startswith('file://')]
        action = dragcontext.get_selected_action()
        logger.debug('Drag received %s, %s', action, files)

        if action == Gdk.DragAction.MOVE:
            self._move_files(files)
        elif action == Gdk.DragAction.ASK:
            menu = Gtk.Menu()

            item = Gtk.MenuItem.new_with_mnemonic(
                _('_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.new_with_mnemonic(
                _('_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.new_with_mnemonic(
                _('Cancel'))  # T: popup menu action on drag-drop of a file
            # cancel action needs no action
            menu.append(item)

            menu.show_all()
            gtk_popup_at_pointer(menu)
        else:
            # Assume Gdk.DragAction.COPY or Gdk.DragAction.DEFAULT
            # on windows we get "0" which is not mapped to any action
            self._copy_files(files)
Exemple #7
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 = [LocalFile(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)
def copy_imagegenerator_src_files(src_file, folder):
	# Helper method to allow copy-paste dealing with image files generated
	# by a BackwardImageGeneratorObjectType instance
	# We want to be agnostic of the exact image object type, so we just look
	# at any files that share the same basename as the image being copied
	basename = src_file.basename
	i = basename.rfind('.')
	basename = basename[:i]

	src_files = []
	for f in src_file.parent():
		if f.basename.startswith(basename) \
			and not '.' in f.basename[len(basename)+1:]:
				src_files.append(f)

	def check_new_file(new_file):
		for f in src_files:
			new_f = _stitch_fileextension(new_file, f.basename)
			if new_f.exists():
				return False
		else:
			return True

	new_file = folder.new_file(src_file.basename, check_new_file)
	for f in src_files:
		new_f = _stitch_fileextension(new_file, f.basename)
		f.copyto(LocalFile(new_f.path))

	return new_file
    def __init__(self, file, page, ext):
        '''Constructor
		@param file: a L{File} object
		@param page: a L{Path} object for the top level page
		@param ext: the file extension to be used for sub-pages, e.g. 'html'
		'''
        if isinstance(file, OldFile):
            file = LocalFile(file.path)
        self.file = file
        self.namespace = page
        self.ext = ext

        basename = file.basename
        if '.' in basename:
            basename, x = basename.rsplit('.', 1)
        self.dir = file.parent().folder(basename + '_files')
        self.relative_root = file.parent()
def adapt_from_oldfs(file):
    from zim.newfs import LocalFile, LocalFolder

    if isinstance(file, File):
        return LocalFile(file.path)
    elif isinstance(file, Dir):
        return LocalFolder(file.path)
    else:
        return file
def _replace_links_to_interwiki_and_copy_images(src_interwiki, notebook,
                                                new_path, node):
    if node.tag == LINK:
        abs_href = node.attrib.pop('_href', None)
        if abs_href:
            my_type = link_type(abs_href)
            if my_type == 'page':
                oldhref = HRef.new_from_wiki_link(
                    node.get('href'))  # *not* abs_href
                new_href = src_interwiki + '?' + abs_href
                new_href += '#' + oldhref.anchor if oldhref.anchor else ''
            elif my_type == 'file':
                # NOTE: no proper syntax for this type of link - just abs file link
                #       should be improved - e.g. path:./file style links like in docuwiki
                new_href = abs_href
            else:
                logger.warn('Could not update link of type "%s": %s', my_type,
                            abs_href)
                raise VisitorSkip

            if node.gettext() == node.get('href'):  # *not* abs_href
                node[:] = [new_href]
            node.set('href', new_href)
            return node
        else:
            raise VisitorSkip
    elif node.tag == IMAGE:
        # Just copy all images - image links to other notebook don't make sense
        abs_src = node.attrib.pop('_src', None)
        if abs_src:
            src_file = LocalFile(abs_src)
            return _copy_image(notebook, new_path, src_file, node)
        else:
            raise VisitorSkip
    elif node.tag == OBJECT:
        abs_src = node.attrib.pop('_src', None)
        if abs_src and node.get('type').startswith('image+'):
            src_file = LocalFile(abs_src)
            return _copy_image_object(notebook, new_path, src_file, node)
        else:
            raise VisitorSkip
    else:
        raise AssertionError('unknown tag')
Exemple #12
0
def build_mhtml_file_exporter(file, template, **opts):
	'''Returns an L{Exporter} that is suitable for exporting a set of
	pages to a single mhtml file
	'''
	from zim.export.exporters.mhtml import MHTMLExporter

	if isinstance(file, File):
		file = LocalFile(file.path)

	template = get_template('html', template)
	return MHTMLExporter(file, template, **opts)
    def _db_connect(self):
        # NOTE: for a locked database, different errors happen on linux and
        # on windows, so test both platforms when modifying here

        if self.dbpath != ':memory:':
            logger.debug('Connecting to database file: %s', self.dbpath)
            file = LocalFile(self.dbpath)
            file.parent().touch()
        else:
            logger.debug('Connecting to in-memory database')

        try:
            self._db = sqlite3.Connection(self.dbpath)
        except:
            self._db_recover()

        self._db.row_factory = sqlite3.Row

        try:
            self._db.execute('PRAGMA synchronous=OFF;')
            # Don't wait for disk writes, we can recover from crashes
            # anyway. Allows us to use commit more frequently.

            if self.get_property('db_version') != DB_VERSION:
                logger.info('Index db_version out of date')
                self._db_init()
            elif self.get_property('db_sortkey_format') != natural_sort_key(
                    DB_SORTKEY_CONTENT):
                logger.info('Index db_sortkey_format out of date')
                self._db_init()

            self.set_property('db_version', DB_VERSION)  # Ensure we can write
        except sqlite3.OperationalError:
            # db is there but table does not exist
            logger.debug('Operational error, init tabels')
            try:
                self._db_init()
            except:
                self._db_recover()
        except sqlite3.DatabaseError:
            self._db_recover()
Exemple #14
0
def build_single_file_exporter(file, format, template, namespace=None, **opts):
	'''Returns an L{Exporter} that is suitable for exporting a set of
	pages to a single file
	'''
	from zim.export.layouts import SingleFileLayout
	from zim.export.exporters.files import SingleFileExporter

	if isinstance(file, File):
		file = LocalFile(file.path)

	template = get_template(format, template)
	layout = SingleFileLayout(file)
	return SingleFileExporter(layout, template, format, **opts)
Exemple #15
0
    def on_delete(self, *a):
        # Only delete custom, may result in reset to default
        custom, default = self.view.get_selected()
        if custom is None or not custom.exists():
            return  # Should not have been sensitive

        try:
            TrashHelper().trash(LocalFile(custom.path))
        except TrashNotSupportedError:
            # TODO warnings
            custom.remove()

        self.view.refresh()
Exemple #16
0
def build_page_exporter(file, format, template, page, **opts):
	'''Returns an L{Exporter} that is suitable for exporting a page with
	subpages to a file and a folder (e.g. "page.html" with "page_files/")
	'''
	from zim.export.layouts import FileLayout
	from zim.export.exporters.files import MultiFileExporter

	if isinstance(file, File):
		file = LocalFile(file.path)

	template = get_template(format, template)
	ext = get_format(format).info['extension']
	layout = FileLayout(file, page, ext)
	return MultiFileExporter(layout, template, format, **opts)
def _replace_links_to_page_and_copy_images(notebook, old_folder, new_path,
                                           node):
    if node.tag == LINK:
        abs_href = node.attrib.pop('_href', None)
        if abs_href:
            my_type = link_type(abs_href)
            if my_type == 'page':
                target = Path(abs_href)
                oldhref = HRef.new_from_wiki_link(
                    node.get('href'))  # *not* abs_href
                return notebook._update_link_tag(node, new_path, target,
                                                 oldhref)
            elif my_type == 'file':
                new_href = notebook.relative_filepath(LocalFile(abs_href),
                                                      new_path)
                if new_href is None:
                    return node  # could be VisitorSkip, but want to get rid of _href
                else:
                    if node.gettext() == node.get('href'):  # *not* abs_href
                        node[:] = [new_href]
                    node.set('href', new_href)
                    return node
            else:
                logger.warn('Could not update link of type "%s": %s', my_type,
                            abs_href)
                raise VisitorSkip
        else:
            raise VisitorSkip
    elif node.tag == IMAGE:
        # Only copy direct attachments - else the image already was a link
        # to a file outside of the attachment folder
        abs_src = node.attrib.pop('_src', None)
        if abs_src:
            src_file = LocalFile(abs_src)
            if src_file.ischild(old_folder):
                return _copy_image(notebook, new_path, src_file, node)
            else:
                return _update_image(notebook, new_path, src_file, node)
        else:
            raise VisitorSkip
    elif node.tag == OBJECT:
        abs_src = node.attrib.pop('_src', None)
        if abs_src and node.get('type').startswith('image+'):
            src_file = LocalFile(abs_src)
            if src_file.ischild(old_folder):
                return _copy_image_object(notebook, new_path, src_file, node)
            else:
                return _update_image(notebook, new_path, src_file, node)
        else:
            raise VisitorSkip
    else:
        raise AssertionError('unknown tag')
	def testQueue(self):
		queue = ThumbnailQueue()
		self.assertTrue(queue.queue_empty())

		# Test input / output
		src_file = self.setUpFolder(mock=tests.MOCK_ALWAYS_REAL).file('test.txt')
		src_file.write('Test 123\n')
		queue.queue_thumbnail_request(src_file, 64)
			# put an error in the queue

		dir = tests.ZIM_DATA_FOLDER.folder('pixmaps')
		pixmaps = set()
		for basename in dir.list_names():
			if not basename.endswith('.svg'):
				file = dir.file(basename)
				pixmaps.add(file.path)
				queue.queue_thumbnail_request(file, 64)

		self.assertFalse(queue.queue_empty())

		with tests.LoggingFilter('zim.plugins.attachmentbrowser', 'Exception'):
			queue.start()

			seen = set()
			i = len(pixmaps)
			while i > 0:
				i -= 1
				file, size, thumbfile, pixbuf, mtime = queue.get_ready_thumbnail(block=True)
				seen.add(file.path)
				self.assertEqual(size, 64)
				self.assertTrue(thumbfile.exists())
				self.assertIsInstance(pixbuf, GdkPixbuf.Pixbuf)
				self.assertEqual(mtime, file.mtime())

		self.assertEqual(seen, pixmaps)

		# Test clear
		self.assertTrue(queue.queue_empty())
		for path in pixmaps:
			file = LocalFile(path)
			queue.queue_thumbnail_request(file, 64)
		self.assertFalse(queue.queue_empty())
		queue.start()
		time.sleep(0.1)
		queue.clear_queue()
		self.assertTrue(queue.queue_empty())
Exemple #19
0
    def _checkargs(self, cwd, args):
        assert args is None or isinstance(args, (tuple, list))
        argv = self._cmd(args)

        # Expand home dir
        if argv[0].startswith('~'):
            cmd = LocalFile(argv[0]).path
            argv = list(argv)
            argv[0] = cmd

        # if it is a python script, insert interpreter as the executable
        if argv[0].endswith('.py') and not _main_is_frozen():
            argv = list(argv)
            argv.insert(0, sys.executable)
        # TODO: consider an additional commandline arg to re-use compiled python interpreter

        if hasattr(cwd, 'path'):
            cwd = cwd.path

        return cwd, argv
Exemple #20
0
	def relative_filepath(self, file, path=None):
		'''Get a file path relative to the notebook or page

		Intended as the counter part of L{resolve_file()}. Typically
		this function is used to present the user with readable paths or to
		shorten the paths inserted in the wiki code. It is advised to
		use file URIs for links that can not be made relative with
		this method.

		The link can be relative:
		  - to the I{document root} (link will start with "/")
		  - the attachments dir (if a C{path} is given) or the notebook
		    (links starting with "./" or "../")
		  - or the users home dir (link like "~/user/")

		Relative file paths are always given with Unix path semantics
		(so "/" even on windows). But a leading "/" does not mean the
		path is absolute, but rather that it is relative to the
		X{document root}.

		@param file: L{File} object we want to link
		@keyword path: L{Path} object for the page where we want to
		link this file

		@returns: relative file path as string, or C{None} when no
		relative path was found
		'''
		from zim.newfs import LocalFile, LocalFolder
		file = LocalFile(file.path) # XXX
		notebook_root = self.layout.root
		document_root = LocalFolder(self.document_root.path) if self.document_root else None# XXX

		rootdir = '/'
		mydir = '.' + SEP
		updir = '..' + SEP

		# Look within the notebook
		if path:
			attachments_dir = self.get_attachments_dir(path)

			if file.ischild(attachments_dir):
				return mydir + file.relpath(attachments_dir)
			elif document_root and notebook_root \
			and document_root.ischild(notebook_root) \
			and file.ischild(document_root) \
			and not attachments_dir.ischild(document_root):
				# special case when document root is below notebook root
				# the case where document_root == attachment_folder is
				# already caught by above if clause
				return rootdir + file.relpath(document_root)
			elif notebook_root \
			and file.ischild(notebook_root) \
			and attachments_dir.ischild(notebook_root):
				parent = file.commonparent(attachments_dir)
				uppath = attachments_dir.relpath(parent)
				downpath = file.relpath(parent)
				up = 1 + uppath.replace('\\', '/').count('/')
				return updir * up + downpath
		else:
			if document_root and notebook_root \
			and document_root.ischild(notebook_root) \
			and file.ischild(document_root):
				# special case when document root is below notebook root
				return rootdir + file.relpath(document_root)
			elif notebook_root and file.ischild(notebook_root):
				return mydir + file.relpath(notebook_root)

		# If that fails look for global folders
		if document_root and file.ischild(document_root):
			return rootdir + file.relpath(document_root)

		# Finally check HOME or give up
		path = file.userpath
		return path if path.startswith('~') else None
 def edit_page(cmd):
     file = LocalFile(cmd[-1])
     self.assertEqual(file, self.page.source_file)
     file.write('New text\n')
Exemple #22
0
 def show_debug_log(self):
     from zim.newfs import LocalFile
     file = LocalFile(zim.debug_log_file)
     open_file(self.widget, file, mimetype='text/plain')
Exemple #23
0
		def open_file(args):
			got = LocalFile(args[-1])
			want = LocalFile(XDG_DATA_HOME.file('zim/templates/html/foo_test.html').path)
			self.assertEqual(got, want)