def define(self, E=None, **F):
		'''Set one or more definitions for this config dict
		Can cause error log when values prior given to C{input()} do
		not match the definition.
		'''
		assert not (E and F)
		update = E or F
		if isinstance(update, abc.Mapping):
			items = list(update.items())
		else:
			items = update

		for key, definition in items:
			if key in self.definitions:
				if definition != self.definitions[key]:
					raise AssertionError('Key is already defined with different definition: %s\n%s != %s'
						% (key, definition, self.definitions[key]))
				else:
					continue

			self.definitions[key] = definition
			if key in self._input:
				value = self._input.pop(key)
				self._set_input(key, value)
			else:
				with self.block_signals('changed'):
					DefinitionOrderedDict.__setitem__(self, key, definition.default)
	def _set_input(self, key, value):
		try:
			value = self.definitions[key].check(value)
		except ValueError as error:
			logger.warn(
				'Invalid config value for %s: "%s" - %s',
					key, value, error.args[0]
			)
			value = self.definitions[key].default

		with self.block_signals('changed'):
			DefinitionOrderedDict.__setitem__(self, key, value)
	def __init__(self, E=None, **F):
		assert not (E and F)
		ControlledDict.__init__(self)
		self.definitions = DefinitionOrderedDict()
		self._input = {}
		if E or F:
			self.input(E or F)
	def update(self, E=(), **F):
		# Only emit changed once here
		with self.block_signals('changed'):
			DefinitionOrderedDict.update(self, E, **F)
		self.emit('changed')
	def __delitem__(self, k):
		v = DefinitionOrderedDict.__delitem__(self, k)
		if isinstance(v, DefinitionOrderedDict):
			self.disconnect_from(v)
		self.emit('changed')
	def __setitem__(self, k, v):
		DefinitionOrderedDict.__setitem__(self, k, v)
		if isinstance(v, ControlledDict):
			self.connectto(v, 'changed', self.on_child_changed)
		self.emit('changed')
	def __init__(self, E=(), **F):
		init_signals_for_new_object(self) # Hack, probably needed because we inherit from "dict"
		DefinitionOrderedDict.__init__(self, E or F)
		self._modified = False
	def __init__(self, notebook, linker_factory, dumper_factory,
		title, content, special=None,
		home=None, up=None, prevpage=None, nextpage=None,
		links=None,
		index_generator=None, index_page=None,
	):
		'''Constructor

		When exporting one notebook page per export page ("multi file"),
		'C{content}' is a list of one page everytime. Even for exporting
		special pages, they go into 'C{content}' one at a time.
		The special pages are linked in 'C{links}' so the template can
		refer to them.

		When exporting multiple notebook pages to a single export page
		("single file"), 'C{content}' is a list of all notebook pages a
		nd 'C{special}' a list.

		@param notebook: L{Notebook} object
		@param linker_factory: function producing L{ExportLinker} objects
		@param dumper_factory: function producing L{DumperClass} objects
		@param title: the export page title
		@param content: list of notebook pages to be exported
		@param special: list of special notebook pages to be exported if any
		@param home: link to home page if any
		@param up: link to parent export page if any
		@param prevpage: link to previous export page if any
		@param nextpage: link to next export page if any
		@param links: list of links to special pages if any, links are
		given as a 2-tuple of a key and a target (either a L{Path} or
		a L{NotebookPathProxy})
		@param index_generator: a generator function or that
		provides L{Path} or L{Page} objects to be used for the
		the C{index()} function. This method should take a single
		argument for the root namespace to show.
		See the definition of L{Index.walk()} or L{PageSelection.index()}.
		@param index_page: the current page to show in the index if any
		'''
		# TODO get rid of need of notebook here!
		template_options = TemplateContextDict({}) # can be modified by template
		self._content = content
		self._linker_factory = linker_factory
		self._dumper_factory = partial(dumper_factory, template_options=template_options)
		self._index_generator = index_generator or content
		self._index_page = index_page

		self.linker = linker_factory()

		def _link(l):
			if isinstance(l, str):
				return UriProxy(l)
			elif isinstance(l, Path):
				return NotebookPathProxy(l)
			else:
				assert l is None or isinstance(l, (NotebookPathProxy, FileProxy))
				return l

		if special:
			pages = ExportTemplatePageIter(
				special=PageListProxy(notebook, special, self._dumper_factory, self._linker_factory),
				content=PageListProxy(notebook, content, self._dumper_factory, self._linker_factory)
			)
		else:
			pages = ExportTemplatePageIter(
				content=PageListProxy(notebook, content, self._dumper_factory, self._linker_factory)
			)

		self.update({
			# Parameters
			'generator': {
					'name': 'Zim %s' % ZIM_VERSION,
					'user': os.environ['USER'], # TODO allow user name in prefs ?
			},
			'title': title,
			'navigation': {
				'home': _link(home),
				'up': _link(up),
				'prev': _link(prevpage),
				'next': _link(nextpage),
			},
			'links': DefinitionOrderedDict(), # keep order of links for iteration
			'pages': pages,

			# Template settings
			'options': template_options, # can be modified by template

			# Functions
			#~ 'toc': self.toc_function,
			'index': self.index_function,
			'pageindex': self.index_function, # backward compatibility
			'uri': self.uri_function,
			'anchor': self.anchor_function,
			'resource': self.resource_function,
		})

		if links:
			for k, l in list(links.items()):
				l = _link(l)
				self['links'][k] = l